RBAC and role assignment using ARM Templates

Roles 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:

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:

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 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 responses

  1. Micah Jardine (@micah_jardine) 2018-08-20 at 00:12

    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. Vincent-Philippe Lauzon 2018-08-20 at 06:14

    I know. It doesn’t get reverse-engineered well either. It’s a bit criptic.

  3. Lauri Naulapää 2018-09-12 at 01:04

    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.

  4. Vincent-Philippe Lauzon 2018-09-12 at 05:19

    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).

  5. Anonymous 2019-11-28 at 11:36

    Salut Vincent, merci pour ton blog, sans toi je ne crois pas avoir été capable!

  6. Vincent-Philippe Lauzon 2019-11-28 at 12:28

    Excellent. Heureux que ça aille aidé quelqu’un!

  7. Anonymous 2020-03-04 at 22:52

    Thanks, this was really helpful. Just a heads up, I think that you definition of ‘Logic App Assignment Name’ used in your last code snippet has an unnecessary concat function (within the guid function). It isn’t concatenating anything, it only contains ‘resourceGroup().id’

Leave a comment