RBAC and role assignment using ARM Templates

Azure supports Role Based Access Control (RBAC) as an access control paradigm.

It allows to map a user (or a group of users) to a role within a given scope (resource, resource group, subscription or management group).

For instance, we could map my user identity to a Virtual Machine Contributor in the scope of a resource group.

A role is itself an aggregation of actions.

It is quite easy to do role assignment using the Azure Portal. I find the online documentation about role assignment using ARM templates lacking. It only covers assignment to resource groups and doesn’t show how to find roles.

So let’s do that here.

Artefacts are in GitHub. It can easily be deployed with this button:

Deploy to Azure

This deploys an empty Logic App and assigns an identity a role to the resource group and the logic app itself. The reason we deploy a Logic App is because it is very fast to deploy and being serverless, it doesn’t incure any cost.

We will lack two parameters: a role and an identity.

Finding a role

First, we need to find a role to assign.

Here we will use the Azure Command Line Interface (CLI). The same thing could be done in PowerShell using the Get-AzureRmRoleDefinition command.

We can type

az role definition list -o table

This gives a list of all the roles available. It’s a little hard to read since the output is large. We can narrow it by using JMESPath standard:

az role definition list --query "[*].{roleName:roleName, name:name}" -o table

This should give us an output similar to:

RoleName                                              Name
----------------------------------------------------  ------------------------------------
Azure Service Deploy Release Management Contributor   21d96096-b162-414a-8302-d8354f9d91b2
CAL-Custom-Role-67b91599-1e50-49eb-8780-881e4f7ca44e  7b266cd7-0bba-4ae2-8423-90ede5e1e898
Dsms Role (deprecated)                                b91f4c0b-46e3-47bb-a242-eecfe23b3b5b
Dsms Role (do not use)                                7aff565e-6c55-448d-83db-ccf482c6da2f
GenevaWarmPathResourceContributor                     9f15f5f5-77bd-413a-aa88-4b9c68b1e7bc

In our case, we would be interested i

az role definition list --query "[? starts_with(roleName, 'Logic')].{roleName:roleName, name:name}" -o table

which returns us:

RoleName               Name
---------------------  ------------------------------------
Logic App Contributor  87a39d53-fc1b-424a-814c-f7e04687dc9e
Logic App Operator     515c2055-d9d4-4321-b1b9-bd0c9a0f79fe

Let’s keep the name of the role, i.e. the GUID. We choose the Logic App Contributor.

Finding an identity

Next we need an identity to assign that role.

There are three types of identity that makes sense here: user, group and service principal.

Finding a user

We can list the users in Azure AD with

az ad user list -o table

For large directories, this would return a lot of data. We can filter by display name prefix. The display name is something like John Smith as opposed to jsmith.

az ad user list --display-name john -o table

We need to find the user we’re interested in and the corresponding ObjectId, which is a GUID.

Finding a group

Similarly, we can find a group starting with admins with

az ad group list --display-name admins -o table

Finding a Service Principal

Similarly for Service principals starting with my

az ad sp list --display-name my -o table

It is important to take the ObjectId and not the AppId. Those two have different values.

Assignment to a resource group

We now have the two parameters we needed to feed the ARM template we proposed at the beginning of this article.

If we run the template, we should have a resource group looking like this:

Deployed Resource Group

We can select the EmptyLogicApp resource. We can then select the Access control (IAM) menu on the left-hand side menu:

Role assignments

Let’s focus on Logic App Contributor section. This is the role we choose.

We have two assignments of the same role under two scopes:

  • The first one is the resource itself
  • The second one is inherited from the resource group

There is a quickstart template doing a resource group role assignment.

Basically, a role assignment is modelled as an Azure resource. This is akeen to relational databases where many-to-many relationships are modelled as an entry in a relation table.

Here is the resource in our template:

    "type": "Microsoft.Authorization/roleAssignments",
    "apiVersion": "2017-09-01",
    "name": "[guid(concat(resourceGroup().id), resourceId('Microsoft.Logic/workflows', 'EmptyLogicApp'), variables('Full Role Definition ID'))]",
    "dependsOn": [
        "[resourceId('Microsoft.Logic/workflows', 'EmptyLogicApp')]"
    "properties": {
        "roleDefinitionId": "[variables('Full Role Definition ID')]",
        "principalId": "[parameters('AAD Object ID')]",
        "scope": "[resourceGroup().id]"

A few observations:

  • The type is Microsoft.Authorization/roleAssignments ; this is a constant type for resource groups
  • The name of the resource needs to be a unique GUID ; we use the guid arm template function, but we could have simply passed a generated GUID
  • We use the role definition id we picked up earlier
  • We use the principal id we picked up earlier
  • The scope is the resource group and for that we need to pass the resource group id

Assignment to a specific resource

There is a quickstart template doing a resource group role assignment.

Although only the scope is different, the solution isn’t so similar. Let’s look at our template again:

    "type": "Microsoft.Logic/workflows/providers/roleAssignments",
    "apiVersion": "2017-05-01",
    "name": "[variables('Logic App Assignment Name')]",
    "dependsOn": [
        "[resourceId('Microsoft.Logic/workflows', 'EmptyLogicApp')]"
    "properties": {
        "roleDefinitionId": "[variables('Full Role Definition ID')]",
        "principalId": "[parameters('AAD Object ID')]"

Again a few observations:

  • The type is Microsoft.Logic/workflows/providers/roleAssignments ; the type is different depending on the related resource, here a Logic App
  • The name of the resource is defined in a variable as [concat(variables('Logic App Name'), '/Microsoft.Authorization/', guid(concat(resourceGroup().id), variables('Full Role Definition ID')))] ; here it isn’t just a random GUID, it is a meaningful name as it refers to both the Logic App name and the Role Definition id
  • Both role definition id & principal id are used as for resource group

The resource content is different from a resource group assignation. It is quite predictable though and easy to replicate.


We’ve seen how to assign a role to both a resource group and a single resource.

This is useful as we can setup RBAC permissions straight from an ARM template.

7 thoughts on “RBAC and role assignment using ARM Templates

  1. Thank you for this, I had been looking last week how to apply rbac to a specific resource, the documentation is a bit unclear that the you have to assign the authorisation on the resource, rather that define the scope on the authorisation.

  2. So in the case of resource specific role assignment the target resource gets parsed from the specially formatted name property?

    Any idea if/how it’s possible to add a new role assignment to an existing resource? For example if I want to add a role assignment to a service bus namespace that already exists and is in a different resource group.

    1. ARM Template can always be used on existing resources. They can be used to create and update. In your case though, you want to create a new resource, i.e. a role assignment. It’s just that that resource is related to an existing resource.

      So yes, definitely possible. I never tried to have a resource in a resource group and an assignment in a different group. It might or might not be supported.

      What you can do though is to deploy something in that group. ARM Template now supports deploying resources in a different resource group (see https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-manager-cross-resource-group-deployment).

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s