Public/Get-AzResourceLocation.ps1
<# .SYNOPSIS Finds the Azure region of a given resource. .DESCRIPTION Resolves a target to get its ip address and finds matching subnets from Azure network service tags. .PARAMETER Target The target DnsName or IpAddress of the resource. .PARAMETER UpdateCache Choose to update the existing service tag cache. .PARAMETER IgnoreCacheDate Don't prompt for a cache update if it is older than 7 days. .PARAMETER ServiceTagSource The source of the service tags. They can either be fetched through Graph API or by downloading a weekly Json file from Microsoft (default). .EXAMPLE Get-AzResourceLocation -Target 'resource.contoso.com' #> Function Get-AzResourceLocation { [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact='Low')] Param( [Parameter( Mandatory, ValueFromPipeline )] [Alias('DnsName', 'IpAddress', 'Host')] [String]$Target, [Switch]$UpdateCache, [Switch]$IgnoreCacheDate, [ServiceTagSource]$ServiceTagSource = [ServiceTagSource]::WeeklyJson ) Begin { # Try to load cache from a previous invocation $Cache = Get-Variable -Scope Script -Name ServiceTagCache -ValueOnly -ErrorAction SilentlyContinue If ($UpdateCache) { Write-Verbose "$($MyInvocation.MyCommand): -UpdateCache used: Force cache update" $Cache = New-AzServiceTagCache -Path $constant_CacheFile -Source $ServiceTagSource If (-not $Cache) { Write-Error "$($MyInvocation.MyCommand): Error during cache creation" Return } } If (-not $Cache) { Write-Verbose "$($MyInvocation.MyCommand): No cache has been loaded yet. Searching for saved cache." # Check if we have a saved cache $Cache = Get-AzServiceTagCache -Path $constant_CacheFile Set-Variable -Scope Script -Name ServiceTagCache -Value $Cache # Do we need to create a new cache? If (-not $Cache) { Write-Verbose "$($MyInvocation.MyCommand): No saved cache has been found. Creating it now." $Cache = New-AzServiceTagCache -Path $constant_CacheFile -Source $ServiceTagSource If (-not $Cache) { Write-Error "$($MyInvocation.MyCommand): Error during cache creation" Return } } Else { Write-Verbose "$($MyInvocation.MyCommand): Saved cache has been found" } } Else { Write-Verbose "$($MyInvocation.MyCommand): Session cache will be used." } # Check cache age and decide if we fetch a new one If($Cache.Date -lt (Get-Date).AddDays(-7) -and -not $IgnoreCacheDate) { Write-Verbose "$($MyInvocation.MyCommand): Cache is outdated. Date: $($Cache.Date)" # TODO: Take actual age of downloaded data into account If($PSCmdlet.ShouldContinue("Your saved cache file is older than 7 days. Would you like to update it?`nUse -IgnoreCacheDate to prevent this message", "Cache out of date")) { $Cache = New-AzServiceTagCache -Path $constant_CacheFile -Source $ServiceTagSource If (-not $Cache) { Write-Error "$($MyInvocation.MyCommand): Error during cache creation" Return } } Else { Write-Verbose "$($MyInvocation.MyCommand): We will use the existing cache" } } } Process { # Check what kind of target we are dealing with # Simple regex test # [System.Net.IPAddress]::TryParse() might be a better option Write-Verbose "$($MyInvocation.MyCommand): Target: $Target" If($Target -notmatch '^(\d+\.){3}\d+') { # Get host addresses $IpAddresses = [System.Net.Dns]::GetHostAddresses($Target).IPAddressToString } Else { # Take target as is $IpAddresses = $Target } # We are treating the target address as collection multiple dns records could have been returned # TODO: Think of a better way to find matches than three loops Foreach($IpAddress in $IpAddresses) { Write-Verbose "$($MyInvocation.MyCommand): Find subnet for address: $IpAddress" Foreach ($ServiceTag in $Cache.Cache) { Foreach ($Subnet in $ServiceTag.Subnets) { If(Test-IpInSubnet -IpAddress $IpAddress -Subnet $Subnet.Subnet -SubnetMask $Subnet.SubnetMask) { [pscustomobject]@{ Target = $Target IpAddress = $IpAddress Region = $ServiceTag.Name SystemService = $ServiceTag.SystemService ChangeNumber = $ServiceTag.ChangeNumber CidrBlock = $Subnet.Subnet + '/' + $Subnet.Cidr } } } } } } } |