Choosing Between Azure Policy and RBAC for Governance
Azure Policy and Azure RBAC get reached for in the same conversations, often for the same problem, but they're not interchangeable — they govern two different things, and knowing which one actually applies to a given requirement is what keeps a governance design from accumulating redundant or conflicting controls.
What each one actually governs
Azure Policy ensures a resource's state complies with organisational rules, regardless of who made the change or whether they had permission to make it — it evaluates the resource itself and acts to keep it compliant. Azure RBAC, by contrast, focuses on user actions: who can access which resources, what they're allowed to do with them, and which scopes they can reach. If the question is "should this person be able to do this," that's RBAC. If the question is "should this resource be allowed to exist in this state," that's Policy — and a user having RBAC permission to perform an action doesn't override Policy; if the result would be a non-compliant resource, Policy still blocks it.
| Azure Policy | Azure RBAC | |
|---|---|---|
| Description | Enforces that resources comply with a set of rules | Authorisation system providing fine-grained access control |
| Main focus | The properties of resources | What resources a user can access |
| Implementation | Specify a set of rules | Assign roles and scopes |
| Default access | Allow, unless a policy says otherwise | Deny, unless a role assignment says otherwise |
That last row is worth sitting with: Policy is opt-out (nothing is restricted until a rule says so) while RBAC is opt-in (nothing is accessible until a role says so) — the two systems start from opposite defaults, which is part of why they're not substitutes for each other.
Designing with Azure Policy
Beyond individual policies, Azure Policy lets you group related definitions into initiatives, and policies are inherited down the organisational hierarchy — scoped and enforced at whichever level (management group, subscription, resource group, resource) actually matches the requirement. Evaluation isn't limited to native Azure resources either: Azure Arc-enabled resources hosted outside Azure are evaluated the same way, which is what makes Policy usable as a governance layer across hybrid and multicloud estates, not just within Azure itself.
Policy also integrates directly into deployment pipelines — Azure Pipelines can apply policy checks pre- and post-deployment, catching non-compliance before it ships rather than after. And the compliance dashboard isn't just a read-only report: it supports bulk remediation for resources that are already non-compliant and automatic remediation for newly created or updated ones, which matters most for anything you'd rather fix automatically than track manually — tagging is the clearest example, where Policy can apply a required tag and reapply it if someone removes it, rather than relying on someone noticing the drift.
Deciding how to actually handle non-compliance is a real design choice, not a default: deny the change outright, log it without blocking anything, alter the resource before or after the change takes effect, or deploy an additional compliant resource alongside it. Which one fits depends on how disruptive blocking the action would be versus how much drift is acceptable in the meantime.
Designing with Azure RBAC
Typical RBAC requirements look like: one user manages virtual machines in a subscription while another manages virtual networks; a database administration group manages every Azure SQL Database instance in a subscription; a user manages every resource in a resource group; an application needs access to every resource in a resource group. Each of these maps to a role definition (the permissions), a role assignment (who gets them), and a scope (where they apply) — the design work is picking the highest scope that still satisfies the requirement, since scoping too broadly grants more than necessary and scoping too narrowly means repeating the same assignment many times over.
Least privilege is the operating principle: grant the access a user actually needs to do their job, nothing more, which both separates team responsibilities cleanly and limits what's at risk if a given identity is ever compromised. Assigning roles to groups rather than individual users keeps this manageable as people join, leave, and change teams — the role assignment doesn't need to change, just group membership. Reach for a custom role only once the built-in roles genuinely don't fit; a small number of well-understood built-in roles is easier to reason about than a sprawling set of bespoke ones.
Anatomy of a custom role definition
A custom role definition's permissions are split across a few JSON fields, and it's worth being precise about which does what — mixing them up is a common source of a role that doesn't actually grant the access it was meant to.
actions control-plane operations: creating, updating, or deleting a resource through Azure Resource Manager.
notActions excludes specific control-plane operations from what actions would otherwise grant.
dataActions data-plane operations: interacting with a resource's actual data or runtime, rather than managing the resource itself.
notDataActions excludes specific data-plane operations from what dataActions would otherwise grant.
assignableScopes where the role can be assigned (management group, subscription, or resource group); it doesn't grant or restrict any permission on its own.
A concrete example of why this distinction matters: permissions like Microsoft.Compute/virtualMachines/login/action and Microsoft.Compute/virtualMachines/loginAsAdmin/action — signing in to a VM, or interacting with what's running on it — are data-plane operations, so they belong in dataActions, not actions. Putting them under actions wouldn't grant the intended access, since actions only governs management-level operations like creating or deleting the VM resource itself, not signing in to it. roleType (built-in vs. custom) is a separate, read-only classification field entirely — it doesn't influence what permissions the role grants either way.
Sources
No new external sources were used for this post — it's a reorganisation of Azure Policy and RBAC concepts already covered and sourced in the "Azure Policy fundamentals" post in this series, plus content relocated from elsewhere in the original draft (see Changelog).