Deploying Azure role assignments from code
There are quite a few options for deploying Azure role assignments from code. Below they are listed and briefly summarised in order from worst to best.
ARM Templates
★ ☆ ☆ ☆ ☆
Deploying using ARM templates may seem like the default option if you're using ARM templates to deploy other resources, however it really is the worst option.
It's complicated, verbose, and uses IDs instead of human readable names.
e.g.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.Authorization/roleAssignments",
"apiVersion": "2022-04-01",
"name": "[guid(resourceGroup().id)]",
"properties": {
"roleDefinitionId": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]",
"principalId": "2681fa10-bc56-48e8-8f10-105bc7f91093"
}
}
]
}
If you like the look of this then Microsoft has documentation: Assign Azure roles using Azure Resource Manager templates
Though I'd recommend reading on for better options.
Bicep
★ ☆ ☆ ☆ ☆
Deploying using Bicep may seem like the default option if you're using Bicep to deploy other resources, it could be considered marginally better than using ARM Templates.
It's complicated, verbose, and uses IDs instead of human readable names.
e.g.
param roleDefinitionResourceId string
param principalId string
targetScope = 'subscription'
resource roleAssignment 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = {
name: guid(subscription().id, principalId, roleDefinitionResourceId)
properties: {
roleDefinitionId: roleDefinitionResourceId
principalId: principalId
principalType: 'ServicePrincipal'
}
}
If you like the look of this then Microsoft has documentation: Create Azure RBAC resources by using Bicep
Though I'd recommend reading on for better options.
CLI
★ ★ ☆ ☆ ☆
The CLI has the advantage of allowing commands to be run so you can stop relying on IDs and to look them up.
It is not idempotent so there is extra overhead in checking to see if role assignments exist before applying them.
e.g.
az role assignment create --assignee "{assignee}" --role "{roleNameOrId}" --resource-group "{resourceGroupName}"
If you like the look of this then Microsoft has documentation: Assign Azure roles using Azure CLI
There is some work involved but solutions can be made using the Azure CLI
PowerShell
★ ★ ★ ☆ ☆
PowerShell has all the advantage of being a programming language and the commands remove the need to use IDs.
It is no longer idempotent so there is extra overhead in checking to see if role assignments exist before applying them.
New-AzRoleAssignment -ResourceGroupName rg1 -SignInName 'Susan.Fisher@osservantex.onmicrosoft.com' -RoleDefinitionName 'Keyvault Reader'
If you like the look of this then Microsoft has documentation: Assign Azure roles using Azure PowerShell
There is some work involved but very good solutions can be made using PowerShell
REST API
★ ★ ★ ☆ ☆
Rest APIs has the advantage of being called from a variety of programming languages so you can stop relying on IDs use APIs to look them up.
It is no longer idempotent so there is extra overhead in checking to see if role assignments exist before applying them.
e.g.
{
"properties": {
"roleDefinitionId": "/subscriptions/{subscriptionId1}/providers/Microsoft.Authorization/roleDefinitions/a795c7a0-d4a2-40c1-ae25-d81f01202912",
"principalId": "{objectId1}"
}
}
PUT https://management.azure.com/subscriptions/{subscriptionId1}/providers/Microsoft.Authorization/roleAssignments/{roleAssignmentId1}?api-version=2022-04-01
If you like the look of this then Microsoft has documentation: Assign Azure roles using the REST API
There is some work involved but very good solutions can be made using the CLI
Terraform
★ ★ ★ ★ ☆
Terraform uses IDs but is able to look them up from their names so you can stop relying on IDs.
It is also idempotent so there is no extra overhead in checking to see if role assignments exist before applying them.
e.g.
resource "azurerm_role_assignment" "example" {
name = "00000000-0000-0000-0000-000000000000"
scope = data.azurerm_subscription.primary.id
role_definition_id = azurerm_role_definition.example.role_definition_resource_id
principal_id = data.azurerm_client_config.example.object_id
}
And of course Terraform has plan and apply stages so you can see what changes are to be made before applying them.
If you like the look of this then the Terraform resource is documented here: azurerm_role_assignment
Excellent solutions can be implemented using Terraform
Osservante RBAC Extension
★ ★ ★ ★ ★
This extension is a ready to go solution written in PowerShell/C#. It is a available in the Visual Studio Marketplace.
It was designed from the ground up as a easy to use centralised solution.
To deploy Azure role assignments you only need to understand YAML or JSON formats, no programming or Terraform skills are required.
e.g.
- YAML
- JSON
---
assignments:
- role: Key Vault Reader
objectName: Susan.Fisher@osservantex.onmicrosoft.com
objectType: User
scope: "/providers/Microsoft.KeyVault/vaults/osxkvappx"
{
"assignments": [
{
"role": "Key Vault Reader",
"objectName": "Susan.Fisher@osservantex.onmicrosoft.com",
"objectType": "User",
"scope": "/providers/Microsoft.KeyVault/vaults/osxkvappx"
}
]
}
The extension enables you to take control of your Azure RBAC.
- Centralise all RBAC configuration in one repository and pipeline
- Simplify with human-readable files, and folder structure
- Control with a plan stage that enables you to review changes and implement approval - esses
- Get started easily by exporting your current configuration to code
If you like the look of this then the find out more at the Osservante website, or in the Visual Studio Marketplace: