I have written a script that will automatically rigger policy remediation, the script below does that.
$InitiativeAssignmentName = "xxxx"
# Loop through each policy and create individual remediation tasks
foreach ($policy in $RemediatablePolicies) {
$remediationName = "rem." + $policy.PolicyDefinitionReferenceId
write-output "Starting the remediation with label ==> $remediationName at $(Get-Date)"
if (!([string]::IsNullOrEmpty($policy.PolicyDefinitionReferenceId)))
{
Start-AzPolicyRemediation -Name $remediationName -PolicyAssignmentId $policy.PolicyAssignmentId -PolicyDefinitionReferenceId $policy.PolicyDefinitionReferenceId -ResourceDiscoveryMode ReEvaluateCompliance
}
}
However the issue is that when I look at the Azure portal, I can see descriptive policy definition such as the following.
Configure diagnostic settings for Storage Accounts to Log Analytics workspace
Deploy Diagnostic Settings for Key Vault to Log Analytics workspace
When I look at the script above, it runs based on a PolicyAssignmentName
which is essentially a GUID and difficult to read/make sense of, what I would like is to provide a list of descriptive policy definition rather than the PolicyAssignmentName
, I tried to retrieve the name as displayed on the portal without much luck using the code below.
Get-AzPolicyState | Where-Object { $_.PolicyAssignmentName -eq $InitiativeAssignmentName -and ($_.PolicyDefinitionAction -eq "deployIfNotExists" -or $_.PolicyDefinitionAction -eq "modify" -or $_.PolicyDefinitionAction -eq "append") } | Select-Object -ExpandProperty AdditionalProperties | select-object * | Format-Table
or even
Get-AzPolicyState | Where-Object { $_.PolicyAssignmentName -eq $InitiativeAssignmentName -and ($_.PolicyDefinitionAction -eq "deployIfNotExists" -or $_.PolicyDefinitionAction -eq "modify" -or $_.PolicyDefinitionAction -eq "append") } | select-object PolicyDefinitionReferenceId, PolicyAssignmentId,PolicyDefinitionName -Unique
what am I trying to achieve?
Provide a descriptive list of policy names and the code can loop through and create remediation tasks. Using PolicyAssignmentName
has a one to many relationship, and as such providing the value PolicyAssignmentName
can lead to the creation of a lot remediation tasks, rather than specific ones.
Here is the updated code to display the Policy Definition Name, Policy Definition Reference ID, Policy Assignment ID, and trigger the remediation using the names.
$policyassignmentNames = @("Storage enable Policy", "Network Security Group rule deny", "NSG_Rule_Deny", "JIT Port deny", "Azure Policy to modify Log analytics workspace destination of a data collection rule","JIM_Port_3389 and 22 Restricted")
$policyAssignments = Get-AzPolicyAssignment -BackwardCompatible | Where-Object { $policyassignmentNames -contains $_.DisplayName }
foreach ($policy in $policyAssignments) {
write-output "Starting the remediation with label ==> $($policy.DisplayName) at $(Get-Date)"
# Get the policy definition details for each assignment
$policyDefinitions = Get-AzPolicyDefinition -BackwardCompatible -Id $policy.PolicyDefinitionId -WarningAction silentlyContinue
$existingRemediations = Get-AzPolicyRemediation -WarningAction silentlyContinue | Where-Object { $_.PolicyAssignmentId -eq $policy.PolicyAssignmentId }
if ($existingRemediations) {
Write-Output "Remediation already in progress for $($policy.DisplayName). Skipping..."
continue
}
$remediationName = "rem." + $policyDefinitions.DisplayName
if (!([string]::IsNullOrEmpty($policyDefinitions.DisplayName))) {
try {
Start-AzPolicyRemediation -Name $remediationName -PolicyAssignmentId $policy.PolicyAssignmentId -PolicyDefinitionReferenceId $policyDefinitions.PolicyDefinitionId -ResourceDiscoveryMode ReEvaluateCompliance
} catch {
Write-Output "Failed to start remediation for $($policy.DisplayName): $_"
}
}
}
Output:
8