Infrastructure-as-code framework for Active Directory objects and Group Policy. Sanitized from production deployment for public sharing.
119 lines
5.6 KiB
PowerShell
119 lines
5.6 KiB
PowerShell
# DefaultDomainPolicy.ps1
|
|
# DSC Configuration: Default Domain Policy for example.internal
|
|
#
|
|
# SINGLE SOURCE OF TRUTH: All values are read from settings.ps1.
|
|
# Do NOT hardcode policy values here -- edit settings.ps1 instead.
|
|
#
|
|
# When applied on a Domain Controller, these settings become the effective
|
|
# domain-wide policy -- matching what the Default Domain Policy GPO enforces.
|
|
|
|
# Load helpers for registry value parsing
|
|
. (Join-Path $PSScriptRoot '..\lib\GPOHelper.ps1')
|
|
|
|
# Load the authoritative settings
|
|
$domainSettings = & (Join-Path $PSScriptRoot 'settings.ps1')
|
|
$sysAccess = $domainSettings.SecurityPolicy['System Access']
|
|
$kerberosPolicy = $domainSettings.SecurityPolicy['Kerberos Policy']
|
|
$regValues = $domainSettings.SecurityPolicy['Registry Values']
|
|
|
|
# --- Value transforms ---
|
|
$toEnabledDisabled = { param($val) if ([int]$val -eq 1) { 'Enabled' } else { 'Disabled' } }
|
|
|
|
# Account Policy
|
|
$dscMinPasswordLength = [int]$sysAccess['MinimumPasswordLength']
|
|
$dscComplexity = & $toEnabledDisabled $sysAccess['PasswordComplexity']
|
|
$dscMaxPasswordAge = [int]$sysAccess['MaximumPasswordAge']
|
|
$dscMinPasswordAge = [int]$sysAccess['MinimumPasswordAge']
|
|
$dscPasswordHistory = [int]$sysAccess['PasswordHistorySize']
|
|
$dscReversibleEncryption = & $toEnabledDisabled $sysAccess['ClearTextPassword']
|
|
$dscLockoutThreshold = [int]$sysAccess['LockoutBadCount']
|
|
|
|
# Lockout duration/reset only meaningful when threshold > 0
|
|
$dscLockoutDuration = if ($dscLockoutThreshold -gt 0) { [int]$sysAccess['LockoutDuration'] } else { 0 }
|
|
$dscResetLockoutCount = if ($dscLockoutThreshold -gt 0) { [int]$sysAccess['ResetLockoutCount'] } else { 0 }
|
|
|
|
# Security Options
|
|
$dscForceLogoff = & $toEnabledDisabled $sysAccess['ForceLogoffWhenHourExpire']
|
|
$dscAnonNameLookup = & $toEnabledDisabled $sysAccess['LSAAnonymousNameLookup']
|
|
$noLmHashValue = Get-GptTmplRegValue $regValues['MACHINE\System\CurrentControlSet\Control\Lsa\NoLMHash']
|
|
$dscNoLmHash = & $toEnabledDisabled $noLmHashValue
|
|
|
|
Configuration DefaultDomainPolicy
|
|
{
|
|
Import-DscResource -ModuleName SecurityPolicyDsc
|
|
|
|
Node 'localhost'
|
|
{
|
|
# ---------------------------------------------------------------
|
|
# Account Policy (Password + Lockout)
|
|
# Only one AccountPolicy resource is allowed per configuration.
|
|
# ---------------------------------------------------------------
|
|
AccountPolicy 'DomainAccountPolicy'
|
|
{
|
|
Name = 'DomainAccountPolicy'
|
|
Minimum_Password_Length = $dscMinPasswordLength
|
|
Password_must_meet_complexity_requirements = $dscComplexity
|
|
Maximum_Password_Age = $dscMaxPasswordAge
|
|
Minimum_Password_Age = $dscMinPasswordAge
|
|
Enforce_password_history = $dscPasswordHistory
|
|
Store_passwords_using_reversible_encryption = $dscReversibleEncryption
|
|
Account_lockout_threshold = $dscLockoutThreshold
|
|
Account_lockout_duration = $dscLockoutDuration
|
|
Reset_account_lockout_counter_after = $dscResetLockoutCount
|
|
}
|
|
|
|
# ---------------------------------------------------------------
|
|
# Security Options
|
|
# ---------------------------------------------------------------
|
|
SecurityOption 'DomainSecurityOptions'
|
|
{
|
|
Name = 'DomainSecurityOptions'
|
|
Network_security_Do_not_store_LAN_Manager_hash_value_on_next_password_change = $dscNoLmHash
|
|
Network_security_Force_logoff_when_logon_hours_expire = $dscForceLogoff
|
|
Network_access_Allow_anonymous_SID_Name_translation = $dscAnonNameLookup
|
|
}
|
|
|
|
# ---------------------------------------------------------------
|
|
# Kerberos Policy (validated via secedit -- no DSC resource exists)
|
|
# SecurityPolicyDsc does not support Kerberos settings.
|
|
# ---------------------------------------------------------------
|
|
Script 'KerberosPolicy'
|
|
{
|
|
GetScript = { @{ Result = 'Kerberos policy validation' } }
|
|
|
|
SetScript = {
|
|
throw 'Kerberos policy remediation not supported via DSC. Use Apply-GPOBaseline.ps1 + gpupdate /force.'
|
|
}
|
|
|
|
TestScript = {
|
|
$tempFile = [System.IO.Path]::GetTempFileName()
|
|
try {
|
|
secedit /export /cfg $tempFile /quiet | Out-Null
|
|
$content = Get-Content $tempFile -Raw
|
|
|
|
$kerberosSettings = $using:kerberosPolicy
|
|
$compliant = $true
|
|
|
|
foreach ($key in $kerberosSettings.Keys) {
|
|
if ($content -match "$key\s*=\s*(\d+)") {
|
|
$actual = [int]$Matches[1]
|
|
$desired = [int]$kerberosSettings[$key]
|
|
if ($actual -ne $desired) {
|
|
Write-Verbose "Kerberos drift: $key = $actual (expected $desired)"
|
|
$compliant = $false
|
|
}
|
|
} else {
|
|
Write-Verbose "Kerberos setting not found in local policy: $key"
|
|
$compliant = $false
|
|
}
|
|
}
|
|
|
|
return $compliant
|
|
} finally {
|
|
Remove-Item $tempFile -Force -ErrorAction SilentlyContinue
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|