Src/Private/Get-AbrPurviewAuditPolicy.ps1
|
function Get-AbrPurviewAuditPolicy { <# .SYNOPSIS Used by As Built Report to retrieve Microsoft Purview Audit configuration information. .DESCRIPTION Collects and reports on the Unified Audit Log configuration, audit-related protection alerts, and custom Audit Log Retention Policies configured in Microsoft Purview. .NOTES Version: 0.1.0 Author: Pai Wei Sing .EXAMPLE Get-AbrPurviewAuditPolicy -TenantId 'contoso.onmicrosoft.com' #> [CmdletBinding()] param ( [Parameter(Position = 0, Mandatory)] [string]$TenantId ) begin { Write-PScriboMessage -Message "Collecting Microsoft Purview Audit Policy information for tenant $TenantId." | Out-Null Show-AbrDebugExecutionTime -Start -TitleMessage 'Audit Policies' } process { #region Audit Log Configuration (InfoLevel 1+) try { $AuditConfig = Get-AdminAuditLogConfig -ErrorAction Stop $OrgConfig = Get-OrganizationConfig -ErrorAction SilentlyContinue if ($AuditConfig) { Section -Style Heading2 'Audit Log Configuration' { $OutObj = [System.Collections.ArrayList]::new() try { $mailboxAuditVal = if ($OrgConfig) { if ($OrgConfig.AuditDisabled -eq $false) { 'Yes' } else { 'No' } } else { 'Unknown' } $_pre_UnifiedAuditLogEnabl_37 = if ($AuditConfig.UnifiedAuditLogIngestionEnabled) { 'Yes' } else { 'No' } $_pre_AdminAuditLogEnabled_39 = if ($AuditConfig.AdminAuditLogEnabled) { 'Yes' } else { 'No' } $_pre_LogCmdlets_41 = if ($AuditConfig.AdminAuditLogCmdlets) { ($AuditConfig.AdminAuditLogCmdlets -join ', ') } else { 'All' } $_pre_LogParameters_42 = if ($AuditConfig.AdminAuditLogParameters) { ($AuditConfig.AdminAuditLogParameters -join ', ') } else { 'All' } $inObj = [ordered] @{ 'Unified Audit Log Enabled' = $_pre_UnifiedAuditLogEnabl_37 'Audit Log Age Limit' = $AuditConfig.AuditLogAgeLimit 'Admin Audit Log Enabled' = $_pre_AdminAuditLogEnabled_39 'Mailbox Auditing Enabled by Default' = $mailboxAuditVal 'Log Cmdlets' = $_pre_LogCmdlets_41 'Log Parameters' = $_pre_LogParameters_42 } $OutObj.Add([pscustomobject]$inObj) | Out-Null } catch { Write-PScriboMessage -IsWarning -Message "Audit Log Config: $($_.Exception.Message)" | Out-Null } if ($Healthcheck -and $script:HealthCheck.Purview.Audit) { $OutObj | Where-Object { $_.'Unified Audit Log Enabled' -eq 'No' } | Set-Style -Style Critical | Out-Null $OutObj | Where-Object { $_.'Admin Audit Log Enabled' -eq 'No' } | Set-Style -Style Critical | Out-Null $OutObj | Where-Object { $_.'Mailbox Auditing Enabled by Default' -eq 'No' } | Set-Style -Style Warning | Out-Null } $TableParams = @{ Name = "Audit Log Configuration - $TenantId"; List = $true; ColumnWidths = 45, 55 } if ($script:Report.ShowTableCaptions) { $TableParams['Caption'] = "- $($TableParams.Name)" } $OutObj | Table @TableParams #region ACSC Inline Check — Audit Log Configuration if ($script:InfoLevel.Audit -ge 3) { $AuditEnabled = [bool]($AuditConfig.UnifiedAuditLogIngestionEnabled) $MailboxAuditDefault = ($OrgConfig -and $OrgConfig.AuditDisabled -eq $false) # Determine max retention days from any custom audit retention policy $MaxRetDays = 90 $RetPolicies = @(try { Get-UnifiedAuditLogRetentionPolicy -ErrorAction SilentlyContinue } catch { @() }) foreach ($rp in $RetPolicies) { $d = switch ($rp.RetentionDuration) { 'ThreeMonths' { 90 }; 'SixMonths' { 180 }; 'NineMonths' { 270 } 'TwelveMonths' { 365 }; 'TwoYears' { 730 }; 'FiveYears' { 1825 } 'SevenYears' { 2555 }; 'TenYears' { 3650 }; default { 0 } } if ($d -gt $MaxRetDays) { $MaxRetDays = $d } } Write-AbrPurviewACSCCheck -TenantId $TenantId -SectionName 'Audit Log Configuration' -Checks @( [pscustomobject]@{ ControlId = 'ISM-0580' E8 = 'N/A' Description = 'Event logging policy implemented and active' Check = 'Unified Audit Log ingestion enabled' Status = if ($AuditEnabled) { 'Pass' } else { 'Fail' } } [pscustomobject]@{ ControlId = 'ISM-0585' E8 = 'N/A' Description = 'Sufficient detail recorded in event logs' Check = 'Mailbox auditing enabled by default for all users' Status = if ($MailboxAuditDefault) { 'Pass' } else { 'Fail' } } [pscustomobject]@{ ControlId = 'ISM-1998' E8 = 'N/A' Description = 'Event logs retained for at least 12 months' Check = "Audit retention policy >= 365 days (current max: $MaxRetDays days)" Status = if ($MaxRetDays -ge 365) { 'Pass' } else { 'Fail' } } [pscustomobject]@{ ControlId = 'ISM-1989' E8 = 'N/A' Description = 'Event logs retained for at least 7 years (records systems)' Check = "Audit retention policy >= 2555 days / 7 years (current max: $MaxRetDays days)" Status = if ($MaxRetDays -ge 2555) { 'Pass' } else { 'Fail' } } ) } #endregion } } else { Write-PScriboMessage -Message "No Audit Log Configuration found for $TenantId. Disabling section." | Out-Null } } catch { Write-PScriboMessage -IsWarning -Message "Audit Log Configuration Section: $($_.Exception.Message)" | Out-Null } #endregion #region Audit-Related Protection Alerts (InfoLevel 1+) try { $AuditAlerts = Get-ProtectionAlert -ErrorAction SilentlyContinue | Where-Object { $_.Name -match 'audit' -or $_.Category -match 'audit' } if ($AuditAlerts) { Section -Style Heading2 'Audit-Related Protection Alerts' { $OutObj = [System.Collections.ArrayList]::new() foreach ($Alert in $AuditAlerts) { try { $_pre_Enabled_134 = if ($Alert.Disabled -eq $false) { 'Yes' } else { 'No' } $_pre_Notify_135 = if ($Alert.NotifyUser) { ($Alert.NotifyUser -join ', ') } else { '--' } $inObj = [ordered] @{ 'Alert Name' = $Alert.Name 'Severity' = $script:TextInfo.ToTitleCase($Alert.Severity) 'Category' = $script:TextInfo.ToTitleCase($Alert.Category) 'Enabled' = $_pre_Enabled_134 'Notify' = $_pre_Notify_135 } $OutObj.Add([pscustomobject]$inObj) | Out-Null } catch { Write-PScriboMessage -IsWarning -Message "Audit Alert '$($Alert.Name)': $($_.Exception.Message)" | Out-Null } } if ($Healthcheck -and $script:HealthCheck.Purview.Audit) { $OutObj | Where-Object { $_.'Enabled' -eq 'No' } | Set-Style -Style Warning | Out-Null } $TableParams = @{ Name = "Audit Protection Alerts - $TenantId"; List = $false; ColumnWidths = 35, 15, 15, 12, 23 } if ($script:Report.ShowTableCaptions) { $TableParams['Caption'] = "- $($TableParams.Name)" } $OutObj | Sort-Object -Property 'Alert Name' | Table @TableParams #region ACSC Inline Check — Audit Alerts if ($script:InfoLevel.Audit -ge 3) { $ActiveAlerts = $AuditAlerts | Where-Object { $_.Disabled -eq $false } Write-AbrPurviewACSCCheck -TenantId $TenantId -SectionName 'Audit Protection Alerts' -Checks @( [pscustomobject]@{ ControlId = 'ISM-0109' E8 = 'E8 ML2, ML3' Description = 'Event logs analysed in timely manner to detect cyber security events' Check = 'Active protection alerts configured for audit/eDiscovery/privilege activities' Status = if ($ActiveAlerts) { 'Pass' } elseif ($AuditAlerts) { 'Partial' } else { 'Fail' } } ) } #endregion } } else { Write-PScriboMessage -Message "No audit-related protection alerts found for $TenantId." | Out-Null } } catch { Write-PScriboMessage -IsWarning -Message "Audit Protection Alerts Section: $($_.Exception.Message)" | Out-Null } #endregion #region Audit Retention Policies (InfoLevel 2+) if ($script:InfoLevel.Audit -ge 2) { try { $AuditRetentionPolicies = Get-UnifiedAuditLogRetentionPolicy -ErrorAction Stop if ($AuditRetentionPolicies) { Section -Style Heading2 'Audit Retention Policies' { $OutObj = [System.Collections.ArrayList]::new() foreach ($Policy in $AuditRetentionPolicies) { try { $_pre_Description_189 = if ($Policy.Description) { $Policy.Description } else { '--' } $_pre_RecordTypes_191 = if ($Policy.RecordTypes) { ($Policy.RecordTypes -join ', ') } else { 'All' } $_pre_Operations_192 = if ($Policy.Operations) { ($Policy.Operations -join ', ') } else { 'All' } $_pre_Users_194 = if ($Policy.UserIds) { ($Policy.UserIds -join ', ') } else { 'All' } $inObj = [ordered] @{ 'Policy Name' = $Policy.Name 'Description' = $_pre_Description_189 'Retention Duration' = $script:TextInfo.ToTitleCase($Policy.RetentionDuration) 'Record Types' = $_pre_RecordTypes_191 'Operations' = $_pre_Operations_192 'Priority' = $Policy.Priority 'Users' = $_pre_Users_194 } $OutObj.Add([pscustomobject]$inObj) | Out-Null } catch { Write-PScriboMessage -IsWarning -Message "Audit Retention Policy '$($Policy.Name)': $($_.Exception.Message)" | Out-Null } } $TableParams = @{ Name = "Audit Retention Policies - $TenantId"; List = $false; ColumnWidths = 18, 16, 14, 16, 14, 10, 12 } if ($script:Report.ShowTableCaptions) { $TableParams['Caption'] = "- $($TableParams.Name)" } $OutObj | Sort-Object -Property 'Priority' | Table @TableParams } } else { Write-PScriboMessage -Message "No Audit Retention Policy information found for $TenantId. Disabling section." | Out-Null } } catch { Write-PScriboMessage -IsWarning -Message "Audit Retention Policy Section: $($_.Exception.Message)" | Out-Null } } #endregion } end { Show-AbrDebugExecutionTime -End -TitleMessage 'Audit Policies' } } |