Azure Policy for Security Compliance Automation
- 2 days ago
- 4 min read
Managing security compliance across Azure environments manually doesn't scale. I've seen too many organisations rely on periodic audits and spreadsheets to track security configurations, only to discover drift during incidents or compliance reviews. Azure Policy provides the automation framework to enforce security baselines, detect configuration drift, and remediate non-compliant resources before they become problems.
This post walks through implementing Azure Policy for security compliance automation, from initial policy assignment through automated remediation. We'll cover built-in security policies, custom policy creation, and integration with Microsoft Defender for Cloud recommendations.
Prerequisites
Azure subscription with Owner or Policy Contributor role at the appropriate scope
Azure CLI installed (version 2.50 or later)
Basic understanding of Azure Resource Manager and JSON syntax
Microsoft Defender for Cloud enabled (for integration scenarios)
Step 1 – Assess Current Compliance Posture
Before deploying policies, understand what you're working with. Start by reviewing existing policy assignments and compliance state.
# List current policy assignments at subscription scope
az policy assignment list --scope "/subscriptions/<subscription-id>" --output table
# Check overall compliance state
az policy state summarize --scope "/subscriptions/<subscription-id>"Pay attention to inherited policies from management groups. I've seen environments where conflicting policies at different scopes create confusion and block legitimate deployments.
Step 2 – Assign Built-In Security Policies
Microsoft provides comprehensive built-in policies aligned with security frameworks. The Azure Security Benchmark initiative is your starting point for foundational security controls.
# Assign Azure Security Benchmark initiative
az policy assignment create \
--name "ASB-Assignment" \
--display-name "Azure Security Benchmark" \
--policy-set-definition "/providers/Microsoft.Authorization/policySetDefinitions/1f3afdf9-d0c9-4c3d-847f-89da613e70a8" \
--scope "/subscriptions/<subscription-id>" \
--location "uksouth" \
--assign-identity \
--identity-scope "/subscriptions/<subscription-id>" \
--role "Contributor"The --assign-identity flag creates a managed identity for remediation tasks. Without this, policies can only audit compliance, not enforce or remediate configurations.
Step 3 – Create Custom Security Policy
Built-in policies cover common scenarios, but every environment has specific requirements. Here's a custom policy that enforces diagnostic settings on Azure Key Vaults to send logs to a specific Log Analytics workspace.
Create a policy definition file keyvault-diagnostics-policy.json:
{
"mode": "All",
"policyRule": {
"if": {
"field": "type",
"equals": "Microsoft.KeyVault/vaults"
},
"then": {
"effect": "deployIfNotExists",
"details": {
"type": "Microsoft.Insights/diagnosticSettings",
"roleDefinitionIds": [
"/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c"
],
"existenceCondition": {
"allOf": [
{
"field": "Microsoft.Insights/diagnosticSettings/logs[*].enabled",
"equals": "true"
},
{
"field": "Microsoft.Insights/diagnosticSettings/workspaceId",
"equals": "[parameters('workspaceId')]"
}
]
},
"deployment": {
"properties": {
"mode": "incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"resourceName": {
"type": "string"
},
"workspaceId": {
"type": "string"
}
},
"resources": [
{
"type": "Microsoft.KeyVault/vaults/providers/diagnosticSettings",
"apiVersion": "2021-05-01-preview",
"name": "[concat(parameters('resourceName'), '/Microsoft.Insights/setByPolicy')]",
"properties": {
"workspaceId": "[parameters('workspaceId')]",
"logs": [
{
"category": "AuditEvent",
"enabled": true
}
]
}
}
]
},
"parameters": {
"resourceName": {
"value": "[field('name')]"
},
"workspaceId": {
"value": "[parameters('workspaceId')]"
}
}
}
}
}
}
},
"parameters": {
"workspaceId": {
"type": "String",
"metadata": {
"displayName": "Log Analytics Workspace ID",
"description": "The workspace ID for the Log Analytics workspace to send diagnostics to"
}
}
}
}Deploy the custom policy:
# Create custom policy definition
az policy definition create \
--name "enforce-keyvault-diagnostics" \
--display-name "Enforce Key Vault Diagnostic Settings" \
--description "Ensures all Key Vaults send audit logs to designated Log Analytics workspace" \
--rules keyvault-diagnostics-policy.json \
--mode All
# Assign the custom policy
az policy assignment create \
--name "keyvault-diagnostics-assignment" \
--policy "enforce-keyvault-diagnostics" \
--scope "/subscriptions/<subscription-id>" \
--params '{"workspaceId":{"value":"/subscriptions/<sub-id>/resourceGroups/<rg>/providers/Microsoft.OperationalInsights/workspaces/<workspace-name>"}}' \
--assign-identity \
--identity-scope "/subscriptions/<subscription-id>" \
--role "Contributor" \
--location "uksouth"Step 4 – Configure Automated Remediation
Policies with deployIfNotExists or modify effects can automatically remediate non-compliant resources. Create a remediation task for existing resources that violate the policy.
# Create remediation task for the Key Vault diagnostics policy
az policy remediation create \
--name "keyvault-diagnostics-remediation" \
--policy-assignment "keyvault-diagnostics-assignment" \
--resource-discovery-mode "ReEvaluateCompliance"Monitor remediation progress:
# Check remediation status
az policy remediation show \
--name "keyvault-diagnostics-remediation" \
--namespace "Microsoft.PolicyInsights"Step 5 – Monitor Compliance with KQL
Integrate policy compliance data into Sentinel or Log Analytics workbooks for continuous monitoring. Policy compliance events flow into the AzureActivity and PolicyInsights tables.
PolicyInsights
| where TimeGenerated > ago(24h)
| where ComplianceState == "NonCompliant"
| summarize NonCompliantResources = dcount(ResourceId) by PolicyDefinitionName, PolicyAssignmentName
| order by NonCompliantResources descFor deeper analysis, join with resource metadata:
PolicyInsights
| where ComplianceState == "NonCompliant"
| join kind=leftouter (
Resources
| project ResourceId = tolower(id), ResourceGroup = resourceGroup, Location = location, Tags = tags
) on ResourceId
| project TimeGenerated, PolicyDefinitionName, ResourceId, ResourceGroup, Location, ComplianceStateTroubleshooting
Policy assignment succeeds but resources remain non-compliant
Check the managed identity has sufficient permissions. The identity scope must cover all resources the policy applies to, and the role must include write permissions for remediation actions.
# Verify managed identity role assignments
az role assignment list --assignee <managed-identity-object-id> --output tableRemediation tasks fail silently
Review the Activity Log for detailed error messages. Most remediation failures relate to resource locks, insufficient permissions, or dependencies on other resources.
# Query Activity Log for policy remediation events
az monitor activity-log list \
--namespace "Microsoft.PolicyInsights" \
--offset 24h \
--query "[?contains(operationName.value, 'remediation')]"Compliance evaluation delays
Policy compliance scans run approximately every 24 hours. For immediate evaluation after policy changes, trigger an on-demand scan:
# Trigger compliance scan
az policy state trigger-scan --no-waitHardening Considerations
Implement Policy Exemptions Carefully
Use policy exemptions for legitimate exceptions, but track them rigorously. I recommend creating a governance process that requires justification and periodic review.
# Create time-limited exemption
az policy exemption create \
--name "temp-exemption-migration" \
--policy-assignment "ASB-Assignment" \
--exemption-category "Waiver" \
--expires-on "2024-12-31" \
--description "Temporary exemption during migration project"Separate Audit and Enforce Phases
Deploy new policies in audit mode first. Monitor compliance trends for 1-2 weeks before switching to enforce mode. This prevents blocking legitimate workloads due to edge cases you didn't anticipate.
Integrate with Defender for Cloud
Link custom policies to Defender for Cloud recommendations using the securityCenter category in policy metadata. This surfaces your custom controls alongside Microsoft's built-in recommendations.
Version Control Policy Definitions
Store custom policy definitions in Git alongside your infrastructure-as-code. Use CI/CD pipelines to deploy policy changes, not manual updates through the portal.


Comments