Private/Azure/Get-AzureEndpoints.ps1
|
function Get-AzureEndpoints { <# .SYNOPSIS Resolves Azure endpoints based on the current cloud environment. .DESCRIPTION Automatically detects the Azure environment (Commercial, Government, China, etc.) from the current Az context and returns the appropriate API endpoints. Supports sovereign clouds and air-gapped environments. Can be overridden with explicit environment name. .PARAMETER AzEnvironment Environment object for testing (mock). .PARAMETER EnvironmentName Explicit environment name override (AzureCloud, AzureUSGovernment, etc.). .OUTPUTS Hashtable with ResourceManagerUrl, PricingApiUrl, and EnvironmentName. .EXAMPLE $endpoints = Get-AzureEndpoints $endpoints.PricingApiUrl # Returns https://prices.azure.com for Commercial .EXAMPLE $endpoints = Get-AzureEndpoints -EnvironmentName 'AzureUSGovernment' $endpoints.PricingApiUrl # Returns https://prices.azure.us #> param( [Parameter(Mandatory = $false)] [object]$AzEnvironment, # For testing - pass a mock environment object [Parameter(Mandatory = $false)] [string]$EnvironmentName # Explicit override by name ) # If explicit environment name provided, look it up if ($EnvironmentName) { try { $AzEnvironment = Get-AzEnvironment -Name $EnvironmentName -ErrorAction Stop if (-not $AzEnvironment) { Write-Warning "Environment '$EnvironmentName' not found. Using default Commercial cloud." } else { Write-Verbose "Using explicit environment: $EnvironmentName" } } catch { Write-Warning "Could not get environment '$EnvironmentName': $_. Using default Commercial cloud." $AzEnvironment = $null } } # Get the current Azure environment if not provided if (-not $AzEnvironment) { try { $context = Get-AzContext -ErrorAction Stop if (-not $context) { Write-Warning "No Azure context found. Using default Commercial cloud endpoints." $AzEnvironment = $null } else { $AzEnvironment = $context.Environment } } catch { Write-Warning "Could not get Azure context: $_. Using default Commercial cloud endpoints." $AzEnvironment = $null } } # Default to Commercial cloud if no environment detected if (-not $AzEnvironment) { return @{ EnvironmentName = 'AzureCloud' ResourceManagerUrl = 'https://management.azure.com' PricingApiUrl = 'https://prices.azure.com/api/retail/prices' } } # Get the Resource Manager URL directly from the environment $armUrl = $AzEnvironment.ResourceManagerUrl if (-not $armUrl) { $armUrl = 'https://management.azure.com' } # Ensure no trailing slash $armUrl = $armUrl.TrimEnd('/') # Derive pricing API URL from the portal URL # Commercial: portal.azure.com -> prices.azure.com # Government: portal.azure.us -> prices.azure.us # China: portal.azure.cn -> prices.azure.cn $portalUrl = $AzEnvironment.ManagementPortalUrl if ($portalUrl) { # Replace only the 'portal' subdomain with 'prices' (more precise than global replace) $pricingUrl = $portalUrl -replace '^(https?://)?portal\.', '${1}prices.' $pricingUrl = $pricingUrl.TrimEnd('/') $pricingApiUrl = "$pricingUrl/api/retail/prices" } else { # Fallback based on known environment names $pricingApiUrl = switch ($AzEnvironment.Name) { 'AzureUSGovernment' { 'https://prices.azure.us/api/retail/prices' } 'AzureChinaCloud' { 'https://prices.azure.cn/api/retail/prices' } 'AzureGermanCloud' { 'https://prices.microsoftazure.de/api/retail/prices' } default { 'https://prices.azure.com/api/retail/prices' } } } $endpoints = @{ EnvironmentName = $AzEnvironment.Name ResourceManagerUrl = $armUrl PricingApiUrl = $pricingApiUrl } Write-Verbose "Azure Environment: $($endpoints.EnvironmentName)" Write-Verbose "Resource Manager URL: $($endpoints.ResourceManagerUrl)" Write-Verbose "Pricing API URL: $($endpoints.PricingApiUrl)" return $endpoints } |