Src/Private/Get-AbrIntuneE8Summary.ps1
|
function Get-AbrIntuneE8Summary { <# .SYNOPSIS Renders a consolidated ACSC Essential Eight Maturity Level assessment chapter. .DESCRIPTION Presents all accumulated E8 checks organised by the 8 pillars, matching the structure used in design documents (User Application Hardening, Office Macros, Patch Applications, Patch OS, Restrict Admin Privileges, Application Control, Phishing-Resistant MFA, and a rollup summary). This function is called AFTER all other sections have run so that $script:E8AllChecks is fully populated. .NOTES Version: 0.1.0 Author: Pai Wei Sing #> [CmdletBinding()] param ( [Parameter(Position = 0, Mandatory)] [string]$TenantId ) begin { Write-PScriboMessage -Message "Rendering ACSC Essential Eight Summary for $TenantId." Show-AbrDebugExecutionTime -Start -TitleMessage 'E8 Summary' } process { if (-not $script:IncludeACSCe8) { return } if (-not $script:E8AllChecks -or $script:E8AllChecks.Count -eq 0) { Write-AbrDebugLog 'E8 Summary: no checks accumulated -- skipping chapter' 'WARN' 'E8SUMMARY' return } Section -Style Heading1 'ACSC Essential Eight Maturity Assessment' { Paragraph "This section provides a consolidated ACSC Essential Eight Maturity Level 1-3 assessment for tenant $TenantId, organised by the eight security control pillars. Controls are evaluated against the Intune configuration collected during this report run." BlankLine # ── Rollup summary table ─────────────────────────────────────────── $AllChecks = @($script:E8AllChecks) $TotalOK = @($AllChecks | Where-Object { $_.Status -eq '[OK]' }).Count $TotalWarn = @($AllChecks | Where-Object { $_.Status -eq '[WARN]' }).Count $TotalFail = @($AllChecks | Where-Object { $_.Status -eq '[FAIL]' }).Count $TotalInfo = @($AllChecks | Where-Object { $_.Status -eq '[INFO]' }).Count $TotalAll = $AllChecks.Count $SummObj = [System.Collections.ArrayList]::new() $SummObj.Add([pscustomobject]@{ Result = '[OK]'; Count = $TotalOK; Description = 'Controls meeting maturity requirements' }) | Out-Null $SummObj.Add([pscustomobject]@{ Result = '[WARN]'; Count = $TotalWarn; Description = 'Controls partially configured or recommended improvements' }) | Out-Null $SummObj.Add([pscustomobject]@{ Result = '[FAIL]'; Count = $TotalFail; Description = 'Controls not meeting maturity requirements' }) | Out-Null $SummObj.Add([pscustomobject]@{ Result = '[INFO]'; Count = $TotalInfo; Description = 'Informational checks (manual verification recommended)' }) | Out-Null $SummObj.Add([pscustomobject]@{ Result = 'Total'; Count = $TotalAll; Description = 'All controls evaluated' }) | Out-Null $null = (& { if ($HealthCheck.Intune.DeviceCompliance -or $HealthCheck.Intune.EndpointSecurity) { $null = ($SummObj | Where-Object { $_.Result -eq '[OK]' } | Set-Style -Style OK | Out-Null) $null = ($SummObj | Where-Object { $_.Result -eq '[WARN]' } | Set-Style -Style Warning | Out-Null) $null = ($SummObj | Where-Object { $_.Result -eq '[FAIL]' } | Set-Style -Style Critical | Out-Null) } }) $SummParams = @{ Name = "E8 Assessment Summary - $TenantId"; ColumnWidths = 12, 12, 76 } if ($Report.ShowTableCaptions) { $SummParams['Caption'] = "- $($SummParams.Name)" } $SummObj | Table @SummParams BlankLine # ── ML breakdown ─────────────────────────────────────────────────── foreach ($ML in @('ML1', 'ML2', 'ML3')) { $mlChecks = @($AllChecks | Where-Object { $_.ML -eq $ML }) if ($mlChecks.Count -eq 0) { continue } $mlOK = @($mlChecks | Where-Object { $_.Status -eq '[OK]' }).Count $mlFail = @($mlChecks | Where-Object { $_.Status -eq '[FAIL]' }).Count $mlWarn = @($mlChecks | Where-Object { $_.Status -eq '[WARN]' }).Count $mlPct = if ($mlChecks.Count -gt 0) { [int](($mlOK / $mlChecks.Count) * 100) } else { 0 } $mlLabel = switch ($ML) { 'ML1' { 'Maturity Level 1 — Partly Aligned' } 'ML2' { 'Maturity Level 2 — Mostly Aligned' } 'ML3' { 'Maturity Level 3 — Fully Aligned' } } BlankLine Paragraph "${mlLabel}: ${mlOK}/$($mlChecks.Count) controls passing (${mlPct}%) — ${mlFail} failing, ${mlWarn} warnings." BlankLine $null = (& { if ($HealthCheck.Intune.DeviceCompliance -or $HealthCheck.Intune.EndpointSecurity) { $null = ($mlChecks | Where-Object { $_.Status -eq '[FAIL]' } | Set-Style -Style Critical | Out-Null) $null = ($mlChecks | Where-Object { $_.Status -eq '[WARN]' } | Set-Style -Style Warning | Out-Null) $null = ($mlChecks | Where-Object { $_.Status -eq '[OK]' } | Set-Style -Style OK | Out-Null) } }) $MLParams = @{ Name = "E8 $ML Controls - $TenantId"; ColumnWidths = 8, 32, 9, 51 } if ($Report.ShowTableCaptions) { $MLParams['Caption'] = "- $($MLParams.Name)" } ($mlChecks | Select-Object ML, Control, Status, Detail) | Table @MLParams } BlankLine # ── Pillar breakdown ─────────────────────────────────────────────── # Map sections to ACSC E8 pillar names $PillarMap = [ordered]@{ 'User Application Hardening' = @('ConfigurationProfiles') 'Restrict Microsoft Office Macros' = @('AppManagement') 'Patch Applications' = @('DeviceCompliance', 'Devices') 'Patch Operating Systems' = @('DeviceCompliance', 'Devices') 'Restrict Administrative Privileges' = @('Scripts', 'EndpointSecurity') 'Application Control' = @('EndpointSecurity') 'Regular Backups' = @() 'Multi-factor Authentication' = @('EnrollmentRestrictions') } Paragraph "Assessment by Essential Eight Control Pillar:" BlankLine $PillarSummObj = [System.Collections.ArrayList]::new() foreach ($Pillar in $PillarMap.GetEnumerator()) { $pillarChecks = if ($Pillar.Value.Count -gt 0) { @($AllChecks | Where-Object { $Pillar.Value -contains $_.Section }) } else { @() } $pOK = @($pillarChecks | Where-Object { $_.Status -eq '[OK]' }).Count $pWarn = @($pillarChecks | Where-Object { $_.Status -eq '[WARN]' }).Count $pFail = @($pillarChecks | Where-Object { $_.Status -eq '[FAIL]' }).Count $pTotal = $pillarChecks.Count $pillarStatus = if ($pTotal -eq 0) { '[INFO]' } elseif ($pFail -gt 0) { '[FAIL]' } elseif ($pWarn -gt 0) { '[WARN]' } else { '[OK]' } $PillarSummObj.Add([pscustomobject]([ordered]@{ 'Pillar' = $Pillar.Key 'Status' = $pillarStatus 'OK' = $pOK 'Warn' = $pWarn 'Fail' = $pFail 'Total Checks' = $pTotal })) | Out-Null } $null = (& { if ($HealthCheck.Intune.DeviceCompliance -or $HealthCheck.Intune.EndpointSecurity) { $null = ($PillarSummObj | Where-Object { $_.Status -eq '[OK]' } | Set-Style -Style OK | Out-Null) $null = ($PillarSummObj | Where-Object { $_.Status -eq '[WARN]' } | Set-Style -Style Warning | Out-Null) $null = ($PillarSummObj | Where-Object { $_.Status -eq '[FAIL]' } | Set-Style -Style Critical | Out-Null) } }) $PillarParams = @{ Name = "E8 Pillar Summary - $TenantId"; ColumnWidths = 36, 10, 9, 9, 9, 27 } if ($Report.ShowTableCaptions) { $PillarParams['Caption'] = "- $($PillarParams.Name)" } $PillarSummObj | Table @PillarParams BlankLine # ── Controls requiring attention ─────────────────────────────────── $FailWarnChecks = @($AllChecks | Where-Object { $_.Status -in @('[FAIL]', '[WARN]') } | Sort-Object ML, Status) if ($FailWarnChecks.Count -gt 0) { BlankLine Paragraph "Controls Requiring Attention ($($FailWarnChecks.Count) item(s)):" BlankLine $null = (& { if ($HealthCheck.Intune.DeviceCompliance -or $HealthCheck.Intune.EndpointSecurity) { $null = ($FailWarnChecks | Where-Object { $_.Status -eq '[FAIL]' } | Set-Style -Style Critical | Out-Null) $null = ($FailWarnChecks | Where-Object { $_.Status -eq '[WARN]' } | Set-Style -Style Warning | Out-Null) } }) $AttnParams = @{ Name = "E8 Controls Requiring Attention - $TenantId"; ColumnWidths = 8, 32, 9, 51 } if ($Report.ShowTableCaptions) { $AttnParams['Caption'] = "- $($AttnParams.Name)" } ($FailWarnChecks | Select-Object ML, Control, Status, Detail) | Table @AttnParams } # ── Store in Excel ───────────────────────────────────────────────── if ((Get-IntuneExcelSheetEnabled -SheetKey 'ACSCe8Assessment') -and $AllChecks.Count -gt 0) { $script:ExcelSheets['ACSC E8 Assessment'] = $AllChecks } } } end { Show-AbrDebugExecutionTime -End -TitleMessage 'E8 Summary' } } |