Azure Azure Governance Azure PowerShell

Azure PowerShell script: Build a management group tree hierarchy

Management groups can be used to effectively manage a company’s various Azure subscriptions and provide them a way to not only control and manage access, but also to apply policies and compliance in an organizational, environment-based or combined hierarchy.

To automate the deployment process of all my planned different child an parent management groups into a tree structure for my Azure test environment, I wrote the below Azure PowerShell script. This script not only allows me to quickly deploy the complete management group hierarchy based on the Enterprise-Scale with hub and spoke architecture. But it is easy to adjust, so it can be used during the deployment of a management group hierarchy for any customer or your own company environment.

This Azure PowerShell script will do all of the following:

  • Checks if PowerShell is run as administrator, otherwise the PowerShell window will be closed (only applies when running the script in Windows Terminal or Windows PowerShell).
  • Import the Azure PowerShell Az module into the PowerShell session.
  • Suppress Breaking Change Messages.
  • Create new GUIDs for all management group IDs (GroupId*) and store them in variables.
  • Define all management group display names (DisplayName*) and store them in variables.
  • Create a customer (or company) management group underneath the tenant root group (root management group).
  • Create top management groups (Platform, Landing Zones, Sandboxes, Decommissioned) underneath the customer management group.
  • Create Platform management groups (Management, Connectivity, Identity) underneath the Platform management group.
  • Create Landing Zones management groups (Corp, Online, SAP) underneath the Landing Zones management group.

* The GroupId (previously GroupName) is a unique identifier which is used by other commands to reference the management group. This ID can not be changed after creation.

* The DisplayName is a human readable name used in the Azure Portal, and which can be changed at all times.


When you run the script, your management group tree hierarchy will be structured like shown in the picture below.



To get a tree overview of your management groups structure, you can follow this Azure tip from a previous blogpost. And if you want to change the default management group for any newly added subscriptions you can follow the guidelines in this blogpost.


Prerequisites

  • In the script change the variables <companyFullName> and <companyShortName> to fit your needs.
  • Before building your Management Group hierarchy, make sure to initialize your root hierarchy.
  • Before running the script logon with “Connect-AzAccount” and select the correct Azure Subscription.


Azure PowerShell script

<#
.SYNOPSIS

A script used to build a management groups tree structure

.DESCRIPTION

A script used to build a management groups tree structure based on the Enterprise-scale architecture with hub and spoke architecture.

.NOTES

Filename:       Build-ManagementGroups-Tree-Hierarchy.ps1
Created:        31/07/2020
Last modified:  29/06/2021
Author:         Wim Matthyssen
PowerShell:     Azure Cloud Shell or Azure PowerShell
Version:        Install latest Azure Powershell modules
Action:         Change variables were needed to fit your needs. 
Disclaimer:     This script is provided "As IS" with no warranties.

.EXAMPLE

Build-ManagementGroups-Tree-Hierarchy.ps1

.LINK

https://wmatthyssen.com/2020/08/01/azure-powershell-script-create-a-management-group-tree-hierarchy/
#>

## ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

## Variables

$companyFullName = "<companyFullName>" # <your company full name here> Example: "myhcjourney"
$companyShortName ="<companyShortName>" # <your company short name here> Best is to use a three letter abbreviation. Example: "myh"

$companyManagementGroupName = "mg-" + $companyFullName 
$companyManagementGroupGuid = New-Guid

$platformManagementGroupName = "mg-" + $companyShortName + "-platform"
$platformManagementGroupGuid = New-Guid
$landingZonesManagementGroupName = "mg-" + $companyShortName + "-landingzones"
$landingZonesManagementGroupGuid = New-Guid
$sandboxesManagementGroupName = "mg-" + $companyShortName + "-sandboxes"
$sandboxesManagementGroupGuid = New-Guid
$decommissionedManagementGroupName = "mg-" + $companyShortName + "-decommissioned"
$decommissionedManagementGroupGuid = New-Guid

$managementManagementGroupName = "mg-" + $companyShortName + "-management"
$managementManagementGroupGuid = New-Guid
$connectivityManagementGroupName = "mg-" + $companyShortName + "-connectivity"
$connectivityManagementGroupGuid = New-Guid
$identityManagementGroupName = "mg-" + $companyShortName + "-identity"
$identityManagementGroupGuid = New-Guid

$corpManagementGroupName = "mg-" + $companyShortName + "-corp"
$corpManagementGroupGuid = New-Guid
$onlineManagementGroupName = "mg-" + $companyShortName + "-online"
$onlineManagementGroupGuid = New-Guid
$sapManagementGroupName = "mg-" + $companyShortName + "-sap"
$sapManagementGroupGuid = New-Guid

$global:currenttime= Set-PSBreakpoint -Variable currenttime -Mode Read -Action {$global:currenttime= Get-Date -UFormat "%A %m/%d/%Y %R"}
$foregroundColor1 = "Red"
$foregroundColor2 = "Yellow"
$writeEmptyLine = "`n"
$writeSeperatorSpaces = " - "

## ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

## Prerequisites

## Check if running as Administrator (when not running from Cloud Shell), otherwise close the PowerShell window

if ($PSVersionTable.Platform -eq "Unix") {
    Write-Host ($writeEmptyLine + "# Running in Cloud Shell" + $writeSeperatorSpaces + $currentTime)
} else {
    $currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
    $isAdministrator = $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)

    if ($isAdministrator -eq $false) {
    Write-Host ($writeEmptyLine + "# Please run PowerShell as Administrator" + $writeSeperatorSpaces + $currentTime +$writeEmptyLine)`
    -foregroundcolor $foregroundColor1
        Start-Sleep -s 4
    exit} else {
        ## Import Az module into the PowerShell session
        Import-Module Az
        Write-Host ($writeEmptyLine + "# Az module imported" + $writeSeperatorSpaces + $currentTime)`
        -foregroundcolor $foregroundColor1 $writeEmptyLine
    }
}

## Suppress breaking change warning messages

Set-Item Env:\SuppressAzurePowerShellBreakingChangeWarnings "true"

## ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

## Deployment started

Write-Host ($writeEmptyLine + "# Deployment started" + $writeSeperatorSpaces + $currentTime)`
-foregroundcolor $foregroundColor1 $writeEmptyLine

## ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

## Create company (or company) management group

New-AzManagementGroup -GroupId $companyManagementGroupGuid -DisplayName $companyManagementGroupName

$companyParentGroup = Get-AzManagementGroup -GroupId $companyManagementGroupGuid

Write-Host ($writeEmptyLine + "# Company management group created" + $writeSeperatorSpaces + $currentTime)`
-foregroundcolor $foregroundColor2 $writeEmptyLine

## ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

## Create top management groups (Platform, Landing Zones, Sandboxes, Decommissioned)

New-AzManagementGroup -GroupId $platformManagementGroupGuid -DisplayName $platformManagementGroupName -ParentObject $companyParentGroup
New-AzManagementGroup -GroupId $landingZonesManagementGroupGuid -DisplayName $landingZonesManagementGroupName -ParentObject $companyParentGroup
New-AzManagementGroup -GroupId $sandboxesManagementGroupGuid -DisplayName $sandboxesManagementGroupName -ParentObject $companyParentGroup
New-AzManagementGroup -GroupId $decommissionedManagementGroupGuid -DisplayName $decommissionedManagementGroupName -ParentObject $companyParentGroup

$platformParentGroup = Get-AzManagementGroup -GroupId $platformManagementGroupGuid 
$landingZonesParentGroup = Get-AzManagementGroup -GroupId $landingZonesManagementGroupGuid

Write-Host ($writeEmptyLine + "# Top management groups created" + $writeSeperatorSpaces + $currentTime)`
-foregroundcolor $foregroundColor2 $writeEmptyLine

## ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

## Create Platform management groups

New-AzManagementGroup -GroupName $managementManagementGroupGuid -DisplayName $managementManagementGroupName -ParentObject $platformParentGroup
New-AzManagementGroup -GroupName $connectivityManagementGroupGuid -DisplayName $connectivityManagementGroupName -ParentObject $platformParentGroup
New-AzManagementGroup -GroupName $identityManagementGroupGuid -DisplayName $identityManagementGroupName -ParentObject $platformParentGroup

Write-Host ($writeEmptyLine + "# Platform management groups created" + $writeSeperatorSpaces + $currentTime)`
-foregroundcolor $foregroundColor2 $writeEmptyLine

## ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

## Create Landing Zones management groups

New-AzManagementGroup -GroupName $corpManagementGroupGuid -DisplayName $corpManagementGroupName -ParentObject $landingZonesParentGroup
New-AzManagementGroup -GroupName $onlineManagementGroupGuid -DisplayName $onlineManagementGroupName -ParentObject $landingZonesParentGroup
New-AzManagementGroup -GroupName $sapManagementGroupGuid -DisplayName $sapManagementGroupName -ParentObject $landingZonesParentGroup

Write-Host ($writeEmptyLine + "# Landing Zones management groups created" + $writeSeperatorSpaces + $currentTime)`
-foregroundcolor $foregroundColor2 $writeEmptyLine

## ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

## Deployment completed

Write-Host ($writeEmptyLine + "# Deployment completed" + $writeSeperatorSpaces + $currentTime)`
-foregroundcolor $foregroundColor1 $writeEmptyLine

## --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------




To use the script copy and save the above as Build-ManagementGroups-Tree-Hierarchy.ps1 or download it from GitHub. Afterwards run the script with Administrator privileges from Windows Terminal, Visual Studio Code, Cloud Shell or PowerShell.



In a previous blog post I have already shown how you can change the display name of the root management group, which can be combined with this script to foresee a uniform naming convention for all your management groups display names.


Conclusion

Management groups are a way to proper organize a companies different Azure subscriptions. They bring more structure, by efficiently managing access, policies and costs in an organizational, environment-based or a combined hierarchy.

Management groups can be up to six levels deep, seven if you include the root management group, and a parent management group can have many child management groups. At the moment a total of up to 10,000 management groups is supported.

Just keep in mind that this number is a limit and definitely not a target. You should avoid to complex structures where it is difficult to keep a good overview or where it is almost impossible to find out which Azure Policy definition or RBAC assignment applies to which child or parent management group.

So I hope this Azure PowerShell script is useful for you and provides a good foundation to foresee a structured management group hierarchy in your Azure ecosystem. If you have any questions or recommendations about it, feel free to contact me through my Twitter handle or to leave a comment.

0 comments on “Azure PowerShell script: Build a management group tree hierarchy

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: