Every customer issue that starts with "we can't tell who owns this subscription" or "someone deployed a public IP in production" goes back to a missing foundation. Build this once, before workloads arrive.
1. Management group hierarchy
A layout that matches the Azure landing zone reference:
Tenant Root Group
└── contoso (intermediate root)
├── platform
│ ├── management (Log Analytics, automation)
│ ├── connectivity (hub VNets, firewall, DNS)
│ └── identity (domain controllers if needed)
├── landingzones
│ ├── corp (private, connected to hub)
│ └── online (internet-facing)
├── sandbox
└── decommissioned
az account management-group create --name contoso --display-name "Contoso"
az account management-group create --name landingzones --parent contoso
az account management-group create --name corp --parent landingzones
Assign policy and RBAC at management group level, never subscription by subscription.
2. Subscriptions are units of scale and ownership
- One subscription per workload per environment (app1-prod, app1-dev), not one huge shared subscription.
- Subscriptions hit limits (resource groups, role assignments, API throttling). Splitting early avoids painful moves later.
- Use subscription vending (Terraform/Bicep pipeline) so a new subscription arrives already placed in the right management group, with budget, tags and networking.
3. Baseline policy assignments
| Scope | Policy (built-in or initiative) | Effect |
|---|---|---|
| contoso | Allowed locations (for example Central India, South India) | Deny |
| contoso | Require tags owner, costCenter, env on resource groups | Deny |
| contoso | Configure diagnostic settings to the central Log Analytics workspace | DeployIfNotExists |
| landingzones | Microsoft cloud security benchmark | Audit |
| corp | Deny public IP addresses on NICs | Deny |
| landingzones | Configure Azure Backup on VMs with a given tag | DeployIfNotExists |
az policy assignment create --name allowed-locations \
--scope /providers/Microsoft.Management/managementGroups/contoso \
--policy e56962a6-4747-49cd-b67b-bf8b01975c4c \
--params '{"listOfAllowedLocations":{"value":["centralindia","southindia"]}}'
Tip
Roll out Deny policies in
Audit(or withenforcementMode DoNotEnforce) first, review compliance for a week, then switch to enforce. It avoids breaking running pipelines.
4. Pair regions early
Decide the primary and DR region now (for example Central India + South India). It drives allowed locations, IP address plans, backup vault redundancy and later Site Recovery design.
5. Day-2 checks
az policy state summarize --management-group contoso --query "results.nonCompliantResources"
az account management-group show --name contoso --expand --recurse -o table
Foundation checklist
- Management groups created and subscriptions placed
- Break-glass accounts and PIM in place (see the identity foundation post)
- Central Log Analytics workspace and diagnostic policy
- Hub network and DNS ready before the first corp workload
- Budgets and tags enforced
- Everything defined in code (Bicep/Terraform, Azure Verified Modules)