I have written in the past about the Azure Portal security model and wanted to take a deeper dive into providers and provider operations. Let’s first define what both are:
Provider – a way to logically group securable objects within Azure Portal
Provider operation – the actual securable objects that a role can be assigned
For example when creating a custom role you are first presented with this screen, these are all Providers within Azure Portal:
Once a particular provider has been selected you are then presented with a listing of the operations associated with that provider:
You’ll notice that each entry here also has an access type attached to it as well. This is somewhat unique to Azure Portal in that each securable object entry has an access type associated with it. For example the ‘Get Virtual Machines’ object has a Read access type already associated with it but the ‘Create or Update Virtual Machines’ object has a Write access associated with it. In other systems you would more than likely see one ‘virtual machine’ object with the ability to set what access is assigned to it.
If we assign the ‘Get Virtual Machines’ and ‘Create or Update Virtual Machines’ entries to our role, we can see the permissions tab is correctly showing both of these being assigned.
If we move over to the JSON tab we can see on the back end how this is being stored. There is one ‘virtualMachines’ object under the ‘Microsoft.Compute’ provider and we now have Read and Write access to it (effectively Write access since the access to Azure objects is hierarchy based).
So what happens if we edit this role to assign the wildcard (*) permission to Microsoft.Compute/virtualMachines’? The only way to achieve this is to go edit this role’s definition in the JSON area.
Now when we go back to the Permission tab we can see we now have full control to all objects within this Azure provider. But how does Azure populate this list? It is able to create this list by determining all operations associated with a particular provider. So the question I had was, is there a way we can programmatically get all provider operations so we can know what objects we are assigning to a role when wildcards (*) are used?
Note: There are over 230+ Azure providers and over 7600+ Azure provider operations within an environment.
How to Obtain Provider and Provider Operations Data Programmatically
The first thing to do was to get a list of providers, this is easy enough via the Azure Mangement REST APIs. The Provider endpoint has a List call that will return all providers within a subscription.
The next thing to do is to gather all provider operations and luckily again the Azure Management REST API has an endpoint for us to use. The Provider Operations Metadata List endpoint process all operations for all resource providers.
End of discussion right? Well… let’s take a look at the data being returned from the Provider Operations Metadata endpoint. If we click on the ‘Try It’ button within the Microsoft documentation of the Provider Operations API we can actually run the query against your own Azure instance with no code (very handy feature).
The output from this call is fairly large and contains a lot of data about each of the provider operations, but one key piece of data is missing. If you remember back to my previous post on Azure Portal security you may remember that there are two different object types Actions and Data. There is no designation anywhere in the call being returned of whether the operation is of type Action or Data even when we used the $expand option.
Without having the object type information we cannot accurately determine what objects a wildcard (*) would grant to a role. So what other options exist? Each provider has an operation endpoint that we could call and looking at the expected return data from the Microsoft documentation it should contain an ‘IsDataAction’ field. What if we looped through the providers and got the operations from each provider individually?
If we look back at the output from our Providers call we can see it gives us information about the ‘capabilities’ of that provider or what services it offers. One of those services is an operations entry:
The reason we need this information is because one unique requirement of all Azure Management APIs is that they must contain an API version when performing the call. And not every provider operation endpoint has the same ApiVersions, so we have to know the valid ApiVersions for each provider. Once we have this though we can go to each provider and call:
https://management.azure.com/providers/<ProviderName>/operations?api-version=<OperationsApiVersion>
If you try this though you will run into three very big issues almost immediately:
1) Some providers include a parameter called ‘isDataAction’ and some do not, for example the Microsoft.AppConfiguration provider includes this field but the Microsoft.Authorization provider does not even though they should be returning the same object type.
2) The ApiVersion information for a large number of the provider operations endpoints is incorrect and even the error messages returned when an incorrect API version is used telling you which APIs are valid are sometimes wrong as well.
3) Some providers don’t have any operations endpoint to call at all.
So now what do we do?
PowerShell to the Rescue
Since the above operations didn’t work for me, I continued my search and finally found some discussion about using an Azure PowerShell command: Get-AzProviderOperation
If we use the same provider as above we can see the output is a super flat, easy to consume object that includes the IsDataAction parameter.
Note: To get all provider operations perform the following call ‘Get-AzProviderOperation *’
This ended up being the method I used and allows me to programmatically determine the provider operations within an Azure Portal environment and the actions that will be assigned when wildcards (*) are used in role designs.
Conclusion
I hope this post helps explain what provider and provider operations are and why they are important to know when setting up security. I also hope that I can help save the potential hours of time I ended up spending trying to get the different Azure Management APIs to work for me before switching over to utilizing PowerShell.