Chapter 2
Governance & access: RBAC, Policy, locks, tags and cost
Chapter 1 created the people. This chapter decides where things live (management groups, subscriptions, resource groups), who may do what (Azure RBAC), what is allowed at all (Azure Policy), how to protect resources (locks), label them (tags) and keep costs in check.
Theory
The resource hierarchy
Azure organises resources in four levels. Everything you set at a higher level β RBAC role assignments and Azure Policy assignments β is inherited by everything below it. This one idea explains a lot of exam questions.
mg-production affects both production subscriptions and every resource in them.Management groups
A management group groups subscriptions so you can apply governance to many at once: "every subscription under Production must only use EU regions." Key facts:
- Every tenant has one Tenant Root Group. All management groups and subscriptions sit somewhere under it.
- Up to six levels of depth below the root, and up to 10,000 management groups per tenant.
- Each management group and subscription has exactly one parent.
- Nobody has access to the root group by default, not even a Global Administrator. A Global Admin can elevate access (Entra ID β Properties β "Access management for Azure resources") to get User Access Administrator at root scope, and should turn it off again afterwards.
Subscriptions
A subscription is a billing boundary and a scale/limits boundary: costs are invoiced per subscription, and many quotas (vCPUs per region, number of VNets) apply per subscription. Organisations use several subscriptions to separate environments, departments or workloads, and to stay under limits.
When you hit a quota (for example "total regional vCPUs"), you request an increase under Subscription β Usage + quotas. The exam likes this: a deployment fails because of a vCPU quota β request a quota increase, not a bigger subscription offer.
Resource groups
A resource group is a logical container for resources that share a lifecycle: you deploy, manage and delete them together. Remember these rules:
- A resource belongs to exactly one resource group. Resource groups can't be nested.
- The resource group's location only says where its metadata is stored. Resources inside it can be in any region.
- Deleting a resource group deletes everything in it.
- You can move resources to another resource group or subscription. During the move both groups are locked for writes and deletes, but the resources keep running. Not every resource type supports moving, and moving never changes the region. Moving to another region is done with Azure Resource Mover or by redeploying. Dependent resources must move together (for example a VM with its disks and NIC).
Azure role-based access control (RBAC)
Azure RBAC answers "who can do what, where". A role assignment always has three parts:
Role definitions
A role definition is a JSON list of permissions:
- Actions: allowed control-plane operations, like
Microsoft.Compute/virtualMachines/start/action. Wildcards are allowed:Microsoft.Compute/*. - NotActions: operations subtracted from Actions. NotActions is not a deny. If another role assignment grants that operation, the user still has it.
- DataActions / NotDataActions: data-plane operations, like reading a blob's content:
Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read. - AssignableScopes: where a custom role can be assigned (management groups, subscriptions, resource groups).
The control plane vs data plane split is one of the most tested ideas. Owner and Contributor manage the storage account but can't read blobs with their Entra identity. For that you need a data role like Storage Blob Data Reader. (Contributor can still fetch the account key and use that, which is why chapter 7 discusses disabling keys.)
Built-in roles to know
| Role | What it allows |
|---|---|
| Owner | Everything, including assigning roles to others. |
| Contributor | Create and manage everything, but can't assign roles and can't manage Blueprints or share image galleries. |
| Reader | View everything, change nothing. |
| User Access Administrator | Manage role assignments only. Can't create resources. |
| Role Based Access Control Administrator | Assign roles, optionally limited by conditions (e.g. "may only assign Storage Blob Data Reader"). Safer than User Access Administrator. |
| Virtual Machine Contributor | Manage VMs, but not the VNet or storage account they connect to, and no login access. |
| Virtual Machine Administrator / User Login | Sign in to VMs with Entra ID (as admin or as normal user). |
| Network Contributor | Manage networks, but no access to them otherwise. |
| Storage Account Contributor | Manage storage accounts, including access keys. |
| Storage Blob Data Owner / Contributor / Reader | Data-plane access to blobs. |
| Tag Contributor | Manage tags without access to the resources themselves. |
Scopes and how access adds up
You can assign roles at four scopes: management group, subscription, resource group, resource. Assignments inherit downward. Azure RBAC is additive: your effective permissions are the union of all your role assignments, at every scope, through every group you are a member of.
Example: Ben is Reader on the subscription and Contributor on rg-az104-lab. In that resource group, he can change things; everywhere else, he can only read.
The only way to block access that another assignment grants is a deny assignment. You can't create those directly; Azure creates them for things like managed applications and deployment stacks with deny settings.
Interpreting access
The exam shows you screenshots of role assignments and asks what someone can do. In the portal, every resource has an Access control (IAM) blade with:
- Check access: pick a user, group or identity to see all its role assignments that apply here, including inherited ones and those through group membership.
- Role assignments tab: the Scope column says "This resource" or "(Inherited)" from a parent scope.
- Roles tab: open any role to see exactly which Actions it contains.
Two practical limits: up to 4,000 role assignments per subscription, and changes can take up to about 10 minutes to apply (users sometimes need to sign out and back in). This is a reason to assign to groups, not individual users.
Custom roles
When no built-in role fits, you create a custom role: usually by cloning a built-in role in the portal, or with JSON and az role definition create. Example: an "operator" who can start, restart and deallocate VMs but not create or delete them.
{
"Name": "VM Operator (custom)",
"Description": "Start, restart and deallocate VMs",
"Actions": [
"Microsoft.Compute/virtualMachines/read",
"Microsoft.Compute/virtualMachines/start/action",
"Microsoft.Compute/virtualMachines/restart/action",
"Microsoft.Compute/virtualMachines/deallocate/action"
],
"NotActions": [],
"AssignableScopes": [ "/subscriptions/<sub-id>" ]
}
Entra directory roles (chapter 1) and Azure RBAC roles are separate. A Global Administrator has no access to Azure resources by default. And a subscription Owner can't create users in Entra ID unless they also have a directory role (or the tenant allows all users to create users).
Azure Policy
RBAC controls who can act. Azure Policy controls what the result may look like, regardless of who does it. Even an Owner can't create a VM in a forbidden region if a policy denies it.
The building blocks:
- Policy definition: one rule in JSON with an
if(condition) and athen(effect). There are hundreds of built-in definitions, like Allowed locations or Require a tag on resources. - Initiative (policy set definition): a group of definitions that belong together, like the Microsoft cloud security benchmark, or "all our tagging rules".
- Assignment: a definition or initiative applied to a scope (management group, subscription, resource group), with parameters (like the list of allowed regions) and optional exclusions (child scopes it doesn't apply to).
- Exemption: excuses a specific scope or resource from an assignment, with a reason (Waiver or Mitigated) and optionally an expiry date.
Effects
| Effect | What happens | Typical use |
|---|---|---|
| Deny | Blocks the create or update request. | Allowed locations, allowed VM SKUs |
| Audit | Allows it, but marks the resource non-compliant. | Trying a rule before enforcing it |
| Append | Adds fields to the request (older, mainly for tags and IP rules). | Add an IP rule to storage |
| Modify | Adds, replaces or removes properties or tags during create/update. | Inherit a tag from the resource group |
| AuditIfNotExists | Marks non-compliant if a related resource is missing. | "VMs should have the backup extension" |
| DeployIfNotExists | Deploys the related resource if it's missing. | Deploy diagnostic settings or an agent |
| DenyAction | Blocks a specific action, currently delete. | Prevent deleting resources with tag X |
| Disabled | Turns the rule off (useful as a parameter value). |
Three behaviours to remember:
- Existing resources aren't changed or deleted by a new Deny policy. They show up as non-compliant, and the next update to them is blocked.
- Modify and DeployIfNotExists need a managed identity on the assignment (with the right roles) so Azure can make changes. For resources that existed before the assignment, you start a remediation task.
- New and updated resources are evaluated immediately. A full compliance scan runs about every 24 hours, and a new assignment can take around 30 minutes to show results.
"Resources must inherit the costcenter tag of their resource group." Tags are not inherited automatically. Use the built-in policy Inherit a tag from the resource group if missing (Modify effect), and run a remediation task for existing resources.
Resource locks
A lock protects resources against accidental changes, even by Owners. There are two types:
- CanNotDelete (called Delete in the portal): users can read and modify, but not delete.
- ReadOnly: users can read, but not modify or delete. Like everyone having the Reader role.
Locks are inherited: a lock on a resource group applies to every resource in it. When multiple locks apply, the most restrictive one wins. To create or remove a lock you need Microsoft.Authorization/locks/*, which Owner and User Access Administrator have; Contributor doesn't.
Locks apply to the control plane (Azure Resource Manager), not the data plane. A ReadOnly lock on a storage account doesn't stop people from writing blobs with a SAS, but it does have surprising side effects:
- Listing storage account keys is a POST operation, so it's blocked. Portal users without data roles then can't browse blobs.
- A ReadOnly lock on a resource group with a VM blocks starting or restarting the VM (those are POST actions too).
- A ReadOnly lock on an App Service blocks Visual Studio Server Explorer and scaling.
"An Owner can't delete a resource group." Look for a CanNotDelete lock on the group or a resource inside it (a lock on any child resource blocks deleting the group). Remove the lock first, then delete.
Tags
Tags are name/value pairs on resources, resource groups and subscriptions, such as env=prod or costcenter=1234. They help with cost reporting, automation (a runbook that shuts down every VM with autoshutdown=yes) and ownership.
- Up to 50 tags per resource. Tag names are case-insensitive, values are case-sensitive.
- Tags are not inherited from resource groups or subscriptions. Use Policy (Modify) for that.
- Not every resource type supports tags, and some (like classic resources) never did.
- To manage tags you need write access to the resource, or the Tag Contributor role.
- In Cost analysis you can group and filter by tag, but only costs after the tag was applied show the tag.
Cost management
Microsoft Cost Management shows what you spend and helps you spend less. The parts the exam asks about:
- Cost analysis: charts of actual and forecast cost, grouped by service, resource group, location or tag.
- Budgets: a monthly, quarterly or yearly amount at a scope (management group, subscription, resource group) with alert thresholds on actual or forecasted cost. When a threshold is hit, people are emailed and an action group can run automation. A budget never stops resources by itself.
- Cost alerts: budget alerts, credit alerts (for prepaid Azure credit), department spending quota alerts (EA), and anomaly alerts that detect unusual spending.
Azure Advisor gives free, personalised recommendations in five categories: Reliability, Security, Performance, Cost and Operational Excellence. Cost recommendations include "resize or shut down underused VMs", "buy reservations" and "delete unattached disks and public IPs". The Advisor score summarises how well you follow them.
Ways to pay less, which you'll need again for AZ-305:
- Reservations: commit to one specific resource type (like a VM size in a region) for 1 or 3 years, for a big discount.
- Savings plans for compute: commit to an amount per hour for 1 or 3 years, flexible across VM sizes and regions.
- Azure Hybrid Benefit: reuse your Windows Server and SQL Server licenses with Software Assurance.
- Spot VMs: very cheap, but Azure can evict them at any time. Good for batch jobs.
- The Pricing calculator estimates new workloads; the TCO calculator compares on-premises with Azure.
AZ-305 starts with "design governance": a management group hierarchy (often following the Azure landing zone design), which policies at which level, and a subscription strategy. The rule of thumb: assign policies and RBAC as high as possible and use exclusions sparingly, because inheritance does the rest.
Self-check
1. A user has Contributor on a storage account but gets "access denied" when opening a blob container in the portal with "Microsoft Entra user account" authentication. Why?
B. Reading blob data with an Entra identity needs a DataAction, which Owner and Contributor don't include.
2. You assign a policy with the Deny effect "Allowed locations: West Europe". There's already a VM in East US. What happens to it?
C. Policy never deletes or moves existing resources. It reports them as non-compliant.
3. Ben has Reader on the subscription and Contributor on rg-app. A custom role assigned to him at the subscription has NotActions: Microsoft.Compute/*. Can Ben create a VM in rg-app?
A. RBAC is additive. NotActions only removes permissions from that one role.
4. Which lock lets administrators keep changing VM sizes but prevents anyone from deleting the VM?
D. ReadOnly would also block resizing.
5. Your monthly budget of β¬100 is exceeded. What does Azure do?
B. Budgets notify. Any automatic shutdown must be built with an action group (e.g. a runbook or Logic App).
Lab: build the governed resource group
You create rg-az104-lab, the resource group that holds everything for the rest of the guide, and put guardrails on it: RBAC, two policies, a lock test and a budget.
Open a terminal on your Linux VM. The variables from chapter 0 load automatically; you only need the subscription ID (or paste the whole block if you skipped that step):
RG=rg-az104-lab; LOC=westeurope; LOC2=northeurope; INIT=xx
SUB=$(az account show --query id -o tsv)
-
Task
Create the lab resource group
Create
rg-az104-labinwesteuropewith the tagsenv = labandcourse = az104.Done when- The resource group's Overview shows both tags.
Solution Β· Portal
Resource groups β Create: subscription, name, region. Tab Tags: add both tags. Review + create.
Solution Β· Azure CLI
az group create -n $RG -l $LOC --tags env=lab course=az104 RGID=$(az group show -n $RG --query id -o tsv) -
Task
Give the right people the right access
On
rg-az104-lab, using built-in roles and least privilege:- Members of
az104-adminscan create and manage VMs, but not networks. - Ben can see everything in the group but change nothing.
Then prove what Ada can do here, and find out why she has that access.
Done when- Check access for Ada shows her role and that it comes through a group.
- You can name one network action her role does include. (Look at the role's permissions.)
Hint
The roles are Virtual Machine Contributor and Reader. Assign the first one to the group, not to Ada.
Solution Β· Portal
rg-az104-labβ Access control (IAM) β Add β Add role assignment.- Role Virtual Machine Contributor β Members: User, group or service principal β select
az104-adminsβ Review + assign. - Again: role Reader β member Ben.
- Check access β select Ada: she has Virtual Machine Contributor via
az104-admins. - Tab Roles β Virtual Machine Contributor β View β Permissions: all of
Microsoft.Compute/*, but for networks only read and join actions (e.g.virtualNetworks/subnets/join/action), so she can attach a VM to an existing subnet but not create one.
Solution Β· Azure CLI
GID=$(az ad group show -g az104-admins --query id -o tsv) az role assignment create --assignee-object-id $GID --assignee-principal-type Group \ --role "Virtual Machine Contributor" --scope $RGID BEN=$(az ad user list --filter "startswith(userPrincipalName,'az104-ben')" --query "[0].id" -o tsv) az role assignment create --assignee-object-id $BEN --assignee-principal-type User --role Reader --scope $RGID az role assignment list --scope $RGID -o table az role definition list --name "Virtual Machine Contributor" --query "[0].permissions[0].actions" -o tsv | grep -i network - Members of
-
Task
Allow only your two lab regions
Make sure nobody, not even you as Owner, can create resources in
rg-az104-laboutside westeurope and northeurope. Use a built-in policy.Done when- An assignment for this rule is visible under Policy β Assignments with scope
rg-az104-lab. (You test it in step 5.)
Solution Β· Portal
- Policy β Assignments β Assign policy.
- Scope: your subscription /
rg-az104-lab. Policy definition: Allowed locations. - Parameters: select both lab regions. Optional non-compliance message: "Only lab regions are allowed". Review + create.
Solution Β· Azure CLI
DEF=$(az policy definition list --query "[?displayName=='Allowed locations'].name" -o tsv) az policy assignment create -n allowed-locations --display-name "Allowed locations (lab)" \ --policy $DEF --scope $RGID \ --params "{\"listOfAllowedLocations\":{\"value\":[\"$LOC\",\"$LOC2\"]}}" - An assignment for this rule is visible under Policy β Assignments with scope
-
Task
Make every new resource inherit the group's tags
Every resource created in
rg-az104-labmust automatically get theenvandcoursetags of the resource group, without blocking deployments that forget them.Done when- Two policy assignments exist (one per tag), each with a managed identity. Why does this policy need one, when Allowed locations didn't?
Hint
Look for a built-in policy with the Modify effect whose name starts with "Inherit a tagβ¦".
Solution Β· Portal
- Policy β Assignments β Assign policy, scope
rg-az104-lab, definition Inherit a tag from the resource group if missing. - Parameters: Tag Name
env. - Remediation: keep Create a Managed Identity (system assigned). A Modify policy changes resources, so it needs an identity with permissions to do so.
- Review + create. Repeat with Tag Name
course.
Solution Β· Azure CLI
DEF2=$(az policy definition list --query "[?displayName=='Inherit a tag from the resource group if missing'].name" -o tsv) for T in env course; do az policy assignment create -n inherit-tag-$T --display-name "Inherit tag $T (lab)" \ --policy $DEF2 --scope $RGID --params "{\"tagName\":{\"value\":\"$T\"}}" \ --mi-system-assigned --location $LOC --identity-scope $RGID --role Contributor done -
Task
Prove both policies work
Policy assignments can take 5 to 30 minutes to take effect, so do steps 6β8 first if needed. Then try to create a free resource (an empty network security group called
nsg-policytest) in East US, and then in your lab region. Delete it afterwards.Done when- The East US attempt fails with
RequestDisallowedByPolicy. - The NSG in your lab region has the
envandcoursetags, even though you didn't set them.
Solution Β· Portal
Create a resource β Network security group, resource group
rg-az104-lab, region East US β validation fails. Change the region to your lab region β create β open its Tags. Then delete it. Policy β Compliance shows your assignments.Solution Β· Azure CLI
az network nsg create -g $RG -n nsg-policytest -l eastus # RequestDisallowedByPolicy az network nsg create -g $RG -n nsg-policytest -l $LOC --query "NewNSG.tags" az network nsg delete -g $RG -n nsg-policytest - The East US attempt fails with
-
Task
Find out what a ReadOnly lock really blocks
Put a ReadOnly lock on
rg-az104-laband, as Owner, try to add a tag to the resource group. Then remove the lock, because later labs need to make changes here.Done when- The tag change failed while the lock was there.
- The lock is gone again.
Solution Β· Portal
rg-az104-labβ Settings β Locks β Add: namelock-readonly-test, type Read-only. Open Tags, addtest=1, Apply β error. Back to Locks β delete it.Solution Β· Azure CLI
az lock create -n lock-readonly-test -g $RG --lock-type ReadOnly az group update -n $RG --set tags.test=1 # fails: ScopeLocked az lock delete -n lock-readonly-test -g $RGIn chapter 3 you put a CanNotDelete lock on the hub VNet, which is the realistic use.
-
Task
Set up a cost safety net
Create a monthly budget of 30 (your billing currency) on your subscription named
budget-az104-lab. You want an email at 50% and 90% of actual spend, and when the forecast says you'll hit 100%.Done when- The budget shows three alert conditions. Can it stop your VMs when it's exceeded?
Solution Β· Portal
- Cost Management β Budgets (scope: your subscription) β Add.
- Name, reset period Monthly, amount 30 β Next.
- Alert conditions: Actual 50%, Actual 90%, Forecasted 100%. Recipient: your email. Create.
No: budgets only notify. Stopping resources would need an action group with automation.
-
Task Β· optional
Explore Advisor and management groups
Find your Advisor score and its five categories. Optionally create a management group
mg-az104-labunder the Tenant Root Group. Only move a subscription under it if it's your own lab subscription.Solution Β· Portal
Advisor β Overview / Advisor score. Management groups β Create β ID and display name
mg-az104-lab. To move a subscription: open the management group β Add subscription.
rg-az104-labexists with tagsenvandcourse.az104-adminsis Virtual Machine Contributor and Ben is Reader on it.- Policies: Allowed locations (Deny) and Inherit tag Γ2 (Modify).
- A budget on the subscription. No lock on the group.
Cost so far: nothing.