Bicep Role Assignments
A role assignment gives an identity permission to act on an Azure resource. A web app that reads files from storage needs such a permission. Bicep creates both the identity and the permission, so no person ever copies a password into the app.
Think of an office badge system. Each badge belongs to one person, and the badge opens only certain doors. A managed identity is the badge, a role is the list of doors, and the role assignment is the act of programming the badge.
The Three Parts
Who? What can they do? Where?
┌──────────────┐ ┌───────────────────┐ ┌───────────────┐
│ Managed │ + │ Role │ + │ Scope │
│ identity │ │ (Storage Blob │ │ (one storage │
│ (principal) │ │ Data Contributor) │ │ account) │
└──────────────┘ └───────────────────┘ └───────────────┘
└───────────── Role assignment ─────────────┘
Create a Managed Identity
A system-assigned identity lives and dies with its resource. Turn it on with one property.
resource webApp 'Microsoft.Web/sites@2023-01-01' = {
name: 'app-shop-001'
location: 'eastus'
identity: {
type: 'SystemAssigned'
}
properties: {
serverFarmId: plan.id
}
}A user-assigned identity exists as its own resource and serves several apps at once.
resource appIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
name: 'id-shop'
location: 'eastus'
}Assign a Role
Each built-in role has a fixed ID. The assignment name must be a GUID, and the guid() function builds a stable one from the scope, identity, and role.
var storageBlobContributor = 'ba92f5b4-2d11-453d-a403-e96b0029c9fe'
resource roleAssign 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(storage.id, webApp.id, storageBlobContributor)
scope: storage
properties: {
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', storageBlobContributor)
principalId: webApp.identity.principalId
principalType: 'ServicePrincipal'
}
}The scope: storage line limits the permission to that single storage account. The app cannot touch any other resource.
Common Built-In Roles
| Role | Role ID | Gives |
|---|---|---|
| Reader | acdd72a7-3385-48ef-bd42-f606fba81ae7 | View resources |
| Contributor | b24988ac-6180-42a0-ab88-20f7382dd24c | Create and edit resources |
| Storage Blob Data Contributor | ba92f5b4-2d11-453d-a403-e96b0029c9fe | Read and write blob data |
Principle of Least Privilege
Grant the smallest role at the smallest scope. A reader role on one resource beats a contributor role on the whole subscription. Narrow permissions limit damage when something goes wrong.
Requirements to Deploy Role Assignments
The deploying account needs permission to write role assignments, such as the Role Based Access Control Administrator role or the Owner role at the target scope. A deployment with only Contributor rights fails with an authorization message.
Why Managed Identities Beat Stored Passwords
A password in a configuration file can leak through a screenshot, a backup, or a shared repository. A managed identity has no password to leak. Azure issues short-lived tokens to the app automatically and rotates them without human effort. Removing an app removes its identity, so no orphaned credentials remain.
Assigning Roles to People and Groups
Role assignments work for users and groups as well. Pass the object ID of the person or group as principalId, and set principalType to User or Group. Groups keep the template short, because adding a person to the group grants access without a code change.
Summary
Role assignments connect an identity, a role, and a scope. Managed identities remove stored passwords, and guid() creates stable assignment names. Least privilege keeps access narrow, and the deploying account needs rights to write role assignments.
