Azure Policy and Governance
Azure Policy enforces organizational standards and compliance at scale — automatically preventing or auditing resources that don’t meet your rules. Combined with management groups, resource locks, and tagging, it forms Azure’s governance framework.
Why Governance?
Section titled “Why Governance?”Without governance, cloud environments drift:
- Developers create VMs without encryption.
- Resources are created in unapproved regions.
- Tags are missing, making cost attribution impossible.
- Public endpoints are exposed accidentally.
Governance automates enforcement so you don’t rely on people remembering the rules.
Azure Policy
Section titled “Azure Policy”Azure Policy evaluates resources against rules and either prevents non-compliant resources from being created or reports on existing non-compliance.
How It Works
Section titled “How It Works”Resource creation/update │ ▼Azure Policy evaluates rules │ ├── Compliant ──► Allowed │ └── Non-compliant ├── Deny ──► Blocked (resource not created) ├── Audit ──► Allowed but flagged in compliance dashboard ├── Modify ──► Automatically fix (e.g. add missing tag) └── DeployIfNotExists ──► Deploy a resource to remediatePolicy Definition
Section titled “Policy Definition”A policy definition is a JSON rule:
{ "mode": "Indexed", "policyRule": { "if": { "allOf": [ { "field": "type", "equals": "Microsoft.Compute/virtualMachines" }, { "field": "Microsoft.Compute/virtualMachines/storageProfile.osDisk.managedDisk", "exists": "false" } ] }, "then": { "effect": "deny" } }}This denies creating VMs without managed disks.
Policy Effects
Section titled “Policy Effects”| Effect | What It Does | Use Case |
|---|---|---|
| Deny | Block resource creation/update | Hard enforcement (must comply) |
| Audit | Allow but flag as non-compliant | Soft enforcement (report only) |
| Modify | Auto-modify resource properties | Add missing tags, enable encryption |
| DeployIfNotExists | Deploy a related resource if missing | Auto-enable diagnostics, install agents |
| Append | Add fields to a resource | Add required tags on creation |
| Disabled | Policy exists but doesn’t evaluate | Temporarily disable a policy |
Built-In Policies (Examples)
Section titled “Built-In Policies (Examples)”Azure provides 700+ built-in policies:
| Policy | Effect | What It Enforces |
|---|---|---|
| Allowed locations | Deny | Resources can only be created in approved regions |
| Require tag on resources | Deny | Every resource must have specific tags |
| Storage accounts should use private link | Audit | Flag storage accounts without private endpoints |
| VMs should use managed disks | Deny | Block VMs with unmanaged disks |
| SQL databases should have TDE enabled | Audit | Flag SQL DBs without encryption |
| Kubernetes clusters should not allow privileged containers | Deny | Block privileged pods in AKS |
Assigning a Policy
Section titled “Assigning a Policy”# Assign a built-in policy: "Allowed locations"az policy assignment create \ --name "allowed-locations" \ --display-name "Restrict to US and EU regions" \ --policy "/providers/Microsoft.Authorization/policyDefinitions/e56962a6-4747-49cd-b67b-bf8b01975c4c" \ --params '{"listOfAllowedLocations": {"value": ["eastus", "eastus2", "westeurope", "northeurope"]}}' \ --scope "/subscriptions/<subscription-id>"
# Assign to a resource group (narrower scope)az policy assignment create \ --name "require-env-tag" \ --display-name "Require Environment tag" \ --policy "/providers/Microsoft.Authorization/policyDefinitions/871b6d14-10aa-478d-b466-ef6698cc4b60" \ --params '{"tagName": {"value": "Environment"}}' \ --scope "/subscriptions/<sub>/resourceGroups/myapp-prod-rg"Policy Initiatives (Policy Sets)
Section titled “Policy Initiatives (Policy Sets)”An initiative groups multiple policies together:
# Assign a built-in initiative: "Azure Security Benchmark"az policy assignment create \ --name "security-benchmark" \ --display-name "Azure Security Benchmark" \ --policy-set-definition "/providers/Microsoft.Authorization/policySetDefinitions/1f3afdf9-d0c9-4c3d-847f-89da613e70a8" \ --scope "/subscriptions/<subscription-id>"Common built-in initiatives:
- Azure Security Benchmark — Comprehensive security controls.
- CIS Microsoft Azure Foundations — CIS benchmark compliance.
- ISO 27001 — Information security standard.
- NIST SP 800-53 — US federal security controls.
Custom Policy Example: Require Tags
Section titled “Custom Policy Example: Require Tags”{ "mode": "Indexed", "policyRule": { "if": { "anyOf": [ { "field": "tags['Environment']", "exists": "false" }, { "field": "tags['Team']", "exists": "false" }, { "field": "tags['CostCenter']", "exists": "false" } ] }, "then": { "effect": "deny" } }}Remediation
Section titled “Remediation”For policies with Modify or DeployIfNotExists effects, remediation tasks fix existing non-compliant resources:
# Create a remediation taskaz policy remediation create \ --name "add-missing-tags" \ --policy-assignment "require-env-tag" \ --resource-group myapp-rgCompliance Dashboard
Section titled “Compliance Dashboard”The Azure portal shows compliance status across all assignments:
Overall Compliance: 87%
Policy Compliant Non-compliantAllowed locations 145 0Require Environment tag 120 25VMs must use managed disks 98 3Storage must use private endpoint 45 12Management Groups
Section titled “Management Groups”Management groups organize subscriptions into a hierarchy for applying policies and RBAC at scale:
Root Management Group ├── Production MG │ ├── Subscription: prod-app │ └── Subscription: prod-data ├── Development MG │ ├── Subscription: dev-app │ └── Subscription: sandbox └── Platform MG └── Subscription: shared-servicesPolicies and RBAC assigned to a management group inherit down to all child subscriptions and resources.
# Create a management groupaz account management-group create --name "Production" --display-name "Production"
# Move a subscription under itaz account management-group subscription add \ --name "Production" \ --subscription <subscription-id>
# Assign a policy to the management groupaz policy assignment create \ --name "prod-allowed-locations" \ --policy "/providers/Microsoft.Authorization/policyDefinitions/e56962a6-..." \ --scope "/providers/Microsoft.Management/managementGroups/Production" \ --params '{"listOfAllowedLocations": {"value": ["eastus", "westeurope"]}}'Resource Locks
Section titled “Resource Locks”Resource locks prevent accidental deletion or modification — even by Owners:
| Lock Level | Prevents |
|---|---|
| CanNotDelete | Deletion (modification allowed) |
| ReadOnly | All changes (read-only, no writes or deletes) |
# Lock a production resource groupaz lock create \ --name "protect-prod" \ --resource-group myapp-prod-rg \ --lock-type CanNotDelete \ --notes "Prevent accidental deletion of production resources"
# Lock a specific resourceaz lock create \ --name "protect-db" \ --resource-group myapp-prod-rg \ --resource-type Microsoft.Sql/servers \ --resource-name my-sql-server \ --lock-type CanNotDeleteTo delete a locked resource, you must remove the lock first — this is intentionally a deliberate action.
Tagging Strategy
Section titled “Tagging Strategy”Tags are critical for cost management, governance, and automation:
Required Tags
Section titled “Required Tags”| Tag | Purpose | Example Values |
|---|---|---|
Environment | Which environment | production, staging, development |
Team | Owning team | platform, backend, data |
CostCenter | Budget category | engineering, marketing |
Application | Application name | web-portal, api-service |
ManagedBy | How it was created | terraform, bicep, manual |
Enforcing Tags
Section titled “Enforcing Tags”- Azure Policy — Deny resources without required tags.
- Modify policy — Auto-add tags (e.g. inherit resource group tags).
- Terraform —
default_tagsin the Azure provider.
Tag Inheritance Policy
Section titled “Tag Inheritance Policy”Auto-inherit a tag from the resource group:
{ "mode": "Indexed", "policyRule": { "if": { "allOf": [ { "field": "tags['Environment']", "exists": "false" }, { "value": "[resourceGroup().tags['Environment']]", "notEquals": "" } ] }, "then": { "effect": "modify", "details": { "roleDefinitionIds": ["/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c"], "operations": [{ "operation": "addOrReplace", "field": "tags['Environment']", "value": "[resourceGroup().tags['Environment']]" }] } } }}Azure Blueprints
Section titled “Azure Blueprints”Blueprints package policies, RBAC assignments, ARM templates, and resource groups into a deployable definition — useful for setting up new subscriptions consistently.
Blueprint: "Production Subscription" ├── Policy: Allowed locations (US + EU) ├── Policy: Require tags ├── RBAC: Reader for audit team ├── Resource Group: networking-rg │ └── ARM template: VNet + NSGs └── Resource Group: monitoring-rg └── ARM template: Log Analytics workspaceNote: Microsoft is deprecating Blueprints in favor of deployment stacks and template specs combined with policy. For new setups, use Azure Policy + Bicep/Terraform.
Governance Best Practices
Section titled “Governance Best Practices”| Practice | How |
|---|---|
| Start with Audit, then Deny | Deploy policies in Audit mode first; review compliance; switch to Deny |
| Use management groups | Apply policies at the MG level for consistent enforcement across subscriptions |
| Enforce tags via policy | Don’t rely on humans — automate tag requirements |
| Lock production resources | CanNotDelete locks on databases, storage, and critical infrastructure |
| Use initiatives | Group related policies (e.g. “Security Baseline”) for easier management |
| Remediate existing resources | Run remediation tasks for Modify/DeployIfNotExists policies |
| Review compliance regularly | Dashboard → fix non-compliant resources → tighten policies |
Key Takeaways
Section titled “Key Takeaways”- Azure Policy enforces rules on resource creation and configuration — Deny (block), Audit (report), Modify (auto-fix).
- Initiatives group related policies (security baselines, compliance standards) for easier assignment.
- Management groups organize subscriptions into a hierarchy for policy and RBAC inheritance.
- Resource locks prevent accidental deletion of critical resources.
- Tags are enforced via policy — require Environment, Team, and CostCenter on every resource.
- Start with Audit mode, review compliance, then switch to Deny once you’re confident.