RBAC and role assignment using ARM Templates
Solution ·
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:
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:
We can select the EmptyLogicApp resource. We can then select the Access control (IAM) menu on the left-hand side menu:
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.
Summary
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