mirror of
https://dev.azure.com/effectory/Survey%20Software/_git/Cloud%20Engineering
synced 2026-02-27 18:52:18 +01:00
added documetation
This commit is contained in:
@@ -1,4 +1,98 @@
|
||||
#Connect-AzAccount
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Generates a hierarchical inventory of Azure Management Groups and Subscriptions.
|
||||
|
||||
.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).
|
||||
|
||||
The script provides detailed organizational visibility including:
|
||||
- Hierarchical management group structure mapping
|
||||
- Subscription placement and organizational context
|
||||
- Subscription state tracking (Active, Disabled, etc.)
|
||||
- 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
|
||||
from a configurable root management group ID.
|
||||
|
||||
.PARAMETER RootManagementGroupId
|
||||
The GUID of the root management group to start the hierarchy discovery from.
|
||||
Defaults to the Effectory organization root management group.
|
||||
|
||||
Example: "12345678-1234-1234-1234-123456789012"
|
||||
|
||||
.OUTPUTS
|
||||
CSV File: "<date> azure_managementgroups.csv"
|
||||
Contains columns for:
|
||||
- Subscription identification (ID, name, state)
|
||||
- Level 0 Management Group (root level)
|
||||
- Level 1 Management Group (department/division level)
|
||||
- Level 2 Management Group (team/project level)
|
||||
|
||||
.EXAMPLE
|
||||
.\ManagementGroups.ps1
|
||||
|
||||
Uses the default Effectory root management group and generates:
|
||||
"2024-10-30 1435 azure_managementgroups.csv"
|
||||
|
||||
.EXAMPLE
|
||||
.\ManagementGroups.ps1 -RootManagementGroupId "87654321-4321-4321-4321-210987654321"
|
||||
|
||||
Discovers management group hierarchy starting from a custom root management group.
|
||||
|
||||
.EXAMPLE
|
||||
.\ManagementGroups.ps1 -RootManagementGroupId "tenant-root-mg" -Verbose
|
||||
|
||||
Runs with verbose output for detailed discovery logging.
|
||||
|
||||
.NOTES
|
||||
File Name : ManagementGroups.ps1
|
||||
Author : Cloud Engineering Team
|
||||
Prerequisite : Azure PowerShell module (Az.Resources, Az.Accounts)
|
||||
Copyright : (c) 2024 Effectory. All rights reserved.
|
||||
|
||||
Version History:
|
||||
1.0 - Initial release with 3-level management group hierarchy discovery
|
||||
1.1 - Added parameterized root management group for flexibility
|
||||
|
||||
.LINK
|
||||
https://docs.microsoft.com/en-us/azure/governance/management-groups/
|
||||
https://docs.microsoft.com/en-us/powershell/module/az.resources/
|
||||
|
||||
.COMPONENT
|
||||
Requires Azure PowerShell modules:
|
||||
- Az.Resources (for management group and subscription enumeration)
|
||||
- Az.Accounts (for authentication and context management)
|
||||
|
||||
.ROLE
|
||||
Required Azure permissions:
|
||||
- Management Group Reader on the root management group and all child groups
|
||||
- Reader access to view subscription details within management groups
|
||||
|
||||
.FUNCTIONALITY
|
||||
- Hierarchical management group discovery (3-level maximum)
|
||||
- Subscription placement mapping and state tracking
|
||||
- Organizational structure documentation and CSV export
|
||||
- Cross-tenant compatible with configurable root management group
|
||||
#>
|
||||
|
||||
#Requires -Modules Az.Resources, Az.Accounts
|
||||
#Requires -Version 5.1
|
||||
|
||||
# Uncomment the following line if authentication is required
|
||||
#Connect-AzAccount
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(
|
||||
Mandatory = $false,
|
||||
HelpMessage = "The GUID of the root management group to start hierarchy discovery from"
|
||||
)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string]$RootManagementGroupId = 'e9792fd7-4044-47e7-a40d-3fba46f1cd09'
|
||||
)
|
||||
|
||||
class ResourceCheck {
|
||||
[string] $SubscriptionId = ""
|
||||
@@ -12,102 +106,286 @@ class ResourceCheck {
|
||||
[string] $Level2_ManagementGroupName = ""
|
||||
}
|
||||
|
||||
Write-Host "======================================================================================================================"
|
||||
Write-Host "Creating list of Effectory Management Groups and subscriptions."
|
||||
Write-Host "- Note: not very dynamic; Starts at hard coded root group and works up max 2 levels."
|
||||
Write-Host "======================================================================================================================"
|
||||
# Initialize script execution
|
||||
$ErrorActionPreference = "Stop"
|
||||
$ProgressPreference = "SilentlyContinue"
|
||||
$startTime = Get-Date
|
||||
|
||||
[string] $date = Get-Date -Format "yyyy-MM-dd HHmm"
|
||||
$fileName = ".\$date azure_managementgroups.csv"
|
||||
[ResourceCheck[]]$Result = @()
|
||||
Write-Host "======================================================================================================================================================================"
|
||||
Write-Host "🏗️ AZURE MANAGEMENT GROUP STRUCTURE DISCOVERY" -ForegroundColor Cyan
|
||||
Write-Host "======================================================================================================================================================================"
|
||||
Write-Host "⏰ Started: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
|
||||
$rootManagementGroup = (Get-AzManagementGroup -GroupId 'e9792fd7-4044-47e7-a40d-3fba46f1cd09' -Expand)[0]
|
||||
|
||||
#level 0
|
||||
Write-Host "---------------------------------------------------------------------------------------------"
|
||||
Write-Host "Level 0 Management group [$($rootManagementGroup.Name)]"
|
||||
Write-Host "---------------------------------------------------------------------------------------------"
|
||||
|
||||
$subscriptions = $rootManagementGroup.Children | Where-Object Type -EQ '/subscriptions'
|
||||
|
||||
foreach ($subscription in $subscriptions)
|
||||
{
|
||||
$scope = $subscription.Id.Substring($subscription.Parent.Length, $subscription.Id.Length - $subscription.Parent.Length)
|
||||
$subscriptionId = $scope.Replace("/subscriptions/", "")
|
||||
Write-Host "Subscription [$($subscription.DisplayName) - $subscriptionId]"
|
||||
|
||||
[ResourceCheck] $resourceCheck = [ResourceCheck]::new()
|
||||
$resourceCheck.Level0_ManagementGroupId = $rootManagementGroup.Id
|
||||
$resourceCheck.Level0_ManagementGroupName = $rootManagementGroup.DisplayName
|
||||
$resourceCheck.SubscriptionId = $subscriptionId
|
||||
$resourceCheck.SubscriptionName = $subscription.DisplayName
|
||||
$resourceCheck.SubscriptionState = $subscription.State
|
||||
$Result += $resourceCheck
|
||||
}
|
||||
|
||||
#level 1
|
||||
foreach ($level1ManagementGroupLister in ($rootManagementGroup.Children | Where-Object Type -EQ 'Microsoft.Management/managementGroups'))
|
||||
{
|
||||
$level1ManagementGroup = (Get-AzManagementGroup -Group $level1ManagementGroupLister.Name -Expand)[0]
|
||||
|
||||
Write-Host " ---------------------------------------------------------------------------------------------"
|
||||
Write-Host " Level 1 Management group [$($level1ManagementGroup.Name)]"
|
||||
Write-Host " ---------------------------------------------------------------------------------------------"
|
||||
|
||||
$subscriptions = $level1ManagementGroup.Children | Where-Object Type -EQ '/subscriptions'
|
||||
|
||||
foreach ($subscription in $subscriptions)
|
||||
{
|
||||
$scope = $subscription.Id.Substring($subscription.Parent.Length, $subscription.Id.Length - $subscription.Parent.Length)
|
||||
$subscriptionId = $scope.Replace("/subscriptions/", "")
|
||||
Write-Host " Subscription [$($subscription.DisplayName) - $subscriptionId]"
|
||||
|
||||
[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.SubscriptionId = $subscriptionId
|
||||
$resourceCheck.SubscriptionName = $subscription.DisplayName
|
||||
$resourceCheck.SubscriptionState = $subscription.State
|
||||
$Result += $resourceCheck
|
||||
try {
|
||||
# Validate Azure authentication
|
||||
$context = Get-AzContext
|
||||
if (-not $context) {
|
||||
throw "No Azure context found. Please run Connect-AzAccount first."
|
||||
}
|
||||
|
||||
Write-Host "🔐 Authenticated as: $($context.Account.Id)" -ForegroundColor Green
|
||||
Write-Host "🏢 Tenant: $($context.Tenant.Id)" -ForegroundColor Green
|
||||
Write-Host "🎯 Root Management Group: $RootManagementGroupId" -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
|
||||
# Initialize output file and tracking variables
|
||||
[string] $date = Get-Date -Format "yyyy-MM-dd HHmm"
|
||||
$fileName = ".\$date azure_managementgroups.csv"
|
||||
Write-Host "📄 Output file: $fileName" -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
|
||||
[ResourceCheck[]]$Result = @()
|
||||
$totalSubscriptions = 0
|
||||
$managementGroupCount = 0
|
||||
|
||||
# Get root management group with error handling
|
||||
Write-Host "🔍 Discovering root management group structure..." -ForegroundColor Cyan
|
||||
$rootManagementGroup = Get-AzManagementGroup -GroupId $RootManagementGroupId -Expand -ErrorAction Stop
|
||||
|
||||
if (-not $rootManagementGroup) {
|
||||
throw "Root management group '$RootManagementGroupId' not found or not accessible."
|
||||
}
|
||||
|
||||
Write-Host "✅ Root Management Group: $($rootManagementGroup.DisplayName)" -ForegroundColor Green
|
||||
Write-Host " ID: $($rootManagementGroup.Id)" -ForegroundColor DarkGray
|
||||
Write-Host ""
|
||||
|
||||
#level 2
|
||||
foreach ($level2ManagementGroupLister in ($level1ManagementGroup.Children | Where-Object Type -EQ 'Microsoft.Management/managementGroups'))
|
||||
{
|
||||
$level2ManagementGroup = (Get-AzManagementGroup -Group $level2ManagementGroupLister.Name -Expand)[0]
|
||||
# Process Level 0 (Root) subscriptions
|
||||
$managementGroupCount++
|
||||
Write-Host "----------------------------------------------------------------------------------------------------------------------------------------------------------------------"
|
||||
Write-Host "📋 LEVEL 0 (Root): $($rootManagementGroup.DisplayName)" -ForegroundColor Cyan
|
||||
Write-Host "----------------------------------------------------------------------------------------------------------------------------------------------------------------------"
|
||||
|
||||
Write-Host " ---------------------------------------------------------------------------------------------"
|
||||
Write-Host " Level 2 Management group [$($level2ManagementGroup.Name)]"
|
||||
Write-Host " ---------------------------------------------------------------------------------------------"
|
||||
|
||||
$subscriptions = $level2ManagementGroup.Children | Where-Object Type -EQ '/subscriptions'
|
||||
$subscriptions = $rootManagementGroup.Children | Where-Object Type -EQ '/subscriptions'
|
||||
Write-Host " 📊 Direct subscriptions: $($subscriptions.Count)" -ForegroundColor Green
|
||||
|
||||
foreach ($subscription in $subscriptions)
|
||||
{
|
||||
foreach ($subscription in $subscriptions) {
|
||||
try {
|
||||
$scope = $subscription.Id.Substring($subscription.Parent.Length, $subscription.Id.Length - $subscription.Parent.Length)
|
||||
$subscriptionId = $scope.Replace("/subscriptions/", "")
|
||||
Write-Host " Subscription [$($subscription.DisplayName) - $subscriptionId]"
|
||||
|
||||
|
||||
# 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.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 1 management groups
|
||||
$level1Groups = $rootManagementGroup.Children | Where-Object Type -EQ 'Microsoft.Management/managementGroups'
|
||||
Write-Host ""
|
||||
Write-Host "🔍 Found $($level1Groups.Count) Level 1 management groups" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
|
||||
foreach ($level1ManagementGroupLister in $level1Groups) {
|
||||
try {
|
||||
$managementGroupCount++
|
||||
$level1ManagementGroup = Get-AzManagementGroup -Group $level1ManagementGroupLister.Name -Expand -ErrorAction Stop
|
||||
|
||||
Write-Host " ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────"
|
||||
Write-Host " 📂 LEVEL 1: $($level1ManagementGroup.DisplayName)" -ForegroundColor Yellow
|
||||
Write-Host " ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────"
|
||||
|
||||
$subscriptions = $level1ManagementGroup.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.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 1 management group '$($level1ManagementGroupLister.Name)': $($_.Exception.Message)" -ForegroundColor Red
|
||||
}
|
||||
|
||||
# Process Level 2 management groups (nested within Level 1)
|
||||
$level2Groups = $level1ManagementGroup.Children | Where-Object Type -EQ 'Microsoft.Management/managementGroups'
|
||||
|
||||
if ($level2Groups.Count -gt 0) {
|
||||
Write-Host " 🔍 Found $($level2Groups.Count) Level 2 management groups" -ForegroundColor Green
|
||||
|
||||
foreach ($level2ManagementGroupLister in $level2Groups) {
|
||||
try {
|
||||
$managementGroupCount++
|
||||
$level2ManagementGroup = Get-AzManagementGroup -Group $level2ManagementGroupLister.Name -Expand -ErrorAction Stop
|
||||
|
||||
Write-Host ""
|
||||
Write-Host " ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────"
|
||||
Write-Host " 📁 LEVEL 2: $($level2ManagementGroup.DisplayName)" -ForegroundColor Magenta
|
||||
Write-Host " ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────"
|
||||
|
||||
$subscriptions = $level2ManagementGroup.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.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 2 management group '$($level2ManagementGroupLister.Name)': $($_.Exception.Message)" -ForegroundColor Red
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Write-Host " ℹ️ No Level 2 management groups found" -ForegroundColor DarkGray
|
||||
}
|
||||
}
|
||||
|
||||
# Export results to CSV
|
||||
Write-Host ""
|
||||
Write-Host "💾 Exporting results to CSV..." -ForegroundColor Cyan
|
||||
$Result | Export-Csv -Path $fileName -NoTypeInformation
|
||||
|
||||
# Calculate execution time and generate summary report
|
||||
$endTime = Get-Date
|
||||
$executionTime = $endTime - $startTime
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "======================================================================================================================================================================"
|
||||
Write-Host "📊 AZURE MANAGEMENT GROUP DISCOVERY SUMMARY" -ForegroundColor Cyan
|
||||
Write-Host "======================================================================================================================================================================"
|
||||
Write-Host "⏰ Execution Time: $($executionTime.ToString('hh\:mm\:ss'))" -ForegroundColor Green
|
||||
Write-Host "🏗️ Management Groups Discovered: $managementGroupCount" -ForegroundColor Green
|
||||
Write-Host "📋 Total Subscriptions Found: $totalSubscriptions" -ForegroundColor Green
|
||||
Write-Host "📄 Results Exported To: $fileName" -ForegroundColor Yellow
|
||||
|
||||
if (Test-Path $fileName) {
|
||||
$fileSize = (Get-Item $fileName).Length
|
||||
Write-Host "💾 File Size: $([math]::Round($fileSize/1KB, 2)) KB" -ForegroundColor Green
|
||||
}
|
||||
|
||||
# Analyze subscription states
|
||||
$subscriptionStates = $Result | Group-Object SubscriptionState
|
||||
if ($subscriptionStates.Count -gt 0) {
|
||||
Write-Host ""
|
||||
Write-Host "📈 SUBSCRIPTION STATE ANALYSIS:" -ForegroundColor Cyan
|
||||
foreach ($state in $subscriptionStates) {
|
||||
$stateColor = switch ($state.Name) {
|
||||
"Enabled" { "Green" }
|
||||
"Disabled" { "Red" }
|
||||
"Warned" { "Yellow" }
|
||||
default { "White" }
|
||||
}
|
||||
Write-Host " $($state.Name): $($state.Count) subscriptions" -ForegroundColor $stateColor
|
||||
}
|
||||
}
|
||||
|
||||
# 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
|
||||
|
||||
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 ""
|
||||
Write-Host "📈 NEXT STEPS:" -ForegroundColor Cyan
|
||||
Write-Host " 1. Review the generated CSV file for detailed organizational mapping" -ForegroundColor White
|
||||
Write-Host " 2. Analyze subscription placement for governance compliance" -ForegroundColor White
|
||||
Write-Host " 3. Consider moving orphaned subscriptions to appropriate management groups" -ForegroundColor White
|
||||
Write-Host " 4. Use this data for policy assignment and resource organization planning" -ForegroundColor White
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "✅ Azure Management Group discovery completed successfully!" -ForegroundColor Green
|
||||
Write-Host "======================================================================================================================================================================"
|
||||
|
||||
} catch {
|
||||
Write-Host ""
|
||||
Write-Host "❌ CRITICAL ERROR OCCURRED" -ForegroundColor Red
|
||||
Write-Host "======================================================================================================================================================================"
|
||||
Write-Host "Error: $($_.Exception.Message)" -ForegroundColor Red
|
||||
Write-Host "Line: $($_.InvocationInfo.ScriptLineNumber)" -ForegroundColor Red
|
||||
Write-Host "Position: $($_.InvocationInfo.OffsetInLine)" -ForegroundColor Red
|
||||
Write-Host ""
|
||||
Write-Host "🔧 TROUBLESHOOTING STEPS:" -ForegroundColor Yellow
|
||||
Write-Host " 1. Verify you are authenticated to Azure (Connect-AzAccount)" -ForegroundColor White
|
||||
Write-Host " 2. Ensure you have Management Group Reader permissions on the root management group" -ForegroundColor White
|
||||
Write-Host " 3. Verify the root management group ID '$RootManagementGroupId' exists and is accessible" -ForegroundColor White
|
||||
Write-Host " 4. Check that Azure PowerShell modules are installed and up to date" -ForegroundColor White
|
||||
Write-Host " 5. Try running with a different root management group ID if the current one is invalid" -ForegroundColor White
|
||||
Write-Host ""
|
||||
Write-Host "📞 For additional support, contact the Cloud Engineering team" -ForegroundColor Cyan
|
||||
Write-Host "======================================================================================================================================================================"
|
||||
|
||||
# Ensure we exit with error code for automation scenarios
|
||||
exit 1
|
||||
} finally {
|
||||
# Reset progress preference
|
||||
$ProgressPreference = "Continue"
|
||||
}
|
||||
|
||||
$Result | Export-Csv -Path $fileName -NoTypeInformation
|
||||
|
||||
|
||||
Write-Host "============================================================================================="
|
||||
Write-Host "Done."
|
||||
|
||||
|
||||
Reference in New Issue
Block a user