Damien Coles f172d00514 Initial release: Declarative AD Framework v2.1.0
Infrastructure-as-code framework for Active Directory objects and Group Policy.
Sanitized from production deployment for public sharing.
2026-02-19 17:02:42 +00:00

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