public/Get-MsecPurviewAlertPolicy.ps1
|
function Get-MsecPurviewAlertPolicy { <# .SYNOPSIS Purview alert policies - the detection layer that decides what anyone ever hears about. .DESCRIPTION Every other Purview command here reports what is PREVENTED. This one reports what is NOTICED, and it is the part people forget to check: a disabled alert policy is silent in exactly the way a working one is, so the gap is invisible until an incident review asks why nobody was told. Measured on one tenant: 65 policies, 7 of them disabled, including "Shared files externally" and "User copies a file with sensitive data to a removable drive". IsEnabled IS THE INVERSE OF THE RAW PROPERTY. The service stores Disabled; reading it straight means every filter reads backwards, and `Where-Object Disabled` quietly returns the healthy ones. Both are on the row, with IsEnabled first, because a positive name is the one people filter on correctly. SYSTEM RULES ARE MOST OF THE LIST AND ARE NOT YOUR CONFIGURATION. Microsoft ships the majority of these; IsSystemRule separates them from the ones your organisation added, and -CustomOnly narrows to the latter. A count that mixes them tells you nothing about how much alerting anyone here actually set up. NotificationEnabled IS NOT WHETHER THE ALERT FIRES. It controls whether an email goes out. An enabled policy with notifications off still raises the alert in the portal and still tells nobody - worth checking separately from IsEnabled, and the reason both are columns. .PARAMETER Name Limit to policies whose name matches. Wildcards allowed. .PARAMETER Category Limit to one category, e.g. ThreatManagement or DataLossPrevention. .PARAMETER CustomOnly Only policies your organisation created, excluding Microsoft's built-ins. .EXAMPLE Connect-Msec -KeyVaultName kv-msec Get-MsecPurviewAlertPolicy | Group-Object Category | Sort-Object Count -Descending .EXAMPLE # Detection that has been switched off - silent in the same way a working policy is. Get-MsecPurviewAlertPolicy | Where-Object { -not $_.IsEnabled } | Format-Table Name, Category, Severity, IsSystemRule .EXAMPLE # Enabled, but nobody is told. Get-MsecPurviewAlertPolicy | Where-Object { $_.IsEnabled -and -not $_.NotificationEnabled -and -not $_.IsSystemRule } .OUTPUTS One PSCustomObject per alert policy, PSTypeName 'MsecPurviewAlertPolicy'. .NOTES Needs Connect-Msec; the compliance session opens on first use. Read-only. #> [CmdletBinding()] [OutputType([PSCustomObject])] param( [Parameter()] [string] $Name, [Parameter()] [string] $Category, [Parameter()] [switch] $CustomOnly ) Initialize-MsecExoSession -Endpoint Compliance Assert-MsecExoCmdlet -Name 'Get-ProtectionAlert' -Feature 'Purview alert policies' $alerts = @(Get-ProtectionAlert -ErrorAction Stop) if ($Name) { $alerts = @($alerts | Where-Object { $_.Name -like $Name }) } if ($Category) { $alerts = @($alerts | Where-Object { [string] $_.Category -eq $Category }) } if ($CustomOnly) { $alerts = @($alerts | Where-Object { -not $_.IsSystemRule }) } foreach ($alert in $alerts) { [PSCustomObject]@{ PSTypeName = 'MsecPurviewAlertPolicy' Name = [string] $alert.Name Category = [string] $alert.Category Severity = [string] $alert.Severity # Positive form first - see the help. Disabled is kept so nothing is hidden. IsEnabled = (-not [bool] $alert.Disabled) Disabled = [bool] $alert.Disabled # Microsoft's own, or something this organisation set up. IsSystemRule = [bool] $alert.IsSystemRule # Whether anyone is EMAILED. An enabled policy with this off still tells nobody. NotificationEnabled = [bool] $alert.NotificationEnabled NotifyUser = @($alert.NotifyUser | ForEach-Object { [string] $_ }) Mode = [string] $alert.Mode ThreatType = [string] $alert.ThreatType Operation = [string] $alert.Operation AggregationType = [string] $alert.AggregationType Threshold = $alert.Threshold Workload = [string] $alert.Workload CreatedBy = [string] $alert.CreatedBy WhenChangedUtc = $alert.WhenChangedUTC Comment = [string] $alert.Comment } } } |