Recommend a Structure for Management Groups, Subscriptions, Resource Groups, and Tagging — Lesson
AZ-305 › Unit 1 › Design governance › Recommend a structure for management groups, subscriptions, and resource groups, and a strategy for resource tagging
Recommend a Structure for Management Groups, Subscriptions, Resource Groups, and Tagging — Lesson
Azure gives architects a four-level resource hierarchy — Management Groups, Subscriptions, Resource Groups, and Resources — along with a free-form tag system that acts as a cross-cutting dimension for cost, ownership, and compliance. This lesson teaches you how to design those levels deliberately so that governance, security, and FinOps requirements propagate top-down without manual effort per subscription. The Azure Cloud Adoption Framework (CAF) and the Azure Landing Zone reference architecture are the canonical sources we align to throughout.
Why This Matters
Imagine Contoso Ltd. spins up its first 12 Azure subscriptions in 18 months without a hierarchy plan. Each business unit drops resources into whatever resource group the first engineer happened to create, tagging is inconsistent, and the finance team cannot produce a chargeback report for the CFO. Six months later, the CISO requires that every production workload enforce a log-retention policy — but because there is no management group structure, that policy has to be assigned 12 times, once per subscription, and every new subscription creates a new gap.
This is the scenario AZ-305 tests: designing the skeleton that holds everything else. Get the management group tree, subscription scope, resource group lifecycle boundaries, and tag taxonomy right on day one, and governance becomes a set of policies assigned once at the right scope. Get them wrong and every future initiative — Zero Trust rollout, cost optimisation, regulatory attestation — becomes a multi-subscription sweep that consumes engineering weeks.
As an Azure Solutions Architect Expert, you are expected to recommend a hierarchy and tagging strategy that satisfies organisational, security, and billing boundaries simultaneously. This is also the foundation you will build on in later lessons covering Azure Policy, RBAC, Cost Management, and landing zones.
Prerequisites
- Azure Resource Manager (ARM) control plane. Self-check: Can I name the four levels of the ARM resource hierarchy in order from the top down?
- Microsoft Entra ID tenants and Enterprise Agreement (EA) / Microsoft Customer Agreement (MCA) billing constructs. Self-check: What is the difference between a tenant and a billing account?
- Azure RBAC basics. Self-check: At what scopes can a role assignment be applied, and how is inheritance evaluated?
- Azure Policy basics — definition vs. assignment. Self-check: What does
deployIfNotExistsdo differently fromaudit? - Cloud Adoption Framework (CAF) terminology. Self-check: What is an Azure Landing Zone, and what does the term "platform subscription" mean?
Learning Objectives
By the end of this lesson, you will be able to:
- Design a management group hierarchy that reflects organisational, geographical, and environmental boundaries without exceeding Azure's structural limits.
- Recommend a subscription segmentation strategy that isolates production, non-production, and platform workloads with an explicit rationale for each split.
- Define resource group boundaries aligned to workload lifecycle, access control, and deployment scope.
- Design a tag taxonomy covering cost allocation, ownership, environment, and data classification using required vs. optional tags.
- Evaluate tag inheritance and enforcement options using Azure Policy to guarantee coverage at scale.
- Analyse trade-offs between a single-subscription vs. many-subscription design for a multi-business-unit tenant.
Building Blocks
Tenant Root Group — Analogy: the root directory of a filesystem. Formal definition: the implicit top-level management group that every Microsoft Entra ID tenant has; its ID equals the tenant ID, and all other management groups and subscriptions sit beneath it. Why it matters: any policy or RBAC assignment placed here cascades to every resource in the tenant, so it is both powerful and dangerous.
Management Group (MG) — Analogy: an organisational folder. Formal definition: an ARM-native container that groups subscriptions (or other MGs) under a single scope, up to 6 levels deep beneath the tenant root, with a maximum of MGs per tenant. Why it matters: it is the only scope above a subscription where you can attach Azure Policy and RBAC that affects multiple subscriptions at once.
Subscription — Analogy: a billing-ring-fenced project. Formal definition: the primary unit of billing, quota, and administrative boundary; every Azure resource belongs to exactly one subscription. Why it matters: quotas (e.g. 980 role assignments per subscription, 250 co-administrators, and per-service core limits) and Azure Policy assignment limits are enforced per subscription, which forces segmentation for large estates.
Resource Group (RG) — Analogy: a shipping container. Formal definition: a flat, non-nested container for resources sharing a lifecycle, region, and access boundary; resources in an RG can be deployed and deleted as a unit. Why it matters: an RG is the unit of az group delete — get the boundary right and teardown is atomic; get it wrong and you leave orphan resources behind.
Tag — Analogy: a sticky label. Formal definition: a case-insensitive key–value string pair (name up to 512 characters, value up to 256 characters) attached to a resource, RG, or subscription; each resource can carry up to 50 tags. Why it matters: tags are the only cross-cutting dimension that cuts across the hierarchical scopes — cost reports, compliance dashboards, and automation all key off them.
Tag Inheritance — Analogy: inheriting traits from a parent. Formal definition: Azure does not automatically copy tags from an RG or subscription down to resources at runtime; the inherit a tag from the resource group built-in Azure Policy (effect modify) must be assigned explicitly. Why it matters: engineers often assume inheritance is automatic and discover missing tags only when a chargeback report lists untagged resources.
Azure Landing Zone (ALZ) — Analogy: a pre-wired office floor. Formal definition: a CAF-aligned deployment pattern that provisions a standard MG hierarchy, subscriptions for platform (identity, management, connectivity) and application landing zones, plus baseline policies, RBAC, and network topology. Why it matters: ALZ is Microsoft's reference implementation — the exam treats it as the canonical starting point unless the scenario explicitly says otherwise.
Deep Dive
Management Group hierarchy design
Every Azure tenant has a Tenant Root Group; you cannot remove it, but you can — and should — create child MGs to reflect the organisation. Azure allows up to 6 levels of MGs under the root, but CAF recommends a flat tree with 3–4 levels maximum: deeper trees make RBAC reasoning harder and policy assignments slower to evaluate.
The canonical CAF pattern has a top-level Platform MG (for foundational subscriptions: Identity, Management, Connectivity) and a top-level Landing Zones MG (for application subscriptions), plus Sandbox (for experimentation) and Decommissioned (for wind-down). Inside Landing Zones, a Corp and Online split separates workloads that need corporate connectivity from those that are internet-exposed.
[!TIP] Design the MG tree around policy boundaries, not organisational charts. If two business units need the same compliance policies, they belong under the same MG even if they report to different VPs. Reorganising an MG tree to fix a policy inheritance mistake is cheap; reassigning 200 policies is not.
The structural limits matter for large enterprises: each directory supports up to MGs; each MG can have up to subscriptions as direct children; you can assign up to 500 policy definitions and 200 policy assignments at each MG scope. A subscription can sit under only one MG at a time, and moving it triggers a re-evaluation of every inherited policy and RBAC assignment.
Subscription segmentation
A subscription is the smallest unit where Azure quotas and limits apply. The most common segmentation axes are environment (prod vs. non-prod), business unit, geographic region (for data-residency), and billing isolation (for chargeback precision or for keeping sandbox spend contained).
[!IMPORTANT] Do not treat a subscription as a "bucket for one app". Treat it as a security and quota boundary. A small app does not need its own subscription; a set of related apps owned by one team with shared policies and a shared spend cap usually does.
The rule of thumb: create a new subscription when at least two of these conditions are true — different environment (prod vs. non-prod), different funding source (different cost centre pays), different compliance obligation (PCI vs. non-PCI), different administrative owner (different platform team), or you are approaching a hard subscription quota (regional vCPU limit, storage accounts, public IPs).
The CAF-aligned Landing Zone reference uses a minimum set of platform subscriptions: Identity (for Microsoft Entra Domain Services and AD Connect), Management (for shared Log Analytics workspace, Automation account, Recovery Services vault), and Connectivity (for hub VNet, Azure Firewall, ExpressRoute circuit). Application teams each get their own Application Landing Zone subscription — one per workload or per application family, depending on isolation requirements.
Resource group boundaries
A resource group is not a security boundary in the way a subscription is; it is a lifecycle and management boundary. The Microsoft guidance is that resources in the same RG should share lifecycle (deployed together, updated together, deleted together) and access control (the same set of people admin them).
A good RG maps 1:1 to a CI/CD deployment artefact: a Bicep or Terraform main module targets one RG, owns every resource declared in the module, and az group delete cleanly removes everything the module created. A bad RG mixes resources with different blast radii — the production database sitting in the same RG as an ephemeral dev VM is an accident waiting to happen.
[!WARNING] Resource groups cannot be nested and cannot span subscriptions. A resource in RG
rg-app-prodin subscriptionS1cannot be "moved" into subscriptionS2by changing a tag; it requires a formalMove-AzResourceoperation, which has per-service restrictions (e.g.,App Service plansare notoriously hard to move across subscriptions).
Naming matters: CAF recommends <abbrev>-{workload}-{env}-{region}-{instance}, making RGs sortable and greppable in the CLI and preventing collisions when two teams name an RG "web". A Bicep deployment targeting a CAF-named RG looks like this:
targetScope = 'subscription'
param workload string = 'ecomm'
param env string = 'prod'
param region string = 'weu'
param instance string = '001'
resource rg 'Microsoft.Resources/resourceGroups@2023-07-01' = {
name: 'rg-${workload}-${env}-${region}-${instance}'
location: 'westeurope'
tags: {
Environment: 'Prod'
CostCenter: 'CC-4471'
Owner: 'team-ecomm@contoso.com'
DataClassification: 'Confidential'
}
}Tag taxonomy
A tag is a free-form string key and string value. This freedom is its strength — and its curse. Without a taxonomy, engineers invent their own keys (owner, Owner, team_owner, team-owner) and finance cannot join them.
The CAF-recommended minimum taxonomy has four required tags: Environment (Prod|NonProd|Sandbox|Shared), CostCenter (numeric code), Owner (email or group alias), and DataClassification (Public|Internal|Confidential|HighlyConfidential). Optional tags commonly added: Application, BusinessUnit, CriticalityTier, DisasterRecoveryTier, AutoShutdown (yes|no|weekend).
Keep tag values enumerable wherever possible; free-text values defeat reporting. Enforce enumerations with Azure Policy deny effects using the allowedValues parameter on the require a tag and its value definition. A policy assignment JSON snippet to enforce Environment at an MG scope:
{
"properties": {
"displayName": "Require Environment tag with allowed values",
"policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/1e30110a-5ceb-460c-a204-c1c3969c6d62",
"parameters": {
"tagName": { "value": "Environment" },
"tagValues": { "value": ["Prod", "NonProd", "Sandbox", "Shared"] }
},
"enforcementMode": "Default"
}
}Tag inheritance and enforcement
Tags set on an RG are not automatically copied onto resources inside that RG — this is the single biggest surprise for engineers new to Azure. There are three mechanisms to enforce tags at scale:
inherit a tag from the resource groupbuilt-in policy (effectmodify) — copies an RG tag onto each resource; the resource can override it.require a tag and its valuebuilt-in policy (effectdeny) — blocks resource creation if the tag is missing.append a tag and its valuebuilt-in policy (effectappend) — adds a default value if not supplied, but does not block or overwrite.
Best practice: combine deny (at the subscription or top MG scope for the CostCenter and Owner tags) with modify (at the RG level for Environment). The deny forces callers to be explicit; the modify fills in defaults that rarely vary per resource.
[!NOTE] Tag-enforcement policies only affect resources created after the policy is assigned. To back-fill existing resources, use scripts like the one below or a
deployIfNotExistspolicy with a remediation task.
A quick Azure CLI back-fill script that copies RG tags onto all resources inside an RG:
rg="rg-ecomm-prod-weu-001"
tags=$(az group show --name "$rg" --query tags -o json)
az resource list --resource-group "$rg" --query "[].id" -o tsv |
while read id; do
az tag update --resource-id "$id" --operation merge --tags "$tags"
doneAnd a reusable Azure Resource Graph query (Kusto) to audit tag coverage across a whole MG:
Resources
| where subscriptionId in~ (toscalar(
ResourceContainers
| where type == "microsoft.resources/subscriptions"
| where properties.managementGroupAncestorsChain has "mg-corp"
| summarize make_list(subscriptionId)))
| extend missingTags = set_difference(dynamic(["Environment", "CostCenter", "Owner", "DataClassification"]), bag_keys(tags))
| where array_length(missingTags) > 0
| project id, type, location, missingTagsWorked Examples
Easy — Contoso Pharma, small estate
Synthetic scenario (AZ-305 style). Contoso Pharma has 3 Azure subscriptions (one prod, one dev, one for a shared Log Analytics workspace). They want to assign a policy that blocks resource creation outside westeurope and northeurope. Should they assign the policy to each subscription or do something else first?
Step-by-step solution.
- Count the target scope: 3 subscriptions, all subject to the same policy.
- Assigning the policy per subscription means 3 assignments today. Any new subscription added later will forget the policy — a classic drift source.
- A management group lets us assign the policy once at a scope that automatically includes any new subscription added underneath.
- Design: create one parent MG
mg-contosounder the tenant root, move all 3 subscriptions into it, and assign the policy atmg-contoso.
[!NOTE] Even at small scale, the rule is: if you have subscriptions that share a policy, put them under an MG. The cost of an MG is zero; the cost of forgetting to assign a policy is one audit finding.
Medium — Fabrikam Retail, environment split
Synthetic scenario (AZ-305 style). Fabrikam Retail runs 12 applications across 4 business units. Production has strict compliance (ISO 27001, no public IPs on compute); dev/test should be more permissive. They want chargeback by business unit. Design an MG plus subscription structure.
Step-by-step solution.
- Axis 1 — compliance scope: prod has different policies from non-prod, so split at the MG level, not inside a subscription.
- Axis 2 — business unit: 4 BUs with separate funding, so one subscription per BU per environment is the baseline ($$4 \times 2 = 8$$ subscriptions minimum).
- MG design:
Tenant Root → mg-fabrikam → {mg-prod, mg-nonprod}; each child MG holds 4 subscriptions (one per BU). - RG design inside each subscription: one RG per application — 12 apps means each BU subscription holds 2–4 RGs.
- Policy assignment: ISO 27001 initiative at
mg-prod; relaxed baseline atmg-nonprod; tenant-wide baseline atmg-fabrikam. - Tagging:
BusinessUnit+CostCenterrequired atmg-fabrikam, enforced with therequire a tag and its valuebuilt-in policy.
[!NOTE] Splitting first by environment (compliance boundary) and then by BU (billing boundary) gives the policy engine the fewest assignments while still isolating chargeback. Swapping the order — BU first, environment second — doubles the policy assignments.
Hard — Contoso Global, multi-region regulated
Synthetic scenario (AZ-305 style). Contoso Global operates in 3 regions: EU (GDPR; data must stay in EU), US (HIPAA for healthcare workloads only), APAC (no specific regulation). Two business units: Healthcare (HIPAA-scoped in US only) and Commerce (everywhere). They want a reusable landing zone so new subscriptions come pre-configured. Design the hierarchy.
Step-by-step solution.
- Start from the CAF Azure Landing Zone template:
Tenant Root → Top-level MG → {Platform, LandingZones, Sandbox, Decommissioned}. - Under
Platform: subscriptionsIdentity,Management,Connectivity(shared across regions, one of each). - Under
LandingZones: split by regulatory posture, not by BU, because policies are regulatory:mg-corp-eu(GDPR),mg-corp-us-hipaa(HIPAA),mg-corp-us-general,mg-corp-apac, plusmg-onlinefor internet-exposed workloads. - Each BU gets one subscription per applicable MG. Healthcare lives under
mg-corp-us-hipaaonly; Commerce has subscriptions under EU, US-general, and APAC MGs. - Apply region-lock and data-residency policies at each regulatory MG; apply HIPAA initiative at
mg-corp-us-hipaaonly. - Tagging:
DataClassificationrequired at top-level MG so every region and BU enforces it.
[!NOTE] The key move is splitting
mg-corp-usinto-hipaaand-generalMGs rather than one MG with conditional policies. MG-scoped assignments are simpler to audit than complex policy conditions built onnotScopeor tag matching.
Visual Explanations
Figure 1: CAF-aligned management group hierarchy
The standard Azure Landing Zone hierarchy:
Caption: The Platform branch holds centrally-owned shared services; Landing Zones holds application subscriptions split into Corp (internal) and Online (internet-facing). Sandbox and Decommissioned provide safe homes for experimentation and wind-down — critical for avoiding pollution of the main tree.
Figure 2: Decision tree — when to create a new subscription
Caption: Apply this decision tree top-down. The cost of a new subscription is low (no per-subscription charge); the cost of mixing incompatible workloads in one subscription is paid in quota contention, compliance risk, and chargeback mess.
Figure 3: Azure hierarchy scopes — TikZ spatial diagram
Caption: The five ARM scopes stacked top-to-bottom, with the governance characteristic of each. A role or policy attached high in the tree propagates to everything below it; breaking the rule of scoping wisely means either over-broad grants or under-covered policies.
Figure 4: Feature comparison — ARM scopes
| Scope | Max depth / count | Policy assignment | RBAC | Billing | Quotas |
|---|---|---|---|---|---|
Tenant Root | 1 per tenant | Yes | Yes | No | No |
Management Group | 6 levels, MGs | Yes (inherits down) | Yes (inherits down) | No | No |
Subscription | per MG | Yes | Yes | Yes | Yes |
Resource Group | Unlimited per sub | Yes | Yes | No (rolls up to sub) | No |
Resource | Varies by service | Yes (via tags/individual) | Yes | No | Per-service |
Caption: The subscription is the only scope with both billing and quota semantics. That is why the "one subscription per X" question is really about where to draw billing and quota boundaries.
Figure 5: CAF required tag taxonomy
| Tag | Required? | Example value | Primary consumer | Enforcement |
|---|---|---|---|---|
Environment | Yes | Prod | Azure Policy | deny at top MG |
CostCenter | Yes | CC-4471 | Cost Management | deny at top MG |
Owner | Yes | team-ecomm@contoso.com | IT Service Mgmt | deny at top MG |
DataClassification | Yes | Confidential | Security | deny at top MG |
Application | Optional | ecomm-cart | FinOps / ITIL | append at RG |
CriticalityTier | Optional | Tier1 | BCDR / SRE | modify inherit from RG |
AutoShutdown | Optional | weekend | Automation | append at RG |
Caption: Required tags are enforced at the highest MG with a deny effect so missing values block deployment. Optional tags default in via append or modify so engineers are not blocked but reporting remains consistent.
Figure 6: Subscription sizing checklist
| Signal | Reuse subscription | New subscription |
|---|---|---|
| Same environment (prod/dev) | Yes | — |
| Same compliance scope | Yes | — |
| Same funding source | Yes | — |
| Expected spend of existing sub | Yes | — |
| Different environment | — | Yes |
| Different compliance regime | — | Yes |
| Different BU with chargeback | — | Yes |
| Quota headroom | — | Yes |
| Need hard blast-radius isolation | — | Yes |
Caption: Use this table as a checklist during design reviews. A workload scoring "Yes" in three or more "New subscription" rows almost always warrants a new subscription.
Figure 7: Tag-policy effect comparison
| Effect | What it does | Blocks deployment? | Overwrites existing values? | Typical use |
|---|---|---|---|---|
audit | Logs non-compliance only | No | No | Discovery phase |
append | Adds a tag if missing | No | No | Default values for optional tags |
modify | Adds or changes a tag | No | Yes (per rule) | Inheriting from RG |
deny | Blocks creation on violation | Yes | N/A | Required tags |
deployIfNotExists | Runs a remediation template | No | Depends on template | Back-filling existing resources |
Caption: Effect selection is the single biggest design choice for tag policy. A new-to-Azure customer typically starts with audit, migrates to append once defaults stabilise, and finishes at deny once the taxonomy is in place.
Common Mistakes
❌ Myth: Tags on a resource group automatically appear on every resource inside it. ✅ Reality: Tag inheritance requires the
inherit a tag from the resource groupbuilt-in Azure Policy with amodifyeffect; without it, resources created after an RG tag is set carry no tags at all. Why it's tricky: The Azure Portal shows RG-level tags in the same UI pane as resource-level tags, so engineers assume the display reflects runtime inheritance. It does not — the portal is showing the RG's own tags, not tags that the resources have inherited.
❌ Myth: A deeper management group tree gives me finer-grained control. ✅ Reality: Each MG level adds policy evaluation latency and RBAC reasoning complexity; CAF recommends 3–4 levels maximum. Past 4 levels, troubleshooting a "why did this policy apply?" question becomes a multi-hour exercise. Why it's tricky: Azure allows up to 6 levels under the root, and architects confuse "allowed" with "recommended". The structural limit exists for edge cases (very large multinationals); the recommendation exists because humans have to reason about this tree.
❌ Myth: I should put each application in its own subscription for isolation. ✅ Reality: Per-app subscriptions create hundreds of subscriptions at scale, each needing the same baseline policies, RBAC assignments, and network plumbing. Use resource groups for per-app isolation within a subscription; reserve new subscriptions for environment, compliance, or billing boundaries. Why it's tricky: The word "isolation" conflates three things: network (use VNets and NSGs), identity (use RBAC scopes), and billing (use tags or a new subscription). Only billing and quota always require a new subscription; the other two almost never do.
❌ Myth: Moving a subscription between management groups is a cosmetic change. ✅ Reality: The move triggers re-evaluation of every Azure Policy and RBAC assignment that inherits from the new parent MG. A
denypolicy newly inherited may block existing workloads until they are brought into compliance, and the move is logged in the Activity Log for audit. Why it's tricky: The Portal operation takes seconds and offers no confirmation step listing the policies that will start or stop applying. Engineers move subscriptions during weekend change windows without a diff — and come back Monday to broken deployments.
❌ Myth: Free-text tag values are fine as long as the tag key is consistent. ✅ Reality:
CostCenter=CC4471,CostCenter=4471, andCostCenter=cc-4471all count as three different values in Cost Management reports. Enforce enumerated values with Azure PolicyallowedValuesparameters on therequire a tagdefinition. Why it's tricky: The exam and real life both test this — Cost Management's "group by tag" will list every distinct value, and a sprawl of near-duplicate values is the single most common FinOps complaint about Azure.
Practice Exercises
Exercise 1 — 🟢 Easy. A customer has 5 subscriptions in a single Microsoft Entra ID tenant with no management groups configured. They need to enforce a region-lock policy on all 5. Should they assign the policy 5 times, or do something else first?
▶💡 Hint
Think about what happens when a sixth subscription is added next month.
▶✅ Solution
Create one management group, move all 5 subscriptions under it, and assign the region-lock policy once at the MG. Any new subscription added to the MG inherits the policy automatically. Five individual assignments work today but create drift risk.
Exercise 2 — 🟢 Easy. Which of the following is a valid CAF-recommended top-level management group name for a hierarchy under the tenant root: Prod, EU, Corp, or Platform?
▶💡 Hint
The CAF reference shows four top-level MGs under the enterprise root MG.
▶✅ Solution
Platform. The CAF reference top-level MGs are Platform, Landing Zones, Sandbox, and Decommissioned. Prod, EU, and Corp appear lower in the tree (usually under Landing Zones).
Exercise 3 — 🟡 Medium. Fabrikam wants every resource group to carry an Environment tag inherited automatically by resources inside it, and also wants deployment to fail if CostCenter is missing on the resource itself. Which two built-in policies should they assign, and at what scope?
▶💡 Hint
Two distinct policy effects: one quietly sets a default, the other refuses the deployment.
▶✅ Solution
Assign inherit a tag from the resource group (effect modify) at the subscription or MG scope for the Environment tag. Assign require a tag and its value (effect deny) at the subscription or MG scope for the CostCenter tag. modify silently inherits; deny blocks.
Exercise 4 — 🟡 Medium. Contoso's Healthcare BU needs to run a HIPAA-compliant subscription only in the US region, while the rest of the BU's non-regulated workloads run anywhere. Should this HIPAA subscription be a sibling of the other Healthcare subscriptions under the same MG, or live under a separate MG?
▶💡 Hint
The compliance policy set for HIPAA is different from the baseline. Which scope lets you attach one without the other?
▶✅ Solution
Separate MG. The HIPAA initiative (and its hard deny rules for public IPs, unencrypted storage, etc.) should be attached only to the subscriptions that need it. Mixing HIPAA and non-HIPAA subscriptions under the same MG forces you to apply HIPAA policies broadly or use exclusions, both of which are audit risks.
Exercise 5 — 🟡 Medium. A team names their resource groups webapp, db, and shared. What two problems will they hit at scale?
▶💡 Hint
What happens when a second team wants to deploy a similar stack, or when ops tries to filter RGs by environment?
▶✅ Solution
(1) Collisions — the next team to need a webapp RG will pick webapp2 or worse; and (2) unfilterable — there is no -prod/-dev suffix so ops cannot filter RGs by environment in the CLI. CAF-recommended naming is rg-{workload}-{env}-{region}-{instance}, e.g. rg-ecomm-prod-weu-001.
Exercise 6 — 🔴 Hard. Design a minimal MG plus subscription structure for a scenario where: 2 regulated BUs (each with prod plus dev environments), a shared platform team (identity plus connectivity), and a sandbox for experimentation. Explain where baseline policies go and where regulatory policies go.
▶💡 Hint
Start from CAF Landing Zones. Map regulatory boundaries to MGs, not to subscriptions.
▶✅ Solution
Tenant Root → mg-corp → {mg-platform, mg-landingzones, mg-sandbox}. Under mg-platform: Identity and Connectivity subscriptions. Under mg-landingzones: mg-bu1-regulated and mg-bu2-regulated, each containing bu-prod and bu-dev subscriptions. Baseline policies (region lock, tagging) assigned at mg-corp. Regulatory policies assigned at each BU's mg-*-regulated MG. Sandbox gets a permissive baseline only. Total: 5 MGs, 6 subscriptions.
Exercise 7 — 🔴 Hard. An auditor asks "show me all Confidential-classified resources in westeurope owned by cost centre CC-4471". The customer says they cannot answer without manual spreadsheet work. What governance problem does this reveal, and how do you fix it going forward?
▶💡 Hint
This is a tag taxonomy and enforcement question, not a tooling question.
▶✅ Solution
The required tags (DataClassification, CostCenter) are not consistently applied — probably because they were introduced after workloads were deployed and enforcement is only audit/append, not deny. Fix: (1) switch to deny enforcement at the top MG for the four CAF required tags; (2) run a remediation task using deployIfNotExists to back-fill missing tags from a reference list; (3) use Azure Resource Graph (Resources | where tags.DataClassification == 'Confidential' and location == 'westeurope' and tags.CostCenter == 'CC-4471') for the auditor's query.
Exercise 8 — 🔴 Hard. A customer has 3 subscriptions per BU × 4 BUs = 12 subscriptions, all under a single MG. They now need to apply different network policies to 2 of the BUs (on-prem connected) vs. the other 2 (internet-only). Should they restructure the MG tree, or use policy exclusions?
▶💡 Hint
MG moves are cheap; policy exclusion lists grow unmanageable.
▶✅ Solution
Restructure: split the existing MG into mg-corp (for on-prem-connected BUs) and mg-online (for internet-only BUs), then move the 6 subscriptions into the appropriate MG. Attach different network policies at each MG. Exclusion lists on a single MG work initially but silently rot — new subscriptions inherit the wrong policy, and troubleshooting "why is this subscription exempt?" requires reading the exclusion array.
Summary & Concept Map
Key takeaways:
- Design the MG tree around policy and regulatory boundaries, not the org chart. Keep it 3–4 levels deep; CAF's Platform / Landing Zones / Sandbox / Decommissioned split is the canonical starting point.
- Subscriptions are the billing and quota boundary. Create one when you need a different environment, funding source, compliance regime, administrator, or when you are approaching quota limits — not for every application.
- Resource groups are the lifecycle boundary, not a security boundary. One RG per CI/CD deployable unit, named with the CAF
rg-{workload}-{env}-{region}-{instance}pattern. - Tags are the cross-cutting dimension. Define a required taxonomy (CAF's
Environment,CostCenter,Owner,DataClassification) and enforce it withdenyat the top MG; layermodify/appendpolicies for optional tags. - Tag inheritance is not automatic. The
inherit a tag from the resource groupbuilt-in policy must be assigned explicitly — this is the most frequently missed detail on the exam. - Moving subscriptions between MGs is a governance operation, not a cosmetic one. Preview policy and RBAC impact before the move.
- Always start from the CAF Azure Landing Zone. Deviations should be justified in writing; greenfield customers get 80% of their governance for free by adopting the template.
Concept map:
Caption: The governance triangle — MGs give you policy and RBAC scope, subscriptions give you billing and quota boundaries, tags give you the cross-cutting dimension. Get all three right and governance becomes a set of one-time assignments; get any one wrong and every future initiative becomes a sweep.