DEV Community

Olivier Miossec
Olivier Miossec

Posted on

Get Azure Policy Compliance State with PowerShell

Working with Azure Policy means that you will have to deal with non-compliant resources. You can see them by going to an Azure Policy assignment and clicking on “View Compliance”, or simply by going to the “Compliance” page in Azure Policy. This is a manual process, what if we can automate it a little?
To deal with non-compliant resources we need to use the Get-azPolicyState. With no parameters, you will get all resources evaluated by any policy in the current subscription for the last day. You can get resources from up to the last 90 days by using -From and -To.

$toToday = Get-Date
$90DaysBefore = $toToday.AddDays(-90)
Get-AzPolicyState -from $90DaysBefore -to $toToday
Enter fullscreen mode Exit fullscreen mode

You can filter by subscription ID

Get-AzPolicyState -from $90DaysBefore -to $toToday -SubscriptionId XXXX-XXXX-XXX
Enter fullscreen mode Exit fullscreen mode

By Policy assignment name

Get-AzPolicyState -from $90DaysBefore -to $toToday -PolicyAssignmentName SecurityCenterBuiltIn
Enter fullscreen mode Exit fullscreen mode

But be careful, the -PolicyAssignmentName only works if the policy is assigned to a subscription, you will get no result if the assignment is at the management group level.
Or by a Management Group

Get-AzPolicyState -from $90DaysBefore -to $toToday -ManagementGroupName rootomiossec
Enter fullscreen mode Exit fullscreen mode

In this case, you will not be able to use the -PolicyAssignmentName parameter.
Now, imagine you need to get only non-compliant resources from a given type, ex you want to list only non-compliant storage accounts. That is where you will need to use the -filter parameter. This parameter uses OData notation to query the result from Get-AzPolicyState.

Get-AzPolicyState -Filter "ComplianceState eq 'NonCompliant' and ResourceType eq 'Microsoft.Storage/storageAccounts'"
Enter fullscreen mode Exit fullscreen mode

With the -filter parameter you can even query the policy state by assignment name even if the assignment is at the management group scope.

Get-AzPolicyState -Filter "ComplianceState eq 'NonCompliant' and ResourceType eq 'Microsoft.Storage/storageAccounts' and PolicyAssignmentName eq 'ca4ce57bdb00420b8a34b759'"
Enter fullscreen mode Exit fullscreen mode

You can restrict the output by using the -select parameter, it works like select-object cmdlet. The parameter accepts a list of fields you want to see in the result.

Get-AzPolicyState -Filter "ComplianceState eq 'NonCompliant' and ResourceType eq 'Microsoft.Storage/storageAccounts' and PolicyAssignmentName eq 'ca4ce57bdb00420b8a34b759'" -Select "ResourceId, ResourceLocation, ResourceGroup"
Enter fullscreen mode Exit fullscreen mode

You can also apply aggregation functions to the result you get.
For example, you can get the number of affected resources

Get-AzPolicyState -Filter "ComplianceState eq 'NonCompliant' and ResourceType eq 'Microsoft.Storage/storageAccounts' and PolicyAssignmentName eq 'ca4ce57bdb00420b8a34b759'" -Apply "aggregate(`$count as NumberOfResource)"
Enter fullscreen mode Exit fullscreen mode

You will have something like
AdditionalProperties : {[NumberOfResource, 16]}
You can directly have the value.

(Get-AzPolicyState -Filter "ComplianceState eq 'NonCompliant' and ResourceType eq 'Microsoft.Storage/storageAccounts' and PolicyAssignmentName eq 'ca4ce57bdb00420b8a34b759'" -Apply "aggregate(`$count as NumberOfRecords)").AdditionalProperties.NumberOfResource
Enter fullscreen mode Exit fullscreen mode

The -apply parameter uses the OData notation to form the query. You can group results to perform some more calculations.

Get-AzPolicyState -Filter "ResourceType eq 'Microsoft.Storage/storageAccounts' " -Apply "groupby((PolicyAssignmentName, ResourceId))/groupby((PolicyAssignmentName), aggregate(`$count as NumNonCompliantResources))"
Enter fullscreen mode Exit fullscreen mode

Here, the cmdlet groups Resource by PolicyAssignmentID and then counts each resource and puts the count result into the $count variable.

The Get-AzPolicyState, is less intuitive than other Azure cmdlets, you need to use OData to perform some calculations. Fortunately, you can still use where-object with -filterscript to obtain the same result if you are not familiar. Also, remember that you will get no result if you try to use the -assignmentName when the assignment is at the management group level.

Top comments (0)