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
You can filter by subscription ID
Get-AzPolicyState -from $90DaysBefore -to $toToday -SubscriptionId XXXX-XXXX-XXX
By Policy assignment name
Get-AzPolicyState -from $90DaysBefore -to $toToday -PolicyAssignmentName SecurityCenterBuiltIn
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
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'"
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'"
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"
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)"
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
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))"
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)