Find Orphaned Azure Resources

As a follow up to my Azure Resource Graph examples repo, I have a few queries to find orphaned Azure resources. These queries are all in the repo, but I’m doing a separate post on this because I feel its a pretty common problem to have orphaned resources. I will also be adding more queries to the repo as I come up with them.

Find Orphaned Azure Resources

We’ll do this using Azure Resource Graph. If you’re not familiar with Azure Resource Graph, it is a completely free service in Azure. It uses Kusto Query Language for its queries. You can find the official docs here. Most of the time you’ll use it in the portal. However, you can also use PowerShell or other languages to query the API. You’ll also need reader level access to any resources you want to query in your subscriptions. If you don’t have reader level access these resources will simply not show up for you.

Azure VMs

These first two come from Azure VMs. When a VM is deleted the NIC and disks are not deleted. This is because you might want to rebuild the VM with the same disks. So it is often the most common resources left orphaned. However, you get changed money for the storage that is still being consumed.

Find Orphaned Disks


Resources
| where type has "microsoft.compute/disks"
| extend diskState = tostring(properties.diskState)
| where managedBy == ""
or diskState == 'Unattached'
| project id, diskState, resourceGroup, location, subscriptionId

This query looks in the Compute/Disks resource type for disks that either have empty managedBy field, or their disk state is Unattached. When a disk is properly attached to a VM the managedBy field will have the resourceId filled out by the corresponding VM. If said VM is deleted its resourceId is also deleted.

Find Orphaned NICs


Resources
| where type has "microsoft.network/networkinterfaces"
| where "{nicWithPrivateEndpoints}" !has id
| where properties !has 'virtualmachine'
| project id, resourceGroup, location, subscriptionId

This query looks through the Network/networkinterfaces resource type for NICs that don’t have a private endpoint listed, and where the properties field doesn’t have a virtualmachine listed under it. The reason we look for NICs without private endpoints, private endpoints use NICs but don’t have a virtual machine listed either. This was leading to false positives in environments that use private endpoints.

NSGs

This query isn’t technically an orphaned resource, however if you make an NSG you typically want it applied to a NIC or subnet.


Resources
| where type =~ 'microsoft.network/networksecuritygroups' and isnull(properties.networkInterfaces) and isnull(properties.subnets)
| project Resource=id, resourceGroup, subscriptionId, location

This query looks through the Network/networksecuritygroups resource type and looks for null network interfaces and subnets under the properties.

 

Summary

Azure Resource Graph is a powerful tool to have in your belt for your management of your Azure environment, from finding all your resources, to summarizing data about your resource groups and subscriptions or finding orphaned resources. I have also put together a Azure Inventory Dashboard using Azure Workbooks, you can check it out here. The Ultimate Azure Inventory Dashboard – Using Azure Resource Graph (cloudsma.com)