Querying Azure Resource Graph

In this blog post, we’ll discuss the purpose and usage of the Azure Resource Graph. This is the first part in a series of posts, so it will updated with links to the following posts in the series as soon as they are published.

Azure Resource Graph is designed to extend Azure Resource Management by providing an efficient and performant resource exploration so that you can effectively govern your environment. It currently supports queries over basic resource fields, specifically – Resource name, ID, Type, Resource Group, Subscription, and Location. Resource Manager also provides facilities for calling individual resource providers for detailed properties one resource at a time.

It’s important to understand that Azure Resource Graph’s query language is based on the Kusto query language. It supports a number of operators and functions. Each work and operate based on Azure Data Explorer.

To query Azure Resource Graph, you’ll need at least read access to the resources you want to query, and then you can use Azure CLI (with the resource-graph extension), the SDK with REST API calls, PowerShell (with the Az.ResourceGraph module) or the the Azure Resource Graph Explorer in the Azure Portal that’s currently in preview. In this post, we will mostly explore the PowerShell method.

To install the Az.ResourceGraph PowerShell module into your computer, or to your CloudShell persistent clouddrive, use the following command:

Install-Module -Name Az.ResourceGraph

As simple example, we will query for the number of Azure resources that exist in the subscriptions that you have access to. It’s also a good query to validate you have the required permissions, and that your shell of choice has the appropriate components installed:

Search-AzGraph -Query "summarize count()"


To expand on this, we’ll add a where operator to our query, in order to filter and get only the number virtual machines we have. The type we are instrested in is “Microsoft.Compute/virtualMachines”:

Search-AzGraph -Query "where type =~ 'Microsoft.Compute/virtualMachines' | summarize count()"


Note that the above command only filters in the ARM virtual machines, and you might still have some classic VMs. For this, we can add the or operator to our query, and search for both types:

Search-AzGraph -Query "where type == 'Microsoft.Compute/virtualMachines' or type == 'Microsoft.ClassicCompute/virtualMachines' | summarize count()"


In another example, we can use the tostring function, to group the results by a property string:

Search-AzGraph -Query "where type =~ 'Microsoft.Compute/virtualMachines' | summarize count() by tostring(properties.storageProfile.osDisk.osType)"

properties_storageProfile_osDisk_osType count_
--------------------------------------- ------
Windows                                 79
Linux                                   57

Using the project operator, we can include, rename or drop columns, or insert new computed columns. For example, adding a SKU column for the vmSize:

Search-AzGraph -Query "where type =~ 'Microsoft.Compute/virtualMachines' | project SKU = tostring(properties.hardwareProfile.vmSize)| summarize count() by SKU"

SKU              count_
---              ------
Standard_B1ms    12
Standard_DS2_v2  25
Standard_DS3_v2  2
Standard_D8s_v3  13

Some other examples for useful queries include:

# Count resources by types per subscription
Search-AzGraph -Query "summarize count() by type, subscriptionId | order by type, subscriptionId asc"

# List VMs that match a regex pattern:
Search-AzGraph -Query "where type =~ 'microsoft.compute/virtualmachines' and name matches regex @'^Contoso(.*)[0-9]+$' | project name | order by name asc"

# List all VMs not using managed disks:
Search-AzGraph -Query "where type =~ 'Microsoft.Compute/virtualMachines' | where isnull(properties.storageProfile.osDisk.managedDisk) | project name, resourceGroup, subscriptionId"

# List all the Public IP Addresses:
Search-AzGraph -Query "where type contains 'publicIPAddresses' and isnotempty(properties.ipAddress) | project properties.ipAddress"

# List WebApps:
Search-AzGraph -Query "where type=='microsoft.web/sites' | project name, subscriptionId, type | order by type, subscriptionId"

# List Storage accounts:
Search-AzureRmGraph -Query "where type=='microsoft.storage/storageaccounts' | project name, resourceGroup,subscriptionId"

# List Storage accounts that don't have encryption enabled:
Search-AzGraph -Query "where type =~ 'microsoft.storage/storageaccounts' | where aliases['Microsoft.Storage/storageAccounts/enableBlobEncryption'] =='false'| project name"

If you have any feedback on Azure Resource Graph, or want to upvote other’s suggestions, see https://feedback.azure.com/forums/915958-azure-governance/category/345061-azure-resource-graph