Azure governance

How to find non-compliant resources in Azure Policy

List resources that Azure Policy marks non-compliant with Azure PowerShell, filter the Compliance page in the Azure portal, or run Altivane's Azure Policy Non-Compliance report.

By the Published

To find non-compliant resources in Azure Policy, read each subscription's latest policy states with Get-AzPolicyState, filtered to ComplianceState eq 'NonCompliant'. A resource created or changed through Azure Resource Manager shows its new state about 15 minutes later; other changes wait for the evaluation Azure runs once every 24 hours.

Choose the method that fits the job
MethodBest fit
PowerShellA CSV of every policy each resource breaks, across your enabled subscriptions.
Admin centreA look at 1 assignment's non-compliant resources, with the activity log a click away.
AltivaneRecommended for regular governance reviews, with each policy by its display name and a count for each.

Before you start

Use an account with the Reader role on the subscriptions you want to check: Reader, like Contributor, has every read operation of Azure Policy. Microsoft lists no separate licence for reading compliance. If the portal shows a state of Not registered, the Microsoft.PolicyInsights resource provider isn't registered on the subscription, or the account can't read compliance data.

Know what the states cover. Get-AzPolicyState returns the latest state of each resource from the last day by default. Azure Policy doesn't evaluate resources of the Microsoft.Resources provider, apart from subscriptions and resource groups. A non-compliant state only says what a policy found: what happens next depends on the policy's effect, such as audit or deny. The example reads and exports; it starts no scan or remediation and changes nothing. The script's finally block disconnects the account and clears its saved Azure contexts.

Option 1

Find non-compliant resources with PowerShell

Install the modules once. The script reads the non-compliant states of each enabled subscription and saves 1 row for each policy a resource breaks.

PowerShell
Install-Module -Name Az.Accounts, Az.PolicyInsights -Repository PSGallery -Scope CurrentUser
PowerShell
$ErrorActionPreference = 'Stop'
Connect-AzAccount -ErrorAction Stop
try {
    $subscriptions = @(Get-AzSubscription | Where-Object State -eq 'Enabled')
    if ($subscriptions.Count -eq 0) {
        Write-Output 'No enabled subscriptions are available to this account.'
        return
    }
    $filter = "ComplianceState eq 'NonCompliant'"
    $rows = [System.Collections.Generic.List[object]]::new()
    foreach ($sub in $subscriptions) {
        foreach ($state in Get-AzPolicyState -SubscriptionId $sub.Id -Filter $filter) {
            $rows.Add([pscustomobject]@{
                Subscription = $sub.Name
                ResourceGroup = $state.ResourceGroup
                ResourceType = $state.ResourceType
                ResourceId = $state.ResourceId
                Policy = $state.PolicyDefinitionName
                Effect = $state.PolicyDefinitionAction
                Assignment = $state.PolicyAssignmentName
                Initiative = $state.PolicySetDefinitionName
                Evaluated = $state.Timestamp
            })
        }
    }
    if ($rows.Count -eq 0) {
        Write-Output 'No non-compliant resources were found.'
    } else {
        $rows | Sort-Object Subscription, ResourceGroup, ResourceId, Policy |
            Export-Csv -Path './policy-non-compliance.csv' -NoTypeInformation -Encoding utf8
        Write-Output "$($rows.Count) non-compliant states saved to policy-non-compliance.csv."
    }
} finally {
    Disconnect-AzAccount | Out-Null
}

The CSV holds the subscription, resource group, resource type and ID, the policy, its effect, the assignment, the initiative it came through and when it was evaluated. A resource that breaks 3 policies has 3 rows. PolicyDefinitionName is the definition's name, which for a built-in policy is a GUID; the portal and Altivane show its display name. To narrow the list, add to the filter, for example and PolicyDefinitionAction eq 'audit'.

Option 2

Review non-compliant resources in the Azure portal

  1. Sign in to the Azure portal with an account that can read the subscriptions.
  2. Search for Policy, open it and choose Compliance.
  3. Use the filters at the top to choose the scope and show the assignments that aren't compliant. Each row gives its non-compliant resources and policies.
  4. Select an assignment, then choose the Resource compliance tab and filter it to non-compliant resources.
  5. To see what happened to a resource, right-click its row and choose Show activity logs.

This suits working through 1 assignment at a time. To export the results, Microsoft points to Azure Resource Graph queries; for a file across every assignment and subscription, use PowerShell or Altivane.

Common questions

I fixed the resource. Why is it still non-compliant?

The state changes when Azure evaluates it again: about 15 minutes after a change made through Azure Resource Manager, otherwise at the next daily cycle. Microsoft also offers an on-demand scan with Start-AzPolicyComplianceScan, which can take a long time to finish.

What does Not registered mean?

The Microsoft.PolicyInsights resource provider isn't registered on the subscription, or the signed-in account can't read compliance data. Check the provider's registration and the account's role.

Can a policy require tags on resources?

Yes, Azure Policy has built-in definitions that require or add tags. To find what is untagged today, see how to find resources without tags in Azure.

Microsoft references

Technical references checked on 6 November 2026. The example scripts have been reviewed and syntax checked; they have not been run against a live tenant.

Talk to us about Altivane

Questions, or pricing? Get in touch.

Contact us