Quick Start with Azure Resources Graph and Python API

Published Jun 01 2020 09:28 AM 2,233 Views
Microsoft

Hello, Everyone! Did ever want to get Azure resources’ s information across hundreds of subscriptions very quick without the need to looping through each subscription? Did you ever try Resources Graph explorer? Or wondered how can we do it programmatically?

 

Azure Resources Graph gives user instance access to resource information across user’s cloud environments. It supports Kusto Query Language (KQL) you can find detail documentation here

 

Azure Resources graph explorer is very handy tool, you could access it from Azure portal and run your query there.

 

The explorer offers good and quick stop to run ad-hoc queries something we want to run once or twice but if we want to extract the data programmatically then we need something else like API.

Graph Resources POST API is used to get azure resources’ information by  passing subscriptions list and query string. Here is an example for the expected post body {

 

 

 

  "subscriptions": [

    "cfbbd179-59d2-4052-aa06-9270a38aa9d6"

  ],

  "query": "where type =~ 'Microsoft.Compute/virtualMachines' | summarize count() by tostring(properties.storageProfile.osDisk.osType)"

}

 

 

 

In the following code example, we will pass a query that collect VM information and its internal and external IP. Notice by default the VM profile information list the NIC GUID only.

So in order to get the IP address, the query use JOIN operator to join provider 'microsoft.network/networkinterfaces' with provider 'microsoft.compute/virtualmachines'

 

Here is the code:

 

 

import adal
import requests
from azure.common.credentials import ServicePrincipalCredentials
import json

TENANT_ID=''
CLIENT=''
KEY=''
SUBSCRIPTION_ID=''
AUTHENTICATION_ENDPOINT='https://login.microsoftonline.com/'
RESOURCE= 'https://management.core.windows.net/'
RESOURCE_GRAPH="https://graph.microsoft.com"  
GRAPH_API_ENDPOINT='https://management.azure.com/providers/Microsoft.ResourceGraph/resources?api-version=2018-09-01-preview'
def get_token():
    context = adal.AuthenticationContext(AUTHENTICATION_ENDPOINT + TENANT_ID)
    token_response = context.acquire_token_with_client_credentials(RESOURCE, CLIENT, KEY)
    return token_response['accessToken']
def get_vm_list(str_qry,subid):
    json_body={
        "subscriptions":
         [
          "<Enter subscriptions ID collection here>",
         ],
         "query":str_qry
    }
        

    str_body=str(json_body)
    headers  = {"Authorization": 'Bearer ' + get_token(),"Content-type": "application/json"}
    json_output = requests.post(GRAPH_API_ENDPOINT,headers=headers,data=str_body).json()
    print (json_output)
def api_example():
    str_qry = "\n".join(["Resources",
                    "| where type =~ 'microsoft.compute/virtualmachines'",
                    "| extend nics=array_length(properties.networkProfile.networkInterfaces)",
                    "| mv-expand nic=properties.networkProfile.networkInterfaces ",
                    "| where nics == 1 or nic.properties.primary =~ 'true' or isempty(nic)", 
                    "| project vmId = id, resourceGroup",
                    ",vmName = name, vmSize=tostring(properties.hardwareProfile.vmSize),tags,location, nicId = tostring(nic.id), vmOS=tostring(properties.storageProfile.imageReference)",
                    "| join kind=leftouter (",
                    "    Resources",
                    "    | where type =~ 'microsoft.network/networkinterfaces' ",
                    "    | extend ipConfigsCount=array_length(properties.ipConfigurations) ",
                    "    | mv-expand ipconfig=properties.ipConfigurations ",
                    "    | where ipConfigsCount == 1 or ipconfig.properties.primary =~ 'true' ",
                    "    | project nicId = id, publicIpId = tostring(ipconfig.properties.publicIPAddress.id))",
                    "on nicId ",
                    "| project-away nicId1 ",
                    "| summarize by vmId, resourceGroup,vmName, vmSize,location,tostring(tags),vmOS, nicId, publicIpId ",
                    "| join kind=leftouter ( ",
                    "    Resources ",
                    "    | where type =~ 'microsoft.network/publicipaddresses' ",
                    "    | project publicIpId = id, publicIpAddress = properties.ipAddress) ",
                    "on publicIpId ",
                    "| project-away publicIpId1 "])

   # print(str_qry)
    get_vm_list(str_qry,SUBSCRIPTION_ID)                
if __name__ == "__main__":
    api_example()

 

 

 

Here is example for the result when we run the code:

2.png

 

We can use JSON Format to inspect the output:

 

 

{
   "totalRecords":1,
   "count":1,
   "data":{
      "columns":[
         {
            "name":"vmId",
            "type":"string"
         
},
         {
            "name":"resourceGroup",
            "type":"string"
         
},
         {
            "name":"vmName",
            "type":"string"
         
},
         {
            "name":"vmSize",
            "type":"string"
         
},
         {
            "name":"location",
            "type":"string"
         
},
         {
            "name":"tags",
            "type":"string"
         
},
         {
            "name":"vmOS",
            "type":"string"
         
},
         {
            "name":"nicId",
            "type":"string"
         
},
         {
            "name":"publicIpId",
            "type":"string"
         
},
         {
            "name":"publicIpAddress",
            "type":"object"
         
}
      
],
      "rows":[
         [
            "/subscriptions/subID /resourceGroups/TestGroup/providers/Microsoft.Compute/virtualMachines/mytestvm",
            "testgroup",
            "mytestvm",
            "Standard_D2s_v3",
            "westus2",
            "",
            "{\"publisher\":\"Canonical\",\"version\":\"latest\",\"exactVersion\":\"18.04.202004290\",\"offer\":\"UbuntuServer\",\"sku\":\"18.04-LTS\"}",
            "/subscriptions/subID/resourceGroups/TestGroup/providers/Microsoft.Network/networkInterfaces/mytestvm296",
            "/subscriptions/subID/resourceGroups/TestGroup/providers/Microsoft.Network/publicIPAddresses/mytestvm-ip",
            "40.91.126.109"
         
]
      
]
   
},
   "facets":[

   
],
   "resultTruncated":"false"
}

 

 

 

As you see calling Resources Graph API is a very simple process and very efficient when deal with large numbers of subscriptions.

 

Thank you for reading!

Version history
Last update:
‎Jun 01 2020 12:09 PM
Updated by: