✨ KQL query collection
Table of content
If you want to create your own or to contribute to an existing GitHub project you are on the right page.

Query Language (KQL) Query Collection
Query Language (KQL) is the language used across Azure Resource Graph, Azure Monitor, Azure Data Explorer, and Azure Log Analytics.
Here is a collection of queries: Resource Graph Queries
⭐✨ Azure Advisor
Service retirement
1advisorresources
2| project id, properties.impact, properties.shortDescription.problem
⭐ AKS
List node pools
1Resources
2| where type == "microsoft.containerservice/managedclusters"
3| extend nodepools = properties.agentPoolProfiles
4| mv-expand nodepools
5| project name, nodepools.name, nodepools.vmSize, nodepools.minCount, nodepools.maxCount, nodepools.powerState.code, nodeCount = tostring(nodepools['count'])
6| sort by name
List nodes pools2
1Resources
2| where type == "microsoft.containerservice/managedclusters"
3| extend properties.agentPoolProfiles
4| project subscriptionId, name, pool = (properties.agentPoolProfiles)
5| mv-expand pool
6| project subscription = subscriptionId, cluster = name, size = pool.vmSize, count = pool.['count']
Get Node pools information
1resources
2| where type == "microsoft.containerservice/managedclusters"
3| extend properties.agentPoolProfiles
4| project subscriptionId, name, nodePool = properties.agentPoolProfiles
5| mv-expand nodePool
6| project subscriptionId, name, sku = nodePool.vmSize, count = nodePool.['count'], powerState = nodePool.powerState.code
⭐ Disks
Get Premium Disks
1resources
2| where type =~ 'microsoft.compute/disks'
3| extend skuName=tostring(sku.name)
4| extend accountType=case(skuName =~ 'Standard_LRS', 'Standard HDD LRS',
5 skuName =~ 'StandardSSD_LRS', 'Standard SSD LRS',
6 skuName =~ 'UltraSSD_LRS', 'Ultra disk LRS',
7 skuName =~ 'Premium_LRS', 'Premium SSD LRS',
8 skuName =~ 'Standard_ZRS', 'Zone-redundant',
9 skuName =~ 'Premium_ZRS', 'Premium SSD ZRS',
10 skuName =~ 'StandardSSD_ZRS', 'Standard SSD ZRS',
11 skuName)
12| where accountType contains "Premium"
Get SSD Disks
1resources
2| where type =~ 'microsoft.compute/disks'
3| extend skuName=tostring(sku.name)
4| extend accountType=case(skuName =~ 'Standard_LRS', 'Standard HDD LRS',
5 skuName =~ 'StandardSSD_LRS', 'Standard SSD LRS',
6 skuName =~ 'UltraSSD_LRS', 'Ultra disk LRS',
7 skuName =~ 'Premium_LRS', 'Premium SSD LRS',
8 skuName =~ 'Standard_ZRS', 'Zone-redundant',
9 skuName =~ 'Premium_ZRS', 'Premium SSD ZRS',
10 skuName =~ 'StandardSSD_ZRS', 'Standard SSD ZRS',
11 skuName)
12| where accountType contains "SSD"
Get ZRS Disks
1resources
2| where type =~ 'microsoft.compute/disks'
3| extend skuName=tostring(sku.name)
4| extend accountType=case(skuName =~ 'Standard_LRS', 'Standard HDD LRS',
5 skuName =~ 'StandardSSD_LRS', 'Standard SSD LRS',
6 skuName =~ 'UltraSSD_LRS', 'Ultra disk LRS',
7 skuName =~ 'Premium_LRS', 'Premium SSD LRS',
8 skuName =~ 'Standard_ZRS', 'Zone-redundant',
9 skuName =~ 'Premium_ZRS', 'Premium SSD ZRS',
10 skuName =~ 'StandardSSD_ZRS', 'Standard SSD ZRS',
11 skuName)
12| where accountType contains "ZRS"
Sort Disks By Size IOPS
1resources
2| where type == "microsoft.compute/disks"
3| project Disk_name=name, SKU=sku.name, Size=strcat(properties['diskSizeGB'],"GB"), IOPS=tolong(properties['diskIOPSReadWrite'])
4| sort by Size
⭐ Frontdoor
Routing rules and accepted protocols
1resources
2| where type == "microsoft.network/frontdoors"
3| project subscriptionId, frontDoorName=name, routingRules = (properties.routingRules)
4| mv-expand routingRules
5| project subscriptionId, frontDoorName, routingRuleName=routingRules.name, protocols = routingRules.properties
⭐ Network
List all subnets with delegation
1resources
2| where type == "microsoft.network/virtualnetworks"
3| project vnetName = name, subnets = (properties.subnets)
4| mvexpand subnets
5| extend subnetName = (subnets.name)
6| extend isDelegated = isnotnull(subnets.properties.delegations) and array_length(subnets.properties.delegations) != 0
7| where isDelegated == 1
8| project vnetName, subnetName
List subnets without NSG
1resources
2| where type == "microsoft.network/virtualnetworks"
3| project vnetName = name, subnets = (properties.subnets)
4| mvexpand subnets
5| extend subnetName = (subnets.name)
6| extend hasNSG = isnotnull(subnets.properties.networkSecurityGroup)
7| where hasNSG == 0
8| project vnetName, subnetName
List subnets with service endpoint
1resources
2| where type == "microsoft.network/virtualnetworks"
3| project vnetName = name, subnets = (properties.subnets)
4| mvexpand subnets
5| extend subnetName = (subnets.name)
6| extend hasServiceEndpoints = isnotnull(subnets.properties.serviceEndpoints) and array_length(subnets.properties.serviceEndpoints) != 0
7| where hasServiceEndpoints == 1
8| project vnetName, subnetName
List subnet with UDR
1resources
2| where type == "microsoft.network/virtualnetworks"
3| project vnetName = name, subnets = (properties.subnets)
4| mvexpand subnets
5| extend subnetName = (subnets.name)
6| extend hasRouteTable = isnotnull(subnets.properties.routeTable)
7| where hasRouteTable == 1
8| project vnetName, subnetName
Subnet IP usage
1resources
2| where type == "microsoft.network/virtualnetworks"
3| project vnetName = name, subnets = (properties.subnets)
4| mvexpand subnets
5| extend subnetName = (subnets.name)
6| extend mask = split(subnets.properties.addressPrefix, '/', 1)[0]
7| extend usedIp = array_length(subnets.properties.ipConfigurations)
8| extend totalIp = case(mask == 29, 3,
9 mask == 28, 11,
10 mask == 27, 27,
11 mask == 26, 59,
12 mask == 25, 123,
13 mask == 24, 251,
14 mask == 23, 507,
15 mask == 22, 1019,
16 mask == 21, 2043,
17 mask == 20, 4091,
18 mask == 19, 8187,
19 mask == 18, 16379,
20 mask == 17, 32763,
21 mask == 16, 65531,
22 mask == 15, 131067,
23 mask == 14, 262139,
24 mask == 13, 524283,
25 mask == 12, 1048571,
26 mask == 11, 2097147,
27 mask == 10, 4194299,
28 mask == 9, 8388603,
29 mask == 8, 16777211,
30 -1)
31| extend availableIp = totalIp - usedIp
32| project vnetName, subnetName, mask, usedIp, totalIp, availableIp, subnets
33| order by toint(mask) desc
⭐ Resources
Display last resources changes since the last week
1resourcechanges
2| extend changeTime = todatetime(properties.changeAttributes.timestamp),
3targetResourceId = tostring(properties.targetResourceId),
4changeType = tostring(properties.changeType), changedBy = tostring(properties.changeAttributes.changedBy),
5changedByType = properties.changeAttributes.changedByType,
6clientType = tostring(properties.changeAttributes.clientType)
7| where changeTime > ago(7d)
8| project changeType, changedBy, changedByType, clientType
9| summarize count() by changedBy, changeType, clientType
10| order by count_ desc
⭐ Resources Groups
Display Empty Resource Groups
1ResourceContainers
2| where type == 'microsoft.resources/subscriptions/resourcegroups'
3| extend rgAndSub = strcat(resourceGroup, '--', subscriptionId)
4| join kind=leftouter (
5 Resources
6 | extend rgAndSub = strcat(resourceGroup, '--', subscriptionId)
7 | summarize count() by rgAndSub
8) on rgAndSub
9| where isnull(count_)
⭐ Policies
Find unused custom policies
1policyresources
2| where type == "microsoft.authorization/policydefinitions"
3| extend policyType = tostring(properties.policyType)
4| where policyType == "Custom"
5| join kind=leftouter (
6 policyresources
7 | where type == "microsoft.authorization/policysetdefinitions"
8 | extend policyType = tostring(properties.policyType)
9 | extend policyDefinitions = properties.policyDefinitions
10 | where policyType == "Custom"
11 | mv-expand policyDefinitions
12 | extend policyDefinitionId = tostring(policyDefinitions.policyDefinitionId)
13 | project associedIdToInitiative=policyDefinitionId
14 | distinct associedIdToInitiative) on $left.id == $right.associedIdToInitiative
15| where associedIdToInitiative == ""
16| join kind=leftouter(
17 policyresources
18 | where type == "microsoft.authorization/policyassignments"
19 | extend policyDefinitionId = tostring(properties.policyDefinitionId)
20 | project associatedDefinitionId=policyDefinitionId
21 | distinct associatedDefinitionId
22) on $left.id == $right.associatedDefinitionId
23| where associatedDefinitionId == ""
24| extend displayName = tostring(properties.displayName)
25| project id, displayName
Count policies assignment by scope
1policyresources
2| where type == "microsoft.authorization/policyassignments"
3| extend scope = tostring(properties.scope)
4| summarize count() by scope
5| order by count_ desc
Count custom policies assignments by scope
1policyresources
2| where type == "microsoft.authorization/policydefinitions"
3| extend policyType = tostring(properties.policyType)
4| where policyType == "Custom"
5| project id
6| extend scope = tostring(split(id, "/providers/Microsoft.Authorization/policyDefinitions/", 0)[0])
7| summarize count() by scope
8| order by count_ desc
⭐ RBAC
List user direct assignment at management group level
1authorizationresources
2| extend scope = tostring(properties.scope)
3| join kind = inner (
4 resourcecontainers
5 | where type == "microsoft.management/managementgroups"
6 | project managementGroupId=id, managementGroupName=properties.displayName
7) on $right.managementGroupId == $left.scope
8| where properties.principaltype == "User"
9| project properties.createdOn, managementGroupName, scope, managementGroupId
List user assignment at subscription level
1authorizationresources
2| join kind = inner (
3 resourcecontainers
4 | where type == "microsoft.resources/subscriptions"
5 | project subscriptionName=name, subscriptionId) on subscriptionId
6| where type == "microsoft.authorization/roleassignments"
7| where properties.principalType == "User"
8| project properties.createdOn, properties.scope, properties.principalId, subscriptionId
All RBAC Assignments
1authorizationresources
2| where type =~ 'microsoft.authorization/roleassignments'
3| extend roleDefinitionId= tolower(tostring(properties.roleDefinitionId))
4| extend principalType = properties.principalType
5| extend principalId = properties.principalId
6| extend description = properties.description
7| extend scope = properties.scope
8| extend createdBy = properties.createdBy
9| join kind = inner (
10authorizationresources
11| where type =~ 'microsoft.authorization/roledefinitions'
12| extend roleDefinitionId = tolower(id)
13| extend roleName = tostring(properties.roleName)
14| extend roleType = tostring(properties.type)
15| project roleDefinitionId,roleName,roleType
16) on roleDefinitionId
17| project principalId,principalType,createdBy,description,roleName,roleType,scope,roleDefinitionId
⭐ Resource Groups
Display Empty Resource Groups
1ResourceContainers
2| where type == 'microsoft.resources/subscriptions/resourcegroups'
3| extend rgAndSub = strcat(resourceGroup, '--', subscriptionId)
4| join kind=leftouter (
5 Resources
6 | extend rgAndSub = strcat(resourceGroup, '--', subscriptionId)
7 | summarize count() by rgAndSub
8) on rgAndSub
9| where isnull(count_)
⭐ Resource changes
Display last resources changes since the last week
1resourcechanges
2| extend changeTime = todatetime(properties.changeAttributes.timestamp),
3targetResourceId = tostring(properties.targetResourceId),
4changeType = tostring(properties.changeType), changedBy = tostring(properties.changeAttributes.changedBy),
5changedByType = properties.changeAttributes.changedByType,
6clientType = tostring(properties.changeAttributes.clientType)
7| where changeTime > ago(7d)
8| project changeType, changedBy, changedByType, clientType
9| summarize count() by changedBy, changeType, clientType
10| order by count_ desc
⭐ Service Health
Display by Impacted resource Id
1servicehealthresources
2| where type == "microsoft.resourcehealth/events/impactedresources"
3| extend TrackingId = split(split(id, "/events/", 1)[0], "/impactedResources", 0)[0]
4| extend p = parse_json(properties)
5| project subscriptionId, TrackingId, targetResourceId= tostring(p.targetResourceId), details = p
6| join kind=inner (
7 resources
8 )
9 on $left.targetResourceId == $right.id
Display by Events (TrackingId)
1ServiceHealthResources
2| where type =~ 'Microsoft.ResourceHealth/events'
3| extend eventType = tostring(properties.EventType), status = properties.Status, description = properties.Title, trackingId = properties.TrackingId, summary = properties.Summary, priority = properties.Priority, impactStartTime = properties.ImpactStartTime, impactMitigationTime = properties.ImpactMitigationTime,
4EventSubType = properties.EventSubType
5| mv-expand Impact = properties.Impact
6| extend ImpactedService = Impact.ImpactedService
7| where eventType == 'HealthAdvisory' and status == 'Active' and EventSubType == 'Retirement'
8| summarize count(subscriptionId) by name
9| order by ['count_subscriptionId'] desc
Display by Events (TrackingId) and Resource Id impacted
1// Filter Specific Tracking IDs and Combine Health Advisory with Impacted Resources
2servicehealthresources
3| where type =~ 'Microsoft.ResourceHealth/events'
4| extend
5 eventType = properties.EventType,
6 EventSubType = properties.EventSubType,
7 status = properties.Status,
8 description = properties.Title,
9 trackingId = tostring(properties.TrackingId), // Explicitly cast TrackingId to string
10 summary = properties.Summary,
11 priority = properties.Priority,
12 impactStartTime = properties.ImpactStartTime,
13 impactMitigationTime = properties.ImpactMitigationTime
14| mv-expand Impact = properties.Impact
15| extend ImpactedService = Impact.ImpactedService
16//| where eventType == 'HealthAdvisory' and status == 'Active' and EventSubType == 'Retirement'
17| where eventType == 'PlannedMaintenance' and status == 'Active'
18| join kind=inner (
19 servicehealthresources
20 | where type == "microsoft.resourcehealth/events/impactedresources"
21 | extend TrackingId = tostring(split(split(id, "/events/", 1)[0], "/impactedResources", 0)[0]) // Explicitly cast TrackingId to string
22 | extend p = parse_json(properties)
23 | project subscriptionId, TrackingId, targetResourceId = tostring(p.targetResourceId), details = p
24) on $left.trackingId == $right.TrackingId
25| project
26 trackingId,
27 subscriptionId,
28 ImpactedService,
29 targetResourceId,
30 description,
31 summary,
32 priority,
33 impactStartTime,
34 impactMitigationTime,
35 details
⭐ Storage Accounts
Count Storage accounts by sku
1resources
2| where type == "microsoft.storage/storageaccounts"
3| extend sku = sku.name
4| summarize count(name) by tostring(sku)
⭐ Subscriptions
List subscriptions part of an EA
1resourcecontainers
2| where type == "microsoft.resources/subscriptions"
3| where properties.state == "Enabled"
4| mv-expand subscriptionPolicies = properties.subscriptionPolicies
5| where name !contains "Visual Studio" and subscriptionPolicies.quotaId startswith "MSDNDevTest" or subscriptionPolicies.quotaId startswith "EnterpriseAgreement"
List subscriptions by MG
1ResourceContainers
2| where type =~ 'microsoft.resources/subscriptions'
3| extend mgParent = properties.managementGroupAncestorsChain
4| mv-expand with_itemindex=MGHierarchy mgParent
5| project subscriptionId, name, mgParent, MGHierarchy, mgParent.name
Count subscriptions by MG
1ResourceContainers
2| where type =~ 'microsoft.management/managementgroups'
3| project mgname = name
4| join kind=leftouter (resourcecontainers | where type=~ 'microsoft.resources/subscriptions'
5| extend mgParent = properties.managementGroupAncestorsChain | project id, mgname = tostring(mgParent[0].name)) on mgname
6| summarize count() by mgname
Count all subscriptions by tenant
1ResourceContainers
2| where type =~ 'microsoft.resources/subscriptions'
3| project SubscriptionName=name, subscriptionId, tenantId
4| summarize count() by tenantId
5| order by ['count_'] desc
List resources part of a list of subscriptions
1resources
2| where subscriptionId in ("subid1-xxx-xxx-xxx-xxx", "subid2-xxx-xxx-xxx-xxx", "subid3-xxx-xxx-xxx-xxx", "subid4-xxx-xxx-xxx-xxx")
Check subscription naming convention
1resourcecontainers
2| where type == "microsoft.resources/subscriptions"
3| where properties.state == 'Enabled'
4| extend NamingCheck = iff((name startswith 'sub-'),"Naming is OK","Naming is not OK")
5| summarize count() by NamingCheck
Check subscription naming convention on a specific management group
1resourcecontainers
2| where type == "microsoft.resources/subscriptions"
3| where properties.state == 'Enabled'
4| where properties.managementGroupAncestorsChain contains 'Production'
5| extend NamingCheck = iff((name startswith 'sub-'),"Naming is OK","Naming is not OK")
6| summarize count() by NamingCheck
List subscriptions in a specific management group
1resourcecontainers
2 | where type == "microsoft.resources/subscriptions"
3 | where (properties.managementGroupAncestorsChain) contains "Sandbox"
Count resources type in a subscription
1resources
2| join kind=leftouter
3 (resourcecontainers
4 | where type == 'microsoft.resources/subscriptions'
5 | project subscriptionName=name, subscriptionId) on subscriptionId
6| where subscriptionName == "<your-sub-name-here>"
7| summarize count() by type, subscriptionName
Count subscriptions by management groups
1resourcecontainers
2| where type == 'microsoft.resources/subscriptions'
3| project subscriptionName = name, managementgroups = (properties.managementGroupAncestorsChain)
4| mv-expand managementgroups
5| summarize count() by tostring(managementgroups.displayName)
6| order by count_ desc
⭐ Tags
Resources without tag
1resourcecontainers
2| where type != "microsoft.management/managementgroups"
3| mv-expand bagexpansion=array tags
4| where isempty(tags)
Resources with specific tags and expand tag names/values to individual rows
1resourcecontainers
2| where type != "microsoft.management/managementgroups"
3| mvexpand parsejson(tags)
4| extend tagname = tostring(bag_keys(tags)[0])
5| extend tagvalue = tostring(tags[tagname])
6| project name,id,type,location,subscriptionId,tagname,tagvalue
7| union (resources
8| mvexpand parsejson(tags)
9| extend tagname = tostring(bag_keys(tags)[0])
10| extend tagvalue = tostring(tags[tagname])
11| project name,id,type,location,subscriptionId,tagname,tagvalue)
12| where tagname == "Environment" or tagname == "Owner"
Resources not containing a specific tag
1resourcecontainers
2| where tags !contains 'Environment'
Resources not containing a tag and count
1resourcecontainers
2| where tags !contains 'Environment'
3| project name, resourceGroup, subscriptionId, location, tags
4| summarize count () by subscriptionId
All tags for resources
1resourcecontainers
2| project name,type,location,subscriptionId,tags
3| union (resources | project name,type,location,subscriptionId,tags)
Count for a specific tag key
1ResourceContainers
2| where type =~ 'microsoft.resources/subscriptions/resourcegroups'
3| mvexpand tags
4| extend tagKey = tostring(bag_keys(tags)[0])
5| extend tagValue = tostring(tags[tagKey])
6| where tagKey == "Environment"
7| summarize count() by tagValue
8| order by ['count_'] desc
TEST
1resources
2| where type =~ 'Microsoft.Compute/virtualMachines'
3| mvexpand tags
4| extend tagKey = tostring(bag_keys(tags)[0])
5| extend tagValue = tostring(tags[tagKey])
6| where tagKey hasprefix "creat" and tagKey hasprefix "cr"
7| project name, tags, tagKey, tagValue