Files
WELA/tests/audit-profiles.Tests.ps1

166 lines
14 KiB
PowerShell

# Deterministic tests: no elevation, Windows policy writes, or Pester dependency.
$ErrorActionPreference = 'Stop'
Import-Module (Join-Path $PSScriptRoot '../modules/AuditProfiles.psm1') -Force
$script:Checks = 0
function Assert([bool]$Condition, [string]$Message) {
$script:Checks++
if (-not $Condition) { throw "Assertion failed: $Message" }
}
function Assert-Throws([scriptblock]$Action, [string]$Pattern) {
try { & $Action | Out-Null } catch { Assert ($_.Exception.Message -match $Pattern) "Expected '$Pattern', got '$($_.Exception.Message)'"; return }
throw "Expected exception matching '$Pattern'."
}
function Policy($Plan, $Id) { $Plan.policies | Where-Object { $_.id -eq $Id } }
$data = Import-WelaAuditProfiles
Assert ($data.catalog.Count -eq 59) 'all canonical audit subcategories are represented'
$zero = @{}
foreach ($policy in $data.catalog) { $zero[$policy.guid] = 0 }
foreach ($profile in $data.profiles) {
foreach ($range in $profile.appliesTo) {
foreach ($role in $range.roles) {
$plan = Get-WelaAuditProfilePlan -Profile $profile.id -Role $role -Build $range.minBuild -Current $zero
Assert ($plan.policies.Count -eq 59) "$($profile.id)/$role preserves omitted policies explicitly"
Assert ($plan.provenance.Count -gt 0 -and $plan.schemaSha256.Length -eq 64) 'versioned source and schema fingerprints'
}
}
}
$wela = Get-WelaAuditProfilePlan -Profile wela-2.2.0 -Role Client -Build 26100 -Current $zero
foreach ($id in @('Process Termination', 'RPC Events', 'Detailed File Share', 'Other Policy Change Events')) {
$row = Policy $wela $id
Assert ($row.mode -eq 'exact' -and $row.targetMask -eq 3) "$id recommendation matches existing configure SF policy"
}
Assert ((Policy $wela 'File System').action -eq 'Optional (not selected)') 'optional controls preserve current state by default'
$opt = Get-WelaAuditProfilePlan -Profile wela-2.2.0 -Role Client -Build 26100 -Current $zero -IncludeOptional
Assert ((Policy $opt 'File System').targetMask -eq 3) 'optional control is explicit opt-in'
Assert ((Policy $opt 'File System').prerequisites -match 'SACL') 'SACL dependency is visible'
Assert ((Policy $wela 'Directory Service Access').mode -eq 'not-applicable') 'DC auditing is role scoped'
$adcs = Get-WelaAuditProfilePlan -Profile wela-2.2.0 -Role ADCS -Build 20348 -Current $zero
Assert ((Policy $adcs 'Certification Services').targetMask -eq 3) 'CA role is supported'
Assert ((Policy $adcs 'Certification Services').prerequisites -match 'AuditFilter') 'CA prerequisite not silently claimed applied'
$shareGuid = (Policy $wela 'Detailed File Share').guid
$current = $zero.Clone(); $current[$shareGuid] = 1
$cis = Get-WelaAuditProfilePlan -Profile cis-win11-v4-l1 -Role Client -Build 26100 -Current $current
Assert ((Policy $cis 'Detailed File Share').mode -eq 'minimum') 'CIS includes Failure is represented as minimum'
Assert ((Policy $cis 'Detailed File Share').targetMask -eq 3) 'minimum Failure preserves preexisting Success'
$asd = Get-WelaAuditProfilePlan -Profile asd-native-2021-10 -Role Client -Build 26100 -Current $current
Assert ((Policy $asd 'Detailed File Share').mode -eq 'not-configured') 'ASD explicit NC is retained'
Assert ($null -eq (Policy $asd 'Detailed File Share').targetMask) 'NC does not become disabled'
Assert ((Policy $asd 'RPC Events').mode -eq 'unchanged') 'omission is unchanged, not no-auditing'
$unknown = Get-WelaAuditProfilePlan -Profile cis-win11-v4-l1 -Role Client -Build 26100
Assert ($null -eq (Policy $unknown 'Detailed File Share').targetMask -and (Policy $unknown 'Detailed File Share').action -eq 'Unknown') 'unknown current does not become disabled before minimum merge'
Assert-Throws { Get-WelaAuditProfilePlan -Profile microsoft-sct-win11-24h2 -Role Client -Build 26200 } 'does not support'
Assert-Throws { Get-WelaAuditProfilePlan -Profile microsoft-sct-win11-24h2 -Role DomainController -Build 26100 } 'does not support'
Assert-Throws { Get-WelaAuditProfilePlan -Profile typo -Role Client -Build 26100 } 'Unknown audit profile'
# Inject a stateful native boundary, exercising actual selection, merge, verify and failure behavior.
$script:State = $zero.Clone(); $script:Writes = @()
$reader = { return $script:State.Clone() }
$writer = { param($Guid, $Mask) $script:Writes += $Guid; $script:State[$Guid] = $Mask }
$context = { [pscustomobject]@{ Role = 'Client'; Build = 26100 } }
$applied = Invoke-WelaAuditProfilePlan -Plan $wela -ReadPolicy $reader -WritePolicy $writer -ReadContext $context -Confirm:$false
Assert $applied.success 'apply succeeds after verified effective reads'
$processResult = $applied.results | Where-Object { $_.id -eq 'Process Creation' }
Assert ($processResult.prerequisites -match 'Command-line' -and $processResult.sourceIds -contains 'wela') 'apply results retain source and event-generation prerequisites'
Assert ($applied.version -eq $wela.version) 'apply result includes selected source version'
Assert ($script:Writes.Count -gt 0) 'selected exact policies were applied'
Assert (@($applied.results | Where-Object { $_.status -eq 'Applied' -and $_.effectiveMask -ne $_.targetMask }).Count -eq 0) 'applied always means verified'
$count = $script:Writes.Count
$again = Invoke-WelaAuditProfilePlan -Plan $wela -ReadPolicy $reader -WritePolicy $writer -ReadContext $context -Confirm:$false
Assert ($again.success -and $script:Writes.Count -eq $count) 'applying twice is idempotent using fresh current state'
# Apply a stale minimum plan after a preexisting Success flag is introduced: merge fresh state.
$script:State = $zero.Clone(); $script:State[$shareGuid] = 1
$minimum = Invoke-WelaAuditProfilePlan -Plan $cis -ReadPolicy $reader -WritePolicy $writer -ReadContext $context -Confirm:$false
Assert ($minimum.success -and $script:State[$shareGuid] -eq 3) 'fresh effective flags are preserved in minimum apply'
# Minimum readback permits additional flags enabled by Windows/GPO after the write.
$single = Get-WelaAuditProfilePlan -Profile cis-win11-v4-l1 -Role Client -Build 26100 -Current $zero
$single.policies = @($single.policies | Where-Object { $_.id -eq 'Detailed File Share' })
$script:State = $zero.Clone()
$extra = Invoke-WelaAuditProfilePlan -Plan $single -ReadPolicy $reader -WritePolicy {
param($Guid, $Mask, $Mode)
Assert ($Mode -eq 'minimum') 'injected writer receives policy semantics'
$script:State[$Guid] = 3
} -ReadContext $context -Confirm:$false
Assert ($extra.success -and $extra.results[0].targetMask -eq 2 -and $extra.results[0].effectiveMask -eq 3) 'minimum Failure accepts post-write Success+Failure'
# A flag introduced after whole-plan preflight is included in the immediate control read.
$script:State = $zero.Clone(); $script:Reads = 0; $script:WrittenMask = $null
$race = Invoke-WelaAuditProfilePlan -Plan $single -ReadPolicy {
$script:Reads++
if ($script:Reads -eq 2) { $script:State[$shareGuid] = 1 }
$script:State.Clone()
} -WritePolicy {
param($Guid, $Mask, $Mode)
$script:WrittenMask = $Mask
$script:State[$Guid] = $Mask
} -ReadContext $context -Confirm:$false
Assert ($race.success -and $script:WrittenMask -eq 3 -and $race.results[0].beforeMask -eq 1) 'fresh per-control read preserves a flag introduced after preflight'
$script:Reads = 0; $script:WrittenMask = $null
$unknownRace = Invoke-WelaAuditProfilePlan -Plan $single -ReadPolicy {
$script:Reads++
if ($script:Reads -eq 1) { $zero.Clone() } else { @{} }
} -WritePolicy { $script:WrittenMask = 1 } -ReadContext $context -Confirm:$false
Assert (-not $unknownRace.success -and $null -eq $script:WrittenMask -and $unknownRace.results[0].sourceIds.Count -gt 0) 'state becoming unknown blocks that write and retains evidence'
# Verify the real native command contract: minimum never supplies an unrequired disable.
$minimumArgs = @(& (Get-Module AuditProfiles) { param($Guid) Get-WelaAuditSetArguments -Guid $Guid -Mask 2 -Mode minimum } $shareGuid)
Assert ($minimumArgs -contains '/failure:enable' -and @($minimumArgs | Where-Object { $_ -like '/success:*' -or $_ -like '*:disable' }).Count -eq 0) 'minimum Failure writes only failure-enable, preserving concurrent Success'
$exactArgs = @(& (Get-Module AuditProfiles) { param($Guid) Get-WelaAuditSetArguments -Guid $Guid -Mask 1 -Mode exact } $shareGuid)
Assert ($exactArgs -contains '/success:enable' -and $exactArgs -contains '/failure:disable') 'exact Success deliberately clears Failure'
# Role classification must not guess when CA presence is unreadable, or omit CA policy on a DC.
$serverOS = { [pscustomobject]@{ ProductType = 3; BuildNumber = 26100 } }
$dcOS = { [pscustomobject]@{ ProductType = 2; BuildNumber = 26100 } }
$memberSystem = { [pscustomobject]@{ DomainRole = 3 } }
$dcSystem = { [pscustomobject]@{ DomainRole = 5 } }
Assert-Throws { Get-WelaHostContext -ReadOperatingSystem $serverOS -ReadComputerSystem $memberSystem -ReadCertificateAuthority { throw 'CA registry access denied' } } 'access denied'
Assert-Throws { Get-WelaHostContext -ReadOperatingSystem $serverOS -ReadComputerSystem $memberSystem -ReadCertificateAuthority { $null } } 'Cannot determine'
Assert-Throws { Get-WelaHostContext -ReadOperatingSystem $dcOS -ReadComputerSystem $dcSystem -ReadCertificateAuthority { $true } } 'Combined domain-controller/CA'
$ca = Get-WelaHostContext -ReadOperatingSystem $serverOS -ReadComputerSystem $memberSystem -ReadCertificateAuthority { $true }
Assert ($ca.Role -eq 'ADCS') 'member-server CA remains supported'
$dc = Get-WelaHostContext -ReadOperatingSystem $dcOS -ReadComputerSystem $dcSystem -ReadCertificateAuthority { $false }
Assert ($dc.Role -eq 'DomainController') 'DC without CA remains supported'
$script:State = $zero.Clone()
$failed = Invoke-WelaAuditProfilePlan -Plan $wela -ReadPolicy $reader -WritePolicy { throw 'command failed' } -ReadContext $context -Confirm:$false
Assert (-not $failed.success -and @($failed.results | Where-Object { $_.status -eq 'Failed' }).Count -gt 0) 'native failure is machine-readable'
$mismatch = Invoke-WelaAuditProfilePlan -Plan $wela -ReadPolicy $reader -WritePolicy { param($Guid, $Mask) } -ReadContext $context -Confirm:$false
Assert (-not $mismatch.success) 'zero exit without effective change does not count as success'
$failedProcess = $mismatch.results | Where-Object { $_.id -eq 'Process Creation' }
Assert ($failedProcess.status -eq 'Failed' -and $null -eq $failedProcess.effectiveMask -and $failedProcess.prerequisites -match 'Command-line') 'failed/unknown effective state still retains prerequisites'
$script:Writes = @()
$whatIf = Invoke-WelaAuditProfilePlan -Plan $wela -ReadPolicy $reader -WritePolicy $writer -ReadContext $context -WhatIf
Assert ($script:Writes.Count -eq 0) 'WhatIf never invokes native writer'
Assert-Throws { Invoke-WelaAuditProfilePlan -Plan $wela -ReadPolicy { @{} } -WritePolicy $writer -ReadContext $context -Confirm:$false } 'unknown current'
Assert ($script:Writes.Count -eq 0) 'unknown preflight refuses all writes'
Assert-Throws { Invoke-WelaAuditProfilePlan -Plan $wela -ReadPolicy $reader -WritePolicy $writer -ReadContext { [pscustomobject]@{ Role = 'DomainController'; Build = 26100 } } } 'actual Windows host'
$defaults = Get-WelaAuditProfilePlan -Profile windows-defaults-reviewed-2026-09 -Role Client -Build 26100 -Current $zero
Assert-Throws { Invoke-WelaAuditProfilePlan -Plan $defaults -ReadPolicy $reader -WritePolicy $writer -ReadContext $context } 'reference'
# Schema rejects bad policy names, duplicate GUIDs, invalid masks/modes, and unknown provenance.
$temp = Join-Path ([System.IO.Path]::GetTempPath()) ('wela-profile-test-' + [guid]::NewGuid().ToString() + '.json')
try {
foreach ($case in @('guid', 'mask', 'mode', 'source', 'unknown')) {
$copy = Get-Content (Join-Path $PSScriptRoot '../config/audit_profiles.json') -Raw | ConvertFrom-Json
switch ($case) {
'guid' { $copy.catalog[1].guid = $copy.catalog[0].guid }
'mask' { $copy.profiles[0].controls.'Process Creation'.mask = 7 }
'mode' { $copy.profiles[0].controls.'Process Creation'.mode = 'invented' }
'source' { $copy.profiles[0].sourceIds = @('unreviewed') }
'unknown' { $copy.profiles[0].controls | Add-Member NoteProperty 'Typo Policy' ([pscustomobject]@{ mode = 'exact'; mask = 3 }) }
}
$copy | ConvertTo-Json -Depth 30 | Set-Content -LiteralPath $temp -Encoding UTF8
Assert-Throws { Import-WelaAuditProfiles -Path $temp } 'Invalid|Unknown|duplicate'
}
} finally { Remove-Item -LiteralPath $temp -Force -ErrorAction SilentlyContinue }
# Legacy Yamato audit display now takes recommendations from the shared profile, including omitted policies.
. (Join-Path $PSScriptRoot '../WELA.ps1') help -Role Client -Build 26100
function GetAuditpol { return @{} }
$legacy = BuildAuditResult -all_rules @() -Baseline YamatoSecurity -enabledguid @()
foreach ($id in @('Process Termination', 'RPC Events', 'Detailed File Share', 'Other Policy Change Events')) {
$entry = $legacy | Where-Object { $_.SubCategory -eq $id }
Assert ($entry.RecommendedSetting -eq 'Success and Failure [exact]') "legacy audit/settings shares $id recommendation"
}
Assert (@($legacy | Where-Object { $_.Category -like 'Security Advanced*' }).Count -eq 59) 'legacy display includes all canonical GUIDs'
# An unsupported legacy configure target must fail before reaching the old setup body.
function TestWindows { return $true }
function TestAdministrator { return $true }
function Get-WelaHostContext { [pscustomobject]@{ Role = 'Client'; Build = 19045 } }
function Get-WelaEffectiveAuditPolicy { return $zero.Clone() }
function CollectAuditpol { throw 'Reached the old configuration body before profile validation' }
Assert-Throws { ConfigureAuditSettings -Auto } 'does not support'
Write-Host "PASS: $script:Checks audit profile checks; no Windows settings changed."