Files
Cloud-20Engineering/Powershell/Lists/Azure/ServiceBus.ps1
Jurjen Ladenius a226ca97ac added documetation
2025-11-03 08:12:01 +01:00

407 lines
23 KiB
PowerShell
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<#
.SYNOPSIS
Generates a comprehensive inventory of Azure Service Bus resources across all management groups and subscriptions.
.DESCRIPTION
This script enumerates all Azure Service Bus namespaces, topics, topic subscriptions, and queues
within active subscriptions across the entire Azure tenant. It provides detailed hierarchical
mapping of Service Bus messaging infrastructure for monitoring, compliance, and governance reporting.
Key capabilities:
- Multi-tenant Service Bus discovery across all management groups
- Hierarchical messaging structure mapping (namespaces → topics → subscriptions, queues)
- Complete Service Bus topology documentation
- Management group and subscription context tracking
- Resource hierarchy analysis for messaging architecture
- Timestamped CSV export for audit trails and capacity planning
The script processes the complete Service Bus messaging estate including:
- Service Bus namespaces (messaging containers)
- Topics (pub/sub messaging endpoints)
- Topic subscriptions (message consumers)
- Queues (point-to-point messaging endpoints)
.PARAMETER None
This script does not accept parameters and will process all Service Bus resources across all accessible namespaces.
.OUTPUTS
CSV File: "<date> azure service bus.csv"
Contains columns for:
- Resource identification (ID, type, location)
- Management hierarchy (management group, subscription, resource group)
- Service Bus namespace information
- Messaging topology (topic names, subscription names, queue names)
.EXAMPLE
.\ServiceBus.ps1
Discovers all Service Bus resources and generates:
"2024-10-30 1435 azure service bus.csv"
.NOTES
File Name : ServiceBus.ps1
Author : Cloud Engineering Team
Prerequisite : Azure PowerShell modules (Az.ServiceBus, Az.Resources, Az.Accounts)
Copyright : (c) 2024 Effectory. All rights reserved.
Version History:
1.0 - Initial release with comprehensive Service Bus inventory functionality
.LINK
https://docs.microsoft.com/en-us/azure/service-bus-messaging/
https://docs.microsoft.com/en-us/powershell/module/az.servicebus/
.COMPONENT
Requires Azure PowerShell modules:
- Az.ServiceBus (for Service Bus namespace, topic, queue, and subscription enumeration)
- Az.Resources (for resource group and management group access)
- Az.Accounts (for authentication and subscription management)
- Az.Automation (for automation context support)
.ROLE
Required Azure permissions:
- Service Bus Data Reader or higher on all Service Bus namespaces
- Management Group Reader for organizational hierarchy access
- Reader access on target subscriptions
.FUNCTIONALITY
- Multi-subscription Service Bus discovery
- Messaging topology analysis and hierarchical mapping
- Complete Service Bus infrastructure documentation
- CSV export with comprehensive messaging architecture details
#>
#Requires -Modules Az.ServiceBus, Az.Resources, Az.Accounts, Az.Automation
#Requires -Version 5.1
[CmdletBinding()]
param()
# Import required modules
Import-Module Az.Accounts
Import-Module Az.Automation
Import-Module Az.ServiceBus
Import-Module Az.Resources
class ResourceCheck {
[string] $ResourceId = ""
[string] $ManagementGroupId = ""
[string] $ManagementGroupName = ""
[string] $SubscriptionId = ""
[string] $SubscriptionName = ""
[string] $ResourceGroup = ""
[string] $RespourceType = ""
[string] $Location = ""
[string] $ServiceBusName = ""
[string] $TopicName = ""
[string] $TopicSubscriptionName = ""
[string] $QueueName = ""
}
# Initialize script execution
$ErrorActionPreference = "Stop"
$ProgressPreference = "SilentlyContinue"
$startTime = Get-Date
Write-Host "======================================================================================================================================================================"
Write-Host "🚌 AZURE SERVICE BUS INVENTORY GENERATOR" -ForegroundColor Cyan
Write-Host "======================================================================================================================================================================"
Write-Host "⏰ Started: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" -ForegroundColor Green
Write-Host ""
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 ""
# Initialize output file and tracking variables
[string] $date = Get-Date -Format "yyyy-MM-dd HHmm"
$fileName = ".\$date azure service bus.csv"
Write-Host "📄 Output file: $fileName" -ForegroundColor Yellow
Write-Host ""
# Initialize counters for progress tracking
$totalNamespaces = 0
$totalTopics = 0
$totalTopicSubscriptions = 0
$totalQueues = 0
$processedManagementGroups = 0
$processedSubscriptions = 0
# Get management groups for organizational structure
Write-Host "🏗️ Discovering management group structure..." -ForegroundColor Cyan
$managementGroups = Get-AzManagementGroup
Write-Host "✅ Found $($managementGroups.Count) management groups" -ForegroundColor Green
Write-Host ""
# Process each management group
foreach ($managementGroup in $managementGroups) {
$processedManagementGroups++
Write-Host "----------------------------------------------------------------------------------------------------------------------------------------------------------------------"
Write-Host "🏗️ Management Group [$($managementGroup.DisplayName)]" -ForegroundColor Cyan
Write-Host " ID: $($managementGroup.Id)" -ForegroundColor DarkGray
try {
# Get active subscriptions in this management group
$subscriptions = Get-AzManagementGroupSubscription -Group $managementGroup.Name | Where-Object State -eq "Active"
Write-Host " 📋 Found $($subscriptions.Count) active subscriptions" -ForegroundColor Green
foreach ($subscription in $subscriptions) {
$processedSubscriptions++
Write-Host ""
Write-Host " 🔄 Processing Subscription: $($subscription.DisplayName)" -ForegroundColor Yellow
try {
# Extract subscription ID and set context
$scope = $subscription.Id.Substring($subscription.Parent.Length, $subscription.Id.Length - $subscription.Parent.Length)
$subscriptionId = $scope.Replace("/subscriptions/", "")
Write-Host " ID: $subscriptionId" -ForegroundColor DarkGray
Set-AzContext -SubscriptionId $subscriptionId | Out-Null
# Get Service Bus namespaces in the subscription
Write-Host " 🔍 Discovering Service Bus namespaces..." -ForegroundColor Cyan
$servicebusses = Get-AzServiceBusNamespaceV2 -ErrorAction SilentlyContinue
if ($servicebusses.Count -gt 0) {
Write-Host " ✅ Found $($servicebusses.Count) Service Bus namespaces" -ForegroundColor Green
$totalNamespaces += $servicebusses.Count
} else {
Write-Host " No Service Bus namespaces found" -ForegroundColor DarkGray
}
foreach ($servicebus in $servicebusses) {
Write-Host " 📦 Processing namespace: $($servicebus.Name)" -ForegroundColor Yellow
try {
[ResourceCheck[]]$Result = @()
$namespaceTopics = 0
$namespaceTopicSubs = 0
$namespaceQueues = 0
# Add namespace entry
[ResourceCheck] $resourceCheck = [ResourceCheck]::new()
$resourceCheck.ResourceId = $servicebus.Id
$resourceCheck.ManagementGroupId = $managementGroup.Id
$resourceCheck.ManagementGroupName = $managementGroup.DisplayName
$resourceCheck.SubscriptionId = $subscription.Id
$resourceCheck.SubscriptionName = $subscription.DisplayName
$resourceCheck.ResourceGroup = $servicebus.ResourceGroupName
$resourceCheck.RespourceType = $servicebus.Type
$resourceCheck.Location = $servicebus.Location
$resourceCheck.ServiceBusName = $servicebus.Name
$Result += $resourceCheck
# Process topics
Write-Host " 🔍 Discovering topics..." -ForegroundColor DarkCyan
try {
$topics = Get-AzServiceBusTopic -NamespaceName $servicebus.Name -ResourceGroupName $servicebus.ResourceGroupName -ErrorAction SilentlyContinue
if ($topics.Count -gt 0) {
Write-Host " 📊 Found $($topics.Count) topics" -ForegroundColor Green
$namespaceTopics = $topics.Count
$totalTopics += $topics.Count
} else {
Write-Host " No topics found" -ForegroundColor DarkGray
}
foreach ($topic in $topics) {
[ResourceCheck] $resourceCheck = [ResourceCheck]::new()
$resourceCheck.ResourceId = $servicebus.Id
$resourceCheck.ManagementGroupId = $managementGroup.Id
$resourceCheck.ManagementGroupName = $managementGroup.DisplayName
$resourceCheck.SubscriptionId = $subscription.Id
$resourceCheck.SubscriptionName = $subscription.DisplayName
$resourceCheck.ResourceGroup = $servicebus.ResourceGroupName
$resourceCheck.RespourceType = $topic.Type
$resourceCheck.Location = $servicebus.Location
$resourceCheck.ServiceBusName = $servicebus.Name
$resourceCheck.TopicName = $topic.Name
$Result += $resourceCheck
# Process topic subscriptions
try {
$topicSubs = Get-AzServiceBusSubscription -NamespaceName $servicebus.Name -ResourceGroupName $servicebus.ResourceGroupName -TopicName $topic.Name -ErrorAction SilentlyContinue
foreach ($topicSub in $topicSubs) {
[ResourceCheck] $resourceCheck = [ResourceCheck]::new()
$resourceCheck.ResourceId = $servicebus.Id
$resourceCheck.ManagementGroupId = $managementGroup.Id
$resourceCheck.ManagementGroupName = $managementGroup.DisplayName
$resourceCheck.SubscriptionId = $subscription.Id
$resourceCheck.SubscriptionName = $subscription.DisplayName
$resourceCheck.ResourceGroup = $servicebus.ResourceGroupName
$resourceCheck.RespourceType = $topicSub.Type
$resourceCheck.Location = $servicebus.Location
$resourceCheck.ServiceBusName = $servicebus.Name
$resourceCheck.TopicName = $topic.Name
$resourceCheck.TopicSubscriptionName = $topicSub.Name
$Result += $resourceCheck
$namespaceTopicSubs++
$totalTopicSubscriptions++
}
} catch {
Write-Host " ⚠️ Error getting subscriptions for topic '$($topic.Name)': $($_.Exception.Message)" -ForegroundColor Yellow
}
}
} catch {
Write-Host " ❌ Error getting topics: $($_.Exception.Message)" -ForegroundColor Red
}
# Process queues
Write-Host " 🔍 Discovering queues..." -ForegroundColor DarkCyan
try {
$queues = Get-AzServiceBusQueue -NamespaceName $servicebus.Name -ResourceGroupName $servicebus.ResourceGroupName -ErrorAction SilentlyContinue
if ($queues.Count -gt 0) {
Write-Host " 📊 Found $($queues.Count) queues" -ForegroundColor Green
$namespaceQueues = $queues.Count
$totalQueues += $queues.Count
} else {
Write-Host " No queues found" -ForegroundColor DarkGray
}
foreach ($queue in $queues) {
[ResourceCheck] $resourceCheck = [ResourceCheck]::new()
$resourceCheck.ResourceId = $servicebus.Id
$resourceCheck.ManagementGroupId = $managementGroup.Id
$resourceCheck.ManagementGroupName = $managementGroup.DisplayName
$resourceCheck.SubscriptionId = $subscription.Id
$resourceCheck.SubscriptionName = $subscription.DisplayName
$resourceCheck.ResourceGroup = $servicebus.ResourceGroupName
$resourceCheck.RespourceType = $queue.Type
$resourceCheck.Location = $servicebus.Location
$resourceCheck.ServiceBusName = $servicebus.Name
$resourceCheck.QueueName = $queue.Name
$Result += $resourceCheck
}
} catch {
Write-Host " ❌ Error getting queues: $($_.Exception.Message)" -ForegroundColor Red
}
# Export results for this namespace
if ($Result.Count -gt 0) {
$Result | Export-Csv -Path $fileName -Append -NoTypeInformation
Write-Host " ✅ Exported $($Result.Count) Service Bus resources" -ForegroundColor Green
Write-Host " Topics: $namespaceTopics, Subscriptions: $namespaceTopicSubs, Queues: $namespaceQueues" -ForegroundColor DarkGray
}
} catch {
Write-Host " ❌ Error processing namespace '$($servicebus.Name)': $($_.Exception.Message)" -ForegroundColor Red
}
}
} catch {
Write-Host " ❌ Error processing subscription: $($_.Exception.Message)" -ForegroundColor Red
}
}
} catch {
Write-Host " ❌ Error accessing management group: $($_.Exception.Message)" -ForegroundColor Red
}
Write-Host ""
}
# Calculate execution time and generate comprehensive summary report
$endTime = Get-Date
$executionTime = $endTime - $startTime
Write-Host "======================================================================================================================================================================"
Write-Host "📊 AZURE SERVICE BUS INVENTORY SUMMARY" -ForegroundColor Cyan
Write-Host "======================================================================================================================================================================"
Write-Host "⏰ Execution Time: $($executionTime.ToString('hh\:mm\:ss'))" -ForegroundColor Green
Write-Host "🏗️ Management Groups Processed: $processedManagementGroups" -ForegroundColor Green
Write-Host "📋 Subscriptions Processed: $processedSubscriptions" -ForegroundColor Green
Write-Host "🚌 Service Bus Namespaces: $totalNamespaces" -ForegroundColor Green
Write-Host "📡 Topics Discovered: $totalTopics" -ForegroundColor Cyan
Write-Host "📨 Topic Subscriptions: $totalTopicSubscriptions" -ForegroundColor Yellow
Write-Host "📬 Queues Discovered: $totalQueues" -ForegroundColor Magenta
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
}
# Calculate messaging topology insights
$totalMessagingEndpoints = $totalTopics + $totalQueues
$averageTopicsPerNamespace = if ($totalNamespaces -gt 0) { [math]::Round($totalTopics / $totalNamespaces, 1) } else { 0 }
$averageQueuesPerNamespace = if ($totalNamespaces -gt 0) { [math]::Round($totalQueues / $totalNamespaces, 1) } else { 0 }
$averageSubsPerTopic = if ($totalTopics -gt 0) { [math]::Round($totalTopicSubscriptions / $totalTopics, 1) } else { 0 }
if ($totalNamespaces -gt 0) {
Write-Host ""
Write-Host "📈 MESSAGING TOPOLOGY ANALYSIS:" -ForegroundColor Cyan
Write-Host " Total Messaging Endpoints: $totalMessagingEndpoints (Topics + Queues)" -ForegroundColor White
Write-Host " Average Topics per Namespace: $averageTopicsPerNamespace" -ForegroundColor White
Write-Host " Average Queues per Namespace: $averageQueuesPerNamespace" -ForegroundColor White
if ($totalTopics -gt 0) {
Write-Host " Average Subscriptions per Topic: $averageSubsPerTopic" -ForegroundColor White
}
# Provide architecture insights
Write-Host ""
Write-Host "🏗️ ARCHITECTURE INSIGHTS:" -ForegroundColor Cyan
if ($totalTopics -gt $totalQueues) {
Write-Host " 📡 Pub/Sub Pattern Dominant: More topics ($totalTopics) than queues ($totalQueues)" -ForegroundColor Green
Write-Host " This indicates a preference for broadcast messaging patterns" -ForegroundColor White
} elseif ($totalQueues -gt $totalTopics) {
Write-Host " 📬 Point-to-Point Pattern Dominant: More queues ($totalQueues) than topics ($totalTopics)" -ForegroundColor Green
Write-Host " This indicates a preference for direct messaging patterns" -ForegroundColor White
} else {
Write-Host " ⚖️ Balanced Architecture: Equal distribution of topics and queues" -ForegroundColor Green
Write-Host " This indicates a mixed messaging architecture approach" -ForegroundColor White
}
if ($totalTopicSubscriptions -gt ($totalTopics * 2)) {
Write-Host " 🔄 High Fan-out: Multiple consumers per topic (avg: $averageSubsPerTopic subscribers)" -ForegroundColor Yellow
Write-Host " Consider monitoring subscription performance and message distribution" -ForegroundColor White
}
}
Write-Host ""
Write-Host "📈 NEXT STEPS:" -ForegroundColor Cyan
Write-Host " 1. Review the generated CSV file for detailed Service Bus topology" -ForegroundColor White
Write-Host " 2. Analyze messaging patterns and identify optimization opportunities" -ForegroundColor White
Write-Host " 3. Monitor Service Bus performance metrics and throughput" -ForegroundColor White
Write-Host " 4. Consider namespace consolidation for cost optimization" -ForegroundColor White
Write-Host " 5. Implement message monitoring and alerting for critical endpoints" -ForegroundColor White
Write-Host " 6. Review security settings and access policies for each namespace" -ForegroundColor White
Write-Host ""
Write-Host "✅ Azure Service Bus inventory 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 Service Bus Data Reader permissions on target namespaces" -ForegroundColor White
Write-Host " 3. Check that the Management Group Reader role is assigned" -ForegroundColor White
Write-Host " 4. Verify Azure PowerShell modules are installed and up to date" -ForegroundColor White
Write-Host " 5. Confirm that Service Bus namespaces are accessible and not deleted" -ForegroundColor White
Write-Host " 6. Try running the script with -Verbose for additional diagnostic information" -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"
}