Lesson 04 — Azure Policy: Governance at Scale

Domain 1 — Identity & Governance AZ-104: 20–25% ~35 min Prereq: Lessons 01–03

What Azure Policy Is — and What It Is Not

Azure Policy enforces resource configurations. RBAC controls who can perform actions. These are orthogonal systems that must both be satisfied for an operation to succeed — but they operate independently, and conflating them is a source of real architectural mistakes.

DimensionAzure RBACAzure Policy
Question it answers Can this identity perform this action? Is this resource configuration allowed in this environment?
Grants permissions? Yes — explicitly grants actions to principals No — never grants permissions; only restricts or audits what permitted users deploy
Can block an Owner? Only via Deny Assignments (not direct RBAC) Yes — a Policy Deny blocks a resource deployment even if the deployer is an Owner
Operates at Identity plane — the principal making the request Resource plane — the resource being created or modified
Both must be satisfied For a resource to be successfully deployed: (1) the deployer must have the RBAC permissions to perform the action, AND (2) the resource configuration must comply with all applicable Azure Policy assignments. Policy Deny fires at the ARM control plane before the resource is written, regardless of who is asking.

Policy Definitions: Structure

A policy definition is a JSON document that specifies a condition (if) and an effect (then). When a resource matches the if condition, the effect is applied.

{
  "mode": "Indexed",
  "policyRule": {
    "if": {
      "allOf": [
        { "field": "type", "equals": "Microsoft.Storage/storageAccounts" },
        { "field": "Microsoft.Storage/storageAccounts/supportsHttpsTrafficOnly",
          "notEquals": true }
      ]
    },
    "then": {
      "effect": "Deny"
    }
  },
  "parameters": {
    "allowedEffect": {
      "type": "String",
      "defaultValue": "Deny",
      "allowedValues": ["Audit", "Deny", "Disabled"]
    }
  }
}

The mode field

ModeWhat it evaluatesWhen to use
All Every resource type, including resource groups and subscriptions themselves Policies that apply to resource group properties, or subscription-level configurations
Indexed Only resource types that support tags and location metadata Tag and location policies — the default for most compliance policies. Avoids false positives on resource types that don't have tags (e.g. extensions, providers).

Policy Effects — Memorise All Seven

The effect determines what Azure does when a resource matches the policy's if condition. This is the most heavily tested aspect of Azure Policy. Know all effects, their purpose, and their sequencing.

Evaluation order for new/updated resources: 1. Disabled — policy is off, nothing happens 2. Append — adds fields/tags to the resource request 3. Modify — adds/replaces/removes properties during create or update 4. Deny — blocks the operation entirely 5. Audit — allows the operation, marks resource non-compliant 6. AuditIfNotExists — audits if a specified related resource does NOT exist 7. DeployIfNotExists — deploys a related resource if it doesn't exist
EffectWhat it doesExample use case
Disabled The policy is present but does nothing. Useful for testing or temporarily suspending a policy without deleting the assignment. Disabling a Deny policy before a planned change window; testing a new policy definition before activating it.
Append Adds fields or tags to a resource during create or update. Does not modify existing fields — only appends. Does not remediate existing resources. Appending a CreatedBy tag using the request context; appending a default NSG rule that must always be present.
Modify Adds, replaces, or removes properties during create or update. More powerful than Append — can change existing values. Requires a managed identity on the assignment for remediation of existing resources. Inheriting a CostCenter tag from the resource group; enforcing a specific tag value; converting HTTP storage accounts to HTTPS on update.
Deny Blocks the resource operation at the ARM layer. The deployment fails before the resource is written. Evaluates at create and update time. Blocking storage accounts without HTTPS; blocking resources in non-allowed regions; blocking VM SKUs not in an approved list.
Audit Allows the resource to be created/updated regardless, but marks it as Non-compliant in the compliance dashboard and creates a compliance event. Auditing storage accounts without a specific tag; auditing VMs without Entra ID login extension — situations where you want visibility without blocking.
AuditIfNotExists Audits a parent resource when a specified related/child resource does not exist. The parent resource is allowed to deploy; the audit marks it non-compliant if the related resource is absent. Audit VMs without the Azure Monitor Agent extension; audit storage accounts without Defender for Storage enabled; audit App Services without diagnostic settings.
DeployIfNotExists (DINE) Deploys a related resource if it doesn't exist. Actively remediates the gap — does not just audit it. Requires a managed identity on the assignment with sufficient permissions to deploy the related resource. Automatically deploy diagnostic settings on new storage accounts; deploy Log Analytics agent to new VMs; enable Defender for Storage on new storage accounts.
AuditIfNotExists vs. Audit — the exam always tests this distinction Audit evaluates the resource itself — it checks a property on the resource being deployed. AuditIfNotExists evaluates whether a related resource (a child resource, an extension, a linked resource) exists. If you want to audit "VMs without the Azure Monitor Agent," use AuditIfNotExists — because you're checking for the absence of a child extension resource, not a property on the VM itself.
DeployIfNotExists requires permissions — and a managed identity A DINE policy that deploys diagnostic settings needs to actually call ARM on your behalf. The policy assignment must have a managed identity (system-assigned, created automatically when you assign the policy) and that identity must have a role with sufficient permissions — typically Monitoring Contributor or a custom role. If the managed identity lacks permissions, the DINE effect will silently fail and resources will remain non-compliant.

Policy Evaluation Logic

Understanding when policies are evaluated is as important as understanding effects.

New and updated resources

When a resource is created or updated (via portal, CLI, ARM template, Terraform, or any other mechanism), Azure evaluates all applicable policies at the ARM layer before writing the resource. Deny effects fire here and return a 403 to the caller. This happens synchronously during the deployment.

Existing resources

Policies do not retroactively block existing non-compliant resources. Existing resources are evaluated during compliance scan cycles. These run:

  • Automatically approximately every 24 hours on a schedule Azure controls
  • On-demand via az policy state trigger-scan or the portal's "Trigger evaluation" button
  • Immediately after a new policy assignment is made (on the resources within that scope)
Compliance is eventually consistent After assigning a new policy, expect up to 30 minutes for initial compliance data to appear in the dashboard, and up to 24 hours for the full scan of all resources in scope to complete. For large environments with thousands of resources, the compliance report is always a point-in-time snapshot, not a real-time view.

Policy Initiatives (Policy Sets)

An initiative is a collection of policy definitions grouped together to achieve a common governance goal. Instead of assigning 50 individual policies, you assign one initiative. Compliance is reported at both the initiative level and the individual policy level within it.

Built-in initiatives for compliance frameworks

InitiativePurposeTypical assignment scope
Azure Security BenchmarkMicrosoft's baseline security recommendations for Azure. Good starting point for any environment.Root Management Group or per-environment subscription
CIS Microsoft Azure Foundations BenchmarkCenter for Internet Security hardening guidelines mapped to Azure policies.Production subscriptions requiring CIS compliance
NIST SP 800-53 Rev. 5US federal controls framework. Required for FedRAMP and many US government workloads.Government or regulated environment subscriptions
PCI DSS v4.0Payment card industry data security standard. Required for cardholder data environments.Subscriptions containing CDE (cardholder data environment) workloads
ISO 27001:2013International information security management standard.Enterprise-wide or per-certification-scope subscriptions
Assign initiatives, not individual policies, for compliance frameworks Built-in compliance initiatives are maintained by Microsoft — when a new control is added to a framework (e.g. a new NIST control), Microsoft updates the initiative and your assignment automatically covers the new policy. If you'd assigned individual policies, you'd need to manually track and add each new one.

Policy Assignments

A policy assignment is the binding of a policy (or initiative) definition to a scope. The same definition can be assigned at multiple scopes with different parameters and different enforcement modes.

Assignment components

ComponentDescription
ScopeManagement Group, Subscription, or Resource Group. Lower scope = narrower application. RBAC applies: you need write permissions on the scope to create an assignment.
ParametersOverride the policy definition's default parameter values for this specific assignment. E.g. set allowedLocations to ["eastus", "westus2"] for this subscription while a different subscription uses ["northeurope"].
Non-compliance messageA custom message shown to deployers when their resource is blocked by this policy. Should clearly explain what the user must do differently.
Enforcement modeEnabled: policy is fully enforced (Deny fires, DINE deploys). Disabled: policy evaluates for compliance reporting only, but Deny does not block and DINE does not deploy — useful for pre-testing a policy in production.
Managed identityRequired for Modify and DeployIfNotExists effects. Azure creates a system-assigned managed identity for the assignment; you must grant it the necessary RBAC role.

Policy Exclusions vs. Exemptions — A Critical Distinction

Both mechanisms allow resources to be excluded from a policy assignment, but they behave very differently:

PropertyExclusion (notScope)Exemption
How configuredA scope listed in notScope on the assignment — set at assignment creation timeA separate Exemption resource created on a specific resource or scope
GranularityEntire scope (subscription, resource group) — cannot target individual resourcesCan target a specific resource, resource group, or subscription
Compliance dashboardExcluded resources are invisible — they do not appear in compliance reports at allExempt resources appear in the compliance dashboard with state Exempt and the documented reason
Time limitPermanent — no expiryTime-bounded — has an optional expiry date (after which the resource becomes non-compliant again)
Documented reasonNo — no audit trail or reason requiredYes — requires a category (Waiver or Mitigated) and a description
Audit trailNo dedicated audit trail — it is just a scope in the assignment definitionAppears in Activity Log; shows in compliance report as Exempt
Prefer exemptions over exclusions in regulated environments In an audited environment, using notScope to exclude a resource makes it invisible to compliance reports — your auditors will have no way to see the exception was made. Exemptions with documented reasons appear in reports as Exempt with justification, satisfying audit requirements. Use notScope only for entire development environments or sandboxes that should never contribute to production compliance metrics.

Remediation Tasks

Policies with Modify or DeployIfNotExists effects can automatically fix non-compliant existing resources through remediation tasks. New resources are handled at deployment time; existing resources require an explicit remediation task.

How remediation works

  1. A policy with DINE or Modify effect is assigned, or resources already exist that are non-compliant with such a policy.
  2. The compliance scan identifies non-compliant resources.
  3. An administrator triggers a Remediation Task from the Policy compliance blade (or it can be configured to auto-remediate on assignment).
  4. Azure iterates through all non-compliant resources in scope and applies the effect — deploying the missing resource (DINE) or modifying the existing resource (Modify).
  5. The remediation task runs using the managed identity attached to the policy assignment. If the managed identity lacks permissions, individual resources will fail to remediate and you'll see per-resource errors in the task log.
Managed identity permissions must be granted before remediation When Azure creates a system-assigned managed identity for a DINE or Modify policy assignment, it does not automatically grant the identity the permissions it needs. You must explicitly assign the required RBAC role to the managed identity. For diagnostic settings DINE policies, grant Monitoring Contributor. For tag Modify policies, grant Tag Contributor or Contributor on the scope. Missing this step is the most common reason DINE policies appear to do nothing.

Compliance States

The Azure Policy compliance dashboard reports four possible states per resource per assignment:

StateMeaningAction required
Compliant Resource satisfies the policy condition None
Non-compliant Resource does not satisfy the policy condition. For Audit/AuditIfNotExists policies, the resource is deployed but flagged. For Deny policies, this state indicates an existing resource that pre-dates the policy assignment. Remediate the resource (for Modify/DINE policies), or manually bring it into compliance
Exempt Resource has an active Exemption applied Review exemption justification and expiry — ensure it is still valid
Conflict Two or more policy assignments produce contradictory evaluations for the same resource (e.g. one policy requires tag value "A" and another requires tag value "B" for the same tag) Resolve by making one policy more specific, adding an exemption, or consolidating the conflicting assignments
Conflict state is rare but important A Conflict state usually indicates overlapping policy assignments with incompatible conditions on the same resource property. The common cause is assigning multiple initiatives that each contain policies targeting the same resource property with different requirements. Resolve by examining which assignments are in conflict in the compliance detail blade, then adjusting scope, parameters, or adding a targeted exemption.

Common Real-World Policies (Production Reference)

These are the policies you will encounter most frequently in real Azure environments. Know their names, effects, and how they are typically configured:

PolicyEffectNotes
Allowed locationsDenyRestricts resource creation to specific Azure regions. Assign at Management Group scope to cover all subscriptions. Use parameters to customise per-environment allowed locations.
Require a tag and its valueDenyBlocks resources that are missing a specific tag or have an incorrect value. Commonly used for CostCenter, Environment, Owner.
Inherit a tag from resource groupModifyCopies a tag value from the resource group to child resources at create/update time. Requires a managed identity on the assignment with Tag Contributor or Contributor role.
Allowed virtual machine SKUsDenyRestricts VM creation to an approved list of SKUs. Prevents engineers from accidentally deploying oversized or expensive SKUs in dev/test environments.
Secure transfer to storage accounts should be enabledDenyBlocks creation of storage accounts with HTTPS-only disabled. One of the most important baseline security policies — no exceptions.
Deploy Log Analytics agent to Windows/Linux VMsDeployIfNotExistsAutomatically deploys the Log Analytics (or Azure Monitor) agent extension to new VMs. Requires managed identity with VM Contributor + Log Analytics Contributor roles.
Audit VMs without backup configuredAuditIfNotExistsAudits VMs that do not have an active Azure Backup protection item. Uses AuditIfNotExists to check for the absence of the backup-related child resource.
Storage accounts should use customer-managed keysAuditFlags storage accounts not encrypted with CMK. Commonly used in regulated industries to enforce CMK over Microsoft-managed keys.

Azure Blueprints vs. Deployment Stacks

Azure Blueprints was Microsoft's original mechanism for packaging ARM templates, RBAC assignments, and Policy assignments together for repeatable environment deployment. Blueprints are deprecated — Microsoft stopped developing them and recommends migration to the replacement: Azure Deployment Stacks.

FeatureAzure Blueprints (deprecated)Azure Deployment Stacks
StatusDeprecated — will be retiredGA — active development
Template supportARM templates onlyARM templates and Bicep files
Deny assignmentsYes — could lock down blueprint-managed resourcesYes — DenySettings control what operations are allowed on stack-managed resources
ScopeSubscription and management groupResource group, subscription, and management group
CI/CD integrationLimitedNative Azure CLI / PowerShell / Bicep support — integrates naturally with pipelines
Exam note: Blueprints may still appear in AZ-104 questions As of 2026, some exam questions may still reference Azure Blueprints since the exam pool is not always immediately updated when features are deprecated. Know what Blueprints are and that they have been superseded by Deployment Stacks. In production, always recommend Deployment Stacks for new implementations.

Hands-On: Assign and Evaluate a Policy

  1. Assign the Azure Security Benchmark initiative: Navigate to Policy → Definitions. Filter by Category = Security Center. Find the Azure Security Benchmark initiative. Click Assign. Set scope to a development subscription. Set enforcement mode to DoNotEnforce (Disabled) — this evaluates for compliance without blocking anything. Submit the assignment.
  2. Trigger a compliance scan: Go to Policy → Compliance. Find your initiative assignment. Click the "…" menu → Trigger evaluation. Wait 5–10 minutes for initial results to appear. Examine which policies show Non-compliant resources.
  3. Create a custom Deny policy: Go to Policy → Definitions → + Policy definition. Set the scope to your subscription. Create a policy that denies storage account creation when supportsHttpsTrafficOnly is not true. Use the JSON example from earlier in this lesson. Assign it with enforcement mode Enabled.
  4. Test the Deny policy: Attempt to create a storage account with Secure transfer required set to Disabled. The deployment should fail with a policy violation message. Examine the error — it will reference the policy definition name and assignment. Then create the same storage account with HTTPS enabled — it should succeed.
  5. Create an exemption: For one non-compliant resource in the compliance dashboard, create an Exemption. Set category to Waiver, add a justification note, and set an expiry date 30 days in the future. Observe how the compliance state changes to Exempt and the exemption appears in the compliance report.
Checkpoint You should now be able to assign policies and initiatives at the correct scope, read a compliance report and interpret each state, create a remediation task for a DINE policy, and explain to a colleague the difference between every policy effect.

Check Your Understanding

Click any option to see immediate feedback. These questions reflect real exam reasoning and production decision-making.

1. You assign a policy with Deny effect to a Management Group. An Owner of a subscription inside that MG deploys a resource that violates the policy. What happens?

Azure Policy Deny fires at the ARM control plane layer — before any resource is written. RBAC authorises the caller (the Owner) to perform the action, but Policy then evaluates whether the resulting resource configuration is permitted. Policy Deny cannot be overridden by RBAC, even by a subscription Owner. This is the precise separation of concerns between RBAC (who can act) and Policy (what configurations are allowed). The only way to allow the deployment is an exemption on the scope or changing the policy assignment.

2. You want to automatically add a missing CostCenter tag to resources deployed without it, inheriting the value from their resource group. Which policy effect should you use?

Modify is the correct effect for inheriting tags from a resource group. The Modify effect can read the resource group's tag value using the resourceGroup().tags['CostCenter'] expression and write it to the resource. Append can add a field but cannot read from a parent scope to inherit a value, and cannot replace an existing incorrect value. Deny (B) would block deployments but not automatically fix them — creating friction for engineers rather than a seamless governance control. AuditIfNotExists (D) only audits and makes no changes.

3. A policy with DeployIfNotExists effect needs to automatically deploy a diagnostic setting on every new storage account. What does the policy assignment require beyond the definition itself?

DeployIfNotExists policies deploy resources on your behalf using a managed identity attached to the policy assignment. Azure creates this system-assigned managed identity automatically when you assign the policy, but you must manually grant it the RBAC role it needs. For deploying diagnostic settings to a storage account, Monitoring Contributor on the subscription (or resource group) scope is the typical grant. Without this role assignment, the DINE effect evaluates correctly but deployment tasks will fail with "Authorization" errors that appear only in the remediation task log — a common source of confusion.

4. What is the difference between a policy exclusion (notScope) and a policy exemption?

The audit trail distinction is the most operationally important difference. notScope makes a scope invisible to the policy entirely — excluded resources don't appear in compliance reports at all. In a regulated environment, this is problematic: you cannot demonstrate to an auditor that exceptions were reviewed and approved. Policy exemptions create a documented, time-bounded exception with a reason, and the resource shows as Exempt in the compliance dashboard — satisfying audit requirements. Both mechanisms stop the Deny effect from firing and both remove resources from compliance counts.

5. You assign an initiative containing 50 policy definitions to a subscription. Three policies in the initiative overlap with a separate Deny policy assigned at the Management Group. What compliance state will a resource show when it satisfies the initiative but violates the standalone MG-level Deny policy?

Conflict is the compliance state assigned when two policy assignments reach contradictory conclusions about the same resource at the same time. It does not mean the stricter wins — it means the system detected an inconsistency that requires human resolution. In practice, resolve Conflicts by: (1) making one policy more specific so it doesn't overlap, (2) adding a targeted exemption, or (3) consolidating overlapping assignments. Note: Conflict is different from a Deny block — a resource in Conflict state may or may not be deployable depending on which conflicting effect fires first.

6. You need to audit whether all VMs have the Azure Monitor Agent extension installed, without blocking deployments of VMs that don't have it. Which policy effect is correct?

AuditIfNotExists is the correct effect here. The presence of the extension is a related resource (a child VM extension object) — not a property on the VM itself. AuditIfNotExists evaluates the parent resource (the VM) and checks whether the specified child/related resource exists. If the extension is absent, the VM is marked Non-compliant, but it was still allowed to deploy. Audit (B) evaluates a property on the resource itself — you cannot use plain Audit to check for the existence of a child resource. DINE (C) would automatically fix the issue rather than just report it. Deny (D) would block all VMs without the extension included at deployment time, which is too disruptive for a first-pass audit posture.
Primary source for this lesson What is Azure Policy? — Microsoft Learn

Also read: Understand Azure Policy effects (the canonical reference for all effect semantics and evaluation order) and Azure Policy exemption structure. The effects article is required reading before the exam.

Questions for your teacher (the AI agent)
This lesson covered the full Azure Policy model. There is significant depth to explore — ask your teacher to go deeper on any of these:
  • Walk me through authoring a complete DeployIfNotExists policy definition in JSON that deploys diagnostic settings to a storage account, including the managed identity configuration.
  • How does the policy evaluation order interact with ARM template deployments that create multiple resources — does each resource get evaluated independently?
  • When should I use Azure Policy's Modify effect vs. a DeployIfNotExists effect for tag inheritance — what are the operational trade-offs?
  • How do I migrate an existing Azure Blueprint assignment to Deployment Stacks without disrupting production environments?
Coming up: Lesson 05 — Resource Locks, Tags & Cost Management With identity, access, and policy governance covered, the next lesson completes the Domain 1 governance triad: resource locks that protect against accidental deletion and modification, tag strategies for cost allocation and resource organisation, and Azure Cost Management for budget controls, cost alerts, and chargeback reporting.