
Resource health through Azure Rest API
As a part of a large monitoring project involving on prem, Azure and Office 365 I have started to explore the different methods on how to acquire all relevent data. Previously, I have written a post on how you authenticate against Microsoft’s partner center API which is a part of the same feasibility project.
Later down the road i will try to write a larger blog series on how we can monitor Microsoft Cloud and on-Prem resources. Hopefully it will be joyful…
This blog post will describe how you can use Powershell to authenticate and get availability status from all resource groups and their resources. If you’re not that interested in monitoring data, use this post as a guide on how to get started with the API and the rest is documented on the Azure API documentation pages.
High level overview:
- Set up an Azure Active Directory Application to authenticate (not covered)
- Build an authentication header with a token from Azure AD
- Get all resource groups within a subscription
- Get the availability of all resources within a resource group
Get Azure AD application token
After setting up/registering the application in Azure AD you will have to use the application ID and secret in order to generate an authentication token to use against Azure management Rest API’s. I have created a basic Powershell function you can use, including an example authentication header.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$result = Get-AADAppoAuthToken -ClientID <AzureAD APPLICATION ID> -ClientSecret <ClientSecret> -TenantId "test.no" | |
$AuthKey = "Bearer " + ($result.access_token) | |
$authHeader = @{ | |
'Content-Type' = 'application/json' | |
'Accept' = 'application/json' | |
'Authorization' = $AuthKey | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.SYNOPSIS | |
Function to connect to the Microsoft login OAuth endpoint and return an OAuth token. | |
.DESCRIPTION | |
Generate Azure AD oauth token. | |
You can specify the resource you want in the paramenter. Default is management.core.windows.net | |
Parts of this function is created from these examples: https://docs.microsoft.com/en-us/azure/monitoring-and-diagnostics/monitoring-rest-api-walkthrough | |
.PARAMETER ClientID | |
Azure AD application ID | |
.PARAMETER ClientSecret | |
Your application secret. | |
.PARAMETER TenantId | |
Your tenant domain name. test.onmicrosoft.com | |
.PARAMETER ResourceName | |
Specify if you are accessing other resources than https://management.core.windows.net | |
For example microsoft partner center would have https://api.partnercenter.microsoft.com | |
.EXAMPLE | |
Get-AADAppoAuthToken -ClientID 'xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' -ClientSecret <application secret> -TenantId "test.no" will return | |
token_type : Bearer | |
expires_in : 3600 | |
ext_expires_in : 0 | |
expires_on : 1505133623 | |
not_before : 1505129723 | |
resource : https://management.core.windows.net/ | |
access_token : eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IkhIQnlLVS0wRHFBcU1aaDZaRlBkMlZXYU90ZyIsImtpZCI6IkhIQnlLVS0wRHFBcU1aaDZaRlB | |
kMlZXYU90ZyJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS53aW5kb3dzLm5ldC8iLCJpc3MiOiJodHRwczovL3N0cy | |
.NOTES | |
v1.0 | |
Martin Ehrnst 2017 | |
#> | |
[Cmdletbinding()] | |
Param( | |
[Parameter(Mandatory = $true)] | |
[string]$ClientID, | |
[Parameter(Mandatory = $true)] | |
[string]$ClientSecret, | |
[Parameter(Mandatory = $true)] | |
[string]$TenantId, | |
[Parameter(Mandatory = $false)] | |
[string]$ResourceName = "https://management.core.windows.net/" | |
) | |
$LoginURL = 'https://login.windows.net' | |
#Get application access token | |
$Body = @{ | |
grant_type = "client_credentials"; | |
resource = $ResourceName; | |
client_id = $ClientID; | |
client_secret = $ClientSecret | |
} | |
Return Invoke-RestMethod -Method Post -Uri $LoginURL/$TenantId/oauth2/token -Body $Body | |
} |
Get all resource groups and resources
Next we will grab all resource groups within a subscription, before looping through each resource group to get the individual resources.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Loop through each reasource group and get all resources. | |
#Add everything to a hash table | |
$Groups = @() | |
foreach ($rg in $ResourceGroups) { | |
$ResourceGroupUri = "https://management.azure.com/subscriptions/$subscriptionID/resourceGroups/$rg/resources?api-version=$APIVersion" | |
$res = (Invoke-RestMethod -Uri $ResourceGroupUri -Method GET -Headers $authHeader).value | |
#Create array of all resources | |
$resources = @{} | |
$resources.Add($rg, $res) | |
#Add all resource groups and their resources to a hash table | |
$Groups += $resources | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#get all resource groups within a subscription | |
$APIVersion = "2017-05-10" | |
$subscriptionID = "xxxxxxxxxxxx-xxx-xxx-xxxxxxxxxx" | |
$RGURI = "https://management.azure.com/subscriptions/$subscriptionID/resourcegroups?api-version=$APIVersion" | |
$ResourceGroups = (Invoke-RestMethod -Uri $RGuri -Method GET -Headers $authHeader).value.name |
Now that we have all resource group and all resources within we can use this to further get the resource health and availability. To be honest we don’t need to get RG before checking the resources it self, but as a starting point i find it very useful to have the resource groups and their resources available within my scripts.
Get the resource availability status
Now we have authenticated, grabbed all resource groups and their resources and it’s time to find our resource health. There are multiple ways on how to get this data, and we have to consider the methods we use. One limitation i hit pretty fast working with this is the number of subscription resource get requests, specified in the response header “x-ms-ratelimit-remaining-subscription-resource-requests: ” All limitations documentet, here
When you hit this limit every substantial requests is dropped. I have to rethink my whole monitoring scenario due to these limitations.
Get Resource health based on resource group
This let’s us get health state on all resources scoped to a resource group. If we reuse the data from previously (we have all resource groups within our subscription) we will get all resource group health this way.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
availabilityState : Unavailable | |
summary : Your virtual machine is unavailable | |
detailedStatus : We're working to automatically recover your virtual machine and to determine the source of the problem. No additional action is required from you at this time. | |
reasonType : Unplanned | |
occuredTime : 2017-07-30T01:13:56Z | |
reasonChronicity : Persistent | |
reportedTime : 2017-09-12T11:27:42.3921293Z | |
resolutionETA : 2017-07-30T01:38:56Z |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#get the health of the whole resource group | |
# Add each health status to a hashtable before output a complete table with all resource groups and their resource health | |
$resourceGroupHealth = @{} | |
foreach ($ResourceGroup in $ResourceGroups) { | |
#Set resource group name and use it in our url | |
$health = Invoke-RestMethod -Uri "https://management.azure.com/subscriptions/$subscriptionID/resourceGroups/$ResourceGroup/Providers/Microsoft.ResourceHealth/availabilityStatuses?api-version=2015-01-01" -Method GET -Headers $authHeader | |
$currentHealth = @{} | |
$currentHealth = @{ | |
[string]"$ResourceGroup" = [object]$health | |
} | |
$resourceGroupHealth += $currentHealth | |
} | |
$resourceGroupHealth | |
#Explore the results | |
$resourceGroupHealth.item('ResourceGroup').Value.Properties |
Other examples are to get availability by Resource and the entire subscription