Lab: Azure foundation, resource hierarchy, and least privilege
Outcome
Create a tagged resource group, deploy one storage account with Bicep, give a test group Reader access only to that resource group, then diagnose why that group cannot create a resource. This is the minimum control-plane loop behind many AZ-104 tasks.
Before you begin
You need a non-production subscription where you can create resource groups and role assignments. Before you create anything, complete this workload card. It turns the lab from a list of portal actions into an operational decision.
| Workload concern | Training decision |
|---|---|
| Owner and cost | Your training identity; a subscription you may charge and clean up. |
| Runtime/data | A StorageV2 account with no workload data. |
| Identity/authorization | A disposable Entra security group receives Reader at one resource group. |
| Network boundary | Blob public access is disabled; this does not configure private networking. |
| Delivery/observability/recovery | Bicep through ARM; CLI/portal state and Activity Log; resource-group deletion. |
In Cloud Shell, set these values. Replace only the values in angle brackets.
az account set --subscription '<training-subscription-id-or-name>'
az group create --name rg-azlearn-governance --location <azure-region> --tags purpose=training owner=<your-alias>If az group create fails, stop: your current account does not have the required subscription access. Record the error; do not ask someone to grant more access than the lab requires.
Learn
- A resource-group groups related resources; deleting it deletes the resources in it.
- RBAC grants access through a principal, role, and scope. Assignments are additive; a narrower Reader assignment does not take away a broader Contributor assignment.
- Policy governs which configurations Azure will accept. It is not a substitute for RBAC.
- bicep sends a declarative desired state to Azure Resource Manager.
Do
Create main.bicep in Cloud Shell with this content:
param location string = resourceGroup().location
param storageName string
resource storage 'Microsoft.Storage/storageAccounts@2023-05-01' = {
name: storageName
location: location
sku: {
name: 'Standard_LRS'
}
kind: 'StorageV2'
properties: {
allowBlobPublicAccess: false
minimumTlsVersion: 'TLS1_2'
}
tags: {
purpose: 'training'
}
}Deploy it. Storage-account names are globally unique, lowercase, and 3–24 characters. Choose a unique value for <unique-storage-name>.
az deployment group create \
--resource-group rg-azlearn-governance \
--template-file main.bicep \
--parameters storageName=<unique-storage-name>In Microsoft Entra ID, create a security group named azlearn-rg-readers and add a test user who does not already have a broader role at this subscription. At the resource-group scope, assign the built-in Reader role to that group. Use the portal’s Access control (IAM) page or this equivalent CLI form:
az role assignment create \
--assignee-object-id '<group-object-id>' \
--assignee-principal-type Group \
--role Reader \
--scope "$(az group show --name rg-azlearn-governance --query id -o tsv)"Verify
Run these checks as your administrator account:
az group show --name rg-azlearn-governance --query '{name:name,tags:tags}' -o json
az storage account show --name <unique-storage-name> --resource-group rg-azlearn-governance --query '{name:name,httpsOnly:enableHttpsTrafficOnly,publicBlob:allowBlobPublicAccess}' -o json
az role assignment list --scope "$(az group show --name rg-azlearn-governance --query id -o tsv)" --all -o tableThen sign in as the test user in a private browser session. They should be able to view the resource group and storage account, but not create a storage account. Explain the result using principal + Reader role + resource-group scope.
Break and fix
- While signed in as the test user, try to create a storage account in
rg-azlearn-governance. Capture the authorization failure. - As the administrator, change the group’s assignment to Contributor at that resource-group scope only. Retest after token/role propagation.
- Remove the Contributor assignment and restore Reader. Confirm that creation fails again.
The lesson is not that Contributor is “stronger” in the abstract. It is that Azure evaluates the roles applicable to the requested action and scope. Do not use a narrower Reader assignment to try to cancel a subscription-level Contributor assignment; role assignments are additive.
Scenario practice
- Configure: Choose the resource-group scope and role for a trainee who must inspect the training workload but never create resources.
- Diagnose: A user can view a storage account but cannot create one. Which identity, role, scope, and ARM evidence explains the result?
- Distinguish: Contrast a tenant, subscription, resource group, ARM deployment, and RBAC role assignment.
Clean up
Delete the training resource group. This removes the deployed storage account.
az group delete --name rg-azlearn-governance --yes --no-waitRemove the lab role assignment and test group only if they were created solely for this exercise.
Ready to move on?
You are ready when you can explain the difference between a tenant, management group, subscription, resource group, resource, ARM deployment, and an RBAC role assignment without looking them up. You should also be able to name the workload owner, identity, authorization scope, data boundary, deployment path, evidence, recovery action, and cost owner.
Sources and re-audit
- Azure Resource Manager overview, Azure RBAC overview, and resource groups, checked 2026-08-22.
Re-audit when ARM deployment behavior, storage-account defaults, resource-group deletion semantics, or RBAC role-assignment behavior changes.
Related
Azure from Zero · RBAC · Azure Policy · Bicep · All labs