From 276aa3bf28a59054ea92a5d1e6fb19989defc5f0 Mon Sep 17 00:00:00 2001 From: Joel Platek Date: Wed, 19 Aug 2026 14:27:48 +0800 Subject: [PATCH] Show canonical ACL overlap remediation as a green status line, not a yellow warning When OU disable-inheritance remediation re-sorts a DACL that contains an explicit Deny and Allow for the same principal (e.g. Exchange Trusted Subsystem), Repair-TierModelCanonicalAcl previously emitted a long yellow WARNING per overlapping pair per OU ? a wall of alarming text during an expected, successful operation. Replace that with a single green "REMEDIATED: Canonical ACL overlap on OU: " line per OU (deduplicated). The detailed per-principal entry (DN + principal) is still recorded in the result's Warnings array for logging and audit. Visual/UX change only ? no change to the sort or repair logic. Two overlap tests updated to assert on the result's Warnings array instead of the warning stream. Full suite 1627/0. --- .../public/Repair-TierModelCanonicalAcl.ps1 | 9 +++++++-- tests/Unit.CanonicalAclRepair.Tests.ps1 | 12 ++++++------ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/modules/TierModel/public/Repair-TierModelCanonicalAcl.ps1 b/modules/TierModel/public/Repair-TierModelCanonicalAcl.ps1 index a438f20..efedc91 100644 --- a/modules/TierModel/public/Repair-TierModelCanonicalAcl.ps1 +++ b/modules/TierModel/public/Repair-TierModelCanonicalAcl.ps1 @@ -186,6 +186,7 @@ function Repair-TierModelCanonicalAcl { $null -ne $q -and $q.AceQualifier -eq [System.Security.AccessControl.AceQualifier]::AccessAllowed -and -not ((([int]$_.Ace.AceFlags) -band ([int][System.Security.AccessControl.AceFlags]::Inherited)) -ne 0) } + $printedOverlapNotice = $false foreach ($dEntry in $explicitDenies) { $dq = $dEntry.Ace -as [System.Security.AccessControl.QualifiedAce] foreach ($aEntry in $explicitAllows) { @@ -193,8 +194,12 @@ function Repair-TierModelCanonicalAcl { if ($dq.SecurityIdentifier -eq $aq.SecurityIdentifier -and (([int]$dq.AccessMask) -band ([int]$aq.AccessMask)) -ne 0) { $sidName = try { $dq.SecurityIdentifier.Translate([System.Security.Principal.NTAccount]).Value } catch { $dq.SecurityIdentifier.Value } - $warnMsg = "Potential effective-access overlap detected on '$DistinguishedName' for principal '$sidName' — review DACL before applying sort" - Write-Warning $warnMsg + $warnMsg = "Deny/Allow overlap on '$DistinguishedName' for principal '$sidName' — canonical reorder applied (effective access may change)." + if (-not $printedOverlapNotice) { + $ouLeaf = if ([string]::IsNullOrEmpty($DistinguishedName)) { $DistinguishedName } else { (($DistinguishedName -split ',')[0] -replace '^\w+=','') } + Write-Host "REMEDIATED: Canonical ACL overlap on OU: $ouLeaf" -ForegroundColor Green + $printedOverlapNotice = $true + } $warnings.Add($warnMsg) } } diff --git a/tests/Unit.CanonicalAclRepair.Tests.ps1 b/tests/Unit.CanonicalAclRepair.Tests.ps1 index 2a12b22..ff123e0 100644 --- a/tests/Unit.CanonicalAclRepair.Tests.ps1 +++ b/tests/Unit.CanonicalAclRepair.Tests.ps1 @@ -319,15 +319,15 @@ Describe "Repair-TierModelCanonicalAcl — ByBytes path" -Tag 'Unit', 'Canonical # ------------------------------------------------------------------------- Context "Deny/Allow overlap warning" { - It "Emits a warning when same SID has both Deny and Allow on overlapping rights" { - $result = Repair-TierModelCanonicalAcl -SecurityDescriptorBytes $script:OverlapInputBytes -WarningVariable warnVar 3>$null - $warnVar | Should -Not -BeNullOrEmpty + It "Records an overlap entry in Warnings when same SID has both Deny and Allow on overlapping rights" { + $result = Repair-TierModelCanonicalAcl -SecurityDescriptorBytes $script:OverlapInputBytes + $result.Warnings | Should -Not -BeNullOrEmpty } - It "Warning message mentions the overlapping principal" { - $result = Repair-TierModelCanonicalAcl -SecurityDescriptorBytes $script:OverlapInputBytes -WarningVariable warnVar 3>$null + It "Warnings entry mentions the overlapping principal" { + $result = Repair-TierModelCanonicalAcl -SecurityDescriptorBytes $script:OverlapInputBytes # au = Authenticated Users (S-1-5-11) - ($warnVar -join ' ') | Should -Match 'overlap|S-1-5-11|Authenticated' + (($result.Warnings) -join ' ') | Should -Match 'overlap|S-1-5-11|Authenticated' } It "Still repairs (IsCanonical=true) despite the overlap warning" {