Automation
Azure Policy: diagnose a deny before creating a production exemption
A production runbook for qualifying an Azure Policy deployment deny with assignment, initiative, deny effect, compliance, scoped exemption, validation and rollback.
An Azure deployment denied by Azure Policy often triggers the wrong reflex: disable the assignment, create a broad exemption, bend the template around the rule, or rerun the pipeline with a more powerful identity. The error can look administrative, but it may point to real drift: an unapproved region, a forbidden SKU, missing encryption, absent diagnostics, a required tag that disappeared, or a resource created outside the governed landing zone.
The use case is a Terraform, Bicep, ARM, Azure DevOps or GitHub Actions deployment that fails in production with a deny effect. The runbook goal is to decide whether the change must be fixed, exempted with tight scope, rerun after propagation, or blocked. An exemption is not a shortcut. It is a production decision with scope, expiry, evidence and rollback.
Identify the exact deny
Start by freezing the deployment and the Policy error. RequestDisallowedByPolicy is not enough. You need the assignment, definition, initiative when applicable, effect, target resource and evaluated field.
Blocked deployment
Environment: production
Tool: Terraform, Bicep, ARM, Azure DevOps or GitHub Actions
Run: deploy-prod-20260710.6
Subscription: sub-prod-core
Resource group: rg-prod-app
Denied resource: Microsoft.Web/sites/orders-api
Operation: create or update
Error: RequestDisallowedByPolicy
Evidence to collect
policyAssignmentId
policyDefinitionId or policySetDefinitionId
policyDefinitionReferenceId when an initiative is involved
effective policy effect: deny, modify, append, audit, deployIfNotExists
evaluated field or alias
assignment parameters
existing or missing exemption
recent policy change If the team cannot map the denial to a specific rule, it should not create an exemption. It may bypass the wrong guardrail.
Read the assignment and parameters
A policy may be valid but incorrectly parameterized at management group, subscription or resource group level. The incident can come from an obsolete region list, a renamed mandatory tag, an updated initiative or an expired exemption.
ASSIGNMENT_ID="/providers/Microsoft.Management/managementGroups/mg-prod/providers/Microsoft.Authorization/policyAssignments/deny-unapproved-web-sku"
az policy assignment show --ids "$ASSIGNMENT_ID" --query "{name:name,scope:scope,notScopes:notScopes,enforcementMode:enforcementMode,definition:policyDefinitionId,parameters:parameters,metadata:metadata}" --output json
az policy exemption list --scope "/subscriptions/<subscription-id>/resourceGroups/rg-prod-app" --query "[].{name:name,assignment:policyAssignmentId,expires:expiresOn,category:exemptionCategory,selectors:resourceSelectors}" --output table Also check whether enforcementMode is Default or DoNotEnforce. A deployment may pass in test because the rule is effectively audit-only there, then fail in production where the deny is active.
Separate template error from governance signal
The diagnosis should answer one practical question: is the policy blocking a genuinely non-compliant change, or is it blocking an acceptable case that the governance model has not captured yet?
Template or plan issue
Region is outside the approved list
SKU is not allowed
Diagnostic settings are missing
Public network access is enabled without justification
Mandatory tag is missing or empty
Managed identity is not enabled
Encryption or minimum TLS is not compliant
Rule too broad or obsolete parameter
New SKU is approved but missing from parameters
Region was added to the landing zone but not to policy
Azure Policy alias does not cover the new resource mode cleanly
Initiative was updated without operational notice
Existing exemption expired without an owner
Block the change when
The requested exemption would cover the whole resource group
The proposed fix disables the assignment
Security or business risk is undocumented
Application rollback is not ready The right fix is often in the template: add diagnostics, tags, identity, an approved SKU or a compliant parameter. Exemption should remain the exception, not the normal deployment path.
Rebuild the decision from logs
Correlate the run with Azure Activity and Policy state. Logs help separate a Policy deny from an RBAC denial, a provider issue or an ARM validation error.
let StartTime = datetime(2026-07-10T08:00:00Z);
let EndTime = datetime(2026-07-10T09:00:00Z);
AzureActivity
| where TimeGenerated between (StartTime .. EndTime)
| where ActivityStatusValue in ("Failure", "Failed")
| where Properties has "RequestDisallowedByPolicy"
or Properties has "policyAssignmentId"
| project TimeGenerated,
OperationNameValue,
ActivityStatusValue,
Caller,
ResourceGroup,
ResourceProviderValue,
ResourceId,
CorrelationId,
Properties
| order by TimeGenerated asc Keep the CorrelationId in the incident record. It proves that the exemption or template fix matches the observed denial, not a generic assumption.
Check compliance before redeploying
Before rerunning the pipeline, evaluate the target resource or scope. A blind rerun can fail the same way, or worse, pass after an overly broad exemption without anyone seeing the accepted risk.
SUBSCRIPTION_ID="<subscription-id>"
RESOURCE_GROUP="rg-prod-app"
az policy state list --subscription "$SUBSCRIPTION_ID" --resource-group "$RESOURCE_GROUP" --query "[?complianceState=='NonCompliant'].{resource:resourceId,assignment:policyAssignmentName,definition:policyDefinitionName,reference:policyDefinitionReferenceId,state:complianceState,timestamp:timestamp}" --output table
az policy state summarize --subscription "$SUBSCRIPTION_ID" --resource-group "$RESOURCE_GROUP" --output json If compliance state has not converged yet, say so. The decision should not depend on a view that is still catching up.
Scope the exemption if it is necessary
A production exemption must be bounded by scope, resource, assignment, duration, owner and exit condition. It must not remove the guardrail for future changes.
exemption:
reason: deploy hotfix while diagnostic settings policy parameter is corrected
assignment: deny-missing-diagnostic-settings
scope: /subscriptions/sub-prod-core/resourceGroups/rg-prod-app/providers/Microsoft.Web/sites/orders-api
category: Waiver
expires_on: 2026-07-17T18:00:00Z
owner: platform-operations
accepted_risk:
- diagnostic setting will be added by follow-up change
- alert coverage remains active through existing Application Insights rules
forbidden:
- exemption at subscription scope
- disabling assignment
- changing policy effect from deny to audit for all resources
exit_criteria:
- template corrected
- compliance scan green
- exemption removed
- deployment validation attached to incident If the need is permanent, fix the policy or its parameters. A long-lived exemption without an owner becomes governance debt.
Decide fix, exemption or block
The runbook should end with an explicit decision. The pipeline should not merely turn green. It should turn green for a reason the team can explain later.
Fix the template
The denial matches a valid requirement
The fix is limited and testable
No policy bypass is required
The plan contains only expected changes
Fix policy or parameters
The rule is legitimate but parameters are obsolete
The governance change is reviewed as code
Impacted scopes are identified
A compliance scan validates the result
Create a scoped exemption
The production need is real and temporary
Accepted risk is documented
Scope, expiry and owner are defined
Exemption exit is planned
Block
The request hides a security or compliance risk
Exemption scope is too broad
Deployment already produced unqualified partial state
Application or infrastructure rollback is missing This matrix avoids two opposite failures: blocking every release through rigidity, or hollowing out Azure Policy with global exceptions.
Validate after action and roll back the guardrail
After a fix or exemption, rerun with the same artifact or a clearly identified plan. Then validate both the service and governance state.
Minimum validation
Deployment uses the approved run and commit
Created or modified resource matches the expected scope
Azure Activity shows no unexpected deny
Unrelated policies remain active
Compliance state is reviewed after propagation
Application probes pass
Exemption has owner, expiry and justification
Rollback
Remove the exemption if validation fails
Revert the template if the fix breaks the service
Restore policy parameters if the initiative was opened too far
Run a new compliance scan
Keep the initial deny, decision and exit evidence in the incident record Conclusion
An Azure Policy deny is not just a deployment error. It is a decision point between compliance, service continuity and operations.
The runbook should therefore produce a traceable outcome: fix the template, adjust the policy, create a temporary scoped exemption, or block. The real validation is not only a green pipeline. It is a compliant resource, an active guardrail and a rollback path if the exception proves too risky.