Azure, Bicep, Professional

Assigning Cosmos Data Plane Roles via RBAC w/ Bicep

Introduction

If one wasn’t already aware, CosmosDB has the ability to assign built in RBAC roles scoped to the account, database, and the container. When trying to achieve this via Bicep I quickly discovered there really wasn’t much content on this topic. In fact the majority of the content on this topic revolved around leveraging the creation of customer Cosmos role definitions. Hopefully this article will help provide some clarity. For this post I designed this as a module in a bicep registry. Full code can be found on my bicep_registry repository.

Background

If you weren’t aware CosmosDB currently provides two built in RBAC roles. Cosmos DB Built-in Data Reader and Cosmos DB Built-in Data Contributor. Just as described one is read only and one is for data operations.

These roles are beneficial as we don’t have to create a custom definition and then worry about maintaining it. Using a built in role is typically the preferred approach as they are viewed as more secure and can configured in any Azure subscription.

These data plane RBAC roles differ significantly in terms of resource configuration than from normal Azure build-in roles. The main reason being, the traditional RBAC roles, are stored behind the Microsoft.Authorization resource provider. For example here is the resource ID for the built in contributor role: /providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c

Cosmos RBAC roles use a different provider for the role definition id. These role definitions are a sub resource of the actual database account. Thus they are formated as: /subscriptions/<mySubscriptionId>/resourceGroups/<myResourceGroup>/providers/Microsoft.DocumentDB/databaseAccounts/<myCosmosAccount>/sqlRoleDefinitions/<roleDefinitionId>

This means to retrieve or use the built in RBAC roles for Cosmos we will need to know the subscriptionid, resource group name, account name, and the role definition id.

Role Assignment

Since the built in RBAC roles for Cosmos are technically a sub resource of the cosmos account this means we will need to ensure that the assignment is either nested in the cosmos account creation or has the account listed as the resource parent.

I prefer the parent approach as this will provide us the ability to leverage the RBAC assignment as a module and thus can call it infinite amount of times.

The other tricky part was finding the above roleDefinitionId. The 'Microsoft.DocumentDB/databaseAccounts/sqlRoleAssignments requires the resource id of the build in role definition id. This wasn’t straight forward in the documentation I have since updated it.

Here is my entire Cosmos SQL Role Assignment Module:

@description('CosmosDB Account to apply the role assignment to')
param databaseAccountName string
@description('Resource group of the CosmosDB Account')
param databaseAccountResourceGroup string
@description('Role definition id to assign to the principal')
@allowed([
  '00000000-0000-0000-0000-000000000001'// Built-in role 'Azure Cosmos DB Built-in Data Reader'
  '00000000-0000-0000-0000-000000000002' // Built-in role 'Azure Cosmos DB Built-in Data Contributor'
])
param roleDefinitionId string = '00000000-0000-0000-0000-000000000002' 
@description('Principal id to assign the role to')
param principalId string


var roleAssignmentId = guid(roleDefinitionId, principalId, databaseAccount.id)
resource databaseAccount 'Microsoft.DocumentDB/databaseAccounts@2023-04-15' existing = {
  name: databaseAccountName
}

resource sqlRoleAssignment 'Microsoft.DocumentDB/databaseAccounts/sqlRoleAssignments@2023-04-15' = {
  name: roleAssignmentId
  parent: databaseAccount
  properties:{
    principalId: principalId
    roleDefinitionId: '/${subscription().id}/resourceGroups/${databaseAccountResourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/${databaseAccount.name}/sqlRoleDefinitions/${roleDefinitionId}'
    scope: databaseAccount.id
  }
}

The complete module can be found here.

I did discover/realized during this process that at this time only User Assigned Identities can be provisioned the RBAC role. When I attempted this with a System Managed Identity access was not granted.

Conclusion

Cosmos RBAC data plane access has traditionally be configured either via PowerShell role assignment or applications leverage the full Cosmos connection strings. This article hopefully walked through and provided you with a way to leverage Bicep to keep these RBAC role assignments in your infrastructure as code. If you are interested more Cosmos feel free to check out my post on the DP – 420 Cosmos Specialty exam.