Azure
RBAC, Policy and Resource Locks: How Azure Governance Fits Together
Three features that sound similar and answer completely different questions: who can act, what is allowed to exist, and what nobody should delete by accident.
Studying for AZ-900, these three kept blurring together for me. They're all about restricting things, they all get described as governance, and reading about them separately made them sound like three versions of the same feature.
They're not. Each one answers a different question, and once I had the questions straight the distinction stopped being confusing.
RBAC answers "who can do this?"
Role-Based Access Control is about identity. A person or a service gets a role, that role has permissions, and it applies at a particular scope.
The scope part is what I initially missed. A role assignment isn't global, it's attached to a level: a management group, a subscription, a resource group, or a single resource. Assign someone Contributor on a resource group and they can do contributor things to everything inside it, but nothing outside it.
Three built-in roles cover most of what you'd expect:
- Owner can do everything, including granting access to other people
- Contributor can create and manage resources, but can't grant access
- Reader can look and not touch
The Contributor and Owner distinction is the interesting one. Being able to manage every resource in a subscription and being able to hand that ability to someone else are genuinely different powers, and separating them is what makes least privilege actually workable.
Azure Policy answers "is this allowed to exist?"
Policy isn't about people at all, which is the thing that finally separated it from RBAC in my head. It evaluates resources against rules regardless of who's creating them.
An Owner has full permission to create resources. A policy that says "virtual machines may only be created in these regions" will still stop them, because the policy isn't checking permissions, it's checking the resource itself.
Typical examples: restricting which regions can be used, requiring specific tags on resources, blocking expensive VM sizes, enforcing that storage accounts require encryption.
Policy can also just report rather than block. A policy in audit mode flags resources that don't comply without preventing them, which is how you'd find out how bad an existing environment is before you start enforcing anything and breaking things.
Resource locks answer "should this be deletable?"
Locks are the simplest of the three and the one I'd have skipped as unimportant. They exist for accidents, not attackers.
Two kinds:
- CanNotDelete allows changes but blocks deletion
- ReadOnly blocks both changes and deletion
The key thing is that a lock applies to everybody, including an Owner. Someone with full permissions who runs the wrong delete command still gets stopped. Which is exactly the point, since the person most able to delete a production database by mistake is someone with permission to delete it.
To actually delete a locked resource you have to remove the lock first, deliberately, as a separate action. That extra step is the whole feature.
Why all three, and not just one
Put together, they cover failures that the others can't:
RBAC stops someone from doing something they shouldn't be able to do at all. It can't stop an authorised person from doing something authorised but wrong.
Policy stops resources that shouldn't exist in the shape they're in, no matter who creates them. It can't stop someone deleting something that already exists and is compliant.
Locks stop accidental destruction by people who genuinely do have permission. They don't restrict who has permission in the first place.
That's why they're three features rather than one. They're not layers of the same restriction, they're answers to three different ways things go wrong.
Where this connects to writing code
The least privilege idea is the same one I already apply in an application, which is what made RBAC feel familiar rather than new. A database account my API connects with shouldn't have permission to drop tables, for the same reason a developer shouldn't have Owner on a production subscription: not because I expect them to abuse it, but because the permission being there at all is what makes the accident possible.
Azure just makes it explicit, with roles and scopes you can actually inspect, instead of it living in a connection string nobody reviews.