Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save celloza/a14cc5dfdd1e25f7e1318face67f1c34 to your computer and use it in GitHub Desktop.
Save celloza/a14cc5dfdd1e25f7e1318face67f1c34 to your computer and use it in GitHub Desktop.
This script iterates over results from the Azure Management API for Microsoft Defender for Cloud Security alerts, and takes the relevant action (usually to dismiss). It was created in order to dismiss thousands of Adaptive Application Control policy violations while the policy was being tuned to no longer show false positives.
<#
.Synopsis
Dismisses Microsoft Defender for Cloud Security Alerts in bulk.
.DESCRIPTION
This script iterates over results from the Azure Management API for Microsoft Defender for Cloud Security alerts, and takes the relevant action (usually to dismiss). It was
created in order to dismiss thousands of Adaptive Application Control policy violations while the policy was being tuned to no longer show false positives.
.INPUTS
Manually set in the script.
.OUTPUTS
Host output with the results of what has happened.
.NOTES
This process is not entirely automated. It requires you to get a token manually and inject it below, and also specify the subscription name on which you'd like to run this
process. Future development possibility is to create a service principal, assign it a token, and then reuse the token below rather than rely on getting it manually every x
couple of minutes.
#>
# Get a token by going to https://resources.azure.com/api/token?plaintext=true. This assumes you're logged in via Azure Portal
$token = '<insert token here>'
Connect-AzAccount
# Get all the subscriptions
$subs = Get-AzSubscription
# Get the subscription Id for the sub you want
$sub = $subs | Where-Object {$_.Name -eq '<insert sub name here>'}
$subId = $sub.Id
# Set the URL we're going iteratively call to go through all the alerts
$getAlertsUri = "https://management.azure.com/subscriptions/$subId/providers/Microsoft.Security/alerts?api-version=2021-01-01"
# Set the URL we're going to call to dismiss an alert
$dismissAlertUri = "https://management.azure.com/subscriptions/$subId/providers/Microsoft.Security/locations/{ascLocation}/alerts/{alertName}/dismiss?api-version=2021-01-01"
# Set the headers for this call
$Headers = @{"Authorization" = "Bearer $token"}
# The alertType we want to dismiss. This can be found by querying a sample set, and checking the alertType value
# Windows: VM_AdaptiveApplicationControlWindowsViolationAudited
# Linux: VM_AdaptiveApplicationControlLinuxViolationAudited
# For extra kudos, modify the script to accept n number of alertTypes, and dismiss them all
$alertTypeToDismiss = 'VM_AdaptiveApplicationControlLinuxViolationAudited'
$dismissedCount = 0
# Loop through pages
while ($null -ne $getAlertsUri) {
try {
# Get the first page of results
$result = Invoke-RestMethod -Uri $getAlertsUri -Method Get -Headers $Headers
$allAlerts = $result.value
# Set the next call's URI to the nextLink property from the results (if it exists)
$getAlertsUri = $result.nextLink
$totalAlerts = $allAlerts.Count
Write-Host "Query returned $totalAlerts rows." -ForegroundColor Blue
# Filter only those alerts we want to dismiss, i.e. Active alerts for the specified alertType
$alertsToDismiss = $result.value | Where-Object {$_.properties.alertType -eq $alertTypeToDismiss -and $_.properties.status -eq 'Active'}
$resultCount = $alertsToDismiss.Count
Write-Host "Dismissing $resultCount where the alertType is $alertTypeToDismiss..." -ForegroundColor Green
foreach($alertToDismiss in $alertsToDismiss)
{
$alertName = $alertToDismiss.name
Write-Host "Dismissing $alertName..."
# Find the location from the alertUri... dunno why it isn't a property
$location = $alertToDismiss.properties.alertUri.Split('/')[-1]
$dismissAlertUriForThisAlert = $dismissAlertUri.Replace("{alertName}", $alertToDismiss.Name).Replace("{ascLocation}", $location)
try {
# Dismiss the alert
Invoke-RestMethod -Uri $dismissAlertUriForThisAlert -Method Post -Headers $Headers
$dismissedCount++
}
catch {
Write-Host "Couldn't dismiss $alertName." -ForegroundColor Red
}
}
}
catch {
Write-Host "Error while processing: " $Error[0] -ForegroundColor Red
exit
}
}
$subName = $sub.Name
Write-Host "Dismissed $dismissedCount alerts of type $alertTypeToDismiss for subscription $subName." -ForegroundColor Green
@AiDevAz
Copy link

AiDevAz commented Mar 18, 2022

Awesome Stuff Thanks :)

@chaoscreater
Copy link

chaoscreater commented Jan 5, 2023

Does this still work? For me, $allAlerts returns a list of values and they don't contain any alert type:

image

And there isn't even a properties.status method. For example, this doesn't return anything:

$result.value | where {$_.properties.status -eq "*"}

Perhaps it's because I'm accessing the subs via Azure Lighthouse? Does the token need to use an account that has direct access to the Azure tenant?

UPDATE:

Oh NVM, it does work with Azure Lighthouse delegated subs.

$result.value | fl will show a list of properties

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment