Public/Find-AzureUtilsPolicyNonCompliant.ps1
|
function Find-AzureUtilsPolicyNonCompliant { <# .SYNOPSIS Finds resources that are non-compliant with Azure Policy. .DESCRIPTION Uses Azure Resource Graph (the 'policyresources' table) to list resources whose current Azure Policy compliance state is 'NonCompliant', naming the offending policy assignment and definition in a 'Reason' column. Returns one object per non-compliant (resource, policy) pair - a resource that violates several policies appears once per policy. Compliance is evaluated on Azure's own schedule; a resource just fixed may still show here until the next evaluation. .PARAMETER SubscriptionId One or more subscription IDs. Default: every enabled subscription. .PARAMETER ManagementGroupId One or more management groups to scan (requires Az.ResourceGraph). .EXAMPLE Find-AzureUtilsPolicyNonCompliant .EXAMPLE Find-AzureUtilsPolicyNonCompliant -ManagementGroupId 'PLAT' | Group-Object PolicyAssignment | Sort-Object Count -Descending .OUTPUTS AzureUtils.PolicyNonCompliant #> [CmdletBinding(DefaultParameterSetName = 'Subscriptions')] [OutputType('AzureUtils.PolicyNonCompliant')] param( [Parameter(ParameterSetName = 'Subscriptions')] [string[]] $SubscriptionId, [Parameter(ParameterSetName = 'ManagementGroup', Mandatory)] [string[]] $ManagementGroupId ) $null = Assert-AzureUtilsContext $resolved = Resolve-AzureUtilsScope -SubscriptionId $SubscriptionId -ManagementGroupId $ManagementGroupId if ($resolved.Type -eq 'Subscription' -and -not $resolved.HasSubscriptions) { Write-Warning 'No accessible subscriptions in scope.' return } $query = New-AzureUtilsPolicyNonCompliantQuery $nameMap = $resolved.NameMap $scope = $resolved.Scope Write-Verbose "Policy-compliance query:`n$query" Invoke-AzureUtilsGraphQuery -Query $query @scope | ForEach-Object { $subId = [string]$_.subscriptionId [pscustomobject]@{ PSTypeName = 'AzureUtils.PolicyNonCompliant' Name = $_.resName ResourceType = $_.resourceType ResourceGroup = $_.resourceGroup Location = $_.location SubscriptionName = if ($nameMap.ContainsKey($subId)) { $nameMap[$subId] } else { $subId } SubscriptionId = $subId PolicyAssignment = $_.policyAssignment PolicyDefinition = $_.policyDefinition Reason = $_.reason ResourceId = $_.resourceId } } } |