%3CLINGO-SUB%20id%3D%22lingo-sub-1431391%22%20slang%3D%22en-US%22%3EQuick%20Start%20with%20Azure%20Resources%20Graph%20and%20Python%20API%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1431391%22%20slang%3D%22en-US%22%3E%3CP%3EHello%2C%20Everyone!%20Did%20ever%20want%20to%20get%20Azure%20resources%E2%80%99%20s%20information%20across%20hundreds%20of%20subscriptions%20very%20quick%20without%20the%20need%20to%20looping%20through%20each%20subscription%3F%20Did%20you%20ever%20try%20Resources%20Graph%20explorer%3F%20Or%20wondered%20how%20can%20we%20do%20it%20programmatically%3F%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CA%20href%3D%22https%3A%2F%2Fazure.microsoft.com%2Fen-us%2Ffeatures%2Fresource-graph%2F%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%22%3EAzure%20Resources%20Graph%3C%2FA%3E%20gives%20user%20instance%20access%20to%20resource%20information%20across%20user%E2%80%99s%20cloud%20environments.%20It%20supports%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fkusto%2Fquery%2Findex%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%22%3EKusto%20Query%20Language%20(KQL)%3C%2FA%3E%20you%20can%20find%20detail%20documentation%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fgovernance%2Fresource-graph%2Foverview%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%22%3Ehere%3C%2FA%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EAzure%20Resources%20graph%20%3CA%20href%3D%22https%3A%2F%2Fms.portal.azure.com%2F%23blade%2FMicrosoft_Azure_Policy%2FPolicyMenuBlade%2FResourceGraph%22%20target%3D%22_blank%22%20rel%3D%22noopener%20nofollow%20noreferrer%22%3Eexplorer%3C%2FA%3E%20is%20very%20handy%20tool%2C%20you%20could%20access%20it%20from%20Azure%20portal%20and%20run%20your%20query%20there.%3C%2FP%3E%0A%3CDIV%20id%3D%22tinyMceEditormagdysalem_2%22%20class%3D%22mceNonEditable%20lia-copypaste-placeholder%22%3E%26nbsp%3B%3C%2FDIV%3E%0A%3CP%3EThe%20explorer%20offers%20good%20and%20quick%20stop%20to%20run%20ad-hoc%20queries%20something%20we%20want%20to%20run%20once%20or%20twice%20but%20if%20we%20want%20to%20extract%20the%20data%20programmatically%20then%20we%20need%20something%20else%20like%20-ERR%3AREF-NOT-FOUND-API.%3C%2FP%3E%0A%3CP%3EGraph%20Resources%20POST%20API%20is%20used%20to%20get%20azure%20resources%E2%80%99%20information%20by%26nbsp%3B%20passing%20subscriptions%20list%20and%20query%20string.%20Here%20is%20an%20example%20for%20the%20expected%20post%20body%20%7B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CPRE%20class%3D%22lia-code-sample%20language-applescript%22%3E%3CCODE%3E%26nbsp%3B%20%22subscriptions%22%3A%20%5B%0A%0A%26nbsp%3B%26nbsp%3B%26nbsp%3B%20%22cfbbd179-59d2-4052-aa06-9270a38aa9d6%22%0A%0A%26nbsp%3B%20%5D%2C%0A%0A%26nbsp%3B%20%22query%22%3A%20%22where%20type%20%3D~%20'Microsoft.Compute%2FvirtualMachines'%20%7C%20summarize%20count()%20by%20tostring(properties.storageProfile.osDisk.osType)%22%0A%0A%7D%3C%2FCODE%3E%3C%2FPRE%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EIn%20the%20following%20code%20example%2C%20we%20will%20pass%20a%20query%20that%20collect%20VM%20information%20and%20its%20internal%20and%20external%20IP.%20Notice%20by%20default%20the%20VM%20profile%20information%20list%20the%20NIC%20GUID%20only.%3C%2FP%3E%0A%3CP%3ESo%20in%20order%20to%20get%20the%20IP%20address%2C%20the%20query%20use%20JOIN%20operator%20to%20join%20provider%20'microsoft.network%2Fnetworkinterfaces'%20with%20provider%20'microsoft.compute%2Fvirtualmachines'%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EHere%20is%20the%20code%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CPRE%20class%3D%22lia-code-sample%20language-python%22%3E%3CCODE%3Eimport%20adal%0Aimport%20requests%0Afrom%20azure.common.credentials%20import%20ServicePrincipalCredentials%0Aimport%20json%0A%0ATENANT_ID%3D''%0ACLIENT%3D''%0AKEY%3D''%0ASUBSCRIPTION_ID%3D''%0AAUTHENTICATION_ENDPOINT%3D'https%3A%2F%2Flogin.microsoftonline.com%2F'%0ARESOURCE%3D%20'https%3A%2F%2Fmanagement.core.windows.net%2F'%0ARESOURCE_GRAPH%3D%22https%3A%2F%2Fgraph.microsoft.com%22%20%20%0AGRAPH_API_ENDPOINT%3D'https%3A%2F%2Fmanagement.azure.com%2Fproviders%2FMicrosoft.ResourceGraph%2Fresources%3Fapi-version%3D2018-09-01-preview'%0Adef%20get_token()%3A%0A%20%20%20%20context%20%3D%20adal.AuthenticationContext(AUTHENTICATION_ENDPOINT%20%2B%20TENANT_ID)%0A%20%20%20%20token_response%20%3D%20context.acquire_token_with_client_credentials(RESOURCE%2C%20CLIENT%2C%20KEY)%0A%20%20%20%20return%20token_response%5B'accessToken'%5D%0Adef%20get_vm_list(str_qry%2Csubid)%3A%0A%20%20%20%20json_body%3D%7B%0A%20%20%20%20%20%20%20%20%22subscriptions%22%3A%0A%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%22%3CENTER%20subscriptions%3D%22%22%20id%3D%22%22%20collection%3D%22%22%20here%3D%22%22%3E%22%2C%0A%20%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%20%20%20%22query%22%3Astr_qry%0A%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%0A%0A%20%20%20%20str_body%3Dstr(json_body)%0A%20%20%20%20headers%20%20%3D%20%7B%22Authorization%22%3A%20'Bearer%20'%20%2B%20get_token()%2C%22Content-type%22%3A%20%22application%2Fjson%22%7D%0A%20%20%20%20json_output%20%3D%20requests.post(GRAPH_API_ENDPOINT%2Cheaders%3Dheaders%2Cdata%3Dstr_body).json()%0A%20%20%20%20print%20(json_output)%0Adef%20api_example()%3A%0A%20%20%20%20str_qry%20%3D%20%22%5Cn%22.join(%5B%22Resources%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%7C%20where%20type%20%3D~%20'microsoft.compute%2Fvirtualmachines'%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%7C%20extend%20nics%3Darray_length(properties.networkProfile.networkInterfaces)%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%7C%20mv-expand%20nic%3Dproperties.networkProfile.networkInterfaces%20%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%7C%20where%20nics%20%3D%3D%201%20or%20nic.properties.primary%20%3D~%20'true'%20or%20isempty(nic)%22%2C%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%7C%20project%20vmId%20%3D%20id%2C%20resourceGroup%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%2CvmName%20%3D%20name%2C%20vmSize%3Dtostring(properties.hardwareProfile.vmSize)%2Ctags%2Clocation%2C%20nicId%20%3D%20tostring(nic.id)%2C%20vmOS%3Dtostring(properties.storageProfile.imageReference)%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%7C%20join%20kind%3Dleftouter%20(%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%20%20%20%20Resources%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%20%20%20%20%7C%20where%20type%20%3D~%20'microsoft.network%2Fnetworkinterfaces'%20%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%20%20%20%20%7C%20extend%20ipConfigsCount%3Darray_length(properties.ipConfigurations)%20%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%20%20%20%20%7C%20mv-expand%20ipconfig%3Dproperties.ipConfigurations%20%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%20%20%20%20%7C%20where%20ipConfigsCount%20%3D%3D%201%20or%20ipconfig.properties.primary%20%3D~%20'true'%20%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%20%20%20%20%7C%20project%20nicId%20%3D%20id%2C%20publicIpId%20%3D%20tostring(ipconfig.properties.publicIPAddress.id))%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22on%20nicId%20%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%7C%20project-away%20nicId1%20%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%7C%20summarize%20by%20vmId%2C%20resourceGroup%2CvmName%2C%20vmSize%2Clocation%2Ctostring(tags)%2CvmOS%2C%20nicId%2C%20publicIpId%20%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%7C%20join%20kind%3Dleftouter%20(%20%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%20%20%20%20Resources%20%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%20%20%20%20%7C%20where%20type%20%3D~%20'microsoft.network%2Fpublicipaddresses'%20%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%20%20%20%20%7C%20project%20publicIpId%20%3D%20id%2C%20publicIpAddress%20%3D%20properties.ipAddress)%20%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22on%20publicIpId%20%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22%7C%20project-away%20publicIpId1%20%22%5D)%0A%0A%20%20%20%23%20print(str_qry)%0A%20%20%20%20get_vm_list(str_qry%2CSUBSCRIPTION_ID)%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20api_example()%0A%3C%2FENTER%3E%3C%2FCODE%3E%3C%2FPRE%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EHere%20is%20example%20for%20the%20result%20when%20we%20run%20the%20code%3A%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%222.png%22%20style%3D%22width%3A%20999px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Fgxcuf89792.i.lithium.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F195769iB3407FD0654056CD%2Fimage-size%2Flarge%3Fv%3D1.0%26amp%3Bpx%3D999%22%20title%3D%222.png%22%20alt%3D%222.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CDIV%20id%3D%22tinyMceEditormagdysalem_3%22%20class%3D%22mceNonEditable%20lia-copypaste-placeholder%22%3E%26nbsp%3B%3C%2FDIV%3E%0A%3CP%3EWe%20can%20use%20JSON%20Format%20to%20inspect%20the%20output%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CPRE%20class%3D%22lia-code-sample%20language-json%22%3E%3CCODE%3E%7B%0A%20%20%20%22totalRecords%22%3A1%2C%0A%20%20%20%22count%22%3A1%2C%0A%20%20%20%22data%22%3A%7B%0A%20%20%20%20%20%20%22columns%22%3A%5B%0A%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%3A%22vmId%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22type%22%3A%22string%22%0A%20%20%20%20%20%20%20%20%20%0A%7D%2C%0A%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%3A%22resourceGroup%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22type%22%3A%22string%22%0A%20%20%20%20%20%20%20%20%20%0A%7D%2C%0A%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%3A%22vmName%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22type%22%3A%22string%22%0A%20%20%20%20%20%20%20%20%20%0A%7D%2C%0A%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%3A%22vmSize%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22type%22%3A%22string%22%0A%20%20%20%20%20%20%20%20%20%0A%7D%2C%0A%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%3A%22location%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22type%22%3A%22string%22%0A%20%20%20%20%20%20%20%20%20%0A%7D%2C%0A%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%3A%22tags%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22type%22%3A%22string%22%0A%20%20%20%20%20%20%20%20%20%0A%7D%2C%0A%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%3A%22vmOS%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22type%22%3A%22string%22%0A%20%20%20%20%20%20%20%20%20%0A%7D%2C%0A%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%3A%22nicId%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22type%22%3A%22string%22%0A%20%20%20%20%20%20%20%20%20%0A%7D%2C%0A%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%3A%22publicIpId%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22type%22%3A%22string%22%0A%20%20%20%20%20%20%20%20%20%0A%7D%2C%0A%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22name%22%3A%22publicIpAddress%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22type%22%3A%22object%22%0A%20%20%20%20%20%20%20%20%20%0A%7D%0A%20%20%20%20%20%20%0A%5D%2C%0A%20%20%20%20%20%20%22rows%22%3A%5B%0A%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%2Fsubscriptions%2FsubID%20%2FresourceGroups%2FTestGroup%2Fproviders%2FMicrosoft.Compute%2FvirtualMachines%2Fmytestvm%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22testgroup%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22mytestvm%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Standard_D2s_v3%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22westus2%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%7B%5C%22publisher%5C%22%3A%5C%22Canonical%5C%22%2C%5C%22version%5C%22%3A%5C%22latest%5C%22%2C%5C%22exactVersion%5C%22%3A%5C%2218.04.202004290%5C%22%2C%5C%22offer%5C%22%3A%5C%22UbuntuServer%5C%22%2C%5C%22sku%5C%22%3A%5C%2218.04-LTS%5C%22%7D%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%2Fsubscriptions%2FsubID%2FresourceGroups%2FTestGroup%2Fproviders%2FMicrosoft.Network%2FnetworkInterfaces%2Fmytestvm296%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%2Fsubscriptions%2FsubID%2FresourceGroups%2FTestGroup%2Fproviders%2FMicrosoft.Network%2FpublicIPAddresses%2Fmytestvm-ip%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%2240.91.126.109%22%0A%20%20%20%20%20%20%20%20%20%0A%5D%0A%20%20%20%20%20%20%0A%5D%0A%20%20%20%0A%7D%2C%0A%20%20%20%22facets%22%3A%5B%0A%0A%20%20%20%0A%5D%2C%0A%20%20%20%22resultTruncated%22%3A%22false%22%0A%7D%0A%3C%2FCODE%3E%3C%2FPRE%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EAs%20you%20see%20calling%20Resources%20Graph%20API%20is%20a%20very%20simple%20process%20and%20very%20efficient%20when%20deal%20with%20large%20numbers%20of%20subscriptions.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EThank%20you%20for%20reading!%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-TEASER%20id%3D%22lingo-teaser-1431391%22%20slang%3D%22en-US%22%3E%3CP%3EHello%2C%20Everyone!%20Did%20ever%20want%20to%20get%20Azure%20resources%E2%80%99%20s%20information%20across%20hundreds%20of%20subscriptions%20very%20quick%20without%20the%20need%20to%20looping%20through%20each%20subscription%3F%20Did%20you%20ever%20try%20Resources%20Graph%20explorer%3F%20Or%20wondered%20how%20can%20we%20do%20it%20programmatically%3F%3C%2FP%3E%3C%2FLINGO-TEASER%3E%3CLINGO-LABS%20id%3D%22lingo-labs-1431391%22%20slang%3D%22en-US%22%3E%3CLINGO-LABEL%3EMagdySalem%3C%2FLINGO-LABEL%3E%3C%2FLINGO-LABS%3E
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!