# 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 } } } } }