mirror of
https://dev.azure.com/effectory/Survey%20Software/_git/Cloud%20Engineering
synced 2026-02-27 18:52:18 +01:00
461 lines
21 KiB
PowerShell
461 lines
21 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Exports Azure Front Door route configuration and origin mappings to a CSV file.
|
|
|
|
.DESCRIPTION
|
|
This script retrieves and documents the complete routing configuration for an Azure Front Door
|
|
(Standard/Premium) CDN profile. It extracts detailed information about endpoints, routes,
|
|
route patterns, origin groups, and individual origins, providing a comprehensive view of
|
|
traffic routing and backend configurations.
|
|
|
|
The script is designed for:
|
|
- Front Door configuration documentation and auditing
|
|
- Traffic routing analysis and optimization
|
|
- Origin backend inventory and health monitoring
|
|
- Troubleshooting routing issues and misconfigurations
|
|
- Migration planning and configuration validation
|
|
- Compliance documentation for CDN configurations
|
|
|
|
Key features:
|
|
- Complete route topology mapping from endpoints to backends
|
|
- Pattern matching rules documentation
|
|
- Origin health and enabled state tracking
|
|
- Route enablement status monitoring
|
|
- Structured CSV export for analysis and reporting
|
|
|
|
The exported data includes full URL construction for both front-end endpoints and
|
|
backend origins, making it easy to understand the complete request flow through
|
|
the Front Door configuration.
|
|
|
|
.PARAMETER SubscriptionId
|
|
The Azure subscription ID containing the Front Door profile.
|
|
This parameter is optional - if not provided, the script will use the current
|
|
subscription context. Must be a valid GUID format.
|
|
|
|
Example: "4820b5d8-cc1d-49bd-93e5-0c7a656371b7"
|
|
|
|
.PARAMETER ResourceGroupName
|
|
The name of the resource group containing the Front Door profile.
|
|
This parameter is mandatory and is case-sensitive.
|
|
|
|
Example: "my-effectory-global"
|
|
|
|
.PARAMETER FrontDoorName
|
|
The name of the Azure Front Door (Standard/Premium) profile to analyze.
|
|
This parameter is mandatory and is case-sensitive. Must be a valid Front Door
|
|
profile name (not the legacy Front Door Classic).
|
|
|
|
Example: "my-effectory-frontDoor"
|
|
|
|
.EXAMPLE
|
|
.\FrontDoorRoutes.ps1 -SubscriptionId "4820b5d8-cc1d-49bd-93e5-0c7a656371b7" -ResourceGroupName "my-effectory-global" -FrontDoorName "my-effectory-frontDoor"
|
|
|
|
Exports all route configurations for the specified Front Door profile with explicit subscription targeting.
|
|
|
|
.EXAMPLE
|
|
.\FrontDoorRoutes.ps1 -ResourceGroupName "production-rg" -FrontDoorName "prod-frontdoor"
|
|
|
|
Exports route configurations using the current subscription context.
|
|
|
|
.EXAMPLE
|
|
# Analyze multiple Front Door profiles
|
|
$frontDoors = @("frontdoor1", "frontdoor2", "frontdoor3")
|
|
foreach ($fd in $frontDoors) {
|
|
.\FrontDoorRoutes.ps1 -ResourceGroupName "global-rg" -FrontDoorName $fd
|
|
}
|
|
|
|
Batch processes multiple Front Door profiles for comprehensive documentation.
|
|
|
|
.EXAMPLE
|
|
# Export and immediately analyze results
|
|
.\FrontDoorRoutes.ps1 -ResourceGroupName "my-rg" -FrontDoorName "my-frontdoor"
|
|
$results = Import-Csv ".\$(Get-Date -Format 'yyyy-MM-dd HHmm') Front Door Routes (my-frontdoor).csv"
|
|
$results | Where-Object RouteEnabled -eq "Disabled" | Format-Table
|
|
|
|
Exports configuration and immediately identifies disabled routes for analysis.
|
|
|
|
.NOTES
|
|
Author: Cloud Engineering Team
|
|
Version: 1.0
|
|
|
|
Prerequisites:
|
|
- Azure PowerShell module (Az) must be installed
|
|
- Az.Cdn module specifically required for Front Door operations
|
|
- User must be authenticated to Azure (Connect-AzAccount)
|
|
- User must have at least 'Reader' permissions on the Front Door profile
|
|
|
|
Required Permissions:
|
|
- Reader access to the subscription and resource group
|
|
- CDN Profile Reader or Contributor permissions on the Front Door profile
|
|
- Access to Front Door endpoints, routes, and origin groups
|
|
|
|
Front Door Compatibility:
|
|
- Supports Azure Front Door Standard and Premium profiles
|
|
- Does NOT support legacy Azure Front Door Classic (different API)
|
|
- Requires Front Door profile to be in Standard or Premium tier
|
|
|
|
Output File:
|
|
- Format: "YYYY-MM-DD HHMM Front Door Routes ({FrontDoorName}).csv"
|
|
- Location: Current directory
|
|
- Content: Complete route topology with origins and patterns
|
|
|
|
CSV Structure:
|
|
- FrontDoorName: Front Door profile name
|
|
- EndpointName: Front Door endpoint name
|
|
- RouteName: Individual route configuration name
|
|
- RoutePatterns: URL patterns matched by this route (semicolon-separated)
|
|
- RouteUrl: Complete front-end URL for the endpoint
|
|
- OriginGroupName: Backend origin group name
|
|
- OriginName: Individual origin/backend name
|
|
- OriginUrl: Backend origin hostname/URL
|
|
- OriginEnabled: Origin availability status
|
|
- RouteEnabled: Route activation status
|
|
|
|
Performance Considerations:
|
|
- Processing time depends on the number of endpoints and routes
|
|
- Large Front Door configurations may require extended execution time
|
|
- Network latency affects configuration retrieval speed
|
|
|
|
Troubleshooting Notes:
|
|
- Ensure Front Door is Standard/Premium (not Classic)
|
|
- Verify resource group and Front Door names are correct
|
|
- Check that all required Az modules are installed and updated
|
|
- Confirm appropriate permissions on the Front Door resource
|
|
|
|
.LINK
|
|
https://docs.microsoft.com/en-us/azure/frontdoor/
|
|
https://docs.microsoft.com/en-us/powershell/module/az.cdn/
|
|
#>
|
|
|
|
param(
|
|
[Parameter(Mandatory = $false, HelpMessage = "Azure subscription ID (optional - uses current context if not specified)")]
|
|
[ValidateScript({
|
|
if ([string]::IsNullOrEmpty($_) -or ($_ -match '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$')) {
|
|
$true
|
|
} else {
|
|
throw "Subscription ID must be a valid GUID format"
|
|
}
|
|
})]
|
|
[string]$SubscriptionId,
|
|
|
|
[Parameter(Mandatory = $true, HelpMessage = "Resource group name containing the Front Door profile")]
|
|
[ValidateNotNullOrEmpty()]
|
|
[ValidateLength(1, 90)]
|
|
[string]$ResourceGroupName,
|
|
|
|
[Parameter(Mandatory = $true, HelpMessage = "Front Door profile name (Standard/Premium)")]
|
|
[ValidateNotNullOrEmpty()]
|
|
[ValidateLength(1, 260)]
|
|
[string]$FrontDoorName
|
|
)
|
|
|
|
# Display script header and configuration
|
|
Write-Host "======================================================================================================================================================================"
|
|
Write-Host "Azure Front Door Route Configuration Export"
|
|
Write-Host "======================================================================================================================================================================"
|
|
Write-Host "Front Door Profile: $FrontDoorName"
|
|
Write-Host "Resource Group: $ResourceGroupName"
|
|
if ($SubscriptionId) {
|
|
Write-Host "Target Subscription: $SubscriptionId"
|
|
} else {
|
|
Write-Host "Using current subscription context"
|
|
}
|
|
Write-Host "Script execution started: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
|
|
Write-Host "======================================================================================================================================================================"
|
|
Write-Host ""
|
|
|
|
# Generate timestamped filename for export
|
|
[string] $date = Get-Date -Format "yyyy-MM-dd HHmm"
|
|
$fileName = ".\$date Front Door Routes ($FrontDoorName).csv"
|
|
Write-Host "Export file: $fileName"
|
|
Write-Host ""
|
|
|
|
# Ensure Azure authentication
|
|
Write-Host "Verifying Azure authentication..."
|
|
if (-not (Get-AzContext)) {
|
|
Write-Host "No Azure context found. Initiating authentication..."
|
|
try {
|
|
Connect-AzAccount -ErrorAction Stop
|
|
Write-Host "✓ Successfully authenticated to Azure"
|
|
} catch {
|
|
Write-Error "Failed to authenticate to Azure. Please run Connect-AzAccount manually."
|
|
throw $_
|
|
}
|
|
} else {
|
|
Write-Host "✓ Azure authentication verified"
|
|
}
|
|
|
|
# Set target subscription if provided
|
|
if ($SubscriptionId) {
|
|
Write-Host "Setting subscription context..."
|
|
try {
|
|
$context = Select-AzSubscription -SubscriptionId $SubscriptionId -ErrorAction Stop
|
|
Write-Host "✓ Successfully connected to subscription: $($context.Subscription.Name)" -ForegroundColor Green
|
|
} catch {
|
|
Write-Error "Failed to select subscription: $SubscriptionId"
|
|
Write-Error "Please verify the subscription ID and ensure you have access"
|
|
throw $_
|
|
}
|
|
} else {
|
|
$currentContext = Get-AzContext
|
|
Write-Host "✓ Using current subscription: $($currentContext.Subscription.Name)" -ForegroundColor Green
|
|
}
|
|
Write-Host ""
|
|
|
|
Write-Host "======================================================================================================================================================================"
|
|
Write-Host "Retrieving Front Door Configuration"
|
|
Write-Host "======================================================================================================================================================================"
|
|
|
|
try {
|
|
# Get Front Door profile and validate existence
|
|
Write-Host "Accessing Front Door profile '$FrontDoorName'..."
|
|
$frontDoor = Get-AzFrontDoorCdnProfile -ResourceGroupName $ResourceGroupName -Name $FrontDoorName -ErrorAction Stop
|
|
|
|
if (-not $frontDoor) {
|
|
Write-Error "Front Door profile '$FrontDoorName' not found in resource group '$ResourceGroupName'"
|
|
Write-Error "Please verify the Front Door name and resource group are correct"
|
|
return
|
|
}
|
|
|
|
Write-Host "✓ Successfully accessed Front Door profile: $($frontDoor.Name)"
|
|
Write-Host " Profile Type: $($frontDoor.Sku.Name)"
|
|
Write-Host " Profile State: $($frontDoor.FrontDoorId)"
|
|
Write-Host ""
|
|
|
|
# Get all endpoints for the Front Door profile
|
|
Write-Host "Discovering Front Door endpoints..."
|
|
$endpoints = Get-AzFrontDoorCdnEndpoint -ResourceGroupName $ResourceGroupName -ProfileName $FrontDoorName -ErrorAction Stop
|
|
|
|
if (-not $endpoints -or $endpoints.Count -eq 0) {
|
|
Write-Warning "No endpoints found for Front Door profile '$FrontDoorName'"
|
|
Write-Host "This Front Door profile may not have any configured endpoints."
|
|
return
|
|
}
|
|
|
|
Write-Host "✓ Found $($endpoints.Count) endpoint(s):"
|
|
foreach ($endpoint in $endpoints) {
|
|
Write-Host " - $($endpoint.Name) (https://$($endpoint.HostName))"
|
|
}
|
|
Write-Host ""
|
|
# Initialize collection for route data and processing counters
|
|
$routeData = @()
|
|
$totalRoutes = 0
|
|
$totalOrigins = 0
|
|
$enabledRoutes = 0
|
|
$disabledRoutes = 0
|
|
$enabledOrigins = 0
|
|
$disabledOrigins = 0
|
|
|
|
Write-Host "Processing endpoints and route configurations..."
|
|
Write-Host ""
|
|
|
|
# Process each endpoint to extract route and origin information
|
|
foreach ($endpoint in $endpoints) {
|
|
Write-Host "Processing endpoint: $($endpoint.Name)"
|
|
Write-Host " Endpoint URL: https://$($endpoint.HostName)"
|
|
|
|
try {
|
|
# Get all routes configured for this endpoint
|
|
$routes = Get-AzFrontDoorCdnRoute -ResourceGroupName $ResourceGroupName -ProfileName $FrontDoorName -EndpointName $endpoint.Name -ErrorAction Stop
|
|
|
|
if (-not $routes -or $routes.Count -eq 0) {
|
|
Write-Host " ⚠ No routes found for this endpoint" -ForegroundColor Yellow
|
|
continue
|
|
}
|
|
|
|
Write-Host " ✓ Found $($routes.Count) route(s) for endpoint"
|
|
|
|
# Process each route in the endpoint
|
|
foreach ($route in $routes) {
|
|
Write-Host " Processing route: $($route.Name)"
|
|
Write-Host " Patterns: $($route.PatternsToMatch -join ', ')"
|
|
Write-Host " Status: $($route.EnabledState)"
|
|
|
|
# Track route statistics
|
|
$totalRoutes++
|
|
if ($route.EnabledState -eq "Enabled") {
|
|
$enabledRoutes++
|
|
} else {
|
|
$disabledRoutes++
|
|
}
|
|
|
|
try {
|
|
# Extract origin group information from route
|
|
$originGroupId = $route.OriginGroupId
|
|
$originGroupName = ($originGroupId -split '/')[-1]
|
|
|
|
Write-Host " Origin Group: $originGroupName"
|
|
|
|
# Get all origins in the origin group
|
|
$origins = Get-AzFrontDoorCdnOrigin -ResourceGroupName $ResourceGroupName -ProfileName $FrontDoorName -OriginGroupName $originGroupName -ErrorAction Stop
|
|
|
|
if (-not $origins -or $origins.Count -eq 0) {
|
|
Write-Host " ⚠ No origins found in origin group '$originGroupName'" -ForegroundColor Yellow
|
|
|
|
# Create entry even if no origins found
|
|
$routeData += [PSCustomObject]@{
|
|
FrontDoorName = $FrontDoorName
|
|
EndpointName = $endpoint.Name
|
|
RouteName = $route.Name
|
|
RoutePatterns = ($route.PatternsToMatch -join '; ')
|
|
RouteUrl = "https://$($endpoint.HostName)"
|
|
OriginGroupName = $originGroupName
|
|
OriginName = "No origins found"
|
|
OriginUrl = "N/A"
|
|
OriginEnabled = "N/A"
|
|
RouteEnabled = $route.EnabledState
|
|
}
|
|
continue
|
|
}
|
|
|
|
Write-Host " ✓ Found $($origins.Count) origin(s) in group"
|
|
|
|
# Process each origin in the origin group
|
|
foreach ($origin in $origins) {
|
|
Write-Host " Origin: $($origin.Name) -> $($origin.HostName) ($($origin.EnabledState))"
|
|
|
|
# Track origin statistics
|
|
$totalOrigins++
|
|
if ($origin.EnabledState -eq "Enabled") {
|
|
$enabledOrigins++
|
|
} else {
|
|
$disabledOrigins++
|
|
}
|
|
|
|
# Create structured data entry for CSV export
|
|
$routeData += [PSCustomObject]@{
|
|
FrontDoorName = $FrontDoorName
|
|
EndpointName = $endpoint.Name
|
|
RouteName = $route.Name
|
|
RoutePatterns = ($route.PatternsToMatch -join '; ')
|
|
RouteUrl = "https://$($endpoint.HostName)"
|
|
OriginGroupName = $originGroupName
|
|
OriginName = $origin.Name
|
|
OriginUrl = $origin.HostName
|
|
OriginEnabled = $origin.EnabledState
|
|
RouteEnabled = $route.EnabledState
|
|
}
|
|
}
|
|
} catch {
|
|
Write-Host " ❌ Error processing origin group: $($_.Exception.Message)" -ForegroundColor Red
|
|
|
|
# Create error entry for troubleshooting
|
|
$routeData += [PSCustomObject]@{
|
|
FrontDoorName = $FrontDoorName
|
|
EndpointName = $endpoint.Name
|
|
RouteName = $route.Name
|
|
RoutePatterns = ($route.PatternsToMatch -join '; ')
|
|
RouteUrl = "https://$($endpoint.HostName)"
|
|
OriginGroupName = "Error retrieving"
|
|
OriginName = "Error"
|
|
OriginUrl = $_.Exception.Message
|
|
OriginEnabled = "Error"
|
|
RouteEnabled = $route.EnabledState
|
|
}
|
|
}
|
|
}
|
|
} catch {
|
|
Write-Host " ❌ Error processing routes for endpoint '$($endpoint.Name)': $($_.Exception.Message)" -ForegroundColor Red
|
|
}
|
|
|
|
Write-Host ""
|
|
}
|
|
Write-Host "======================================================================================================================================================================"
|
|
Write-Host "Exporting Results and Analysis"
|
|
Write-Host "======================================================================================================================================================================"
|
|
|
|
# Export route configuration to CSV file
|
|
Write-Host "Exporting Front Door route configuration to CSV..."
|
|
try {
|
|
$routeData | Export-Csv -Path $fileName -NoTypeInformation -Force
|
|
Write-Host "✓ Successfully exported $($routeData.Count) route entries to: $fileName" -ForegroundColor Green
|
|
} catch {
|
|
Write-Error "Failed to export route data to CSV: $($_.Exception.Message)"
|
|
throw $_
|
|
}
|
|
|
|
# Display configuration summary table
|
|
Write-Host ""
|
|
Write-Host "Front Door Route Configuration Summary:"
|
|
Write-Host "======================================================================================================================================================================"
|
|
$routeData | Format-Table -Property FrontDoorName, EndpointName, RouteName, RoutePatterns, OriginGroupName, OriginName, RouteEnabled, OriginEnabled -AutoSize
|
|
|
|
# Generate detailed analysis and statistics
|
|
Write-Host ""
|
|
Write-Host "======================================================================================================================================================================"
|
|
Write-Host "Configuration Analysis Summary"
|
|
Write-Host "======================================================================================================================================================================"
|
|
Write-Host "Export completed: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
|
|
Write-Host ""
|
|
Write-Host "Front Door Statistics:"
|
|
Write-Host " Profile Name: $FrontDoorName"
|
|
Write-Host " Profile Type: $($frontDoor.Sku.Name)"
|
|
Write-Host " Total Endpoints: $($endpoints.Count)"
|
|
Write-Host " Total Routes: $totalRoutes"
|
|
Write-Host " Total Origins: $totalOrigins"
|
|
Write-Host ""
|
|
|
|
# Analyze route and origin health status
|
|
Write-Host "Route Status Analysis:"
|
|
Write-Host " ✓ Enabled Routes: $enabledRoutes"
|
|
Write-Host " ❌ Disabled Routes: $disabledRoutes"
|
|
Write-Host ""
|
|
|
|
Write-Host "Origin Status Analysis:"
|
|
Write-Host " ✓ Enabled Origins: $enabledOrigins"
|
|
Write-Host " ❌ Disabled Origins: $disabledOrigins"
|
|
Write-Host ""
|
|
|
|
# Identify potential issues
|
|
$issuesFound = @()
|
|
if ($disabledRoutes -gt 0) {
|
|
$issuesFound += "Some routes are disabled"
|
|
}
|
|
if ($disabledOrigins -gt 0) {
|
|
$issuesFound += "Some origins are disabled"
|
|
}
|
|
|
|
$errorEntries = $routeData | Where-Object { $_.OriginName -eq "Error" }
|
|
if ($errorEntries.Count -gt 0) {
|
|
$issuesFound += "Configuration retrieval errors detected"
|
|
}
|
|
|
|
if ($issuesFound.Count -gt 0) {
|
|
Write-Host "⚠ ATTENTION REQUIRED:"
|
|
foreach ($issue in $issuesFound) {
|
|
Write-Host " - $issue" -ForegroundColor Yellow
|
|
}
|
|
Write-Host " Review the CSV file for detailed information on affected routes/origins"
|
|
} else {
|
|
Write-Host "✓ All routes and origins are enabled and accessible"
|
|
}
|
|
|
|
Write-Host ""
|
|
Write-Host "Output File Information:"
|
|
Write-Host " File Path: $fileName"
|
|
Write-Host " File Size: $([Math]::Round((Get-Item $fileName).Length / 1KB, 2)) KB"
|
|
Write-Host " Records Exported: $($routeData.Count)"
|
|
Write-Host ""
|
|
Write-Host "Recommendations:"
|
|
Write-Host " - Review disabled routes and origins for intentional configuration"
|
|
Write-Host " - Validate routing patterns match expected traffic flow"
|
|
Write-Host " - Monitor origin health and performance regularly"
|
|
Write-Host " - Document configuration changes for audit trails"
|
|
Write-Host "======================================================================================================================================================================"
|
|
|
|
} catch {
|
|
Write-Host ""
|
|
Write-Host "======================================================================================================================================================================"
|
|
Write-Host "❌ ERROR OCCURRED DURING PROCESSING"
|
|
Write-Host "======================================================================================================================================================================"
|
|
Write-Error "Error retrieving Front Door route configuration: $($_.Exception.Message)"
|
|
Write-Host ""
|
|
Write-Host "Troubleshooting Steps:"
|
|
Write-Host " 1. Verify Front Door profile name and resource group are correct"
|
|
Write-Host " 2. ensure the Front Door is Standard or Premium (not Classic)"
|
|
Write-Host " 3. Check that you have appropriate permissions on the Front Door resource"
|
|
Write-Host " 4. Confirm the Az.Cdn PowerShell module is installed and up to date"
|
|
Write-Host " 5. Verify network connectivity to Azure services"
|
|
Write-Host "======================================================================================================================================================================"
|
|
throw $_
|
|
} |