← Back to Demo

Azure Policy at Scale — Modify, Audit, Deny, Remediate

The Microsoft Build 2026 refresh frames the SPA as an Azure governance operations dashboard. It shows how a platform team manages 29 active assignments across modify, audit, deny, and DeployIfNotExists effects; uses non-blocking tag governance as the default pattern; runs remediation tasks to back-fill drift; and protects production changes through time-bound Privileged Identity Management rather than standing administrator access.
29
Assignments
Modify-First
Default Governance
Tags
Cost & Owner Signals
Drift
Remediation Queue
Define→ Assign→ Evaluate→ Remediate→ Audit

1. Effects: Audit vs Modify vs Deny vs DeployIfNotExists

Azure Policy effect choice is the architecture decision behind every governance rule. The SPA intentionally exposes effect next to scope and compliance because an enterprise policy program cannot be judged by assignment count alone. A safe rollout usually starts with audit, graduates routine metadata to modify, reserves deny for high-confidence guardrails, and uses DeployIfNotExists when missing platform plumbing must be deployed after evaluation.

This effect model mirrors the operating runbook mindset: identify the failing control, check identity and scope, remediate the resource or assignment, then document the outcome. Policy is not a static catalog. It is a closed-loop system that needs owners, evidence, escalation paths, and a clear line between non-blocking hygiene and hard safety boundaries.

EffectBehaviorBest Use CaseOperational Watchout
AuditRecords non-compliance without blocking create or update operationsDiscovery, baseline measurement, pilot rollout, and standards that still need evidenceMust feed a review queue or it becomes background noise
ModifyAdds, replaces, or normalizes fields during a deployment or remediation taskTags, inherited metadata, diagnostic defaults, and safe resource propertiesRequires a managed identity and clear documentation of what was changed
DenyRejects non-compliant requests before deployment completesPublic exposure, disallowed locations, weak encryption, and other hard guardrailsCan block delivery if exemptions and migration windows are not ready
DeployIfNotExistsChecks for a related resource or setting and deploys it when missingMonitoring agents, diagnostic settings, flow logs, and required platform attachmentsMore moving parts: assignment identity, role grants, templates, and remediation status

Assignment Categories Shown in the Dashboard

CategorySanitized CountPrimary EffectExample Control
Tagging and ownership8ModifyApply CostCenter, Environment, Owner, and Project tags from subscription or resource group context
Security baseline7Deny / AuditRequire secure transfer, TLS posture, soft delete, and restricted public access
Monitoring and diagnostics6DeployIfNotExistsDeploy diagnostic settings, agents, or flow logs where they are missing
Network governance4Audit / DenyFlag missing private endpoint patterns or prevent unsafe ingress defaults
Cost and platform standards4Audit / ModifyCheck CAF naming, required metadata, and environment classification

2. The Tagging Governance Pattern (modify-effect, non-blocking)

The most important design choice in the refreshed article is the modify-first tagging pattern. Required tags are governance inputs: they connect resources to owners, budget centers, environments, projects, and incident routing. Blocking every deployment that misses a tag creates friction; modifying safe metadata in-flight makes the paved road easier to use while still improving reporting quality.

The dashboard treats tag governance as a platform service. A policy assignment can inherit a default from the resource group, normalize casing, or add a placeholder value that routes back to a remediation queue. That keeps delivery moving, but it also makes drift visible. The owner still needs to clean up inaccurate values; policy simply prevents missing metadata from becoming invisible technical debt.

// Modify-effect policy rule sketch for required ownership metadata { "if": { "allOf": [ { "field": "type", "notEquals": "Microsoft.Resources/subscriptions/resourceGroups" }, { "field": "tags['CostCenter']", "exists": false } ] }, "then": { "effect": "modify", "details": { "roleDefinitionIds": [ "/providers/Microsoft.Authorization/roleDefinitions/<tag-contributor-role-id>" ], "operations": [ { "operation": "add", "field": "tags['CostCenter']", "value": "[resourceGroup().tags['CostCenter']]" } ] } } }
The public pattern is the point: inherit safe metadata when possible, avoid logging sensitive values, and use placeholders for tenant IDs, subscription IDs, role definition IDs, and assignment identifiers in external documentation.

3. Policy as Code (Bicep policy definitions, deployment via stacks)

At scale, a policy definition should not be a portal-only artifact. The article positions policy as code: definitions, initiatives, assignments, parameters, and managed identities are reviewed, deployed, and versioned through infrastructure stacks. That gives policy changes the same discipline as any other production control: pull request review, environment parameters, repeatable deployment, and rollback history.

Bicep is a natural fit for the definition and assignment layer. A stack can publish a custom policy definition, assign it at a management group or subscription scope, grant the assignment identity only the permissions needed for remediation, and expose environment-specific parameters without embedding tenant-specific IDs in the source. That makes the dashboard's numbers reproducible without leaking implementation details.

Policy-as-Code Deployment Shape

targetScope = 'managementGroup' param assignmentScope string = '/providers/Microsoft.Management/managementGroups/<mg-name>' param requiredTags array = [ 'CostCenter', 'Environment', 'Owner', 'Project' ] resource tagPolicy 'Microsoft.Authorization/policyDefinitions@2023-04-01' = { name: 'modify-required-tags' properties: { policyType: 'Custom' mode: 'Indexed' displayName: 'Modify required resource tags' metadata: { category: 'Tag Governance' } parameters: { requiredTags: { type: 'Array' } } policyRule: loadJsonContent('policyRules/modify-required-tags.json') } } resource assignment 'Microsoft.Authorization/policyAssignments@2024-04-01' = { name: 'tag-governance-modify' scope: managementGroup('<mg-name>') identity: { type: 'SystemAssigned' } properties: { displayName: 'Tag governance — modify required tags' policyDefinitionId: tagPolicy.id parameters: { requiredTags: { value: requiredTags } } enforcementMode: 'Default' } }

Deployment stacks add lifecycle clarity. They make it easier to understand which environment owns the current assignment, whether a change is idempotent, and how to remove a deprecated assignment without leaving orphaned definitions or unmanaged role grants behind.

4. Exemptions: When and Why (request, approve, time-box)

Exemptions are not exceptions to governance; they are governed records that explain why a resource or scope is temporarily outside the standard. A healthy exemption flow starts with a request, captures business justification, assigns an approver role, records an expiration date, and keeps the remediation owner visible. The article uses role labels instead of named owners so the public version demonstrates the pattern without exposing internal accountability data.

Use exemptions when a control is correct but immediate enforcement would create unacceptable business risk: legacy migration windows, vendor constraints, emergency incident response, or platform dependencies that are being remediated in phases. Avoid permanent exemptions. If an exemption never expires, the policy is either too broad, the exception is actually a standard, or the owning team needs a migration plan.

Exemption ScenarioRequesterApproverTime BoxEvidence Required
Legacy workload migrationApplication owner rolePlatform governance role30–90 daysMigration ticket, target design, and review date
Emergency incident responseIncident commander roleSecurity operations roleHours to daysIncident number, impact statement, and post-incident cleanup notes
Vendor limitationService owner roleArchitecture review roleOne renewal cycleVendor documentation and compensating control
Staged deny rolloutSubscription owner roleCloud platform roleUntil rollout milestoneAudit results, communication plan, and enforcement date

5. Remediation Tasks (back-filling non-compliant resources)

Modify and DeployIfNotExists policies only change new or updated resources automatically. Existing resources need remediation tasks to back-fill the estate. That is why the SPA's compliance score should be read as an operations queue: identify the non-compliant set, verify the assignment identity has the required role, run remediation in a controlled scope, and monitor completion before escalating residual failures.

The runbook pattern applies here too. Start with the failing control, check permissions, confirm the target scope, execute the repair, then document what changed. If a remediation task fails, common causes include missing managed identity permissions, resources locked by deployment policy, unsupported resource types, or stale exemptions that need review.

Remediation Control Loop

Evaluate → query compliance state by assignment and scope Authorize → verify assignment identity has the minimum remediation role Remediate → create remediation task for the targeted policy assignment Monitor → track succeeded, failed, and skipped resources Document → record outcome, residual risk, and next review date

For public examples, use generic assignment names such as tag-governance-modify, placeholder scopes such as /subscriptions/<subscription-id>, and role labels instead of named exemption owners. Microsoft Learn URLs can remain exact because they are public documentation references.

6. JIT Access via PIM (eligible vs active assignments, time-bound elevation)

Policy operations sometimes require elevated access: creating a remediation task, changing an assignment, or approving a short-lived exemption. The refreshed article connects those tasks to just-in-time access through Microsoft Entra Privileged Identity Management. Eligible assignment means a user or group can request access; active assignment means the access is currently usable and will expire automatically after the approved duration.

The public pattern is intentionally generic. A production operations group is eligible for the minimum role needed, activates through My Access or the Azure PIM portal, enters a ticket-backed justification, waits for propagation, completes the operation, and lets access expire. The same pattern works for emergency changes and planned maintenance: no standing human access, time-bound elevation, and a written trail of why the access was used.

PIM StateMeaningUsed ForGovernance Requirement
EligibleThe role can be activated, but it is not currently granting accessPrepared operators, break-glass groups, and approval-based access packagesMembership review, MFA, and clear activation policy
ActiveThe role is currently effective for a bounded durationPolicy assignment updates, remediation tasks, incident repair, and verificationTicket justification, shortest practical duration, and activity logging
ExpiredThe activation window ended automaticallyNormal post-change stateNo manual cleanup required unless early deactivation is needed
Denied or missingThe principal has no eligible assignment or approval failedTroubleshooting access requestsRoute to the access owner role; do not bypass PIM with standing permissions
The article deliberately avoids tenant IDs, group object IDs, named users, and workspace identifiers. Use placeholders like <tenant-id>, <group-id>, <workspace-id>, and <ticket-id> when documenting the public Build 2026 pattern.