About Azure, Management groups, Subscriptions, and PowerShell, or how to use recursion in PWSH

Olivier Miossec - Sep 20 '21 - - Dev Community

Using management groups is a way to organize your subscriptions into a hierarchy. You can create up to 6 levels of depth under the root level to manage RBAC authorization and Azure Policy. The hierarchy includes containers, management groups, and subscriptions.

In the management group hierarchy child objects, management group or subscription can only have one direct parent and a management group can have several child objects, other management groups, or subscriptions.

After creating the hierarchy and moving subscriptions under management groups how to pragmatically listing subscriptions under any management group container.

PowerShell offers a cmdlet to explore management group

Get-AzManagementGroup
Enter fullscreen mode Exit fullscreen mode

But if you run this cmdlet you will only get an object with the list of your management group without any link between them and no information about attached subscriptions.

For that we need to run the same cmdlet with two switches -expand to list all the children (subscriptions and management groups) and -recurse to recursively list all children. These two switches can only be used with the -groupID parameter. You need to provide a starting point, a management group ID, or the root management group ID (The root management group ID is equal to your tenant ID).

Get-AzManagementGroup -expand -recurse -groupID <ID>
Enter fullscreen mode Exit fullscreen mode

The cmdlet return a PSManagementGroup Object:

Id : /providers/Microsoft.Management/managementGroups/XXX
Type : /providers/Microsoft.Management/managementGroups
Name : XXX
TenantId : XXX
DisplayName : Tenant Root Group
UpdatedTime : 01/01/0001 00:00:00
UpdatedBy :
ParentId :
ParentName :
ParentDisplayName :
Children : {rootomc, group01, group02, First-MG}

You can find several string properties, like ID, the type, the name (the management group ID for management group), displayname, … you will also find a collection (IList) of PSManagementGroupChildInfo. Each member has an index, like in an array, and if you look at one member.

Type : /providers/Microsoft.Management/managementGroups
Id : /providers/Microsoft.Management/managementGroups/rootomc
Name : XXXXX
DisplayName : rootomc
Children : {xxxx}

You will find that PSManagementGroupChildInfo objects are similar to PSManagementGroup objects. You have a type, a name, displayname, ID, and a collection of PSManagementGroupChildInfo. Each element can be either a Management group (/providers/Microsoft.Management/managementGroups) or a subscription (/subscriptions).

So how to list subscriptions from one management group when knowing that data from the cmdlet produce such output? Recursion!
In short, recursion is a function calling itself.

The function needs only one parameter, the collection of PSManagementGroupChildInfo. Then it needs to parse the collection and look at each item type. If the type is a subscription add it to an array, if the type is another management group, call the same function with the child object.

function Expand-ManagementGroup 
{
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [object] 
        $ChildObject
    )
        $subscriptionList = @()
        ForEach($item in $ChildObject.GetEnumerator()) { 
            if ($item.type -eq "/subscriptions") {
                $subHash = @{
                    "name"      = $item.Name   
                    "subId"     = $item.DisplayName 
                }
                $subscriptionList += $subHash
            } 
            elseif ($item.type -eq "/providers/Microsoft.Management/managementGroups") {

                if ($null -ne $item.children) {
                    $subscriptionList += Expand-ManagementGroup -ChildObject $item.children
                }
            }         
        } 
        return $subscriptionList
}
Enter fullscreen mode Exit fullscreen mode

To use the function

Expand-ManagementGroup -ChildObject (Get-AzManagementGroup -GroupId c986548e-494d-4f3a-b716-42287a39531b -Expand -Recurse).Children 
Enter fullscreen mode Exit fullscreen mode
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player