Skip to content

Governance · Runbook

Azure Policy baseline: audit first, then enforce safely

• 11 min read

An Azure Policy baseline built on Microsoft Learn guidance: audit first, stage rollout, handle exemptions and remediation, then move to enforcement.

  • Effort: 1-2 days
  • Risk: Medium
  • Rollback: Partial

Applies to: Azure Policy

On this page
  1. What good looks like
  2. Who is affected
  3. Why it matters
  4. Decisions to make
  5. Effect order
  6. Exclusion or exemption
  7. Which rollout lever
  8. Runbook
  9. About enrollments
  10. Checks
  11. Rollback
  12. Common pitfalls
TL;DR

A sound Azure Policy baseline starts with audit, not deny. Microsoft Learn recommends starting with audit or auditIfNotExists before any enforcement effect, then widening scope in stages. Use DoNotEnforce, resource selectors and overrides to roll out, use exclusions only for permanent broad bypasses, and keep exemptions time-bound and tracked.

Source and what to verify

Official Microsoft Learn sources (checked on 2026-10-17):

Confirm before acting:

  • Enroll mode: Learn describes it, but the page does not label it generally available or preview, and its sample uses apiVersion 2025-02-01-preview. Treat it as preview or unconfirmed until you have seen a status from Microsoft.
  • Portal labels: the portal wording for creating a remediation task is documented for subscription-scope assignments. Check the exact labels in your portal before you write them into a procedure.
  • Starting policies: choose your first built-in policies or initiatives from Microsoft’s built-in policy lists, and confirm the definition IDs in your own tenant before you assign anything.
  • Limits: the numbers below are Learn’s figures at the time of checking. Re-read the overview page before you design around them.

What good looks like

A baseline here is a rollout method, not a list of policies. The Learn pages agree on the shape:

  • Policy resources live in source control and deploy through one central mechanism (GitHub workflows or Azure Pipelines). Learn says write permissions to policy resources can be restricted to the deployment identity.
  • Definitions sit at a management group or subscription. Learn suggests a management group near the root, shared by all target resources. Assignments go on child scopes.
  • Learn recommends assigning initiatives even when you start with a single policy.
  • New policies start in audit, or in DoNotEnforce, and move to enforcement in stages.
  • Exceptions are tracked, time-bound and reviewed.

If you are building the wider platform around this, the Azure Landing Zones secure-by-default guide covers the foundation these guardrails sit on.

Who is affected

  • Platform teams who own definitions, initiatives and assignments.
  • Workload teams whose deployments get blocked, or whose resources show as non-compliant.
  • Security and compliance teams. Learn’s guidance on evaluating a new policy says scope changes should be validated and communicated to them.

Roles matter here. Learn lists these:

  • Resource Policy Contributor includes most Policy operations.
  • Owner has full rights.
  • Contributor and Reader get read operations. Contributor can trigger remediation but cannot create or update definitions and assignments.
  • User Access Administrator is needed to grant the managed identity its permissions on deployIfNotExists and modify assignments.
  • Creating an exemption needs Microsoft.Authorization/policyExemptions/write plus the exempt/Action verb on the target assignment. Learn says Resource Policy Contributor and Security Admin have read and write on exemptions.

For the wider role model, see the identity baseline for landing zones.

Why it matters

  • Deny blocks work. In Resource Manager mode, Learn says deny stops the create or update request before it reaches the resource provider and returns 403 (Forbidden). Learn also warns that enforcement can hinder existing automation such as autoscale scripts.
  • Azure Policy is an explicit deny system. Learn says that if any assignment denies a resource, the only way to allow it is to modify the denying assignment, for example by excluding scopes.
  • Overlapping assignments stack. They are evaluated independently, and Learn describes the net result as cumulative most restrictive. A deny at any scope blocks the resource.
  • Definition edits hit every assignment. Learn says that if an assigned definition changes, all existing assignments use the updated logic when evaluating. Treat a definition edit as a change to every assignment of it.
  • Feedback is slow. Learn gives about five minutes for a new assignment to apply to its scope before the evaluation cycle begins, with no predefined completion time for large scopes. Resource create or update results appear in the portal and SDKs around 15 minutes later. The standard cycle runs every 24 hours. Don’t judge a rollout on the first ten minutes of data.

Decisions to make

Effect order

Learn gives the evaluation order as disabled, then append and modify, then deny, then audit, then manual, then auditIfNotExists, with denyAction last. Deny is evaluated before audit, which prevents double logging of an undesired resource. Existing resources that match a deny definition are marked non-compliant, not deleted.

Exclusion or exemption

NeedUseWhat Learn says
Permanently bypass a broad scope, such as a test environmentExclusion (notScopes)Resources are not evaluated or counted in compliance. Set on the assignment, so it means modifying the assignment.
Time-bound or specific case that should stay trackedExemptionThe resource is shown as exempt for tracking, and creating an exemption doesn’t require modifying the assignment.

Exemption categories are Mitigated (intent met another way) and Waiver (non-compliance temporarily accepted). An exemption can target specific policies in an initiative through policyDefinitionReferenceId. It is a child object of the exempted scope or resource, so it is removed if the parent is removed.

Learn says expiresOn stops an exemption being honoured but does not delete the object. Expired exemptions need housekeeping.

Which rollout lever

LeverUse it forLimit from Learn
enforcementMode DoNotEnforceEvaluate before enforcing. No effect, no Activity log entry.Changing it on an existing assignment is an assignment update.
OverridesChange the effect of policies in an initiative without editing the definition, for example audit now and deny later.Up to 50 policyDefinitionReferenceId per override, up to 10 overrides per assignment.
Resource selectorsGradual rollout by resource location or type.Up to 10 resourceSelectors per assignment.
Enroll mode (unconfirmed status)Staged enforcement through child enrollment objects.See the warning above.

Learn also lists object limits worth knowing: 200 assignments per scope, 1000 exemptions per scope, 400 notScopes per assignment, 500 policy definitions per scope, 200 initiative definitions per scope, and 50,000 resources per remediation task.

Runbook

  1. Put policy in source control

    Keep definitions, initiatives, assignments and exemptions in GitHub or Azure DevOps. Deploy them through a central pipeline. Restrict write permissions on policy resources to the deployment identity, as Learn suggests.

  2. Choose where definitions live

    Create definitions at a management group (near the root if they are shared) or subscription. Learn says a definition at a management group can be assigned to child management groups and subscriptions. Wrap even a single policy in an initiative, as Learn recommends.

  3. Test the definition properly

    Learn says to define tightly, test on a subset, audit new and updated resources, deploy to a subset, then widen, with continuous monitoring. For the test, assign in a Dev environment with enforcement mode Disabled (doNotEnforce) so the effect does not trigger. Learn also says enforcement mode is no substitute for testing with PUT and PATCH calls, compliant and non-compliant resources, and edge cases such as a missing property.

  4. Assign in audit or DoNotEnforce

    For a deny or append policy, Learn’s safe deployment pattern is to assign at the highest scope, narrow with a resourceLocation resource selector to the least critical tier, and set the effect to Audit with an assignment override.

    For modify and deployIfNotExists policies, set enforcementMode to DoNotEnforce with the same location selectors.

    Add a nonComplianceMessages entry so engineers see a clear reason if the policy later denies. Learn says this is supported only for Resource Manager mode definitions.

  5. Sort out the managed identity before remediation

    Learn says remediation uses the assignment’s managed identity, which needs the minimum required RBAC role. In the portal the roles are granted automatically. With SDK, CLI, PowerShell or IaC, Learn says you must grant the roles manually or the remediation deployment fails.

    An assignment with a system-assigned identity needs a location. Learn says it cannot be global and cannot be changed. If roleDefinitionIds are edited in the definition later, the new permissions must be granted manually, even in the portal.

  6. Wait, then read the compliance data

    Allow for the timings above. Review results under Policy > Compliance in the portal. Learn also says audit and deny results from new and updated resources can be queried in the AzureActivity table with Kusto queries, which is a route to alerting.

    To trigger an on-demand scan of a resource group, Learn gives this Azure CLI command (asynchronous, covers a subscription or resource group):

    BASH
    az policy state trigger-scan --resource-group "resourceGroupName"

    and the PowerShell equivalent:

    POWERSHELL
    Start-AzPolicyComplianceScan -ResourceGroupName 'resourceGroupName'
  7. Widen tier by tier, with checks

    Learn’s safe deployment page recommends automated compliance checks in the CI/CD pipeline at each rollout stage, with the pipeline failing and debugging starting when results are not as expected. Expand the location selector tier by tier, checking compliance and application health at each step.

  8. Remediate existing resources

    Remediation applies only to deployIfNotExists and modify policies and acts on existing resources. Learn says you can start remediation tasks even when the assignment is on DoNotEnforce. Use Policy > Remediation (the policies to remediate tab), or Policy > Compliance, open the non-compliant assignment and create a remediation task. Confirm the labels in your portal.

    A task remediates one policy at a time. Learn also names Start-AzPolicyRemediation and az policy remediation create for scripted use. Defaults per Learn: ResourceCount 500 (maximum 50,000), ParallelDeploymentCount 10 (range 1 to 30), FailureThreshold 100%. Check the command reference for exact parameters before you script it.

  9. Switch to enforcement

    For deny or append, Learn’s pattern is: once all tiers are audited, change the override effect to deny and reset the selectors to Tier 0, then repeat the expansion. For modify and deployIfNotExists, trigger remediation to confirm existing resources become compliant, then change enforcementMode to Default and reset the selector to Tier 0. Make this change first in an environment far from production.

  10. Stage definition version upgrades

    For built-in definition upgrades, Learn describes an assignment override of kind definitionVersion with a resourceLocation selector. Resources outside the selector keep using the top-level definitionVersion. When all locations are covered, remove the override and update definitionVersion.

  11. Run exemptions as a register

    Use exemptions for tracked, time-bound cases. Set expiresOn, pick Mitigated or Waiver honestly, and review regularly. Learn says to remove those that don’t qualify. Creating, updating or deleting an exemption triggers evaluation of the corresponding assignment.

About enrollments

Learn describes a policy enrollment (Microsoft.Authorization/policyEnrollments) as a child object that adds resource hierarchies or resources to the enforcement path of an assignment set to Enroll mode. Enrolled resources have the effect enforced. Other in-scope resources still get compliance records but are not enforced.

Learn says the referenced assignment must already exist with Enroll enforcement mode. Enrollments are managed through Azure CLI, ARM, Bicep or Terraform AzAPI. Only assignmentScopeValidation and resourceSelectors can be updated by PATCH, with up to 10 resourceSelectors per enrollment. Given the unconfirmed status described above, don’t build your baseline on it until you have checked the availability in your tenant.

Checks

  • Every new assignment started in audit, auditIfNotExists or DoNotEnforce, and the result was reviewed before enforcement.

  • Compliance data was read after the five-minute apply window and the evaluation cycle, not before.

  • Each deployIfNotExists or modify assignment has a managed identity with the required roles, granted manually where you used IaC, CLI or PowerShell.

  • A test remediation task completed on a small scope before any wide run.

  • Every exclusion has a recorded reason. Every exemption has a category and an expiresOn date.

  • Expired exemptions are listed and deleted on a schedule.

  • Deny assignments carry a non-compliance message (Resource Manager mode).

  • Policy writes are limited to the deployment identity, and the pipeline fails when compliance results are not as expected.

  • Definition edits are reviewed as changes to every existing assignment of that definition.

When a deployment is denied, Azure CLI, PowerShell and the portal Activity log show RequestDisallowedByPolicy with the policy assignment and definition identifiers. Learn says the name is the last segment of each ID. Use az policy definition show and az policy assignment show to inspect them, and check the command reference for parameters.

Rollback

Rollback is partial. The bullets below cover the assignment, definition and enrollment side. Plan remediation separately (last bullet).

  • Deny causing damage: set enforcementMode to DoNotEnforce. Learn says changing the value on an existing assignment is an assignment update, and it lists an updated assignment as an evaluation trigger, so allow for the timings above. If you rolled out with an override, Learn’s safe deployment pattern uses an assignment override to set the effect to Audit, so setting it back is the matching step. Confirm how your pipeline applies that change.
  • Deny on a specific resource: Learn says the only route is to modify the denying assignment. Use an exemption for a tracked, time-bound case or notScopes for a permanent broad bypass.
  • Bad definition edit: all existing assignments use the updated logic when evaluating, so revert the definition from source control.
  • Enrollment: Learn says deleting an enrollment does not delete the underlying assignment, so enforcement is withdrawn for that scope.
  • Remediation: Learn says tasks act on existing resources, so pilot on a small scope first. Before you run a wide remediation, decide how you would undo it, and check the remediate-resources page for current guidance.

Common pitfalls

  • Going straight to deny. Microsoft recommends audit first because enforcement can break existing automation.
  • Forgetting the identity roles. Outside the portal, remediation fails without manually granted roles. Editing roleDefinitionIds later does not update the identity.
  • Reading compliance too early. There is a delay of about five minutes to apply, then evaluation, and around 15 minutes for a resource change to show.
  • Confusing exclusion and exemption. Learn says resources in an exclusion aren’t evaluated or included in the compliance count. An exemption is the tracked, time-bound option and shows the resource as exempt.
  • Letting exemptions rot. Expiry stops the exemption working but leaves the object behind.
  • Editing a definition casually. Every assignment picks up the change.
  • Assuming DoNotEnforce blocks remediation. Learn says remediation tasks can still be started for deployIfNotExists policies in that mode.
  • Skipping real test cases. Enforcement mode is not a replacement for testing create, update and edge cases.
  • Hitting limits late. 200 assignments per scope and 1000 exemptions per scope are easier to plan for than to untangle.