Skip to content

Commit 28ba94b

Browse files
committed
Fixes ORCA242
1 parent 2851db0 commit 28ba94b

4 files changed

Lines changed: 104 additions & 13 deletions

File tree

Config/CIPPDBCacheTypes.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,11 @@
249249
"friendlyName": "Exchange Inbound Connectors",
250250
"description": "Exchange Online inbound connectors (includes enhanced filtering settings)"
251251
},
252+
{
253+
"type": "ExoProtectionAlert",
254+
"friendlyName": "Exchange Protection Alerts",
255+
"description": "Microsoft 365 protection alert policies (Security & Compliance endpoint)"
256+
},
252257
{
253258
"type": "Mailboxes",
254259
"friendlyName": "Mailboxes",

Modules/CIPPCore/Public/Invoke-CIPPDBCacheCollection.ps1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ function Invoke-CIPPDBCacheCollection {
8888
'ExoPresetSecurityPolicy'
8989
'ExoTenantAllowBlockList'
9090
'ExoInboundConnector'
91+
'ExoProtectionAlert'
9192
'OwaMailboxPolicy'
9293
'ReportSubmissionPolicy'
9394
'ExoTransportConfig'
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
function Set-CIPPDBCacheExoProtectionAlert {
2+
<#
3+
.SYNOPSIS
4+
Caches Exchange Online / Purview protection alert policies
5+
6+
.DESCRIPTION
7+
Calls Get-ProtectionAlert via the Security & Compliance PowerShell endpoint
8+
(requires the -Compliance switch on New-ExoRequest).
9+
10+
.PARAMETER TenantFilter
11+
The tenant to cache protection alert data for
12+
13+
.PARAMETER QueueId
14+
The queue ID to update with total tasks (optional)
15+
#>
16+
[CmdletBinding()]
17+
param(
18+
[Parameter(Mandatory = $true)]
19+
[string]$TenantFilter,
20+
[string]$QueueId
21+
)
22+
23+
try {
24+
Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message 'Caching Exchange protection alerts' -sev Debug
25+
26+
$ProtectionAlerts = New-ExoRequest -tenantid $TenantFilter -cmdlet 'Get-ProtectionAlert' -Compliance
27+
if ($ProtectionAlerts) {
28+
Add-CIPPDbItem -TenantFilter $TenantFilter -Type 'ExoProtectionAlert' -Data $ProtectionAlerts -AddCount
29+
Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message "Cached $($ProtectionAlerts.Count) protection alerts" -sev Debug
30+
}
31+
$ProtectionAlerts = $null
32+
33+
} catch {
34+
Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message "Failed to cache protection alert data: $($_.Exception.Message)" -sev Error
35+
}
36+
}

Modules/CIPPTests/Public/Tests/ORCA/Identity/Invoke-CippTestORCA242.ps1

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,68 @@ function Invoke-CippTestORCA242 {
66
param($Tenant)
77

88
try {
9-
# This test would check for alert policies related to ATP/Defender for Office 365
10-
# Since we don't have an alert policy cache, we'll provide informational guidance
11-
12-
$Status = 'Informational'
13-
$Result = [System.Text.StringBuilder]::new("Alert policies for protection features should be enabled and monitored.`n`n")
14-
$null = $Result.Append("**Recommended Alert Policies:**`n`n")
15-
$null = $Result.Append("- Messages reported by users as malware or phish`n")
16-
$null = $Result.Append("- Email sending limit exceeded`n")
17-
$null = $Result.Append("- Suspicious email forwarding activity`n")
18-
$null = $Result.Append("- Malware campaign detected`n")
19-
$null = $Result.Append("- Suspicious connector activity`n")
20-
$null = $Result.Append("- Unusual external user file activity`n")
21-
$null = $Result.Append("`n**Action Required:** Verify alert policies are configured in Microsoft 365 Security & Compliance Center")
9+
$Alerts = Get-CIPPTestData -TenantFilter $Tenant -Type 'ExoProtectionAlert'
10+
11+
if (-not $Alerts) {
12+
Add-CippTestResult -TenantFilter $Tenant -TestId 'ORCA242' -TestType 'Identity' -Status 'Skipped' -ResultMarkdown 'No protection alert data found. This may be due to missing required licenses or data collection not yet completed.' -Risk 'Medium' -Name 'Important protection alerts enabled' -UserImpact 'Low' -ImplementationEffort 'Medium' -Category 'Configuration'
13+
return
14+
}
15+
16+
# ORCA-242: alerts that drive Automated Incident Response (AIR).
17+
# Alerts not present in the tenant are skipped (Microsoft hasn't deployed them).
18+
$ImportantAlerts = @(
19+
'A potentially malicious URL click was detected'
20+
'Teams message reported by user as security risk'
21+
'Email messages containing phish URLs removed after delivery'
22+
'Suspicious Email Forwarding Activity'
23+
'Malware not zapped because ZAP is disabled'
24+
'Phish delivered due to an ETR override'
25+
'Email messages containing malicious file removed after delivery'
26+
'Email reported by user as malware or phish'
27+
'Email messages containing malicious URL removed after delivery'
28+
'Email messages containing malware removed after delivery'
29+
'A user clicked through to a potentially malicious URL'
30+
'Email messages from a campaign removed after delivery'
31+
'Email messages removed after delivery'
32+
'Suspicious email sending patterns detected'
33+
)
34+
35+
$FailedAlerts = [System.Collections.Generic.List[object]]::new()
36+
$PassedAlerts = [System.Collections.Generic.List[object]]::new()
37+
38+
foreach ($AlertName in $ImportantAlerts) {
39+
$Found = $Alerts | Where-Object { $_.Name -eq $AlertName } | Select-Object -First 1
40+
if ($null -eq $Found) { continue }
41+
42+
if ($Found.Disabled -eq $true) {
43+
$FailedAlerts.Add($Found) | Out-Null
44+
} else {
45+
$PassedAlerts.Add($Found) | Out-Null
46+
}
47+
}
48+
49+
if ($FailedAlerts.Count -eq 0 -and $PassedAlerts.Count -eq 0) {
50+
$Status = 'Skipped'
51+
$Result = [System.Text.StringBuilder]::new('None of the AIR-related protection alerts are deployed to this tenant. This may indicate missing Defender for Office 365 licensing.')
52+
} elseif ($FailedAlerts.Count -eq 0) {
53+
$Status = 'Passed'
54+
$Result = [System.Text.StringBuilder]::new("All AIR-related protection alerts deployed to this tenant are enabled.`n`n")
55+
$null = $Result.Append("**Enabled Alerts:** $($PassedAlerts.Count)`n`n")
56+
$null = $Result.Append("| Alert Name |`n|------------|`n")
57+
foreach ($Alert in $PassedAlerts) {
58+
$null = $Result.Append("| $($Alert.Name) |`n")
59+
}
60+
} else {
61+
$Status = 'Failed'
62+
$Result = [System.Text.StringBuilder]::new("$($FailedAlerts.Count) AIR-related protection alerts are disabled.`n`n")
63+
$null = $Result.Append("**Disabled:** $($FailedAlerts.Count) | **Enabled:** $($PassedAlerts.Count)`n`n")
64+
$null = $Result.Append("### Disabled Alerts`n`n")
65+
$null = $Result.Append("| Alert Name | Disabled |`n|------------|----------|`n")
66+
foreach ($Alert in $FailedAlerts) {
67+
$null = $Result.Append("| $($Alert.Name) | $($Alert.Disabled) |`n")
68+
}
69+
$null = $Result.Append("`n**Remediation:** Re-enable these alert policies. Automated Incident Response (AIR) triggers from them and cannot function correctly when they are disabled.")
70+
}
2271

2372
Add-CippTestResult -TenantFilter $Tenant -TestId 'ORCA242' -TestType 'Identity' -Status $Status -ResultMarkdown $Result -Risk 'Medium' -Name 'Important protection alerts enabled' -UserImpact 'Low' -ImplementationEffort 'Medium' -Category 'Configuration'
2473

0 commit comments

Comments
 (0)