Why does Azure's Role Definitions API return more than Permission struct for a role definition?

96 Views Asked by At

I'm using the Azure Go SDK to call the Role Definitions - Get endpoint.

The data that comes back confuses me. I see a *Permissions pointer in the response, but it's not by itself. It's in a slice of pointers. How can there be more than one *Permissions pointer in the response? After reading Azure custom roles - Custom role properties, I learned that there are Actions, DataActions, NotActions, and NotDataActions. But, wouldn't you be able to describe all of these within one Permissions struct?

I have a test program I used to see this in action too. I noticed that my slice of pointers always had just one pointer. But I did see the expected actions and not actions in it (I was testing the Contributor built-in role for my subscription).

Before running my program, I authenticated my Azure CLI, so that the default credentials would use these credentials and the code would run without error.

package main

import (
    "context"
    "fmt"

    "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
    "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v2"
)

func main() {
    // Default cred from env vars
    cred, _ := azidentity.NewDefaultAzureCredential(nil)
    client, _ := armauthorization.NewRoleDefinitionsClient(cred, nil)

    // Get the role definition using its roleDefinitionId and its scope.
    roleDefinitionID := "b24988ac-6180-42a0-ab88-20f7382dd24c"
    scope := "/subscriptions/<my-subscription>"
    rd, _ := client.Get(context.TODO(), scope, roleDefinitionID, nil)

    lenPerms := len((*rd.RoleDefinition.Properties).Permissions)
    fmt.Printf("length of Permissions = %d\n", lenPerms)
    lenActions := len((*(*rd.RoleDefinition.Properties).Permissions[0]).Actions)
    fmt.Printf("length of Actions in Permissions = %d\n", lenActions)
    lenNotActions := len((*(*rd.RoleDefinition.Properties).Permissions[0]).NotActions)
    fmt.Printf("length of NotActions in Permissions = %d\n", lenNotActions)
}

It produced the following output:

length of Permissions = 1
length of Actions in Permissions = 1
length of NotActions in Permissions = 8

While troubleshooting, one theory I had for why there could be a list of Permissions structs instead of just one is that maybe each time a new action is added to a role, Azure would store this as a "permission added event" etc, and the API response is showing us all of these events.

I tested this theory by trying this test instead with a custom role that I created. While creating my custom role, I cloned the permissions of the built-in role Contributor. Then I ran my test program. I got 1, 1, 8 (like before with the built-in Contributor role). Then, I added a new NotAction to my custom role and finally I ran my test program again. I got 1, 1, 9 this time. So it still put all the data in the first Permissions struct.

For more context, the reason this is important to me is that I'm making software that needs to know which Actions, NotActions, DataActions, and NotDataActions exist on a role definition. And I'm wondering if I need to take into account every Permissions struct pointed to by the slice Properties.Permissions, or if I can safely assume that the first item in that slice is all the data the program will ever need to take into account.

0

There are 0 best solutions below