Skip to main content

Policy Baseline

A long policy catalogue looks impressive and helps almost no one. What matters is the small set of guardrails enforced before workloads spread everywhere, while the environment is still small enough to shape. This page defines that baseline and the lifecycle that operates it.

Purpose

This page defines Azure Policy as the central governance engine for the platform — used to enforce standards, evaluate compliance, deploy supporting configuration, and remediate drift.

Design Reasoning

A good policy baseline is not a pile of individual assignments. It is packaged into initiatives, parameterized, assigned at appropriate scopes, and operated with a lifecycle.

Azure Policy effects fall into a few categories you will actually use:

  • Deny — block non-compliant create/update requests (allowed locations, public access, resource types).
  • Audit / AuditIfNotExists — report non-compliance without blocking; the safe way to measure impact first.
  • Modify / Append — adjust requests, typically to add or inherit tags.
  • DeployIfNotExists — deploy supporting configuration (diagnostic settings, agents) when it is missing.

Manual, DenyAction, and Disabled also exist; the four above cover most of a landing zone baseline. Crucially, only Modify and DeployIfNotExists support remediation — and both require a managed identity with the right permissions.

Audit before you deny

Start guardrails that could break in-flight workloads in Audit, measure the real impact, communicate required changes, and only then tighten to Deny, Modify, or DeployIfNotExists. Breaking teams is how governance loses trust permanently.

Policy exemptions must be treated as managed exceptions — each with a reason, an owner, and an expiration date — not as a quiet way to make a warning disappear.

Architecture Decision Record

DecisionChoiceRationale
Policy packagingGroup related policies into initiativesInitiatives simplify assignment, parameterization, review, and lifecycle management.
Rollout modelAudit, then enforceA staged lifecycle surfaces impact before enforcement, avoiding broken deployments and lost trust.

Tradeoff: Initiatives add a layer of indirection over individual policies. For anything beyond a handful of assignments, that indirection is what keeps the baseline reviewable.

The guardrails worth enabling first, with the effect to start from:

AreaApproachEffect
Allowed locationsInitiative parameter for permitted regionsDeny
Required tagsBuilt-in required-tag policies and tag inheritanceDeny or Modify
Public IP restrictionsBuilt-in or custom policies by resource typeDeny
Storage public accessBuilt-in storage policiesDeny
Storage secure transferBuilt-in storage policiesDeny
Diagnostic settingsInitiative using category groupsDeployIfNotExists
Resource type restrictionsBuilt-in “not allowed resource types” policyDeny
Private endpoints for sensitive servicesBuilt-in where available, custom where notAudit, then Deny or DeployIfNotExists

In a landing zone, DeployIfNotExists and Modify should deploy or adjust supporting resources and configuration — diagnostic settings, tags, agents — not full application workloads.

Example Implementation

A management-group-scoped assignment of a DeployIfNotExists initiative, with the system-assigned identity that remediation requires:

targetScope = 'managementGroup'
@description('Resource ID of the diagnostic-settings initiative to assign.')
param policyDefinitionId string
@description('Name of the policy assignment.')
param assignmentName string = 'diag-settings-baseline'
@description('Resource ID of the central Log Analytics workspace.')
param logAnalyticsId string
resource assignment 'Microsoft.Authorization/policyAssignments@2025-03-01' = {
name: assignmentName
location: 'switzerlandnorth'
identity: {
type: 'SystemAssigned'
}
properties: {
displayName: 'Deploy diagnostic settings baseline'
policyDefinitionId: policyDefinitionId
enforcementMode: 'Default'
parameters: {
logAnalytics: {
value: logAnalyticsId
}
}
}
}

The managed identity still needs a role assignment (for example, Contributor or a least-privilege custom role) at the remediation scope so it can deploy the missing configuration.

Validation Steps

Terminal window
# Assignments at the intermediate root scope
az policy assignment list \
--scope /providers/Microsoft.Management/managementGroups/contoso
# Exemptions for a subscription — every one should have an owner and expiry
az policy exemption list --scope /subscriptions/<subscription-id>
# Remediation tasks (policyinsights extension)
az policy remediation list --management-group contoso

Operate the baseline as a lifecycle:

  1. Start with Audit or AuditIfNotExists.
  2. Measure impact across the estate.
  3. Communicate the required changes.
  4. Move to Deny, Modify, or DeployIfNotExists.
  5. Create remediation tasks where needed.
  6. Review exemptions regularly.

Common Mistakes

  • Exemptions without expiration dates, which become permanent, undocumented exceptions.
  • Many individual assignments instead of initiatives, which makes the baseline unreviewable.
  • Using DeployIfNotExists to deploy workloads rather than supporting configuration.
  • Assigning policies too broadly at the tenant root.
  • Missing managed identity permissions for remediation, so remediation silently fails.
  • Leaving policies in Audit forever, which provides visibility but never a guardrail.

References