AZ-104 · Manage Azure identities and governance · Updated August 7, 2026
Azure Policy vs. Azure RBAC: Controlling Who Can Act vs. What State Resources Must Be In
Azure RBAC and Azure Policy get confused constantly because both sit in the governance space and both apply at management group, subscription, resource group, or resource scope with downward inheritance. But they answer two different questions. RBAC answers “who is allowed to perform this action?” Policy answers “does this resource’s configuration meet our standard, regardless of who created it?” A user can have every RBAC permission in the world to create a public storage account and still get blocked, because Policy evaluates the resulting resource state independently of the identity that requested it.
What Azure RBAC controls
Azure RBAC is an identity-focused authorization system. It evaluates a security principal (user, group, service principal, or managed identity), a role definition, and a scope, and decides whether that principal may take a given action, like creating a virtual machine, deleting a storage account, or reading a key vault’s configuration. RBAC has no opinion about the resource’s properties once the action is allowed. If a Contributor can create storage accounts, RBAC doesn’t care whether that account ends up with public blob access enabled, uses TLS 1.2, or sits in an approved region. That’s not RBAC’s job.
What Azure Policy controls
Azure Policy is a resource-state enforcement system. It evaluates resource properties, described in JSON policy definitions, against business rules, and applies those rules regardless of who is making the request or what RBAC permissions they hold. Policy answers questions like: is public network access disabled on this storage account? Is this VM SKU on the approved list? Does this resource carry the required cost-center tag? Even a Global Administrator with Owner everywhere in the tenant can have a resource creation blocked by Policy, because Policy checks the resource, not the identity, by default.
Policy does have one identity-aware capability worth knowing: policy rules can inspect requestContext().identity to decide based on who is making a request, such as blocking a delete unless it comes from an MFA-verified user, or exempting a specific security group from an otherwise universal restriction. That blurs the line slightly, but the core design holds: Policy exists to guarantee resource state, and only secondarily touches identity as one more inspectable property.
Azure Policy vs. Azure RBAC, side by side
| Azure RBAC | Azure Policy | |
|---|---|---|
| Answers | Who can perform this action? | Is this resource’s state compliant? |
| Evaluates | The requesting security principal | The resource’s properties (and optionally the requester’s identity) |
| Applies even to Owners/Admins | No (Owners can do anything RBAC allows) | Yes (Policy enforces regardless of RBAC permission level) |
| Managed through | Azure Resource Manager role assignments | JSON policy definitions and assignments |
| Combines multiple rules | Additively (sum of role assignments) | Cumulative most restrictive (any deny blocks) |
| Typical unit of work | Role assignment | Policy definition, grouped into an initiative |
Policy effects: what happens when a rule is triggered
Every policy definition has exactly one effect in its policy rule, and the effect determines what happens on evaluation. The effects that come up most on the exam:
- Deny: blocks the create or update request outright; the resource is never created in a non-compliant state.
- Audit: lets the request proceed but logs the resource as non-compliant on the compliance dashboard.
- AuditIfNotExists: audits based on whether a related child or extension resource exists, rather than the resource’s own properties (for example, flagging a VM missing a monitoring extension).
- Append: adds fields or properties to the request as it’s created or updated, such as forcing a network setting, without blocking it.
- Modify: adds, updates, or removes properties or tags on a resource, and can update existing resources through remediation, using a managed identity.
- DeployIfNotExists: triggers a related deployment when a resource lacks an associated compliant resource, such as auto-deploying a monitoring extension after a VM is created.
- Disabled: turns the policy rule off without deleting the assignment, useful for testing.
A practical progression teams follow: start a new policy with Audit to see its real-world impact without breaking anything, confirm the compliance results look right, then tighten it to Deny (or DeployIfNotExists/Modify for auto-remediation) once you trust it.
When multiple policy assignments with different effects apply to overlapping scopes, the outcome is cumulative and most restrictive. If any applicable assignment says Deny, the resource is blocked, even if a separate assignment at a narrower scope would have allowed it, unless that narrower scope is explicitly excluded from the broader assignment.
Initiatives: grouping policies toward one goal
An initiative (also called a policy set) bundles multiple related policy definitions under a single assignment, aimed at one overarching goal, such as “Enable Monitoring in Microsoft Defender for Cloud.” Instead of managing dozens of individual policies, you assign the initiative once and every policy inside it gets evaluated together. Initiatives also let you add a new policy definition to the group later without creating a new assignment to track. Best practice is to build and assign initiatives even for a single starting policy, since that leaves room to grow it later without multiplying assignments.
Exemptions: excluding a resource without weakening the rule
An exemption is a formal, auditable carve-out that excuses a specific resource or resource hierarchy from one or more policy or initiative assignments, without deleting or narrowing the assignment itself. Exempt resources still count toward overall compliance reporting; they’re just not evaluated, or their non-compliance is accepted, for the duration of the exemption. Exemptions fall into two categories:
- Waiver: the non-compliant state is temporarily accepted, often because a resource is scheduled for deletion or a fix is already planned.
- Mitigated: the intent of the policy is actually satisfied through some other control, so continued flagging would be a false positive.
Exemptions can carry an expiration date, and creating one requires both write access on the target resource and the exempt/Action permission on the assignment, a deliberately higher bar than an ordinary RBAC write.
When to reach for RBAC, Policy, or both
- Restricting who can delete production resources → RBAC. Assign a narrower role, or a deny assignment, to the group that shouldn’t have delete rights. A resource lock can back this up by blocking deletes regardless of role.
- Guaranteeing every storage account disables public blob access, no matter who creates it → Policy, with a Deny or DeployIfNotExists effect, since RBAC can’t inspect the resulting configuration.
- Letting a team deploy VMs, but only in an approved region from an approved SKU list → both. RBAC grants Contributor so the team can act; Policy constrains what “acting” is allowed to produce.
- Auto-tagging every new resource with a cost center → Policy with a Modify or Append effect; RBAC has no mechanism to alter resource properties on creation.
- Letting security review a subscription without changing anything → RBAC, with Reader.
The two systems are complementary, not substitutable. A tenant using only RBAC has no way to stop a fully authorized Contributor from creating a non-compliant resource. A tenant using only Policy has no way to prevent an unauthorized user from attempting the action; it can only catch or block the resulting state. Mature Azure governance uses RBAC to gate who can act and Policy to guarantee what they’re allowed to produce.
How the AZ-104 exam tests this
- The “even the admin got blocked” scenario. A stem describes an Owner or Contributor whose deployment fails despite full RBAC rights. The explanation is almost always a Deny-effect policy evaluating resource state, not an RBAC gap.
- The effect-selection question. A stem needs a missing tag added automatically, or a monitoring extension deployed automatically, and asks which effect fits. Append/Modify handles tag and property changes; DeployIfNotExists triggers a companion deployment.
- The audit-vs-deny rollout pattern. A stem describes rolling out a new governance rule cautiously to measure impact before enforcing it. That’s Audit before Deny, not the reverse.
- The “exclude one resource without changing the rule for everyone else” scenario. That’s a policy exemption, scoped to the specific resource, not an edit to the assignment.
- The RBAC-vs-Policy discrimination itself. Any stem contrasting “who can perform an action” against “what state a resource must be in” tests whether you can tell the two systems apart at a glance.
Pairing this with Azure RBAC built-in roles and the Azure resource hierarchy covers how both systems inherit through the same scope structure, just for different purposes.