Src/Private/Get-AbrExoAntiSpam.ps1
|
function Get-AbrExoAntiSpam { <# .SYNOPSIS Documents Exchange Online anti-spam policy configuration with ACSC E8 and CIS compliance assessments. .NOTES Version: 0.1.0 Author: Pai Wei Sing #> [CmdletBinding()] param ( [Parameter(Position = 0, Mandatory)] [string]$TenantId ) begin { Write-PScriboMessage -Message "Collecting Exchange Online Anti-Spam configuration for $TenantId." Show-AbrDebugExecutionTime -Start -TitleMessage 'AntiSpam' } process { Section -Style Heading2 'Anti-Spam Policies' { Paragraph "The following section documents the inbound and outbound anti-spam policies configured for tenant $TenantId." BlankLine #region Inbound Anti-Spam try { Write-Host " - Retrieving inbound anti-spam policies..." $InboundPolicies = Get-HostedContentFilterPolicy -ErrorAction Stop | Sort-Object IsDefault -Descending $InboundSpamPolicyCount = @($InboundPolicies).Count $DefaultInboundPolicy = $InboundPolicies | Where-Object { $_.IsDefault } | Select-Object -First 1 if (-not $DefaultInboundPolicy) { $DefaultInboundPolicy = $InboundPolicies | Select-Object -First 1 } $HighConfidenceSpamAction = $DefaultInboundPolicy.HighConfidenceSpamAction $HighConfidenceSpamActionOk = $HighConfidenceSpamAction -in @('Quarantine', 'Delete') $PhishSpamAction = $DefaultInboundPolicy.PhishSpamAction $PhishSpamActionOk = $PhishSpamAction -in @('Quarantine', 'MoveToJmf', 'Delete') $BulkThresholdRaw = $DefaultInboundPolicy.BulkThreshold $BulkThreshold = if ($null -ne $BulkThresholdRaw -and "$BulkThresholdRaw" -match '^\d+$') { [int]$BulkThresholdRaw } else { 7 } if ($InboundPolicies) { Section -Style Heading3 'Inbound Anti-Spam Policies' { Paragraph "The following $InboundSpamPolicyCount inbound anti-spam policy/policies are configured in tenant $TenantId." BlankLine $InboundObj = [System.Collections.ArrayList]::new() foreach ($Policy in $InboundPolicies) { $inboundInObj = [ordered] @{ 'Policy Name' = $Policy.Name 'Default Policy' = $Policy.IsDefault 'Spam Action' = $Policy.SpamAction 'HC Spam Action' = $Policy.HighConfidenceSpamAction 'Phish Action' = $Policy.PhishSpamAction 'HC Phish Action' = $Policy.HighConfidencePhishAction 'BCL Threshold' = if ($null -ne $Policy.BulkThreshold) { $Policy.BulkThreshold } else { '--' } 'Bulk Action' = $Policy.BulkSpamAction 'ZAP Spam' = $Policy.SpamZapEnabled 'ZAP Phish' = $Policy.PhishZapEnabled } $InboundObj.Add([pscustomobject](ConvertTo-HashToYN $inboundInObj)) | Out-Null } $null = (& { if ($HealthCheck.ExchangeOnline.AntiSpam) { $null = ($InboundObj | Where-Object { $_.'HC Spam Action' -notin @('Quarantine', 'Delete') } | Set-Style -Style Critical | Out-Null) $null = ($InboundObj | Where-Object { $_.'BCL Threshold' -ne '--' -and [int]$_.'BCL Threshold' -gt 6 } | Set-Style -Style Warning | Out-Null) } }) $InboundTableParams = @{ Name = "Inbound Anti-Spam Policies - $TenantId" List = $false ColumnWidths = 20, 8, 10, 12, 10, 12, 8, 10, 5, 5 } if ($Report.ShowTableCaptions) { $InboundTableParams['Caption'] = "- $($InboundTableParams.Name)" } $InboundObj | Table @InboundTableParams $script:ExcelSheets['Anti-Spam Inbound'] = $InboundObj } } # Retrieve filter rules (policy assignments) $FilterRules = Get-HostedContentFilterRule -ErrorAction SilentlyContinue | Sort-Object Priority if ($InfoLevel.AntiSpam -ge 2 -and $FilterRules) { Section -Style Heading3 'Anti-Spam Policy Assignments' { Paragraph "The following anti-spam policy assignments determine which users/groups receive each policy." BlankLine $RuleObj = [System.Collections.ArrayList]::new() foreach ($Rule in $FilterRules) { $ruleInObj = [ordered] @{ 'Rule Name' = $Rule.Name 'Priority' = $Rule.Priority 'State' = $Rule.State 'Policy' = $Rule.HostedContentFilterPolicy 'Applied To' = (@($Rule.SentTo) + @($Rule.SentToMemberOf) + @($Rule.RecipientDomainIs)) -join ', ' 'Except' = (@($Rule.ExceptIfSentTo) + @($Rule.ExceptIfSentToMemberOf)) -join ', ' } $RuleObj.Add([pscustomobject]$ruleInObj) | Out-Null } $null = (& { if ($HealthCheck.ExchangeOnline.AntiSpam) { $null = ($RuleObj | Where-Object { $_.State -eq 'Disabled' } | Set-Style -Style Warning | Out-Null) } }) $RuleTableParams = @{ Name = "Anti-Spam Policy Assignments - $TenantId"; List = $false; ColumnWidths = 20, 8, 8, 20, 24, 20 } if ($Report.ShowTableCaptions) { $RuleTableParams['Caption'] = "- $($RuleTableParams.Name)" } $RuleObj | Table @RuleTableParams } } } catch { Write-ExoError 'AntiSpam' "Unable to retrieve inbound anti-spam policies: $($_.Exception.Message)" Paragraph "Unable to retrieve inbound anti-spam policy data." } #endregion #region Outbound Anti-Spam try { Write-Host " - Retrieving outbound anti-spam policies..." $OutboundPolicies = Get-HostedOutboundSpamFilterPolicy -ErrorAction Stop $OutboundSpamPolicyCount = @($OutboundPolicies).Count if ($OutboundPolicies) { Section -Style Heading3 'Outbound Anti-Spam Policies' { Paragraph "The following $OutboundSpamPolicyCount outbound anti-spam policy/policies are configured for tenant $TenantId." BlankLine $OutboundObj = [System.Collections.ArrayList]::new() foreach ($Policy in $OutboundPolicies) { $outInObj = [ordered] @{ 'Policy Name' = $Policy.Name 'Default Policy' = $Policy.IsDefault 'Action on Limit Exceeded' = $Policy.ActionWhenThresholdReached 'Recipient Limit (external/hr)' = $Policy.RecipientLimitExternalPerHour 'Recipient Limit (internal/hr)' = $Policy.RecipientLimitInternalPerHour 'Recipient Limit (all/day)' = $Policy.RecipientLimitPerDay 'Auto-Forward Mode' = $Policy.AutoForwardingMode 'Notify Sender on Limit' = $Policy.NotifyOutboundSpam 'BCC Notification Address' = if ($Policy.BccSuspiciousOutboundMail) { $Policy.BccSuspiciousOutboundAdditionalRecipients -join ', ' } else { 'None' } } $OutboundObj.Add([pscustomobject](ConvertTo-HashToYN $outInObj)) | Out-Null } $null = (& { if ($HealthCheck.ExchangeOnline.AntiSpam) { # Auto-forwarding should be Off or Automatic (not On) $null = ($OutboundObj | Where-Object { $_.'Auto-Forward Mode' -eq 'On' } | Set-Style -Style Critical | Out-Null) $null = ($OutboundObj | Where-Object { $_.'Auto-Forward Mode' -eq 'Automatic' } | Set-Style -Style Warning | Out-Null) } }) $OutboundTableParams = @{ Name = "Outbound Anti-Spam Policies - $TenantId"; List = $false; ColumnWidths = 14, 7, 13, 12, 12, 12, 12, 10, 8 } if ($Report.ShowTableCaptions) { $OutboundTableParams['Caption'] = "- $($OutboundTableParams.Name)" } $OutboundObj | Table @OutboundTableParams $script:ExcelSheets['Anti-Spam Outbound'] = $OutboundObj } } } catch { Write-ExoError 'AntiSpam' "Unable to retrieve outbound anti-spam policies: $($_.Exception.Message)" } #endregion BlankLine Paragraph "ACSC Essential Eight Assessment" BlankLine $e8Vars = @{ InboundSpamPolicyCount = $InboundSpamPolicyCount HighConfidenceSpamAction = $HighConfidenceSpamAction HighConfidenceSpamActionOk = $HighConfidenceSpamActionOk PhishSpamAction = $PhishSpamAction PhishSpamActionOk = $PhishSpamActionOk BulkThreshold = $BulkThreshold OutboundSpamPolicyCount = $OutboundSpamPolicyCount } $e8Checks = Build-AbrExoComplianceChecks -Definitions (Get-AbrExoE8Checks 'AntiSpam') -Framework 'E8' -CallerVariables $e8Vars New-AbrExoE8AssessmentTable -Checks $e8Checks -Name 'Anti-Spam' -TenantId $TenantId if ($e8Checks) { foreach ($row in $e8Checks) { $null = $script:E8AllChecks.Add([pscustomobject]@{ Section = 'Anti-Spam' ML = $row.ML Control = $row.Control Status = $row.Status Detail = $row.Detail }) } } BlankLine Paragraph "CIS Microsoft 365 Foundations Benchmark Assessment" BlankLine $cisVars = @{ InboundSpamPolicyCount = $InboundSpamPolicyCount BulkThreshold = $BulkThreshold HighConfidenceSpamAction = $HighConfidenceSpamAction HighConfidenceSpamActionOk = $HighConfidenceSpamActionOk } $cisChecks = Build-AbrExoComplianceChecks -Definitions (Get-AbrExoCISChecks 'AntiSpam') -Framework 'CIS' -CallerVariables $cisVars New-AbrExoCISAssessmentTable -Checks $cisChecks -Name 'Anti-Spam' -TenantId $TenantId if ($cisChecks) { foreach ($row in $cisChecks) { $null = $script:CISAllChecks.Add([pscustomobject]@{ Section = 'Anti-Spam' CISControl = $row.CISControl Level = $row.Level Status = $row.Status Detail = $row.Detail }) } } } } end { Show-AbrDebugExecutionTime -End -TitleMessage 'AntiSpam' } } |