Since this question was asked back in 2016, Microsoft decided to no longer maintain the AzureRM
module past Dec 2020, and along with it, the *-AzureRM*
cmdlets. The Az
module replaces it going forward.
However, there's a fast alternative for retrieving the list of Azure VMs with their associated IPs (private and public ones), by using Azure Resource Graph (ARG).
Concretely, for several thousand VMs, spread across several hundred Azure subscriptions, it takes mere seconds with ARG as opposed to 20+ minutes using Az
's Get-AzVM
cmdlet.
The script further down will report correctly even on multiple vmNics and multiple IP configurations per vmNic. It will retrieve all ARM VM data across the Azure subscriptions in the tenant. If running from either a local Powershell session or Cloud Shell, make sure you have the Az.ResourceGraph
module installed first.
Sample output on a small test Azure tenant:
The script follows:
function RunARGquery {
param (
[string[]]$SubscriptionIds,
[string]$ARG_query
)
$fullResultSet = @()
$pageSize = 5000
# Subscription batching code below taken
# from https://docs.microsoft.com/en-us/azure/governance/resource-graph/troubleshoot/general#toomanysubscription
# Create a counter, set the batch size, and prepare a variable for the results
$counter = [PSCustomObject] @{ Value = 0 }
$batchSize = 1000
# Group the subscriptions into batches
$subscriptionsBatch = $subscriptionIds | Group -Property { [math]::Floor($counter.Value++ / $batchSize) }
$currentBatchNo = 0
# Run the query for each batch
foreach ($batch in $subscriptionsBatch) {
$pagesProcessedSoFar = 0
do {
$results = @()
if($pagesProcessedSoFar -eq 0) {
$results = Search-AzGraph -Subscription $batch.Group -Query $ARG_query -First $pageSize
}
else {
$results = Search-AzGraph -Subscription $batch.Group -Query $ARG_query -First $pageSize -Skip ($pagesProcessedSoFar * $pageSize)
}
$pagesProcessedSoFar++
Write-Host "Processed $pagesProcessedSoFar pages so far. A number of $(($results | Measure-Object).count) results returned in the last page"
$fullResultSet += $results
} while(($results | Measure-Object).count -eq $pageSize)
Write-Host "Finished subscription batch $currentBatchNo"
$currentBatchNo++
}
return $fullResultSet
}
# Get the date/time now, for timestamping both output files
$currentDateTime = Get-Date -Uformat "%Y%m%d-%H%M%S"
Write-Host "Getting list of Azure subscriptions..."
# Fetch the full array of subscription IDs
$subscriptions = Get-AzSubscription
$subscriptionIds = $subscriptions.Id
Write-Host "Found $(($subscriptionIds | Measure-Object).count) subscriptions"
# ARG query from Listing 23
$ARM_ARG_query = @"
Resources
| where type =~ 'microsoft.compute/virtualmachines'
| project id, vmId = tolower(tostring(id)), vmName = name
| join (Resources
| where type =~ 'microsoft.network/networkinterfaces'
| mv-expand ipconfig=properties.ipConfigurations
| project vmId = tolower(tostring(properties.virtualMachine.id)), privateIp = ipconfig.properties.privateIPAddress, publicIpId = tostring(ipconfig.properties.publicIPAddress.id)
| join kind=leftouter (Resources
| where type =~ 'microsoft.network/publicipaddresses'
| project publicIpId = id, publicIp = properties.ipAddress
) on publicIpId
| project-away publicIpId, publicIpId1
| summarize privateIps = make_list(privateIp), publicIps = make_list(publicIp) by vmId
) on vmId
| project-away vmId, vmId1
| sort by vmName asc
"@
Write-Host "Running ARM ARG query..."
RunARGquery -SubscriptionIds $subscriptionIds -ARG_query $ARM_ARG_query `
| Select-Object -ExcludeProperty ResourceId `
| Sort-Object -Property vmName `
| Export-Csv -NoTypeInformation "AzureVMs_$currentDateTime.csv"
If you're looking to also retrieve the classic Azure VMs (ASM model), using ARG as well, a script is available here. A detailed discussion around the Azure Resource Graph queries for retrieving the VM data, throttling, permissions, etc can be found in this post.