Public/Helpers/Find-AzureServiceTag.ps1
using namespace System.Management.Automation # used for auto-generating the valid values for the ServiceName parameter class AzureServiceNames : IValidateSetValuesGenerator { [string[]] GetValidValues() { try { # Check if serviceTags is loaded and contains items if ($null -eq $script:SessionVariables -or $null -eq $script:SessionVariables.serviceTags) { Write-Warning "Service tags not loaded. Run Update-ServiceTag first." return @('LoadServiceTagsFirst') } # Extract all unique system services from the service tags array return ($script:SessionVariables.serviceTags | Where-Object { $_.properties.systemService } | ForEach-Object { $_.properties.systemService } | Sort-Object -Unique) } catch { Write-Warning "Error retrieving service names: $_" return @('ErrorLoadingServiceNames') } } } class AzureRegionNames : IValidateSetValuesGenerator { [string[]] GetValidValues() { try { # Check if serviceTags is loaded and contains items if ($null -eq $script:SessionVariables -or $null -eq $script:SessionVariables.serviceTags) { Write-Warning "Service tags not loaded. Run Update-ServiceTag first." return @('LoadServiceTagsFirst') } # Extract all unique regions from the service tags array return ($script:SessionVariables.serviceTags | Where-Object { $_.properties.region } | ForEach-Object { $_.properties.region } | Where-Object { -not [string]::IsNullOrWhiteSpace($_) } | Sort-Object -Unique) } catch { Write-Warning "Error retrieving region names: $_" return @('ErrorLoadingRegionNames') } } } function Find-AzureServiceTag { [CmdletBinding(DefaultParameterSetName = 'ByFilters')] [Alias('Get-ServiceTag', 'Find-ServiceTag', 'azure-service-tag', 'find-service-tag')] [OutputType([PSCustomObject[]])] param ( [Parameter( Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'ByIP', HelpMessage = "IP address to lookup in Azure service tags (IPv4 or IPv6)" )] [Alias('ip', 'address', 'host')] [ValidateScript({ if ($_ -match '^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$|^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$|^::1$|^\*\.') { return $true } throw "Invalid IP address format. Please provide a valid IPv4 or IPv6 address." })] [string[]]$IPAddress, [Parameter( Mandatory = $false, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'ByFilters', HelpMessage = "Azure service name to filter by" )] [ValidateSet([AzureServiceNames])] [Alias('service', 'svc', 'service-name')] [string]$ServiceName, [Parameter( Mandatory = $false, ValueFromPipelineByPropertyName = $true, ParameterSetName = 'ByFilters', HelpMessage = "Azure region to filter by" )] [ValidateSet([AzureRegionNames])] [Alias('location', 'region-name', 'loc')] [string]$Region, [Parameter(Mandatory = $false)] [Alias('json', 'raw')] [switch]$AsJson, [Parameter(Mandatory = $false)] [Alias('table', 'list')] [switch]$Detailed ) begin { # Check if service tags are loaded if ($null -eq $script:SessionVariables -or $null -eq $script:SessionVariables.serviceTags -or ($script:SessionVariables.serviceTags).count -le 1) { $errorMsg = "Service tags not loaded. Please run the 'Update-ServiceTag' function." Write-Error $errorMsg -ErrorAction Stop } $results = @() # Create filter for the CIDR to improve performance if IP address is provided if ($IPAddress) { foreach ($ip in $IPAddress) { if ($ip -match '^([0-9A-Fa-f]{1,4}):([0-9A-Fa-f]{1,4}):') { Write-Verbose "Processing IPv6 address: $ip" $firstTwoSegments = $ip.Split(':')[0..1] -join ':' } else { Write-Verbose "Processing IPv4 address: $ip" $firstTwoSegments = $ip.Split('.')[0..1] -join '.' } } } } process { try { if ($IpAddress) { $results = @() $SessionVariables.serviceTags | ForEach-Object { # Check if the IP address matches any of the service tag prefixes within the CIDR range Write-Verbose "Checking service tag: $($_.Name)" foreach ($prefix in $_.properties.addressPrefixes) { if ($IpAddress.Contains("*")) { if ($prefix -match "^$firstTwoSegments") { $addresses = @(Get-CidrAddresses -CidrRange $prefix) if ($addresses -match "$($ipAddress)") { $result = [PSCustomObject]@{ ServiceTagName = $_.Name changeNumber = $_.properties.changeNumber region = ($_.Name.split('.'))[1] regionId = $_.properties.regionId platform = $_.properties.platform systemService = $_.properties.systemService addressPrefixes = $prefix networkFeatures = $_.properties.networkFeatures } $results += $result } } } elseif ($prefix -match "^$firstTwoSegments") { $ip = [System.Net.IPAddress]::Parse($IpAddress) $network = [System.Net.IPNetwork]::Parse($prefix) if ($network.Contains($ip)) { $result = [PSCustomObject]@{ ServiceTagName = $_.Name changeNumber = $_.properties.changeNumber region = ($_.Name.split('.'))[1] regionId = $_.properties.regionId platform = $_.properties.platform systemService = $_.properties.systemService addressPrefixes = $prefix networkFeatures = $_.properties.networkFeatures } $results += $result } } } } if ($results.Count -eq 0) { $results = "No matching service tag found for the given IP address." } } else { $filteredTags = $SessionVariables.serviceTags | Where-Object { $_.properties.region -like "*$Region*" -and $_.properties.systemService -like "*$ServiceName*" } # Create detailed results if needed $results = @() foreach ($tag in $filteredTags) { foreach ($prefix in $tag.properties.addressPrefixes) { if ($Detailed) { $results += [PSCustomObject]@{ ServiceTagName = $tag.Name SystemService = $tag.properties.systemService Region = $tag.properties.region RegionId = $tag.properties.regionId Platform = $tag.properties.platform ChangeNumber = $tag.properties.changeNumber AddressPrefix = $prefix NetworkFeatures = $tag.properties.networkFeatures -join ',' } } else { $results += [PSCustomObject]@{ SystemService = $tag.properties.systemService Region = $tag.properties.region AddressPrefix = $prefix } } } } } # Format the output based on switches if ($AsJson) { return ($results | ConvertTo-Json -Depth 4) } elseif ($Detailed) { return ($results | Format-Table -AutoSize) } else { return $results } } catch { Write-Message -FunctionName $($MyInvocation.MyCommand.Name) -Message $($_.Exception.Message) -Severity 'Error' } } } |