Microsoft Defender for Cloud - Create exemptions using REST API
- Intro
- Prepare variables
- Deterministic assignment name helper
- Create the exemption
- Create a time-bound exemption
Intro
This article is part of a series: Navigate to series page
In this post I show how to create a Defender for Cloud recommendation exemption (standard assignment with effect set to Exempt) by using REST API.
If you did not read part 1 yet, start there for authentication and for how to retrieve existing exemptions:
Microsoft Defender for Cloud - Get exemptions using REST API
Prepare variables
$displayName = "ckj-test-exemption-privileged-role-subscription-level"
$description = "Exemption of: Privileged roles should not have permanent access at the subscription and resource group level"
$identityObjectId = "12345678-1234-1234-ab12-12345678abcd" # Entra object ID for the user, group, or service principal you are exempting
$assessmentKey = "706b33f0-129e-4ed0-a179-f450b9ee4145" # Recommendation assessment key (maps to a specific Defender for Cloud recommendation)
If you do not have the Entra object ID, look it up for the target user, group, or service principal.
For assessmentKey, it is often easiest to inspect an existing exemption from part 1.
Deterministic assignment name helper
Using a deterministic GUID for standardAssignmentName is a good idea in automation.
It lets you recalculate the same assignment ID later for update/delete operations and helps avoid duplicate assignments caused by random GUID generation.
function New-DeterministicGuidFromText {
param([Parameter(Mandatory)][string]$InputText)
$bytes = [System.Text.Encoding]::UTF8.GetBytes($InputText)
$hash = [System.Security.Cryptography.SHA256]::Create().ComputeHash($bytes)
$hashHex = ($hash | ForEach-Object { $_.ToString("x2") }) -join ""
return "{0}-{1}-{2}-{3}-{4}" -f $hashHex.Substring(0, 8), $hashHex.Substring(8, 4), $hashHex.Substring(12, 4), $hashHex.Substring(16, 4), $hashHex.Substring(20, 12)
}
Create the exemption
# For endpoint details, see:
# https://learn.microsoft.com/en-us/rest/api/defenderforcloud/standard-assignments/create?view=rest-defenderforcloud-2024-08-01
$apiVersion = "2024-08-01"
# Deterministic assignment name (same input = same GUID)
# Useful when you want to recalculate the same ID later for update/delete automation
$assignmentSeed = "$subscriptionId|$identityObjectId|$assessmentKey|$displayName"
$standardAssignmentName = New-DeterministicGuidFromText -InputText $assignmentSeed
# Resource scope where the exemption is created
# Here we use CloudPosture/securityentitydata and target the Entra object ID
$resourceScope = "/subscriptions/$subscriptionId/providers/Microsoft.Security/pricings/CloudPosture/securityentitydata/$identityObjectId"
# Full ARM endpoint for creating the standard assignment (exemption)
$uri = "https://management.azure.com/$resourceScope/providers/Microsoft.Security/standardAssignments/$standardAssignmentName?api-version=$apiVersion"
$body = @{
properties = @{
description = $description
displayName = $displayName
effect = "Exempt" # Exemption mode
exemptionData = @{
exemptionCategory = "Waiver" # Common values: Waiver or Mitigated
assignedAssessment = @{
assessmentKey = $assessmentKey # Recommendation to exempt
}
}
}
}
$bodyJson = $body | ConvertTo-Json -Depth 10
Invoke-RestMethod -Uri $uri -Method Put -Headers $headers -Body $bodyJson
The output should look similar to this:

Create a time-bound exemption
In many cases, it is better to create exemptions with an expiry date, so they are reviewed automatically.
$displayName = "ckj-test-exemption-timebound"
$description = "Temporary exemption while remediation is in progress"
$identityObjectId = "12345678-1234-1234-ab12-12345678abcd"
$assessmentKey = "706b33f0-129e-4ed0-a179-f450b9ee4145"
$expiresOn = (Get-Date).ToUniversalTime().AddDays(30).ToString("o") # Expires in 30 days (UTC ISO 8601)
$apiVersion = "2024-08-01"
# Reuse deterministic naming so the assignment ID is reproducible
$assignmentSeed = "$subscriptionId|$identityObjectId|$assessmentKey|$displayName"
$standardAssignmentName = New-DeterministicGuidFromText -InputText $assignmentSeed
$resourceScope = "/subscriptions/$subscriptionId/providers/Microsoft.Security/pricings/CloudPosture/securityentitydata/$identityObjectId"
$uri = "https://management.azure.com/$resourceScope/providers/Microsoft.Security/standardAssignments/$standardAssignmentName?api-version=$apiVersion"
$body = @{
properties = @{
description = $description
displayName = $displayName
effect = "Exempt"
expiresOn = $expiresOn # Time-bound exemption
exemptionData = @{
exemptionCategory = "Waiver"
assignedAssessment = @{
assessmentKey = $assessmentKey
}
}
}
}
$bodyJson = $body | ConvertTo-Json -Depth 10
Invoke-RestMethod -Uri $uri -Method Put -Headers $headers -Body $bodyJson
You can adjust AddDays(30) to your preferred review cycle.
In the next post I show how to delete an existing exemption:
Microsoft Defender for Cloud - Delete exemptions using REST API
Have feedback on this post?
Send me a message and I'll get back to you.