How to query Azure APIs using PowerShell
Azure REST APIs are a great way to manage your Azure resources. You can use them to create, update, delete, and list resources, as well as get information about them.
In many cases, the tools provided by Microsoft - like Azure CLI and Azure PowerShell, do not provide the functionality you need and thus you have to turn to the APIs. As an example, we're going to create a script that will get the size of the storage consumed by Recovery Services Vaults, that is available in Azure Portal but not in the command line tools. So If you have a lot of vaults and you need the size of the storage behind them, you need to automate the process using the Azure APIs.
Below is the entire script, but don't dive right in, let's take it a step at a time!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | # Enable basic parameters [cmdletBinding()] param() # Log in first with Connect-AzAccount if not using Cloud Shell # Get all subscriptions Write-Verbose "Getting available subscriptions" $subscriptions = Get-AzSubscription Write-Verbose ("Found " + $subscriptions.Count.ToString() + " subscriptions") # Get all vaults foreach($s in $subscriptions) { # Select the subscription Set-AzContext -SubscriptionObject $s | out-null # Save subscription info $subscriptionId = $s.id $subscriptionName = $s.Name # Write progress Write-Verbose "`tProcessing subscription $subscriptionName ($subscriptionId)" # Configure the request $azContext = Get-AzContext $azProfile = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile $profileClient = New-Object -TypeName Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient -ArgumentList ($azProfile) $token = $profileClient.AcquireAccessToken($azContext.Subscription.TenantId) $authHeader = @{ 'Content-Type'='application/json' 'Authorization'='Bearer ' + $token.AccessToken 'Accept'='application/json' } # Get the vaults in the subscription $vaults = Get-AzRecoveryServicesVault Write-Verbose ("`tFound " + $vaults.Count.ToString() + " vaults") # Process each vault foreach($v in $vaults) { # Save vault information $vaultId = $v.ID $vaultName = $v.Name $resourceGroupName = $v.ResourceGroupName # Write progress Write-Verbose ("`t`tGetting information for vault " + $vaultName) # Set the URL $restUri = 'https://management.azure.com/Subscriptions/' + $subscriptionId + '/resourceGroups/' + $resourceGroupName + '/providers/Microsoft.RecoveryServices/vaults/' + $vaultName + '/usages?api-version=2022-04-01' # Invoke the API $response = Invoke-RestMethod -Uri $restUri -Method Get -Headers $authHeader -Verbose:$false # Create a custom object $obj = New-Object PSObject $obj | Add-Member -MemberType NoteProperty -Name SubscriptionID -Value $subscriptionId $obj | Add-Member -MemberType NoteProperty -Name SubscriptionName -Value $subscriptionName $obj | Add-Member -MemberType NoteProperty -Name VaultName -Value $vaultName $obj | Add-Member -MemberType NoteProperty -Name VaultID -Value $vaultId $obj | Add-Member -MemberType NoteProperty -Name VaultResourceGroupName -Value $resourceGroupName $obj | Add-Member -MemberType NoteProperty -Name VaultLocation -Value $v.Location # Parse the output $response.value | Where-Object {$_.unit -eq "Bytes"} | ForEach-Object{ # Add a new property for each storage type $size = $_.currentValue $tmp = [PSCustomObject]$_.name $obj | Add-Member -MemberType NoteProperty -Name $tmp.value -Value $size } # Return the new object $obj } } |
The following are the five key steps to query an Azure API:
- Install the Azure PowerShell module.
- Connect to your Azure account.
- Find the endpoint of the API you want to query.
- Create an HTTP request.
- Send the request and receive the response.
Install the Azure PowerShell module
To install the Azure PowerShell module, you can use the Install-Module cmdlet. We are going to need this module in order to log in and get an access token.
Install-Module -Name Az
Connect to your Azure account
Now that we have the Az module installed, it's time to connect to our Azure account, using the Connect-AzAccount cmdlet.
Connect-AzAccount
No special steps up until now, just the usual commands when connecting Powershell to Azure.
Find the endpoint of the API you want to query
Depending on the action you would like to perform, you need to find the right endpoint of the API. For that, we're going to use the Azure documentation.
The primary endpoint of the Azure Resource Manager API is https://management.azure.com, the rest of the path depends on the action to perform and the particular resource. In our case, we would like to get information related to Recovery Services Vaults, thus it is something like:
$restUri = 'https://management.azure.com/Subscriptions/' + $subscriptionId + '/resourceGroups/' + $resourceGroupName + '/providers/Microsoft.RecoveryServices/vaults/' + $vaultName + '/usages?api-version=2022-04-01'
In this case, we're using the Get-AzRecoveryServicesVault cmdlet on each subscription to get the available vaults and use their details on the placeholders in the request Uri.
Create the HTTP request
Now that we have the request Uri ready, it's time to address another requirement for using Azure APIs, which is to use authentication. The request should be authenticated, thus we are extracting the right information from the Powershell session:
$azContext = Get-AzContext $azProfile = [Microsoft.Azure.Commands.Common.Authentication.Abstractions.AzureRmProfileProvider]::Instance.Profile $profileClient = New-Object -TypeName Microsoft.Azure.Commands.ResourceManager.Common.RMProfileClient -ArgumentList ($azProfile) $token = $profileClient.AcquireAccessToken($azContext.Subscription.TenantId) $authHeader = @{ 'Content-Type'='application/json' 'Authorization'='Bearer ' + $token.AccessToken 'Accept'='application/json' }
The better approach is to do this for every subscription, in order to avoid issues with the tokens.
Send the request and receive the response
With the request Uri and headers prepared, it's time to send the request using the Invoke-RestMethod cmdlet.
$response = Invoke-RestMethod -Uri $restUri -Method Get -Headers $authHeader -Verbose:$false
The $response variable contains the response from the Azure API. You can use the ConvertFrom-Json cmdlet to convert the response to a PowerShell object and extract the information you need. From this point on, it's up to you to decide how to handle the information. I usually create custom objects in order to maintain the types of properties.
Below is the output from the execution against my tenant, where I have only one vault:
If you take a closer look at the properties of the objects you'll see that apart from the details of the vault, there are separate properties for each storage type:
For more information about how to query Azure APIs using PowerShell, you can refer to the following documentation: