Make a rule hold: an allowed-locations policy and two resource locks
Task
Assign the built-in Azure Policy definition Allowed locations to a resource group of your own, watch it reject a storage account in the wrong region and accept the same account in the right one, and read its compliance view. Then put a Delete lock and a ReadOnly lock on the group and see each one stop a request that your role would otherwise allow. You will finish able to say, from your own results, which of lesson 13's three tools answers which question: Azure Policy for how resources are configured, resource locks for accidental change or deletion, and Microsoft Purview for where sensitive data lives. Everything you add is removed again, locks first.
Steps
- Open Cloud Shell (Bash), choose your subscription and create the lab's resource group:
az account set --subscription 00000000-0000-0000-0000-000000000000
az group create --name az900-lab13-rg --location eastus
- Find the built-in policy definition. Azure ships it; you do not write any JSON:
az policy definition show --name e56962a6-4747-49cd-b67b-bf8b01975c4c --query displayName -o tsv
It prints Allowed locations. Assign it to the lab's resource group only, allowing eastus and nothing else:
az policy assignment create --name az900-lab13-allowed-locations --display-name "AZ-900 lab 13 allowed locations" --policy e56962a6-4747-49cd-b67b-bf8b01975c4c --scope "$(az group show --name az900-lab13-rg --query id -o tsv)" --params '{"listOfAllowedLocations": {"value": ["eastus"]}}'
An assignment at a resource group reaches only that group. The same assignment at a management group would cover every subscription beneath it. 3. Test the rule. A new assignment can take several minutes to take effect, so wait about five minutes, then try to create a private storage account in a region the policy does not allow. Replace the digits 48213 with your own, and keep the same name for the rest of the lab:
az storage account create --name az900lab1348213 --resource-group az900-lab13-rg --location westus --sku Standard_LRS --allow-blob-public-access false
It fails with RequestDisallowedByPolicy and names your assignment. Your role allowed the request; the policy denied it, because RBAC decides who may act and Azure Policy decides what a resource may look like. Now create the same account in the allowed region:
az storage account create --name az900lab1348213 --resource-group az900-lab13-rg --location eastus --sku Standard_LRS --allow-blob-public-access false
This one succeeds. 4. Read the compliance view. In the portal, open Policy, choose Compliance, and select the assignment AZ-900 lab 13 allowed locations. Evaluation of a new assignment can take a while; when it has run, the storage account is listed as compliant. A resource that broke the rule and existed before the assignment would be reported as non-compliant, never deleted. 5. Add a Delete lock to the resource group, read it back, and only if the second command prints CanNotDelete, try to delete the storage account inside it:
az lock create --name az900-lab13-nodelete --lock-type CanNotDelete --resource-group az900-lab13-rg
az lock show --name az900-lab13-nodelete --resource-group az900-lab13-rg --query level -o tsv
az storage account delete --name az900lab1348213 --resource-group az900-lab13-rg --yes
The delete fails with ScopeLocked, even though you are allowed to delete storage accounts: the lock on the group is inherited by everything in it and applies to Owners too. A Delete lock still allows changes, so this works:
az storage account update --name az900lab1348213 --resource-group az900-lab13-rg --tags Purpose=lab
- Add a ReadOnly lock to the same group and try the same kind of change again:
az lock create --name az900-lab13-readonly --lock-type ReadOnly --resource-group az900-lab13-rg
az storage account update --name az900lab1348213 --resource-group az900-lab13-rg --tags Purpose=frozen
The update now fails with ScopeLocked. ReadOnly allows reading and nothing else. Locks act on management operations, not on data: a Delete lock on a storage account would not stop someone deleting the blobs inside it. 7. Decide which tool fits each need, then check your answers in the Notes. (a) Stop anyone deploying resources outside two approved regions. (b) Find which file shares and databases hold card numbers, across Azure and an on-premises file server. (c) Make sure nobody, Owners included, deletes the production network by mistake, while still allowing its settings to change. (d) Show which upstream tables feed a report before one of them is changed. (e) Freeze a network security group completely until a change window opens.
Verify
The policy allows exactly one region, and both locks are in place.
az policy assignment show --name az900-lab13-allowed-locations --scope "$(az group show --name az900-lab13-rg --query id -o tsv)" --query 'parameters.listOfAllowedLocations.value[0]' -o tsv
Expected output: eastus.
az storage account show --name az900lab1348213 --resource-group az900-lab13-rg --query location -o tsv
Expected output: eastus.
az lock show --name az900-lab13-nodelete --resource-group az900-lab13-rg --query level -o tsv
Expected output: CanNotDelete.
az lock show --name az900-lab13-readonly --resource-group az900-lab13-rg --query level -o tsv
Expected output: ReadOnly.
Cost and clean-up
Azure Policy assignments of built-in definitions and resource locks are free. The storage account holds no data and costs next to nothing while it exists, but charges are possible, so clean up today.
Created by this lab: the resource group az900-lab13-rg; the policy assignment az900-lab13-allowed-locations on that group; the lock az900-lab13-nodelete and the lock az900-lab13-readonly on that group; the storage account az900lab1348213 (with your own digits) and its tag.
- Remove both locks first. A lock blocks the resource group delete, and a ReadOnly lock blocks almost every other step of the clean-up:
az lock delete --name az900-lab13-readonly --resource-group az900-lab13-rg
az lock delete --name az900-lab13-nodelete --resource-group az900-lab13-rg
- Remove the policy assignment, so nothing outlives the group it was made for:
az policy assignment delete --name az900-lab13-allowed-locations --scope "$(az group show --name az900-lab13-rg --query id -o tsv)"
- Delete the resource group, which deletes the storage account
az900lab1348213with it. Lesson 1's budget is not touched:
az group delete --name az900-lab13-rg --yes
Check it is gone
az group exists --name az900-lab13-rg
Expected output: false.
az policy assignment list --disable-scope-strict-match --query "length([?name=='az900-lab13-allowed-locations'])" -o tsv
Expected output: 0.
Notes
Answers to step 7: (a) Azure Policy, with the Allowed locations definition and a deny effect. (b) Microsoft Purview: its scans and classifications find sensitive data wherever it lives. (c) A Delete lock (CanNotDelete): changes are still allowed. (d) Microsoft Purview's data lineage. (e) A ReadOnly lock: a Delete lock would still let someone edit the rules.
If the storage account in westus is created instead of refused, the assignment had not taken effect yet. That is harmless: it is in the lab's resource group and goes with it at clean-up. Delete it with az storage account delete --name az900lab1348213 --resource-group az900-lab13-rg --yes, wait a few more minutes, then run both commands of step 3 again.
If az lock create fails with an authorization error, your identity is not an Owner or User Access Administrator: that is lesson 13's point about who can manage locks, demonstrated on you.
This is an independent study companion for the Microsoft Azure Fundamentals (AZ-900) exam and is not produced by or endorsed by Microsoft. Microsoft, Azure and Microsoft Entra are trademarks of the Microsoft group of companies.
This is an independent study companion for Microsoft Azure Fundamentals AZ-900 and is not produced by or endorsed by CompTIA.