Skip to content

Manage Management Groups

The engineer's guide to the management group hierarchy. Use this runbook to:

  • Add a management group.
  • Move or rename one.
  • Get a change applied (any engineer can write it; a senior lets it go live).

For what each group is for, see Management Group Hierarchy. For why it's applied this way, see Tier 0 Just-in-Time CI Apply.

This is Tier 0

Moving a subscription or a group changes which policies and roles it inherits from mg-intermediate-root. Read the plan for every destroy and every parent change before you merge.

Where it lives

Project: t0-azure-management-groups

One file per management group, mg-<name>.tf, each calling solution-manage-management-groups:

module "mg_online" {
  source = "git::https://gitlab.com/grinntec-cloud/terraform-modules/terraform-solutions/solution-manage-management-groups.git?ref=v1.0.0"

  name                       = "mg-online"
  display_name               = "Online"
  parent_management_group_id = module.mg_landingzones.id
}

Platform subscriptions are placed in mg-platform.tf. Workload subscriptions are placed by subscription vending, not here.

Who does what

Step Who Needs
Write the change and open the MR Any engineer Developer on the project
Review and merge A senior engineer Maintainer
Check the saved plan, grant CI access A senior engineer (tier 0) Management Groups (pag-t0-management-groups), PIM-activated
Click apply Anyone who can run main pipelines Allowed to merge to main (protected-branch jobs)

Make a change

Add a management group

  1. Copy an existing mg-*.tf file to mg-<name>.tf.
  2. Set name (mg-<name>, lowercase), display_name and parent_management_group_id.
  3. Rename the module and the output to match.
  4. Keep role_assignments empty. Nothing in this project can grant roles at these groups, and that's on purpose.

Rename or move one

  • display_name: safe, changes in place.
  • Parent: change parent_management_group_id. Moves in place, with its subscriptions and children.
  • name: can't be changed. Azure destroys the group and its role assignments, and moves its children to the tenant root. Create a new group, move things across, then delete the old one in a later MR.

Open the MR

Push a branch and open an MR. CI runs secret scan, fmt, tflint, validate, checkov and plan, and posts the plan as a comment. Get it reviewed and merged.

Apply it

After the merge, the main pipeline plans again, saves the plan, and stops at a manual apply job.

Senior:

  1. Open the main pipeline and read the plan job's output. It's what will be applied.
  2. In PIM → My roles → Groups, activate (tier 0) Management Groups with a justification.
  3. From your checkout of the project:

    az account clear; az login
    git checkout main; git pull
    ./authorize-apply.ps1
    

    It checks your group is active, then gives CI's write identity Management Group Contributor at the tenant root for 30 minutes. You should see "Gave … for 30 minutes".

  4. Tell the engineer to click apply. You're done: you don't revoke anything.

Engineer:

  1. On the same main pipeline, click the apply job's play button. It waits for the access (up to 5 minutes), applies, and removes any Owner Azure gave it. Look for "Apply complete!".

The access ends 30 minutes after step 3, by itself.

Check it worked

  • The apply job ends with "Apply complete!" and "No creator-Owner to remove" (or "Removed Owner …" if it created a group).
  • The portal shows the hierarchy you expect (Management groups).
  • After the 30 minutes, the write identity holds nothing:

    ./authorize-apply.ps1 -Revoke   # also ends the access early if you need to
    

    It ends with "… holds no Azure roles".

When it fails

You see Meaning Do this
apply: "Not authorised yet (try N of 5)" The grant isn't there yet, or the 30 minutes ran out Senior runs ./authorize-apply.ps1 again. The job picks it up on its next try, or retry the job
apply: "No access after 5 tries. Nothing was applied." No grant within 5 minutes Grant, then Retry the job
authorize-apply.ps1: "… isn't active for you" PIM group not active, or you signed in before activating Activate, then az account clear; az login
authorize-apply.ps1: "already has … at the tenant root" An earlier grant is still running Nothing to do; it's usable until it ends
"Saved plan is stale" State changed after CI planned. Nothing was applied Re-run the main pipeline, then grant and apply again
A 403 during the apply The change needs more than Management Group Contributor (for example a role assignment) That change doesn't belong in this project. Don't widen the grant
-Revoke: "still holds the roles above" Someone gave the write identity a role by another route Treat it as a finding: find out who, then remove it

Fallback: human apply

If CI can't run, a senior can still apply main's saved plan locally with ./apply.ps1 and the same PIM group. See Lane A Apply. If that apply creates a management group, you become its Owner. Remove that afterwards (see the project README).