Defender for Cloud - Managing Recommendation Owners at Scale
Governance rules in Defender for Cloud are a great way to drive remediation accountability - but when owners go stale (people leave, addresses change), cleaning them up through the portal quickly becomes a manual chore. Here’s how to handle it at scale using Azure Resource Graph and a couple of PowerShell functions.
What Are Governance Rules?
Governance rules are a feature in Microsoft Defender for Cloud designed to push remediation responsibility down to the right teams. Instead of a central security team owning every open recommendation, you define rules that automatically assign owners to specific recommendations based on criteria like subscription, resource type, or severity.
Each assignment attaches an owner (an email address) to a recommendation with an optional due date and grace period. The idea is simple: security findings should belong to the person or team responsible for the affected resource, not to whoever happens to be looking at the Defender dashboard.
More details on how governance rules work: https://learn.microsoft.com/en-us/azure/defender-for-cloud/governance-rules
The Problem: Orphaned Owners at Scale
The concept is solid, but over time governance assignments accumulate stale owners - people who have left the organisation, distribution lists that no longer exist, or addresses that were set during a pilot and never revisited. At that point, the assignments are noise: they show up as assigned but nobody is actually acting on them. This is as even when owners on resources change, the old assignments don’t automatically update or remove themselves. They just linger until someone manually cleans them up.
The natural instinct is to fix this through the portal. As far as I can tell, there’s no bulk management view that lets you select and remove owners across hundreds of assignments in one go. Thus the API is the way to go.
⚠️ The approach below uses
DELETEto remove the governance assignment entirely. If you want to reassign to a new owner instead of removing, swap the method toPATCHand include the updated owner in the request body. Same approach, different HTTP verb.
The Fix: Resource Graph + Invoke-AzRest
Governance assignments are surfaced in Azure Resource Graph under the securityresources table as type microsoft.security/assessments/governanceassignments. That means you can enumerate every assignment across your entire tenant with a single ARG query - then loop over the results and hit the REST API to delete each one.
Two functions do the job. The first is a general-purpose paged ARG query helper (ARG caps results at 1000 rows per call, so pagination matters at scale). The second does the actual work to delete the assignments.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
function Invoke-AzResourceGraphQuery {
param(
[Parameter(Mandatory = $true)]
[string]$query
)
$assignments = @()
$skipToken = $null
do {
$argParams = @{ Query = $query; First = 1000 }
if ($skipToken) { $argParams["SkipToken"] = $skipToken }
$page = Search-AzGraph @argParams
$assignments += $page.Data ?? $page
$skipToken = $page.SkipToken
} while ($skipToken)
return $page
}
function Remove-DefenderCloudRecommendationOwnersAtScale {
param(
[string]$Method = "DELETE",
[string]$apiVersion = "2025-05-04"
)
$query = 'securityresources | where type == "microsoft.security/assessments/governanceassignments" | project id'
$assignments = Invoke-AzResourceGraphQuery -query $query
$assignments | ForEach-Object {
try {
$response = Invoke-AzRest -Method $Method -Path $($_.ResourceId + "?api-version=" + $apiVersion)
Write-Host $($response.RequestUri) -ForegroundColor Green
}
catch {
Write-Error $_.Exception.Message
}
}
}
You’ll need the
Az.ResourceGraphmodule forSearch-AzGraphand theAzmodule forInvoke-AzRest. Make sure you’re connected withConnect-AzAccountand have sufficient permissions on the subscriptions you’re targeting.
Once connected, running Remove-DefenderCloudRecommendationOwnersAtScale will enumerate all governance assignments in scope and delete them one by one, printing each request URI to the console as it goes.
Conclusion
Governance rules are worth using - automatic owner assignment at scale is genuinely useful when your Defender estate spans many subscriptions. The weak point is lifecycle management: the portal doesn’t give you a clean way to bulk-remove or reassign stale owners, so a small scripted wrapper around the REST API fills that gap nicely.
The same pattern extends beyond just deleting owners. Swap DELETE for PATCH with an updated owner payload and you have a bulk reassignment tool. The securityresources table in ARG is the common thread - it’s a reliable source of truth for everything governance-related across your tenant.