Microsoft Azureintermediate

Azure Policy Governance Guide

Complete guide to implementing Azure Policy governance guardrails, including policy definitions, initiatives, assignments, compliance monitoring, and automated remediation.

12 min readUpdated 2026-01-14

Azure Policy enables you to enforce organizational standards and assess compliance across your Azure environment. This guide covers creating policy definitions, building initiatives, assigning policies, monitoring compliance, and implementing automated remediation.

This article is part of our comprehensive guide on Cloud Security Tips for 2026, which covers essential security practices across all major cloud platforms.

Overview

Azure Policy provides:

  • Preventive controls: Block non-compliant resource deployments
  • Detective controls: Identify existing non-compliant resources
  • Remediation: Automatically fix non-compliant configurations
  • Compliance reporting: Track adherence to organizational standards

Policy effects determine how violations are handled: Deny, Audit, Append, Modify, DeployIfNotExists, AuditIfNotExists, and Disabled.

Prerequisites

Before implementing Azure Policy, ensure you have:

  • Azure subscription with Owner or Policy Contributor role
  • Management group structure (recommended for enterprise)
  • Azure CLI installed (version 2.50 or later)
  • Understanding of ARM templates and resource properties
  • Documentation of organizational standards to enforce

Step 1: Understand Policy Concepts

Policy Definition

A policy definition describes the condition and effect:

{
  "if": {
    "field": "type",
    "equals": "Microsoft.Storage/storageAccounts"
  },
  "then": {
    "effect": "deny"
  }
}

Policy Initiative (Definition Set)

Groups multiple policies for easier assignment:

  • Microsoft Cloud Security Benchmark
  • CIS Azure Foundations Benchmark
  • Custom organizational initiatives

Policy Assignment

Applies policies to a scope (management group, subscription, or resource group).

Policy Effects

EffectWhen AppliedUse Case
DenyBlocks non-compliant deploymentsEnforce security requirements
AuditLogs non-compliance, allows deploymentAssessment and testing
AppendAdds properties to resourcesAuto-tagging
ModifyChanges properties on existing resourcesRemediation
DeployIfNotExistsDeploys related resourcesDeploy diagnostics
AuditIfNotExistsAudits for related resourcesCheck for dependencies

Step 2: Explore Built-in Policies

Browse Policies in Portal

  1. Sign in to the Azure Portal
  2. Search for Policy and select it
  3. Go to Definitions
  4. Filter by:
    • Type: Built-in
    • Category: Security, Tags, Compute, Storage, etc.
  5. Click a policy to view its definition and parameters

List Built-in Policies via CLI

# List all built-in policies
az policy definition list \
  --filter "policyType eq 'BuiltIn'" \
  --query "[].{Name:displayName, Category:metadata.category}" \
  -o table | head -50

# Search for storage-related policies
az policy definition list \
  --filter "policyType eq 'BuiltIn'" \
  --query "[?contains(displayName, 'storage')].{Name:displayName, ID:name}" \
  -o table

# Get details of a specific policy
az policy definition show \
  --name "404c3081-a854-4457-ae30-26a93ef643f9" \
  --query "{Name:displayName, Description:description, Effect:policyRule.then.effect}"

Key Security Policies

Policy NameEffectPurpose
Storage accounts should use customer-managed keyAuditData encryption
VMs should use managed disksDenySecurity baseline
Subnets should have NSG associatedAuditNetwork security
Key Vault should use RBACAuditAccess control
SQL databases should have TDE enabledDeployIfNotExistsData protection

Step 3: Create Custom Policy Definitions

Create Policy via Portal

  1. In Policy, go to Definitions
  2. Click + Policy definition
  3. Configure:
    • Definition location: Select management group or subscription
    • Name: Require-Resource-Tags
    • Category: Create new or select existing
  4. Enter policy rule (JSON)
  5. Click Save

Create Policy via Azure CLI

# Create a policy requiring specific tags
cat > /tmp/require-env-tag.json << 'EOF'
{
  "if": {
    "allOf": [
      {
        "field": "type",
        "equals": "Microsoft.Resources/subscriptions/resourceGroups"
      },
      {
        "field": "tags['Environment']",
        "exists": "false"
      }
    ]
  },
  "then": {
    "effect": "deny"
  }
}
EOF

az policy definition create \
  --name "require-environment-tag" \
  --display-name "Require Environment tag on resource groups" \
  --description "Denies creation of resource groups without an Environment tag" \
  --rules /tmp/require-env-tag.json \
  --mode All

# Create policy to restrict VM sizes
cat > /tmp/allowed-vm-sizes.json << 'EOF'
{
  "if": {
    "allOf": [
      {
        "field": "type",
        "equals": "Microsoft.Compute/virtualMachines"
      },
      {
        "not": {
          "field": "Microsoft.Compute/virtualMachines/sku.name",
          "in": "[parameters('allowedSizes')]"
        }
      }
    ]
  },
  "then": {
    "effect": "deny"
  }
}
EOF

cat > /tmp/allowed-vm-sizes-params.json << 'EOF'
{
  "allowedSizes": {
    "type": "Array",
    "metadata": {
      "displayName": "Allowed VM Sizes",
      "description": "List of allowed VM sizes"
    },
    "defaultValue": ["Standard_D2s_v3", "Standard_D4s_v3", "Standard_D8s_v3"]
  }
}
EOF

az policy definition create \
  --name "allowed-vm-sizes" \
  --display-name "Allowed virtual machine sizes" \
  --description "Restricts VM deployments to approved sizes" \
  --rules /tmp/allowed-vm-sizes.json \
  --params /tmp/allowed-vm-sizes-params.json \
  --mode All

Create Policy with DeployIfNotExists

# Policy to auto-deploy diagnostics to storage accounts
cat > /tmp/deploy-storage-diagnostics.json << 'EOF'
{
  "if": {
    "field": "type",
    "equals": "Microsoft.Storage/storageAccounts"
  },
  "then": {
    "effect": "deployIfNotExists",
    "details": {
      "type": "Microsoft.Insights/diagnosticSettings",
      "name": "storageAccountDiagnostics",
      "existenceCondition": {
        "allOf": [
          {
            "field": "Microsoft.Insights/diagnosticSettings/logs.enabled",
            "equals": "true"
          }
        ]
      },
      "roleDefinitionIds": [
        "/providers/Microsoft.Authorization/roleDefinitions/749f88d5-cbae-40b8-bcfc-e573ddc772fa",
        "/providers/Microsoft.Authorization/roleDefinitions/92aaf0da-9dab-42b6-94a3-d43ce8d16293"
      ],
      "deployment": {
        "properties": {
          "mode": "incremental",
          "template": {
            "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
            "contentVersion": "1.0.0.0",
            "parameters": {
              "storageAccountName": { "type": "string" },
              "logAnalyticsWorkspaceId": { "type": "string" }
            },
            "resources": [
              {
                "type": "Microsoft.Storage/storageAccounts/providers/diagnosticSettings",
                "apiVersion": "2021-05-01-preview",
                "name": "[concat(parameters('storageAccountName'), '/Microsoft.Insights/storageAccountDiagnostics')]",
                "properties": {
                  "workspaceId": "[parameters('logAnalyticsWorkspaceId')]",
                  "logs": [
                    { "category": "StorageRead", "enabled": true },
                    { "category": "StorageWrite", "enabled": true }
                  ]
                }
              }
            ]
          }
        }
      }
    }
  }
}
EOF

Step 4: Create Policy Initiatives

Create Initiative via Portal

  1. In Policy, go to Definitions
  2. Click + Initiative definition
  3. Configure:
    • Definition location: Management group or subscription
    • Name: Security-Baseline-Initiative
    • Category: Security
  4. Add policy definitions to the initiative
  5. Configure parameters and groupings
  6. Click Create

Create Initiative via Azure CLI

# Create initiative combining multiple policies
cat > /tmp/security-initiative.json << 'EOF'
{
  "properties": {
    "displayName": "Organization Security Baseline",
    "description": "Enforces security requirements for all resources",
    "policyDefinitions": [
      {
        "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/404c3081-a854-4457-ae30-26a93ef643f9",
        "parameters": {}
      },
      {
        "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/0a914e76-4921-4c19-b460-a2d36003525a",
        "parameters": {}
      },
      {
        "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/e71308d3-144b-4262-b144-efdc3cc90517",
        "parameters": {}
      }
    ]
  }
}
EOF

az policy set-definition create \
  --name "org-security-baseline" \
  --display-name "Organization Security Baseline" \
  --description "Security policies required for all subscriptions" \
  --definitions '[
    {"policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/404c3081-a854-4457-ae30-26a93ef643f9"},
    {"policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/0a914e76-4921-4c19-b460-a2d36003525a"},
    {"policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/e71308d3-144b-4262-b144-efdc3cc90517"}
  ]'

Step 5: Assign Policies

Assign via Portal

  1. In Policy, go to Assignments
  2. Click Assign policy or Assign initiative
  3. Configure:
    • Scope: Management group, subscription, or resource group
    • Exclusions: Optional exclusions
    • Policy definition: Select policy or initiative
  4. Configure parameters (if applicable)
  5. Configure remediation (for DeployIfNotExists)
  6. Set Non-compliance message
  7. Click Create

Assign via Azure CLI

# Assign a single policy to a subscription
az policy assignment create \
  --name "require-tags-assignment" \
  --display-name "Require Environment Tag" \
  --policy "require-environment-tag" \
  --scope "/subscriptions/$SUBSCRIPTION_ID" \
  --enforcement-mode Default

# Assign policy with parameters
az policy assignment create \
  --name "allowed-vm-sizes-assignment" \
  --display-name "Restrict VM Sizes" \
  --policy "allowed-vm-sizes" \
  --scope "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/rg-production" \
  --params '{"allowedSizes": {"value": ["Standard_D2s_v3", "Standard_D4s_v3"]}}'

# Assign built-in initiative (Microsoft Cloud Security Benchmark)
az policy assignment create \
  --name "mcsb-assignment" \
  --display-name "Microsoft Cloud Security Benchmark" \
  --policy-set-definition "1f3afdf9-d0c9-4c3d-847f-89da613e70a8" \
  --scope "/subscriptions/$SUBSCRIPTION_ID" \
  --mi-system-assigned \
  --location "eastus"

# Assign to management group
MANAGEMENT_GROUP_ID="mg-production"
az policy assignment create \
  --name "security-baseline-mg" \
  --display-name "Security Baseline" \
  --policy-set-definition "org-security-baseline" \
  --scope "/providers/Microsoft.Management/managementGroups/$MANAGEMENT_GROUP_ID"

Enable Remediation with Managed Identity

# Assign policy with managed identity for remediation
az policy assignment create \
  --name "deploy-diagnostics" \
  --display-name "Deploy Storage Diagnostics" \
  --policy "deploy-storage-diagnostics" \
  --scope "/subscriptions/$SUBSCRIPTION_ID" \
  --mi-system-assigned \
  --location "eastus" \
  --role "Contributor" \
  --identity-scope "/subscriptions/$SUBSCRIPTION_ID"

Step 6: Monitor Compliance

View Compliance in Portal

  1. In Policy, go to Compliance
  2. Review:
    • Overall compliance percentage
    • Non-compliant resources by policy
    • Compliance by scope
  3. Click a policy to see affected resources
  4. Export compliance data for reporting

Query Compliance via CLI

# Get overall compliance state
az policy state summarize \
  --query "{Compliant:results.complianceState.compliant, NonCompliant:results.complianceState.nonCompliant}"

# List non-compliant resources
az policy state list \
  --filter "complianceState eq 'NonCompliant'" \
  --query "[].{Resource:resourceId, Policy:policyDefinitionName}" \
  -o table

# Get compliance for specific policy
az policy state list \
  --policy-assignment "require-tags-assignment" \
  --query "[].{Resource:resourceId, State:complianceState}" \
  -o table

Query with Azure Resource Graph

# Comprehensive compliance report
az graph query -q "
  policyresources
  | where type == 'microsoft.policyinsights/policystates'
  | where properties.complianceState == 'NonCompliant'
  | extend policy = tostring(properties.policyDefinitionName)
  | extend resource = tostring(properties.resourceId)
  | summarize NonCompliantCount=count() by policy
  | order by NonCompliantCount desc
"

# Non-compliant resources by subscription
az graph query -q "
  policyresources
  | where type == 'microsoft.policyinsights/policystates'
  | where properties.complianceState == 'NonCompliant'
  | extend subscriptionId = tostring(split(properties.resourceId, '/')[2])
  | summarize count() by subscriptionId
"

Step 7: Remediate Non-Compliance

Create Remediation Task via Portal

  1. In Policy, go to Compliance
  2. Select a non-compliant policy
  3. Click Create remediation task
  4. Configure:
    • Scope for remediation
    • Resource discovery mode
  5. Click Remediate

Create Remediation Task via CLI

# List non-compliant resources for a policy
az policy state list \
  --policy-assignment "deploy-diagnostics" \
  --filter "complianceState eq 'NonCompliant'" \
  --query "[].resourceId" -o tsv

# Create remediation task
az policy remediation create \
  --name "remediate-storage-diagnostics" \
  --policy-assignment "deploy-diagnostics" \
  --resource-discovery-mode ExistingNonCompliant \
  --resource-group "rg-production"

# Check remediation status
az policy remediation show \
  --name "remediate-storage-diagnostics" \
  --resource-group "rg-production" \
  --query "{Status:provisioningState, Progress:deploymentStatus}"

# List all remediation tasks
az policy remediation list \
  --query "[].{Name:name, Status:provisioningState, Failed:deploymentStatus.failedDeployments}" \
  -o table

Best Practices

  1. Start with Audit effect: Assess impact before enforcing Deny
  2. Use management groups: Apply policies consistently across subscriptions
  3. Document exclusions: Track why resources are exempted
  4. Version control policies: Store definitions in Git repositories
  5. Test in non-production: Validate policies before production rollout
  6. Monitor remediation: Review failed remediation tasks regularly
  7. Use initiatives: Group related policies for easier management
  8. Set meaningful messages: Help users understand non-compliance reasons

Troubleshooting

Policy not evaluating new resources:

  • Allow 30 minutes for evaluation cycle
  • Trigger manual evaluation: az policy state trigger-scan
  • Verify policy assignment scope includes the resource

Remediation task failing:

  • Check managed identity has required permissions
  • Verify resource supports the remediation action
  • Review deployment logs in remediation task details

Policy conflicts:

  • Check for overlapping assignments at different scopes
  • Lower scope assignments override higher scope
  • Use exemptions to resolve legitimate conflicts

Compliance showing incorrect state:

  • Trigger policy evaluation refresh
  • Check if resource type is supported by policy
  • Verify policy definition logic is correct

Next Steps

After implementing Azure Policy, enhance your governance:

  • Implement Azure Blueprints for environment templates
  • Configure Privileged Identity Management for admin access
  • Enable Microsoft Defender for Cloud regulatory compliance
  • Review Cloud Security Tips for 2026 for comprehensive cloud security guidance

Frequently Asked Questions

Find answers to common questions

Azure RBAC controls who can perform actions on Azure resources (identity-based access control). Azure Policy controls what properties resources can have (resource configuration control). RBAC answers "Can this user create a VM?" while Policy answers "Must this VM use managed disks?" Use both together: RBAC restricts who can deploy, Policy ensures what's deployed meets standards.

Azure Infrastructure Experts

Comprehensive Azure management including architecture, migration, security, and 24/7 operations.