Private/Audit/Compare-FortificationState.ps1
|
# PSGuerrilla - Jim Tyler, Microsoft MVP - CC BY 4.0 # https://github.com/jimrtyler/PSGuerrilla | https://creativecommons.org/licenses/by/4.0/ # AI/LLM use: see AI-USAGE.md for required attribution function Compare-FortificationState { [CmdletBinding()] param( [Parameter(Mandatory)] [PSCustomObject[]]$CurrentFindings, [Parameter(Mandatory)] [hashtable]$PreviousState ) $previousFindings = @($PreviousState.findings ?? @()) # Build lookup of previous findings by checkId + orgUnitPath $prevLookup = @{} foreach ($pf in $previousFindings) { $key = "$($pf.checkId)|$($pf.orgUnitPath ?? '/')" $prevLookup[$key] = $pf } $newFailures = [System.Collections.Generic.List[PSCustomObject]]::new() $resolved = [System.Collections.Generic.List[PSCustomObject]]::new() # Find new failures: current FAIL that was previously PASS or didn't exist foreach ($cf in $CurrentFindings) { if ($cf.Status -ne 'FAIL') { continue } $key = "$($cf.CheckId)|$($cf.OrgUnitPath ?? '/')" $prev = $prevLookup[$key] if (-not $prev -or $prev.status -ne 'FAIL') { $newFailures.Add([PSCustomObject]@{ CheckId = $cf.CheckId CheckName = $cf.CheckName Category = $cf.Category Severity = $cf.Severity CurrentValue = $cf.CurrentValue OrgUnitPath = $cf.OrgUnitPath PreviousStatus = if ($prev) { $prev.status } else { 'NEW' } }) } } # Find resolved: previously FAIL, now PASS $currentLookup = @{} foreach ($cf in $CurrentFindings) { $key = "$($cf.CheckId)|$($cf.OrgUnitPath ?? '/')" $currentLookup[$key] = $cf } foreach ($pf in $previousFindings) { if ($pf.status -ne 'FAIL') { continue } $key = "$($pf.checkId)|$($pf.orgUnitPath ?? '/')" $curr = $currentLookup[$key] if ($curr -and $curr.Status -eq 'PASS') { $resolved.Add([PSCustomObject]@{ CheckId = $pf.checkId CheckName = $curr.CheckName Category = $curr.Category Severity = $pf.severity PreviousValue = $pf.currentValue CurrentValue = $curr.CurrentValue OrgUnitPath = $pf.orgUnitPath ?? '/' }) } } # Score change $previousScore = $PreviousState.overallScore ?? 0 $currentScore = 0 if ($CurrentFindings.Count -gt 0) { $scoreResult = Get-AuditPostureScore -Findings $CurrentFindings $currentScore = $scoreResult.OverallScore } $scoreChange = $currentScore - $previousScore return @{ NewFailures = @($newFailures) Resolved = @($resolved) ScoreChange = $scoreChange PreviousScore = $previousScore CurrentScore = $currentScore PreviousScanId = $PreviousState.lastScanId ?? '' PreviousScanTimestamp = $PreviousState.lastScanTimestamp ?? '' } } |