Search code examples
c#azureazure-active-directorypermissionsazure-app-registration

Systematic Way to Identify Through Azure UI Required "App Registration" API Permission


Ok, I have this code (snippet) that is responsible for starting a VM:

var azure = Azure
    .Configure()
    .Authenticate(credentials)
    .WithSubscription(data.SubscriptionId);

var vm = await azure.VirtualMachines.GetByResourceGroupAsync("YourResourceGroupName", data.VmName);

if (vm == null)
{
    return new NotFoundObjectResult($"VM with name {data.VmName} not found");
}

await vm.StartAsync();

I run it from a Azure function, it fails:

System.Private.CoreLib: Exception while executing function: StartVM. Microsoft.Azure.Management.Compute.Fluent: The client 'XXX' with object id 'XXX' does not have authorization to perform action 'Microsoft.Compute/virtualMachines/read' over scope '/subscriptions/XXX/resourceGroups/YourResourceGroupName/providers/Microsoft.Compute/virtualMachines/XXX' or the scope is invalid. If access was recently granted, please refresh your credentials.

Fair... as I haven't added that permission to my Azure "App Registration", so I go there:

enter image description here

An honestly, I have not idea where to find this, I've clicked through most of them. I've faced this issue several times so my question is, is there a easy way on the Azure UI or programmatically to go from the permission path stated in the error to adding it in the UI?

Microsoft.Compute/virtualMachines/read

Corresponds to which category in the UI and which subcategory, and how do I determine that in a generic sense in the future (with the next permissions error)?


Solution

  • The error occurs if the service principal does not have proper permissions or roles to perform the operation.

    I have one Azure VM named srivm which is in "Stopped" state as below:

    enter image description here

    Initially, I too got same error when I tried to start the VM by authenticating with service principal not having any Azure RBAC roles under VM:

    enter image description here

    To find which Azure RBAC role has 'Microsoft.Compute/virtualMachines/read or other permissions, you can refer this Azure built-in roles for Compute document:

    enter image description here

    In my case, I assigned "Virtual Machine Contributor" role to service principal under Azure VM:

    enter image description here

    After assigning the role, I ran below sample code and got response like this:

    using Azure.Core;
    using Azure;
    using Azure.Identity;
    using Azure.ResourceManager;
    using Azure.ResourceManager.Compute;
    
    namespace StartVM
    {
        class Program
        {
            static async Task Main(string[] args)
            {
                var data = new StartVmData
                {
                    SubscriptionId = "subId",
                    ResourceGroupName = "rgname",
                    VmName = "vmname",
                    ClientId = "appId",
                    ClientSecret = "secret",
                    TenantId = "tenantId"
                };
    
                await StartVirtualMachineAsync(data);
            }
    
            public static async Task StartVirtualMachineAsync(StartVmData data)
            {
                try
                {
                    var credential = new ClientSecretCredential(data.TenantId, data.ClientId, data.ClientSecret);
                    var armClient = new ArmClient(credential, data.SubscriptionId);
                    var resourceGroup = armClient.GetResourceGroupResource(new ResourceIdentifier($"/subscriptions/{data.SubscriptionId}/resourceGroups/{data.ResourceGroupName}"));
                    var vm = await resourceGroup.GetVirtualMachineAsync(data.VmName);
    
                    if (vm == null)
                    {
                        Console.WriteLine($"VM with name {data.VmName} not found.");
                        return;
                    }
    
                    Console.WriteLine($"Starting VM {data.VmName}...");
                    var operation = await vm.Value.PowerOnAsync(WaitUntil.Completed);
                    Console.WriteLine($"VM {data.VmName} has been started successfully.");
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Error occurred: {ex.Message}");
                }
            }
        }
    
        public class StartVmData
        {
            public string SubscriptionId { get; set; } = string.Empty;
            public string ResourceGroupName { get; set; } = string.Empty;
            public string VmName { get; set; } = string.Empty;
            public string ClientId { get; set; } = string.Empty;
            public string ClientSecret { get; set; } = string.Empty;
            public string TenantId { get; set; } = string.Empty;
        }
    }
    

    Response:

    enter image description here

    To confirm that, I checked the same in Portal where VM started successfully as below:

    enter image description here

    Note that, API permissions are required when you are working with tenant level Microsoft APIs like Microsoft Graph, SharePoint, Power BI etc...

    While working with subscription-level Azure resources, you must assign Azure RBAC roles to the user or service principal under scopes like subscription, resource group or resource level.