mirror of
https://github.com/Yamato-Security/WELA.git
synced 2026-11-01 18:58:16 +01:00
Gate conditional IPsec auditing on native prerequisite evidence (#439)
* Gate conditional stronger-profile IPsec auditing on native evidence * Use supported literal shells in native prerequisite matrix * Retain native IPsec fixture diagnostics and allow inactive rule omission * Expose exact native rule fields when prerequisite classification fails * Recognize native inactive IPsec rules without granting applicability * Restore standalone regression loading and valid owned IPsec auth defaults
This commit is contained in:
1 parent
7cd2eb9dbf
commit
b7e649185b
15 files changed
+442
-12
No files matched your search
@@ -1,5 +1,6 @@
|
||||
# Mocked registry/audit policy; no Windows policy changes.
|
||||
$ErrorActionPreference = 'Stop'
|
||||
Import-Module (Join-Path $PSScriptRoot '../modules/AuditProfiles.psm1') -Force
|
||||
. (Join-Path $PSScriptRoot '../scripts/Configuration.ps1')
|
||||
$script:assertions = 0
|
||||
$script:paths = @()
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$repo = Split-Path $PSScriptRoot -Parent
|
||||
$script:ScriptRoot = $repo
|
||||
Import-Module (Join-Path $repo 'modules/AuditProfiles.psm1') -Force
|
||||
. (Join-Path $repo 'scripts/Configuration.ps1')
|
||||
$script:checks=0
|
||||
function Assert($Condition,[string]$Message) { if (-not $Condition) { throw "FAIL: $Message" }; $script:checks++ }
|
||||
function Rule([string]$Enabled='True',[string]$Inbound='Require',[string]$Outbound='Request',[string]$Health='OK') {
|
||||
[pscustomobject]@{Name='owned';Enabled=$Enabled;InboundSecurity=$Inbound;OutboundSecurity=$Outbound;PrimaryStatus=$Health}
|
||||
}
|
||||
$script:rule=Rule
|
||||
$positive=Get-WelaIpsecPrerequisite -ReadRules {$script:rule} -ReadAssociations {}
|
||||
Assert ($positive.Status -eq 'Applicable' -and $positive.Rules[0].Qualifies) 'healthy effective securing rule qualifies'
|
||||
$none=Get-WelaIpsecPrerequisite -ReadRules {} -ReadAssociations {}
|
||||
Assert ($none.Status -eq 'NotObservedWithinScope' -and $none.Limitations -match 'legacy IPsec') 'empty complete inventory is scope-limited absence'
|
||||
foreach ($candidate in @((Rule False),(Rule False Require Request Inactive),(Rule True None None))) {
|
||||
$script:rule=$candidate
|
||||
$evidence=Get-WelaIpsecPrerequisite -ReadRules {$script:rule} -ReadAssociations {}
|
||||
Assert ($evidence.Status -eq 'NotObservedWithinScope' -and -not $evidence.Rules[0].Qualifies) 'disabled and exemption-only policies do not qualify'
|
||||
}
|
||||
foreach ($candidate in @((Rule True Require Request Error),(Rule True Require Request Unknown),(Rule True Require Request Inactive),(Rule Maybe),([pscustomobject]@{Name='missing'}))) {
|
||||
$script:rule=$candidate
|
||||
Assert ((Get-WelaIpsecPrerequisite -ReadRules {$script:rule} -ReadAssociations {}).Status -eq 'Unknown') 'invalid or unhealthy policy stays unknown'
|
||||
}
|
||||
$script:rule=Rule
|
||||
Assert ((Get-WelaIpsecPrerequisite -ReadRules {$script:rule; throw 'denied midway'} -ReadAssociations {}).Status -eq 'Unknown') 'partial failed enumeration never qualifies'
|
||||
Assert ((Get-WelaIpsecPrerequisite -ReadRules {$script:rule} -ReadAssociations {throw 'denied'}).Status -eq 'Unknown') 'failed independent SA observation prevents complete positive evidence'
|
||||
Assert ((Get-WelaIpsecPrerequisite -ReadRules {$script:rule;$script:rule} -ReadAssociations {}).Status -eq 'Unknown') 'duplicate rule identities rejected'
|
||||
Assert ((Get-WelaIpsecPrerequisite -ReadRules {1..4097} -ReadAssociations {}).Status -eq 'Unknown') 'native inventory cap remains unknown'
|
||||
$sa=Get-WelaIpsecPrerequisite -ReadRules {} -ReadAssociations {[pscustomobject]@{Name='1';LocalEndpoint='192.0.2.1';RemoteEndpoint='192.0.2.2'}}
|
||||
Assert ($sa.Status -eq 'Applicable' -and $sa.MainModeAssociations.Count -eq 1) 'valid native SA is independently positive evidence'
|
||||
Assert ((Get-WelaIpsecPrerequisite -ReadRules {} -ReadAssociations {[pscustomobject]@{Name='1';LocalEndpoint='unknown';RemoteEndpoint='192.0.2.2'}}).Status -eq 'Unknown') 'malformed SA does not qualify'
|
||||
Assert ((Get-WelaIpsecPrerequisite -Offline -ReadRules {throw 'must not run'} -ReadAssociations {throw 'must not run'}).Status -eq 'Unknown') 'offline never queries this host'
|
||||
$script:zero=@{}; foreach ($policy in (Import-WelaAuditProfiles).catalog) {$script:zero[$policy.guid]=0}
|
||||
$profile='microsoft-stronger-reviewed-2026-09';$guid='0CCE9218-69AE-11D9-BED3-505054503030'
|
||||
function Plan([switch]$Optional,[switch]$Observe) { Get-WelaAuditProfilePlan -Profile $profile -Role MemberServer -Build 26100 -Current $script:zero -IncludeOptional:$Optional -ObserveIpsec:$Observe -ReadIpsec {$script:evidence} }
|
||||
$script:evidence=$positive
|
||||
$plan=Plan -Optional
|
||||
$row=@($plan.policies|Where-Object id -eq 'IPsec Main Mode')[0]
|
||||
Assert ($row.conditionalPrerequisite.Status -eq 'Unknown' -and $null -eq $row.targetMask) 'offline conditional plan has no applicable target'
|
||||
$plan=Plan -Observe
|
||||
Assert (($plan.policies|Where-Object id -eq 'IPsec Main Mode').action -eq 'Optional (not selected)') 'positive evidence never substitutes for explicit selection'
|
||||
$plan=Plan -Observe -Optional
|
||||
Assert (($plan.policies|Where-Object id -eq 'IPsec Main Mode').targetMask -eq 3) 'live selected positive plan retains exact SF mask'
|
||||
$script:evidence=$none;$plan=Plan -Observe -Optional
|
||||
Assert (($plan.policies|Where-Object id -eq 'IPsec Main Mode').action -like 'Preserve*') 'scope-limited absence explicitly preserves'
|
||||
function Single-Plan {
|
||||
$p=Plan -Optional -Observe
|
||||
$p.policies=@($p.policies|Where-Object id -eq 'IPsec Main Mode')
|
||||
$p
|
||||
}
|
||||
$script:evidence=$positive;$plan=Single-Plan
|
||||
$script:state=$script:zero.Clone();$script:writes=0;$script:reads=0
|
||||
$contextReader={ [pscustomobject]@{Role='MemberServer';Build=26100} }
|
||||
$writer={param($Guid,$Mask) $script:writes++;$script:state[$Guid]=$Mask}
|
||||
$reader={$script:state.Clone()}
|
||||
$result=Invoke-WelaAuditProfilePlan $plan -ReadContext $contextReader -ReadPolicy $reader -WritePolicy $writer -ReadIpsec {$positive} -Confirm:$false
|
||||
Assert ($result.success -and $script:writes -eq 1 -and $result.results[0].prerequisiteObservations.Count -eq 2) 'direct executor observes and rechecks before write'
|
||||
$script:state[$guid]=0;$script:writes=0
|
||||
$result=Invoke-WelaAuditProfilePlan $plan -ReadContext $contextReader -ReadPolicy $reader -WritePolicy $writer -ReadIpsec {$none} -Confirm:$false
|
||||
Assert ($result.success -and $script:writes -eq 0 -and $result.results[0].status -eq 'Skipped') 'unobserved condition never writes'
|
||||
$result=Invoke-WelaAuditProfilePlan $plan -ReadContext $contextReader -ReadPolicy $reader -WritePolicy $writer -ReadIpsec {$script:reads++;if($script:reads -eq 1){$positive}else{$none}} -Confirm:$false
|
||||
Assert (-not $result.success -and $script:writes -eq 0 -and $result.results[0].prerequisiteObservations.Count -eq 2) 'last-moment condition drift blocks direct executor'
|
||||
$plan.profile='microsoft-sct-server2025-2602'
|
||||
$result=Invoke-WelaAuditProfilePlan $plan -ReadContext $contextReader -ReadPolicy $reader -WritePolicy $writer -ReadIpsec {throw 'unrelated query'} -Confirm:$false
|
||||
Assert ($result.success -and $script:writes -eq 1) 'other profile intent is unaffected'
|
||||
$plan=Single-Plan;$plan|Add-Member NoteProperty CustomProfileSource ([pscustomobject]@{})
|
||||
Assert (-not (Test-WelaIpsecConditionalPolicy $plan $plan.policies[0])) 'custom profile intent is not reclassified by its id'
|
||||
|
||||
# Public configure adapter: real runner and durable journal, injected native boundaries.
|
||||
function Get-WelaRegistryState {param($Path,$Name) [pscustomobject]@{ValueExists=$true;Type='DWord';Value=1} }
|
||||
function Get-WelaAuditPrecedenceSource { $null }
|
||||
function Get-WelaNativeAuditPolicy {param($Guid) $script:state[$Guid] }
|
||||
function Invoke-WelaNative {param($FilePath,$Arguments)
|
||||
Assert (Test-Path -LiteralPath (Join-Path $script:backup 'before.jsonl')) 'journal precedes native write'
|
||||
$script:writes++;$script:state[$guid]=3
|
||||
}
|
||||
function Read-Host {param($Prompt) $script:evidence=$none; 'y' }
|
||||
$root=Join-Path ([IO.Path]::GetTempPath()) ('wela-ipsec-'+[guid]::NewGuid().ToString('N'))
|
||||
try {
|
||||
$script:evidence=$positive;$plan=Single-Plan;$script:state[$guid]=0;$script:writes=0
|
||||
$script:backup=Join-Path $root 'race';$ctx=New-WelaConfigurationContext -BackupPath $script:backup
|
||||
Set-WelaProfileAuditControls $ctx $plan -ReadIpsec {$script:evidence}
|
||||
$result=Complete-WelaConfiguration $ctx -Plan $plan
|
||||
$row=@($result.Results|Where-Object Id -eq 'AuditPolicy/IPsec Main Mode')[0]
|
||||
Assert ($row.Status -eq 'Failed' -and $script:writes -eq 0 -and $row.PrerequisiteObservations[-1].Status -eq 'NotObservedWithinScope') 'public runner rechecks after prompt/journal and retains negative evidence'
|
||||
$script:evidence=$positive;$script:backup=Join-Path $root 'positive';$ctx=New-WelaConfigurationContext -Auto -BackupPath $script:backup
|
||||
Set-WelaProfileAuditControls $ctx $plan -ReadIpsec {$script:evidence}
|
||||
$result=Complete-WelaConfiguration $ctx -Plan $plan
|
||||
$row=@($result.Results|Where-Object Id -eq 'AuditPolicy/IPsec Main Mode')[0]
|
||||
Assert ($row.Status -eq 'Applied' -and $script:writes -eq 1 -and $row.PrerequisiteObservations.Count -eq 5) 'public runner keeps plan/read/prewrite/readback/final native prerequisite observations'
|
||||
$script:evidence=$none;$script:backup=Join-Path $root 'negative';$ctx=New-WelaConfigurationContext -Auto -BackupPath $script:backup
|
||||
Set-WelaProfileAuditControls $ctx $plan -ReadIpsec {$script:evidence}
|
||||
$result=Complete-WelaConfiguration $ctx -Plan $plan
|
||||
Assert ($result.Skipped -eq 1 -and $script:writes -eq 1) 'negative public prerequisite is visible even when audit mask already matches'
|
||||
} finally {if(Test-Path $root){Remove-Item $root -Recurse -Force}}
|
||||
Write-Host "Passed $script:checks IPsec prerequisite assertions. No native mutations."
|
||||
@@ -0,0 +1,109 @@
|
||||
param([switch]$AllowDisposablePolicyWrite,[switch]$AllowDisposableIpsecRule)
|
||||
$ErrorActionPreference='Stop'
|
||||
if ($env:OS -ne 'Windows_NT') {throw 'Native Windows fixture required.'}
|
||||
if (-not $AllowDisposablePolicyWrite -or -not $AllowDisposableIpsecRule) {throw 'Disposable audit-policy and owned IPsec-rule opt-in are both required.'}
|
||||
$repo=Split-Path $PSScriptRoot -Parent;$script:ScriptRoot=$repo
|
||||
Import-Module (Join-Path $repo 'modules/AuditProfiles.psm1') -Force
|
||||
Import-Module NetSecurity -ErrorAction Stop
|
||||
. (Join-Path $repo 'scripts/Configuration.ps1')
|
||||
$script:checks=0
|
||||
function Assert($Condition,[string]$Message) {if(-not $Condition){throw "FAIL: $Message"};$script:checks++}
|
||||
$identity=[Security.Principal.WindowsIdentity]::GetCurrent()
|
||||
Assert ([Security.Principal.WindowsPrincipal]::new($identity).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) 'fixture is elevated'
|
||||
$root=Join-Path $env:RUNNER_TEMP ('wela-ipsec-'+[guid]::NewGuid().ToString('N'))
|
||||
$null=New-Item $root -ItemType Directory
|
||||
$name='wela-ipsec-'+[guid]::NewGuid().ToString('N')
|
||||
$guid='0CCE9218-69AE-11D9-BED3-505054503030'
|
||||
$before=Get-WelaEffectiveAuditPolicy
|
||||
$precedencePath='HKLM:\SYSTEM\CurrentControlSet\Control\Lsa'
|
||||
$precedence=Get-WelaRegistryState $precedencePath SCENoApplyLegacyAuditPolicy
|
||||
$beforeRules=@(Get-NetIPsecRule -PolicyStore ActiveStore -ErrorAction Stop|Select-Object Name,Enabled,InboundSecurity,OutboundSecurity,PrimaryStatus|Sort-Object Name|ConvertTo-Json -Depth 5 -Compress)
|
||||
$engine=(Get-Process -Id $PID).Path
|
||||
$created=$false;$cleanup=$false
|
||||
try {
|
||||
$baseline=Get-WelaIpsecPrerequisite
|
||||
$baseline|ConvertTo-Json -Depth 10|Set-Content (Join-Path $root 'baseline.json') -Encoding UTF8
|
||||
Assert ($baseline.Status -ne 'Unknown') "both native sources are readable: $($baseline.Diagnostic)"
|
||||
# Both endpoints are documentation-only addresses; no packets or negotiations are generated.
|
||||
$null=New-NetIPsecRule -Name $name -DisplayName $name -PolicyStore PersistentStore -Profile Any -Enabled False -LocalAddress 192.0.2.250 -RemoteAddress 192.0.2.251 -InboundSecurity Request -OutboundSecurity Request -ErrorAction Stop
|
||||
$created=$true
|
||||
$evidence=Get-WelaIpsecPrerequisite
|
||||
$evidence|ConvertTo-Json -Depth 10|Set-Content (Join-Path $root 'disabled.json') -Encoding UTF8
|
||||
Get-NetIPsecRule -Name $name -PolicyStore PersistentStore -ErrorAction Stop|Select-Object *|Export-Clixml (Join-Path $root 'disabled-native.xml')
|
||||
Get-NetIPsecRule -PolicyStore ActiveStore -ErrorAction Stop|Select-Object *|Export-Clixml (Join-Path $root 'disabled-active-native.xml')
|
||||
$owned=@($evidence.Rules|Where-Object Name -eq $name)
|
||||
Assert ((Get-NetIPsecRule -Name $name -PolicyStore PersistentStore -ErrorAction Stop).Enabled -eq 'False') 'owned persistent rule is actually disabled'
|
||||
Assert ($evidence.Status -ne 'Unknown' -and @($owned|Where-Object Qualifies).Count -eq 0) "disabled rule does not qualify (ActiveStore may omit it): $($evidence.Diagnostic)"
|
||||
Set-NetIPsecRule -Name $name -PolicyStore PersistentStore -Enabled True -InboundSecurity None -OutboundSecurity None -ErrorAction Stop
|
||||
$evidence=Get-WelaIpsecPrerequisite
|
||||
$owned=@($evidence.Rules|Where-Object Name -eq $name)
|
||||
$evidence|ConvertTo-Json -Depth 10|Set-Content (Join-Path $root 'exemption.json') -Encoding UTF8
|
||||
Get-NetIPsecRule -Name $name -PolicyStore PersistentStore -ErrorAction Stop|Select-Object *|Export-Clixml (Join-Path $root 'exemption-native.xml')
|
||||
Assert ($evidence.Status -ne 'Unknown' -and @($owned|Where-Object Qualifies).Count -eq 0) "real exemption-only rule does not qualify: $($evidence.Diagnostic)"
|
||||
# Converting to an exemption clears its authentication-set references. Recreate
|
||||
# only this owned fixture so New-NetIPsecRule supplies valid native defaults.
|
||||
Remove-NetIPsecRule -Name $name -PolicyStore PersistentStore -ErrorAction Stop
|
||||
$created=$false
|
||||
$null=New-NetIPsecRule -Name $name -DisplayName $name -PolicyStore PersistentStore -Profile Any -Enabled True -LocalAddress 192.0.2.250 -RemoteAddress 192.0.2.251 -InboundSecurity Request -OutboundSecurity Request -ErrorAction Stop
|
||||
$created=$true
|
||||
$evidence=Get-WelaIpsecPrerequisite
|
||||
$evidence|ConvertTo-Json -Depth 10|Set-Content (Join-Path $root 'positive.json') -Encoding UTF8
|
||||
Get-NetIPsecRule -Name $name -PolicyStore ActiveStore -ErrorAction Stop|Select-Object *|Export-Clixml (Join-Path $root 'positive-native.xml')
|
||||
$owned=@($evidence.Rules|Where-Object Name -eq $name)
|
||||
Assert ($evidence.Status -eq 'Applicable' -and $owned.Count -eq 1 -and $owned[0].Qualifies) "real enabled securing ActiveStore rule establishes scoped applicability: $($evidence.Diagnostic)"
|
||||
$planPath=Join-Path $root 'plan.json'
|
||||
& $engine -NoProfile -File (Join-Path $repo 'WELA.ps1') plan -Profile microsoft-stronger-reviewed-2026-09 -IncludeOptional -SaclMode Skip -PlanPath $planPath
|
||||
Assert ($LASTEXITCODE -eq 0) 'public live plan succeeds'
|
||||
$plan=Get-Content $planPath -Raw|ConvertFrom-Json
|
||||
$row=@($plan.policies|Where-Object id -eq 'IPsec Main Mode')[0]
|
||||
Assert ($row.conditionalPrerequisite.Status -eq 'Applicable' -and $row.targetMask -eq 3) 'public plan contains native evidence and selected SF mask'
|
||||
$dryPath=Join-Path $root 'dry.json'
|
||||
& $engine -NoProfile -File (Join-Path $repo 'WELA.ps1') configure -Profile microsoft-stronger-reviewed-2026-09 -IncludeOptional -SaclMode Skip -DryRun -Auto -ResultsPath $dryPath
|
||||
Assert ($LASTEXITCODE -eq 0) 'public configure dry-run succeeds'
|
||||
$current=Get-WelaEffectiveAuditPolicy
|
||||
Assert (@($before.Keys|Where-Object {$before[$_] -ne $current[$_]}).Count -eq 0) 'dry-run preserves all59 effective masks'
|
||||
$dry=Get-Content $dryPath -Raw|ConvertFrom-Json
|
||||
$row=@($dry.Results|Where-Object Id -eq 'AuditPolicy/IPsec Main Mode')[0]
|
||||
Assert ($row.PrerequisiteObservations.Count -ge 2 -and $row.Status -in @('Skipped','AlreadyCompliant')) 'public dry-run retains native prerequisite evidence'
|
||||
|
||||
# Actual public configure must produce a write for this control, then read it back.
|
||||
Set-WelaEffectiveAuditPolicy -Guid $guid -Mask 0 -Mode exact
|
||||
$resultPath=Join-Path $root 'configure.json'
|
||||
& $engine -NoProfile -File (Join-Path $repo 'WELA.ps1') configure -Profile microsoft-stronger-reviewed-2026-09 -IncludeOptional -SaclMode Skip -Auto -BackupPath (Join-Path $root 'backup') -ResultsPath $resultPath
|
||||
Assert ($LASTEXITCODE -eq 0) 'actual public configure succeeds'
|
||||
$result=Get-Content $resultPath -Raw|ConvertFrom-Json
|
||||
$row=@($result.Results|Where-Object Id -eq 'AuditPolicy/IPsec Main Mode')[0]
|
||||
Assert ($row.Status -eq 'Applied' -and $row.After -eq 3 -and $row.PrerequisiteObservations.Count -eq 5) 'actual gated policy write retains all five native observations'
|
||||
Assert (@($row.PrerequisiteObservations|Where-Object Status -ne Applicable).Count -eq 0) 'every configure boundary has positive native evidence'
|
||||
$journal=@(Get-Content (Join-Path $root 'backup/before.jsonl')|ConvertFrom-Json)
|
||||
Assert (@($journal|Where-Object {$_.Id -eq 'AuditPolicy/IPsec Main Mode' -and $_.Before -eq 0 -and $_.Desired.Mask -eq 3}).Count -eq 1) 'real public recovery journal retains exact policy transition'
|
||||
|
||||
# Native drift after prompt: exercise the real configuration callback and native reader.
|
||||
Set-WelaEffectiveAuditPolicy -Guid $guid -Mask 0 -Mode exact
|
||||
$plan.policies=@($plan.policies|Where-Object id -eq 'IPsec Main Mode')
|
||||
function Read-Host {param($Prompt) Remove-NetIPsecRule -Name $name -PolicyStore PersistentStore -ErrorAction Stop; $script:created=$false; 'y'}
|
||||
$ctx=New-WelaConfigurationContext -BackupPath (Join-Path $root 'drift-backup')
|
||||
Set-WelaProfileAuditControls $ctx $plan
|
||||
$drift=Complete-WelaConfiguration $ctx -Plan $plan -ResultsPath (Join-Path $root 'drift.json')
|
||||
$row=@($drift.Results|Where-Object Id -eq 'AuditPolicy/IPsec Main Mode')[0]
|
||||
if($baseline.Status -eq 'NotObservedWithinScope') {
|
||||
Assert ($row.Status -eq 'Failed' -and (Get-WelaEffectiveAuditPolicy)[$guid] -eq 0) 'real rule disappearance after prompt blocks auditpol write'
|
||||
} else {
|
||||
Assert ($row.Status -eq 'Applied') 'independent baseline prerequisite remains applicable after owned-rule removal'
|
||||
}
|
||||
} finally {
|
||||
if(@(Get-NetIPsecRule -Name $name -PolicyStore PersistentStore -ErrorAction SilentlyContinue).Count){Remove-NetIPsecRule -Name $name -PolicyStore PersistentStore -ErrorAction Stop}
|
||||
foreach($id in $before.Keys){Set-WelaEffectiveAuditPolicy -Guid $id -Mask $before[$id] -Mode exact}
|
||||
if($precedence.ValueExists){Set-ItemProperty -LiteralPath $precedencePath -Name SCENoApplyLegacyAuditPolicy -Type $precedence.Type -Value $precedence.Value -ErrorAction Stop}
|
||||
else {Remove-ItemProperty -LiteralPath $precedencePath -Name SCENoApplyLegacyAuditPolicy -ErrorAction SilentlyContinue}
|
||||
$after=Get-WelaEffectiveAuditPolicy
|
||||
Assert (@($before.Keys|Where-Object {$before[$_] -ne $after[$_]}).Count -eq 0) 'all59 original masks restored'
|
||||
$afterPrecedence=Get-WelaRegistryState $precedencePath SCENoApplyLegacyAuditPolicy
|
||||
Assert (($precedence|ConvertTo-Json -Compress) -ceq ($afterPrecedence|ConvertTo-Json -Compress)) 'typed precedence/absence restored'
|
||||
$afterRules=@(Get-NetIPsecRule -PolicyStore ActiveStore -ErrorAction Stop|Select-Object Name,Enabled,InboundSecurity,OutboundSecurity,PrimaryStatus|Sort-Object Name|ConvertTo-Json -Depth 5 -Compress)
|
||||
Assert (($beforeRules -join '') -ceq ($afterRules -join '')) 'native rule inventory restored exactly'
|
||||
Assert (@(Get-NetIPsecRule -Name $name -PolicyStore PersistentStore -ErrorAction SilentlyContinue).Count -eq 0) 'owned persistent rule removed'
|
||||
$cleanup=$true
|
||||
[pscustomobject]@{CleanupVerified=$cleanup;Checks=$script:checks;Engine=$PSVersionTable.PSVersion.ToString();Computer=$env:COMPUTERNAME;NoTrafficGenerated=$true}|ConvertTo-Json|Set-Content (Join-Path $root 'cleanup.json') -Encoding UTF8
|
||||
}
|
||||
Write-Host "Passed $script:checks native IPsec checks; artifacts: $root"
|
||||
Reference in new issue
Block a user