Scripts/Helpers/Test-HydrationCaf3Hierarchy.ps1 (120 lines of code) (raw):
function Test-HydrationCaf3Hierarchy {
<#
.SYNOPSIS
Tests the hierarchy of Azure Management Groups for a specified tenant to see if a standard CAF 3.0 hierarchy is in place.
.DESCRIPTION
This script retrieves the structure of Azure Management Groups for a specified tenant and verifies that the management groups have the correct parent-child relationships.
.PARAMETER TenantId
The Tenant ID of the Azure Active Directory tenant. If not specified, the Tenant ID from the current Azure context will be used.
.EXAMPLE
.\Test-HydrationCaf3Hierarchy -TenantId "your-tenant-id"
This example runs the script for the specified Tenant ID.
.EXAMPLE
.\Test-HydrationCaf3Hierarchy
This example runs the script using the Tenant ID from the current Azure context.
.LINK
https://aka.ms/epac
https://github.com/Azure/enterprise-azure-policy-as-code/tree/main/Docs/start-hydration-kit.md
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $false)]
[string]
$TenantId,
[Parameter(Mandatory = $false)]
[string]
$TenantIntermediateRoot = "TenantIntermediateRoot",
$LogFilePath,
$Output = "./Output",
$MgPrefix = "",
$MgSuffix = ""
)
if (!($LogFilePath)) {
$LogFilePath = Join-Path $Output "Logs" "HydrationTests.log"
}
$mgPairs = [ordered]@{
LandingZones = @("Corp", "Online")
Platform = @("Identity", "Management", "Connectivity")
$TenantIntermediateRoot = @("Decomissioned", "Sandbox", "Platform", "LandingZones")
}
if ((!$TenantId) -or ($TenantId -eq "")) {
$TenantId = (Get-AzContext).Tenant.Id
}
$mgPullIncrement = 0
do {
$mgPullIncrement++
try {
$mgStructure = Get-AzManagementGroupRestMethod -GroupId $TenantId -Expand -Recurse
}
catch {
if ($mgPullIncrement -eq 3) {
Write-Error "Failed to retrieve Management Group structure after 3 attempts, exiting. Reconnect to Azure and retry test."
}
Write-Warning "Failed to retrieve Management Group structure, retrying $(10-$mgPullIncrement) more times..."
}
}until($mgStructure -or $mgPullIncrement -eq 3)
$testResults = @{}
try {
$tenantIntermediateRootResult = Get-AzManagementGroupRestMethod -GroupId $TenantIntermediateRoot -ErrorAction Stop
}
catch {
if (($_.Exception.Message -like "*error 403*" -or $_.Exception.Message -like "*error 404*")) {
$tenantIntermediateRootResult = "Available"
}
else {
Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "$_.Exception.Message" -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Red
Write-Error $_.Exception.Message
}
}
foreach ($mgKey in $mgPairs.keys) {
$currentList = $mgPairs.$mgKey
if($mgKey -eq $TenantIntermediateRoot) {
$parentName = $mgKey
}else{
$parentName = $(-join ($mgPrefix, $mgKey, $mgSuffix))
}
foreach ($mgBase in $currentList) {
$mg = $(-join ($mgPrefix, $mgBase, $mgSuffix))
try {
$mgListing = Get-AzManagementGroupRestMethod -GroupId $mg -ErrorAction Stop
}
catch {
if ($_.Exception.Message -like "*error 403*" -or $_.Exception.Message -like "*error 404*") {
$testResults.add($mg, "Available")
Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "$mg Available: Failed to retrieve management group $mg" -Silent -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
continue
}
else {
Write-Error $_.Exception.Message
Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "$_.Exception.Message" -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Red
return "Failed"
}
}
if ($mgListing.properties.details.parent.name -eq $parentName) {
$testResults.add($mg, "ParentPassed")
Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "$mg has standard CAF3 parent, $parentName" -Silent -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Green
}
else {
Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Standard CAF3 Naming Option Will Fail: Actual Parent `"$($mgListing.properties.details.parent.name)`" for management group `"$mg`" does not match expected parent `"$parentName`"..." -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Yellow
return "FailedNameCollision"
}
}
}
if ($testResults.count -gt 1) {
if ($testResults.Values -contains "ParentPassed" -and (!($testResults.Values -contains "Available"))) {
Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Passed: All Management Groups have the correct parent-child relationships in the CAF3 hierarchy under the management group `"$TenantIntermediateRoot`"." -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Green
return "PassedCaf3Exists"
}
elseif ($testResults.Values -contains "Available" -and (!($testResults.Values -contains "FailedNameCollision"))) {
# Write-HydrationLogFile -EntryType logEntryDataAsPresented -EntryData "Passed: There are existing Management Groups with the same name, but they exist in the appropriate place in the CAF3 hierarchy under the management group `"$TenantIntermediateRoot`". However, the deployment remains incomplete." -LogFilePath $logFilePath -UseUtc:$UseUtc -ForegroundColor Green
return "PassedRunCaf3"
}
else {
$failString = $testResults | ConvertTo-Json -Depth 20
return "Failed, report bug to EPAC team. Data: $failString"
}
}
else {
return "Failed, report bug to EPAC team. No evaluations returned for Test-HydrationCaf3Hierarchy...."
}
}