Azure

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.


$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
}


<#
.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.


#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
}


#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

view raw

GetAzureRG.ps1

hosted with ❤ by GitHub

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.


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

view raw

example-output

hosted with ❤ by GitHub


#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

 

 

 

16 COMMENTS
  • binance
    Reply

    Your point of view caught my eye and was very interesting. Thanks. I have a question for you.

  • Working with Azure Monitor Rest API - SquaredUp
    Reply

    […] Powershell I am connecting to AAD and generating authentication header, reusing code from earlier blog post about Azure Resource health. For the purpose of this post I will focus on these two Azure Monitor API endpoints: Alert Rules – […]

  • Monitoring Microsoft Azure and Hybrid Cloud | SquaredUp
    Reply

    […] Here’s where our problems started. I wanted to discover all our manged tenants automatically. Take advantage of being a CSP we set out to create our own Management Pack(s). I have created one Management Pack for the CSP platform that integrates with the Partner Center API (see example in this blog post) to do the initial discovery. Tenants and subscriptions are populated as objects in SCOM. Further, using a Partner Center Managed Application we can pre-consent access to all managed tenants. That means we can use this applications credentials to authenticate against each of our managed tenants, by-passing the limitation within the official Management Pack. All resources are then created as object with a hosting relationship to resource group, subscription and tenant. Basic monitoring is done through Azure Resource Health API. […]

  • Working with Azure Monitor Rest API | SquaredUp
    Reply

    […] I am connecting to AAD and generating authentication header, reusing code from earlier blog post about Azure Resource health. For the purpose of this post I will focus on these two Azure Monitor API endpoints: Alert […]

  • Working with Azure Monitor Rest API | adatum
    Reply

    […] Powershell I am connecting to AAD and generating authentication header, reusing code from earlier blog post about Azure Resource health. For the purpose of this post I will focus on these two Azure Monitor API endpoints: Alert Rules […]

  • Lucas Alvarez Lacasa
    Reply

    Hey Martin!. Can you cover the first part? I cannot find how to properly register my application in the Azure portal. I have followed this tutorial but with .NET Core and I’m getting a forbidden every time I perform the request.
    The authentication token is coming as expected, the problem arises when I query the Resource Health API. I think this is because I cannot find a way to tell the application that it should have permissions to read from this API. How did you do this in the Azure portal?

    Thanks, Lucas!.

    1. Martin Ehrnst
      Reply

      Hi Lucas,

      You have to add the Azure Management API’s to you application.
      The process is described here: https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-integrating-applications#configure-a-client-application-to-access-web-apis

      1. Lucas Alvarez Lacasa
        Reply

        Hello Martin!. Thanks for replying so fast.
        Yeah, I already checked on that link earlier today. The problem is that I don’t know which API I need to enable for the Resource Health Api.
        I wish I could send you an image of what I see in the Azure portal when I go to the possible APIs for the application that I register, but nothing related to Resource Health Api is found in the list.

        1. Martin Ehrnst
          Reply

          It should be azure management something

          1. Lucas Alvarez Lacasa

            The only options that include management that I can see are: Microsoft Rights Management Services (Microsoft.Azure.RMS), Windows Azure Service Management API and Office 365 Management APIs.
            I will try with the second one, since it’s the one that looks more related to what I’m trying to accomplish.

            It would be nice if Microsoft included some documentation about this small details.

          2. Lucas Alvarez Lacasa

            Adding Windows Azure Service Management API permissions didn’t make the trick, I’m still getting a forbidden when trying to query the Resource Health Api.

            Let me know if you remember how you did it.

            Thanks!.

          3. Martin Ehrnst

            Hey. That’s strange. Try to upload a few pics of your configuration somewhere and post the links

          4. Martin Ehrnst

            Lucas, do the app have ‘reader’ permissions on the subscription level?

          5. Lucas Alvarez Lacasa

            Hello Martin, after many tries I was finally able to communicate with the API. The issue was produced by how I was obtaining the authentication token.
            Now it’s working fine 🙂 Thank you.

  • Sam Lord
    Reply

    Hey Martin! All the code samples are centred, what’s happening?

    I wonder how difficult it is to do the token requests without the Azure PowerShell commandlets 😉

    1. Martin Ehrnst
      Reply

      Ooops, whats with this CSS, i’ll look in to it, but in the mean time you can copy the code or view it on github directly 🙂 https://gist.github.com/ehrnst/a8db76bce82cc48f29165a01af95b077#file-get-aadappoauthtoken-ps1

      The easiest is to use the powershell module 🙂 but if you cannot use that, the REST API is a good canditate.
      I think i know what you are saying and I’ll give it at try soon 🙂

Engage by commenting