Posts Edit Azure Policy Assignments with custom PowerShell API
Post
Cancel

Edit Azure Policy Assignments with custom PowerShell API

Custom PowerShell API for Azure Governance - AzureIs.Fun

In my previous article I explained how to Create Your Own PowerShell APIs for Azure Governance with Azure Function App and how that can be useful for your daily Azure Administrator tasks.

Today I have another example of how to use that PowerShell API.

Azure Policies are a great way to prevent users from messing up your environment. But sometimes we need to make an exception to be able to deploy or edit something.

Here is a very simple PowerShell script that will allow you to add/remove exception Resource Group from your existing Azure Policy Assignment:

function Update-PolicyAssignmentExclusionList {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string]$PolicyAssignmentName,
[Parameter(Mandatory = $true)]
[string]$ResourceGroupName,
[Parameter(Mandatory = $true)]
[string]$Action
)
# Set the Azure context to the current subscription
Select-AzSubscription -SubscriptionId (Get-AzContext).Subscription.Id
# Get the policy assignment by name
$PolicyScope = "/subscriptions/$((Get-AzContext).Subscription.Id)"
$PolicyAssignment = Get-AzPolicyAssignment -Scope $PolicyScope | Where-Object { $_.Name -eq $PolicyAssignmentName }
if (!$PolicyAssignment) {
Write-Error "Policy assignment '$PolicyAssignmentName' does not exist."
} else {
# Get the resource group to modify
$ResourceGroup = Get-AzResourceGroup -Name $ResourceGroupName -ErrorAction SilentlyContinue
if (!$ResourceGroup) {
Write-Error "Resource group '$ResourceGroupName' does not exist."
} else {
# Get the existing exclusion list
$ExclusionList = $PolicyAssignment.Properties.NotScopes
# Add or remove the resource group from the exclusion list
if ($Action -eq "add") {
$ExclusionList += "/subscriptions/$((Get-AzContext).Subscription.Id)/resourceGroups/$ResourceGroupName"
} elseif ($Action -eq "remove") {
$ExclusionList = $ExclusionList | Where-Object { $_ -ne "/subscriptions/$((Get-AzContext).Subscription.Id)/resourceGroups/$ResourceGroupName" }
}
# Update the policy assignment with the new exclusion list
$PolicyAssignment.Properties.NotScopes = $ExclusionList
# NotScopes does not update if value is not provided. If the exclusion list is empty, set the NotScopes property to an empty array instead
if ($ExclusionList.Count -eq 0) {
$PolicyAssignment.Properties.NotScopes = @()
}
#Update the policy assignment
$PolicyAssignment | Set-AzPolicyAssignment
}
}
}

Please note that if you created Policy Assignments from Portal and not from Templates, Policy Assignment Name will not be the name you see in the portal, but something completely different. You can check names like this:

Get-AzPolicyAssignment | select Name

The script will check if the provided policy assignment name exists and if the resource group exists before editing the policy assignment. If either one does not exist, it will return an error message and exit without modifying the policy assignment.

Here is how you can call your function:

Update-PolicyAssignmentExclusionList -PolicyAssignmentName "MyPolicyAssignment" -ResourceGroupName "MyResourceGroup" -Action "add"

Parameter values:

  • <policy-assignment-name>: The name of the policy assignment to edit.
  • <resource-group-to-modify>: The name of the resource group to add or remove from the exclusion list.
  • <add-or-remove>: Either “add” or “remove” to indicate whether you want to add or remove the resource group from the exclusion list.

You can easily rewrite it to work inside Azure Functions. Additionally, you can customize the script further to suit your specific needs. For example, you can modify the script to add or remove multiple resource groups from the exclusion list at once, or to accept Subscriptions and Management Groups, or you can add error handling to provide more informative error messages.

Next time you receive a message that your deployment was denied due to Azure Policy, you will have a quick and easy way to crate temporary exception and proceed with your deployment.

And as a bonus, here is anoter quick script that you can use to quickly get the list of all Policy Assignments:

<#
This script will collect all policy assignments in available subscriptions and list them as a table.
#>
# Log in to your Azure account
#Connect-AzAccount
function Get-ScopeName($scopeId) {
if ($scopeId -match "/providers/Microsoft.Management/managementGroups/") {
$mgId = $scopeId -replace "/providers/Microsoft.Management/managementGroups/", ""
$mg = Get-AzManagementGroup -GroupName $mgId
return $mg.DisplayName
} elseif ($scopeId -match "/subscriptions/") {
$subId = $scopeId -replace "/subscriptions/", ""
$sub = Get-AzSubscription -SubscriptionId $subId
return $sub.Name
} elseif ($scopeId -match "/resourceGroups/") {
$subId = $scopeId -replace "/resourceGroups/.*", ""
$rgName = $scopeId -replace ".*/resourceGroups/", ""
$rg = Get-AzResourceGroup -Name $rgName -Scope "/subscriptions/$subId"
return $rg.ResourceGroupName
} else {
return "Unknown"
}
}
# Get all subscriptions
$subscriptions = Get-AzSubscription
# Initialize an empty array to store policy assignments and their scopes
$policyAssignmentsWithScopes = @()
# Loop through each subscription
foreach ($subscription in $subscriptions) {
# Select the current subscription
Set-AzContext -SubscriptionId $subscription.Id
# Get all policy assignments for the current subscription
$policyAssignments = Get-AzPolicyAssignment
# Loop through each policy assignment
foreach ($policyAssignment in $policyAssignments) {
# Get the scope name
$scopeName = Get-ScopeName -scopeId $policyAssignment.Properties.Scope
# Add policy assignment name and scope to the array
$policyAssignmentsWithScopes += [PSCustomObject]@{
PolicyAssignmentName = $policyAssignment.Name
ScopeName = $scopeName
PolicyName = $policyAssignment.Properties.DisplayName
PolicyDescription = $policyAssignment.Properties.Description
Enforced = $policyAssignment.Properties.EnforcementMode
}
}
}
# Display policy assignments and their scopes
$policyAssignmentsWithScopes | Format-Table -AutoSize

I hope this was useful. Keep clouding around.

Vukasin Terzic

Updated 2 years ago2023-03-16T02:47:43+01:00
This post is licensed under CC BY 4.0