Skip to main content

Discovering Azure Resources via MapAz

Published June 11, 2025

Discovering Azure Resources via MapAz

TL;DR  

If you are not interested in the technicalities of this post, just know this: 

  • Getting a complete list of Azure resources may sound like a trivial task, but it isn’t  
  • Full resource visibility is essential for securing Azure resources  
  • Download the MapAz module to get all resources via the command: Get-MApAzResource -ScanSubResources 

Now, let’s dive in… 

Why Should I Care?  

Resources that you are not aware of are probably not secured well. For example, key vault secrets are a resource, and an important one too, as they could give privileged access to more resources inside or outside of Azure. So even if muhsecret is easily found when I look for secrets inside my Azure key vault: 

It is missing when you list resources using standard Azure APIs, even when you query the resource by name:

It is clear that a better approach is required for enumerating resources in your Azure tenant. MapAz is a Powershell module that – among other functionalities – can help you enumerate resources that are not visible by default when using standard Azure APIs & tools. 

Resources and Resource Providers 

If this intro left you wondering, “but what is a resource anyway,” this short paragraph should sort you out. According to Microsoft (who created Azure, so they should know) a resource is “A manageable item that's available through Azure.” Basically any “thing” that is created in Azure is a resource: virtual machines, networks, firewalls, and even secrets.  

Resources are managed by Resource Providers, which are the control plane services that manage the lifecycle of a resource of a specific type. Let’s look at a short example to clarify.  

Using Azure’s PowerShell module - Az, we can query all registered resource providers and how many resource types they support in a tenant: 

As seen above, each provider has a namespace, under which certain resource types can be managed. For example, looking at the Microsoft.KeyVault provider, we will find 21 resource types, which we can list: 

Notice that the Microsoft.KeyVault provider supports vaults, but also additional child resources under a vault, such as secrets, accessPolicies, eventGridFilters, and keys

To sum up, Microsoft.KeyVault is an Azure provider that can manage 21 different kinds of resources such as vaults, but also child resources such as vaults/secrets.

Think You Know Your Azure Resources? Think Again! 

Now that we know what resources and resource providers are, let’s try and get all of those pesky resources in a tenant. Because most Azure tooling that enumerates resources (such as blackcat and Stormspotter) rely on Azure APIs – we will test those same APIs, but also try to go a step further with MapAz to find additional resources.  

For testing, I’ve set up a tenant with various types of resources inside, and tested the following methods of listing resources:  

  • Viewing resources via Azure Portal Resource Browser 
  • Running a query via Azure Resource Management API 
  • Running a query in Azure Resource Graph via the portal  
  • Running a query in Azure Resource Graph via API 
  • Using Get-MapAzResource with the -ScanSubResources parameter 

Resources via Azure Portal 

Using the Azure Portal, I can view all resources in my tenant via the GUI, using the “All Resources” service or quickly access it via this link: https://portal.azure.com/#browse/all. Looking at the bottom of the table, you can see that the total number of resources in my tenant is 178. 

 

Listing Resources via ARM API  

178 resources sounds about right, or does it?  Let’s try and validate this number by working with Azure’s REST API, or one of Azure’s SDKs. Let’s query for all resources across subscriptions using Azure’s PowerShell module - Az

All in all, across 2 subscriptions of our tenant, we have a total of 187 resources, obviously some resources were not accounted for in the GUI. 

When finding differences between the results in the GUI VS the API, I’ve found 3 resource types that were not listed in the GUI:  

  • Microsoft.Compute/virtualMachines/extensions - 7 
  • Microsoft.Migrate/moveCollections – 1 
  • Microsoft.Cdn/profiles/afdendpoints – 1  

The fact that there is a difference between what the user “sees” in the GUI VS what is returned from the API raises some questions. Obviously, if a resource is important enough to be listed via the API, it should also be listed in the GUI. For example, Microsoft.Compute/virtualMachines/extensions can be used to create scripts that run when a VM is starting – someone could misuse this resource to persist malware.  

Well, at least we know for sure that our tenant has 187 resources in total and nothing more. Right? Well, not exactly… 

Listing Resources via the Azure Resource Graph Explorer 

The Azure Resource Graph is a service that aims to provide more robust access to Azure resources across subscriptions and tenants. It completes the ARM API by providing more flexibility in the querying of resources, as well as the fields that can be queried for resources.  

Sounds promising! Let’s try and use this service via the Graph Explorer and query for all the resources across all subscriptions:

Somewhat disappointingly, we only got 163 resources this time.  

Listing Resources via Azure Resource Graph’s API 

Let’s do the same thing, but query directly the Azure Resource Graph endpoint via its REST API:

187 is equivalent to what we found using ARM’s API before.  

Enumerating Sub Resources via MapAz 

Before diving into Get-MapAzResource method and how it works, let’s run it against the same Azure tenant and see how many resources it finds:

With 247, it’s much higher than we got from using any other method. Before moving on to MapAz internals, let’s take a look at the results summary so far:

Method Resource Count
Azure Portal Resource Browser 178
Azure Resource Management API 187
Azure Resource Graph via Portal 163
Azure Resource Graph via API 187
MapAz 247

The most resources we found so far were by using Get-MapAzResource cmdlet from the MapAz module, with 60 resources more than we found via other Azure APIs.  

Let’s dive deeper into MapAz internals to find out what’s going on. 

Finding “Hidden” Resources 

Let’s take a closer look at a Microsoft.KeyVault resource. When looking at the GUI, we can see the vault’s secrets.

This secret, like pretty much anything else in Azure, is a resource. When clicking it, we can see it also has its own IAM control for controlling granular access to the secret. 

However, “muhsecret,” or any other secret for that matter, is not visible in the resources list in the GUI. Also, when trying to query for the secret via the API function we don’t get any results, even when we give it all the relevant parameters:

This returns nothing. When running the same command with the -Debug flag, it becomes clear why this failed – as the Az module queries the same API we used to list all resources. 

Now, let’s try and list secrets in a vault using a proprietary Az command Get-AzKeyVaultSecret

When we run this command with the -Debug flag, it’s apparent why using this method successfully found the secrets. It is because the PS code queries the vault resource directly. 

There doesn’t seem to be a fallback for this query, because once I disable network access to my vault, the function fails with code: Forbidden. 

This is very worrying, because it means that some resources can’t be listed without having direct network access to their parent resource (in this case, the key vault resource).  

Let’s not be discouraged – it's time to try another method. When reading Azure’s REST API documentation, you will come across List operations. Those are usually HTTP GET operations in the following form: 

https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{ProviderName}/{ResourceType}?api-version={version}

In other words, once we know the resource type we want to list (we listed subtypes for a given provider at the beginning of this post), and a URL or a parent object, we should be able to easily run a query for child resources for each type.  

One quick “hack” of performing this operation without constructing full URLs is using the Get-AzResource cmdlet (which basically constructs the full URL and does an HTTP GET to the “ResourceId” parameter) with the ResourceId parameter as the parent objectId + the sub type of the resource. Now it’s possible to list the subkeys of a known keyvault like so by querying the secrets resource type:

Because it’s not very effective to construct these URLs by hand to map all of the resources inside an Azure tenant, we’ve built MapAz. Among other functionalities, it can also automate the process of enumerating Azure resources.  

When calling the Get-MapAzResource cmdlet with the -ScanSubResources flag, MapAz enumerates sub resources by trying every type of child resource against an already found parent resource. In this manner, many more resources are discovered as compared with Azure’s native tools and APIs. This process is not optimized and may take some time for large environments. This issue will be addressed in a newer release. 

Summary and Further Research 

Azure’s native tools and APIs don’t tell the whole story of resources inside Azure tenants. MapAz uses a naïve approach of trying to enumerate child resources while assuming the native APIs at least provide all the parent resources. This assumption of course could be wrong – there may be resources that are not correctly returned by Azure native APIs, but finding such resources is outside the scope of this blog and may require further research.  

We hope you will find MapAz useful, and share your thoughts, results, and suggestions in our Zero Labs Slack channel