Azure Resource Graph: Answering Estate Questions in Milliseconds

October closes with the tool that answers the question every other post this month eventually raises: what is actually out there? Azure Resource Graph indexes the resource model of every subscription you can see and exposes it to KQL, so estate questions that would take the ARM APIs minutes of throttled pagination return in milliseconds. It is the read side of governance, and platform teams that internalize it stop guessing.

The Query Patterns That Earn a Bookmark

The language is the KQL from the Monitor and Sentinel posts aimed at resources instead of logs, and a handful of shapes cover most needs. Inventory with properties unpacked: every VM by size, OS, and zone, every storage account by TLS floor and public access flag, every public IP and what holds it. Compliance sweeps that complement policy: policy states what violates, graph finds what exists in any shape you can express, including the shapes you have not written policy for yet. The tag audit from the FinOps post, resources missing costcenter grouped by owning subscription, is one query and one shame dashboard. And the security sweeps the October posts imply: NSGs containing any to any rules, Key Vaults without purge protection, VMs missing the Arc or monitoring extensions, disks left unattached and billing.

Resources
| where type == "microsoft.storage/storageaccounts"
| extend publicAccess = tostring(properties.publicNetworkAccess),
         tlsMin = tostring(properties.minimumTlsVersion)
| where publicAccess =~ "Enabled" or tlsMin != "TLS1_2"
| join kind=leftouter (
    ResourceContainers
    | where type == "microsoft.resources/subscriptions"
    | project subscriptionId, subName = name
  ) on subscriptionId
| project name, resourceGroup, subName, publicAccess, tlsMin, tags.costcenter
| order by subName asc

The join there is the underused feature: graph tables join, so resources correlate with their subscriptions, their health (the HealthResources table carries availability states, join VMs to their current health for the fleet status board), and policy states, producing the enriched views no single API returns.

Change Tracking and the Forensic Angle

The change analysis tables record what changed on a resource and when, property level diffs queryable like everything else, which turns two recurring conversations from archaeology into queries: the incident review’s “what changed in this resource group in the hour before the alert”, and the drift hunt’s “which NSGs were modified outside pipeline hours this month”, the complement to the prevention machinery from the deployment stacks and GitOps posts. It will not tell you who in every case, that correlation belongs to the activity logs in Sentinel, but it narrows the search space to specific properties and timestamps, and joined with the sign in and activity data the September posts centralized, the full story assembles in minutes.

From Queries to Machinery

The graduation path is queries becoming infrastructure. Shared queries stored as resources give the team a versioned library, in the repo like everything else. Workbooks from the Monitor post visualize graph queries directly, which is how the estate dashboards, coverage, compliance, orphan counts, the unallocated cost bucket, get built without exporting anything. Scheduled automation runs the sweeps, the Automation post’s runbooks or a function querying graph weekly, opening tickets for new orphans and untagged arrivals rather than waiting for the quarterly cleanup. And the Terraform brownfield campaign from earlier this month gets its progress metric here, resources under management versus total, one query, trending on a dashboard until it stops moving. Resource Graph is the estate’s read replica: cheap to query, always current enough, and the difference between a platform team that knows and one that believes. November continues the series with the AI services, IoT, and the specialty platforms.

Cheers
Osama

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.