mirror of
https://dev.azure.com/effectory/Survey%20Software/_git/Cloud%20Engineering
synced 2026-02-27 10:45:02 +01:00
updated management groups overview with extra levels for the cost overview #125630
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
.DESCRIPTION
|
||||
This script creates a comprehensive mapping of Azure organizational structure by traversing
|
||||
the management group hierarchy starting from a specified root management group. It discovers
|
||||
and documents all subscriptions within a 3-level management group structure (Level 0-2).
|
||||
and documents all subscriptions within a 5-level management group structure (Level 0-4).
|
||||
|
||||
The script provides detailed organizational visibility including:
|
||||
- Hierarchical management group structure mapping
|
||||
@@ -14,7 +14,7 @@
|
||||
- Multi-level governance structure documentation
|
||||
- CSV export for organizational analysis and compliance reporting
|
||||
|
||||
Note: The script is optimized for a maximum 3-level management group depth and starts
|
||||
Note: The script is optimized for a maximum 5-level management group depth and starts
|
||||
from a configurable root management group ID.
|
||||
|
||||
.PARAMETER RootManagementGroupId
|
||||
@@ -30,6 +30,8 @@
|
||||
- Level 0 Management Group (root level)
|
||||
- Level 1 Management Group (department/division level)
|
||||
- Level 2 Management Group (team/project level)
|
||||
- Level 3 Management Group (workload/application level)
|
||||
- Level 4 Management Group (environment/instance level)
|
||||
|
||||
.EXAMPLE
|
||||
.\ManagementGroups.ps1
|
||||
@@ -56,6 +58,8 @@
|
||||
Version History:
|
||||
1.0 - Initial release with 3-level management group hierarchy discovery
|
||||
1.1 - Added parameterized root management group for flexibility
|
||||
1.2 - Extended to 4-level management group hierarchy (added Level 3)
|
||||
1.3 - Extended to 5-level management group hierarchy (added Level 4)
|
||||
|
||||
.LINK
|
||||
https://docs.microsoft.com/en-us/azure/governance/management-groups/
|
||||
@@ -72,7 +76,7 @@
|
||||
- Reader access to view subscription details within management groups
|
||||
|
||||
.FUNCTIONALITY
|
||||
- Hierarchical management group discovery (3-level maximum)
|
||||
- Hierarchical management group discovery (5-level maximum)
|
||||
- Subscription placement mapping and state tracking
|
||||
- Organizational structure documentation and CSV export
|
||||
- Cross-tenant compatible with configurable root management group
|
||||
@@ -101,9 +105,13 @@ class ResourceCheck {
|
||||
[string] $Level0_ManagementGroupId = ""
|
||||
[string] $Level1_ManagementGroupId = ""
|
||||
[string] $Level2_ManagementGroupId = ""
|
||||
[string] $Level3_ManagementGroupId = ""
|
||||
[string] $Level4_ManagementGroupId = ""
|
||||
[string] $Level0_ManagementGroupName = ""
|
||||
[string] $Level1_ManagementGroupName = ""
|
||||
[string] $Level2_ManagementGroupName = ""
|
||||
[string] $Level3_ManagementGroupName = ""
|
||||
[string] $Level4_ManagementGroupName = ""
|
||||
}
|
||||
|
||||
# Initialize script execution
|
||||
@@ -294,6 +302,132 @@ try {
|
||||
}
|
||||
}
|
||||
|
||||
# Process Level 3 management groups (nested within Level 2)
|
||||
$level3Groups = $level2ManagementGroup.Children | Where-Object Type -EQ 'Microsoft.Management/managementGroups'
|
||||
|
||||
if ($level3Groups.Count -gt 0) {
|
||||
Write-Host " 🔍 Found $($level3Groups.Count) Level 3 management groups" -ForegroundColor Green
|
||||
|
||||
foreach ($level3ManagementGroupLister in $level3Groups) {
|
||||
try {
|
||||
$managementGroupCount++
|
||||
$level3ManagementGroup = Get-AzManagementGroup -Group $level3ManagementGroupLister.Name -Expand -ErrorAction Stop
|
||||
|
||||
Write-Host ""
|
||||
Write-Host " ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────"
|
||||
Write-Host " 📁 LEVEL 3: $($level3ManagementGroup.DisplayName)" -ForegroundColor DarkCyan
|
||||
Write-Host " ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────"
|
||||
|
||||
$subscriptions = $level3ManagementGroup.Children | Where-Object Type -EQ '/subscriptions'
|
||||
Write-Host " 📊 Direct subscriptions: $($subscriptions.Count)" -ForegroundColor Green
|
||||
|
||||
foreach ($subscription in $subscriptions) {
|
||||
try {
|
||||
$scope = $subscription.Id.Substring($subscription.Parent.Length, $subscription.Id.Length - $subscription.Parent.Length)
|
||||
$subscriptionId = $scope.Replace("/subscriptions/", "")
|
||||
|
||||
# Color code subscription state
|
||||
$stateColor = switch ($subscription.State) {
|
||||
"Enabled" { "Green" }
|
||||
"Disabled" { "Red" }
|
||||
"Warned" { "Yellow" }
|
||||
default { "White" }
|
||||
}
|
||||
|
||||
Write-Host " 📋 Subscription: $($subscription.DisplayName) [$subscriptionId] - $($subscription.State)" -ForegroundColor $stateColor
|
||||
|
||||
[ResourceCheck] $resourceCheck = [ResourceCheck]::new()
|
||||
$resourceCheck.Level0_ManagementGroupId = $rootManagementGroup.Id
|
||||
$resourceCheck.Level0_ManagementGroupName = $rootManagementGroup.DisplayName
|
||||
$resourceCheck.Level1_ManagementGroupId = $level1ManagementGroup.Id
|
||||
$resourceCheck.Level1_ManagementGroupName = $level1ManagementGroup.DisplayName
|
||||
$resourceCheck.Level2_ManagementGroupId = $level2ManagementGroup.Id
|
||||
$resourceCheck.Level2_ManagementGroupName = $level2ManagementGroup.DisplayName
|
||||
$resourceCheck.Level3_ManagementGroupId = $level3ManagementGroup.Id
|
||||
$resourceCheck.Level3_ManagementGroupName = $level3ManagementGroup.DisplayName
|
||||
$resourceCheck.SubscriptionId = $subscriptionId
|
||||
$resourceCheck.SubscriptionName = $subscription.DisplayName
|
||||
$resourceCheck.SubscriptionState = $subscription.State
|
||||
$Result += $resourceCheck
|
||||
$totalSubscriptions++
|
||||
|
||||
} catch {
|
||||
Write-Host " ❌ Error processing subscription: $($_.Exception.Message)" -ForegroundColor Red
|
||||
}
|
||||
}
|
||||
|
||||
# Process Level 4 management groups (nested within Level 3)
|
||||
$level4Groups = $level3ManagementGroup.Children | Where-Object Type -EQ 'Microsoft.Management/managementGroups'
|
||||
|
||||
if ($level4Groups.Count -gt 0) {
|
||||
Write-Host " 🔍 Found $($level4Groups.Count) Level 4 management groups" -ForegroundColor Green
|
||||
|
||||
foreach ($level4ManagementGroupLister in $level4Groups) {
|
||||
try {
|
||||
$managementGroupCount++
|
||||
$level4ManagementGroup = Get-AzManagementGroup -Group $level4ManagementGroupLister.Name -Expand -ErrorAction Stop
|
||||
|
||||
Write-Host ""
|
||||
Write-Host " ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────"
|
||||
Write-Host " 📂 LEVEL 4: $($level4ManagementGroup.DisplayName)" -ForegroundColor Blue
|
||||
Write-Host " ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────"
|
||||
|
||||
$subscriptions = $level4ManagementGroup.Children | Where-Object Type -EQ '/subscriptions'
|
||||
Write-Host " 📊 Direct subscriptions: $($subscriptions.Count)" -ForegroundColor Green
|
||||
|
||||
foreach ($subscription in $subscriptions) {
|
||||
try {
|
||||
$scope = $subscription.Id.Substring($subscription.Parent.Length, $subscription.Id.Length - $subscription.Parent.Length)
|
||||
$subscriptionId = $scope.Replace("/subscriptions/", "")
|
||||
|
||||
# Color code subscription state
|
||||
$stateColor = switch ($subscription.State) {
|
||||
"Enabled" { "Green" }
|
||||
"Disabled" { "Red" }
|
||||
"Warned" { "Yellow" }
|
||||
default { "White" }
|
||||
}
|
||||
|
||||
Write-Host " 📋 Subscription: $($subscription.DisplayName) [$subscriptionId] - $($subscription.State)" -ForegroundColor $stateColor
|
||||
|
||||
[ResourceCheck] $resourceCheck = [ResourceCheck]::new()
|
||||
$resourceCheck.Level0_ManagementGroupId = $rootManagementGroup.Id
|
||||
$resourceCheck.Level0_ManagementGroupName = $rootManagementGroup.DisplayName
|
||||
$resourceCheck.Level1_ManagementGroupId = $level1ManagementGroup.Id
|
||||
$resourceCheck.Level1_ManagementGroupName = $level1ManagementGroup.DisplayName
|
||||
$resourceCheck.Level2_ManagementGroupId = $level2ManagementGroup.Id
|
||||
$resourceCheck.Level2_ManagementGroupName = $level2ManagementGroup.DisplayName
|
||||
$resourceCheck.Level3_ManagementGroupId = $level3ManagementGroup.Id
|
||||
$resourceCheck.Level3_ManagementGroupName = $level3ManagementGroup.DisplayName
|
||||
$resourceCheck.Level4_ManagementGroupId = $level4ManagementGroup.Id
|
||||
$resourceCheck.Level4_ManagementGroupName = $level4ManagementGroup.DisplayName
|
||||
$resourceCheck.SubscriptionId = $subscriptionId
|
||||
$resourceCheck.SubscriptionName = $subscription.DisplayName
|
||||
$resourceCheck.SubscriptionState = $subscription.State
|
||||
$Result += $resourceCheck
|
||||
$totalSubscriptions++
|
||||
|
||||
} catch {
|
||||
Write-Host " ❌ Error processing subscription: $($_.Exception.Message)" -ForegroundColor Red
|
||||
}
|
||||
}
|
||||
|
||||
} catch {
|
||||
Write-Host " ❌ Error accessing Level 4 management group '$($level4ManagementGroupLister.Name)': $($_.Exception.Message)" -ForegroundColor Red
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Write-Host " ℹ️ No Level 4 management groups found" -ForegroundColor DarkGray
|
||||
}
|
||||
|
||||
} catch {
|
||||
Write-Host " ❌ Error accessing Level 3 management group '$($level3ManagementGroupLister.Name)': $($_.Exception.Message)" -ForegroundColor Red
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Write-Host " ℹ️ No Level 3 management groups found" -ForegroundColor DarkGray
|
||||
}
|
||||
|
||||
} catch {
|
||||
Write-Host " ❌ Error accessing Level 2 management group '$($level2ManagementGroupLister.Name)': $($_.Exception.Message)" -ForegroundColor Red
|
||||
}
|
||||
@@ -345,13 +479,17 @@ try {
|
||||
# Provide organizational insights
|
||||
$level0Subs = ($Result | Where-Object { [string]::IsNullOrEmpty($_.Level1_ManagementGroupId) }).Count
|
||||
$level1Subs = ($Result | Where-Object { -not [string]::IsNullOrEmpty($_.Level1_ManagementGroupId) -and [string]::IsNullOrEmpty($_.Level2_ManagementGroupId) }).Count
|
||||
$level2Subs = ($Result | Where-Object { -not [string]::IsNullOrEmpty($_.Level2_ManagementGroupId) }).Count
|
||||
$level2Subs = ($Result | Where-Object { -not [string]::IsNullOrEmpty($_.Level2_ManagementGroupId) -and [string]::IsNullOrEmpty($_.Level3_ManagementGroupId) }).Count
|
||||
$level3Subs = ($Result | Where-Object { -not [string]::IsNullOrEmpty($_.Level3_ManagementGroupId) -and [string]::IsNullOrEmpty($_.Level4_ManagementGroupId) }).Count
|
||||
$level4Subs = ($Result | Where-Object { -not [string]::IsNullOrEmpty($_.Level4_ManagementGroupId) }).Count
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "🏗️ ORGANIZATIONAL STRUCTURE:" -ForegroundColor Cyan
|
||||
Write-Host " Root Level (Level 0): $level0Subs subscriptions" -ForegroundColor Green
|
||||
Write-Host " Department/Division Level (Level 1): $level1Subs subscriptions" -ForegroundColor Yellow
|
||||
Write-Host " Team/Project Level (Level 2): $level2Subs subscriptions" -ForegroundColor Magenta
|
||||
Write-Host " Workload/Application Level (Level 3): $level3Subs subscriptions" -ForegroundColor DarkCyan
|
||||
Write-Host " Environment/Instance Level (Level 4): $level4Subs subscriptions" -ForegroundColor Blue
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "📈 NEXT STEPS:" -ForegroundColor Cyan
|
||||
|
||||
Reference in New Issue
Block a user