Configure role-based access control with Azure Active Directory for your Azure Cosmos DB account

APPLIES TO: SQL API

Note

This article is about role-based access control for data plane operations in Azure Cosmos DB. If you are using management plane operations, see role-based access control applied to your management plane operations article.

Azure Cosmos DB exposes a built-in role-based access control (RBAC) system that lets you:

  • Authenticate your data requests with an Azure Active Directory (Azure AD) identity.
  • Authorize your data requests with a fine-grained, role-based permission model.

Concepts

The Azure Cosmos DB data plane RBAC is built on concepts that are commonly found in other RBAC systems like Azure RBAC:

  • The permission model is composed of a set of actions; each of these actions maps to one or multiple database operations. Some examples of actions include reading an item, writing an item, or executing a query.

  • Azure Cosmos DB users create role definitions containing a list of allowed actions.

  • Role definitions get assigned to specific Azure AD identities through role assignments. A role assignment also defines the scope that the role definition applies to; currently, three scopes are currently:

    • An Azure Cosmos DB account,
    • An Azure Cosmos DB database,
    • An Azure Cosmos DB container.

    RBAC concepts

Permission model

Important

This permission model covers only database operations that involve reading and writing data. It does not cover any kind of management operations on management resources, for example:

  • Create/Replace/Delete Database
  • Create/Replace/Delete Container
  • Replace Container Throughput
  • Create/Replace/Delete/Read Stored Procedures
  • Create/Replace/Delete/Read Triggers
  • Create/Replace/Delete/Read User Defined Functions

You cannot use any Azure Cosmos DB data plane SDK to authenticate management operations with an Azure AD identity. Instead, you must use Azure RBAC through one of the following options:

Read Database and Read Container are considered metadata requests. Access to these operations can be granted as stated in the following section.

The table below lists all the actions exposed by the permission model.

Name Corresponding database operation(s)
Microsoft.DocumentDB/databaseAccounts/readMetadata Read account metadata. See Metadata requests for details.
Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/create Create a new item.
Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/read Read an individual item by its ID and partition key (point-read).
Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/replace Replace an existing item.
Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/upsert "Upsert" an item, which means create it if it doesn't exist, or replace it if it exists.
Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/delete Delete an item.
Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/executeQuery Execute a SQL query.
Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/readChangeFeed Read from the container's change feed.
Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/executeStoredProcedure Execute a stored procedure.
Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/manageConflicts Manage conflicts for multi-write region accounts (that is, list and delete items from the conflict feed).

Wildcards are supported at both containers and items levels:

  • Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*
  • Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*

Metadata requests

When using Azure Cosmos DB SDKs, these SDKs issue read-only metadata requests during initialization and to serve specific data requests. These metadata requests fetch various configuration details such as:

  • The global configuration of your account, which includes the Azure regions the account is available in.
  • The partition key of your containers or their indexing policy.
  • The list of physical partitions that make a container and their addresses.

They do not fetch any of the data that you've stored in your account.

To ensure the best transparency of our permission model, these metadata requests are explicitly covered by the Microsoft.DocumentDB/databaseAccounts/readMetadata action. This action should be allowed in every situation where your Azure Cosmos DB account is accessed through one of the Azure Cosmos DB SDKs. It can be assigned (through a role assignment) at any level in the Azure Cosmos DB hierarchy (that is, account, database, or container).

The actual metadata requests allowed by the Microsoft.DocumentDB/databaseAccounts/readMetadata action depend on the scope that the action is assigned to:

Scope Requests allowed by the action
Account - Listing the databases under the account
- For each database under the account, the allowed actions at the database scope
Database - Reading database metadata
- Listing the containers under the database
- For each container under the database, the allowed actions at the container scope
Container - Reading container metadata
- Listing physical partitions under the container
- Resolving the address of each physical partition

Built-in role definitions

Azure Cosmos DB exposes 2 built-in role definitions:

ID Name Included actions
00000000-0000-0000-0000-000000000001 Cosmos DB Built-in Data Reader Microsoft.DocumentDB/databaseAccounts/readMetadata
Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/read
Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/executeQuery
Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/readChangeFeed
00000000-0000-0000-0000-000000000002 Cosmos DB Built-in Data Contributor Microsoft.DocumentDB/databaseAccounts/readMetadata
Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*
Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*

Create custom role definitions

When creating a custom role definition, you need to provide:

  • The name of your Azure Cosmos DB account.
  • The resource group containing your account.
  • The type of the role definition: CustomRole.
  • The name of the role definition.
  • A list of actions that you want the role to allow.
  • One or multiple scope(s) that the role definition can be assigned at; supported scopes are:
    • / (account-level),
    • /dbs/<database-name> (database-level),
    • /dbs/<database-name>/colls/<container-name> (container-level).

Note

The operations described below are available in:

Using Azure PowerShell

Create a role named MyReadOnlyRole that only contains read actions:

$resourceGroupName = "<myResourceGroup>"
$accountName = "<myCosmosAccount>"
New-AzCosmosDBSqlRoleDefinition -AccountName $accountName `
    -ResourceGroupName $resourceGroupName `
    -Type CustomRole -RoleName MyReadOnlyRole `
    -DataAction @( `
        'Microsoft.DocumentDB/databaseAccounts/readMetadata',
        'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/read', `
        'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/executeQuery', `
        'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/readChangeFeed') `
    -AssignableScope "/"

Create a role named MyReadWriteRole that contains all actions:

New-AzCosmosDBSqlRoleDefinition -AccountName $accountName `
    -ResourceGroupName $resourceGroupName `
    -Type CustomRole -RoleName MyReadWriteRole `
    -DataAction @( `
        'Microsoft.DocumentDB/databaseAccounts/readMetadata',
        'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*', `
        'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*') `
    -AssignableScope "/"

List the role definitions you've created to fetch their IDs:

Get-AzCosmosDBSqlRoleDefinition -AccountName $accountName `
    -ResourceGroupName $resourceGroupName
RoleName         : MyReadWriteRole
Id               : /subscriptions/<mySubscriptionId>/resourceGroups/<myResourceGroup>/providers/Microsoft.DocumentDB/databaseAcc
                   ounts/<myCosmosAccount>/sqlRoleDefinitions/<roleDefinitionId>
Type             : CustomRole
Permissions      : {Microsoft.Azure.Management.CosmosDB.Models.Permission}
AssignableScopes : {/subscriptions/<mySubscriptionId>/resourceGroups/<myResourceGroup>/providers/Microsoft.DocumentDB/databaseAc
                   counts/<myCosmosAccount>}

RoleName         : MyReadOnlyRole
Id               : /subscriptions/<mySubscriptionId>/resourceGroups/<myResourceGroup>/providers/Microsoft.DocumentDB/databaseAcc
                   ounts/<myCosmosAccount>/sqlRoleDefinitions/<roleDefinitionId>
Type             : CustomRole
Permissions      : {Microsoft.Azure.Management.CosmosDB.Models.Permission}
AssignableScopes : {/subscriptions/<mySubscriptionId>/resourceGroups/<myResourceGroup>/providers/Microsoft.DocumentDB/databaseAc
                   counts/<myCosmosAccount>}

Using the Azure CLI

Create a role named MyReadOnlyRole that only contains read actions:

// role-definition-ro.json
{
    "RoleName": "MyReadOnlyRole",
    "Type": "CustomRole",
    "AssignableScopes": ["/"],
    "Permissions": [{
        "DataActions": [
            "Microsoft.DocumentDB/databaseAccounts/readMetadata",
            "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/read",
            "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/executeQuery",
            "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/readChangeFeed"
        ]
    }]
}
resourceGroupName='<myResourceGroup>'
accountName='<myCosmosAccount>'
az cosmosdb sql role definition create --account-name $accountName --resource-group $resourceGroupName --body @role-definition-ro.json

Create a role named MyReadWriteRole that contains all actions:

// role-definition-rw.json
{
    "RoleName": "MyReadWriteRole",
    "Type": "CustomRole",
    "AssignableScopes": ["/"],
    "Permissions": [{
        "DataActions": [
            "Microsoft.DocumentDB/databaseAccounts/readMetadata",
            "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*",
            "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*"
        ]
    }]
}
az cosmosdb sql role definition create --account-name $accountName --resource-group $resourceGroupName --body @role-definition-rw.json

List the role definitions you've created to fetch their IDs:

az cosmosdb sql role definition list --account-name $accountName --resource-group $resourceGroupName
[
  {
    "assignableScopes": [
      "/subscriptions/<mySubscriptionId>/resourceGroups/<myResourceGroup>/providers/Microsoft.DocumentDB/databaseAccounts/<myCosmosAccount>"
    ],
    "id": "/subscriptions/<mySubscriptionId>/resourceGroups/<myResourceGroup>/providers/Microsoft.DocumentDB/databaseAccounts/<myCosmosAccount>/sqlRoleDefinitions/<roleDefinitionId>",
    "name": "<roleDefinitionId>",
    "permissions": [
      {
        "dataActions": [
          "Microsoft.DocumentDB/databaseAccounts/readMetadata",
          "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*",
          "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*"
        ],
        "notDataActions": []
      }
    ],
    "resourceGroup": "<myResourceGroup>",
    "roleName": "MyReadWriteRole",
    "sqlRoleDefinitionGetResultsType": "CustomRole",
    "type": "Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions"
  },
  {
    "assignableScopes": [
      "/subscriptions/<mySubscriptionId>/resourceGroups/<myResourceGroup>/providers/Microsoft.DocumentDB/databaseAccounts/<myCosmosAccount>"
    ],
    "id": "/subscriptions/<mySubscriptionId>/resourceGroups/<myResourceGroup>/providers/Microsoft.DocumentDB/databaseAccounts/<myCosmosAccount>/sqlRoleDefinitions/<roleDefinitionId>",
    "name": "<roleDefinitionId>",
    "permissions": [
      {
        "dataActions": [
          "Microsoft.DocumentDB/databaseAccounts/readMetadata",
          "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/read",
          "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/executeQuery",
          "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/readChangeFeed"
        ],
        "notDataActions": []
      }
    ],
    "resourceGroup": "<myResourceGroup>",
    "roleName": "MyReadOnlyRole",
    "sqlRoleDefinitionGetResultsType": "CustomRole",
    "type": "Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions"
  }
]

Using Azure Resource Manager templates

See this page for a reference and examples of using Azure Resource Manager templates to create role definitions.

Create role assignments

You can associate built-in or custom role definitions with your Azure AD identities. When creating a role assignment, you need to provide:

  • The name of your Azure Cosmos DB account.

  • The resource group containing your account.

  • The ID of the role definition to assign.

  • The principal ID of the identity that the role definition should be assigned to.

  • The scope of the role assignment; supported scopes are:

    • / (account-level)
    • /dbs/<database-name> (database-level)
    • /dbs/<database-name>/colls/<container-name> (container-level)

    The scope must match or be a sub-scope of one of the role definition's assignable scopes.

Note

If you want to create a role assignment for a service principal, make sure to use its Object ID as found in the Enterprise applications section of the Azure Active Directory portal blade.

Note

The operations described below are available in:

Using Azure PowerShell

Assign a role to an identity:

$resourceGroupName = "<myResourceGroup>"
$accountName = "<myCosmosAccount>"
$readOnlyRoleDefinitionId = "<roleDefinitionId>" # as fetched above
$principalId = "<aadPrincipalId>"
New-AzCosmosDBSqlRoleAssignment -AccountName $accountName `
    -ResourceGroupName $resourceGroupName `
    -RoleDefinitionId $readOnlyRoleDefinitionId `
    -Scope "/" `
    -PrincipalId $principalId

Using the Azure CLI

Assign a role to an identity:

resourceGroupName='<myResourceGroup>'
accountName='<myCosmosAccount>'
readOnlyRoleDefinitionId = '<roleDefinitionId>' # as fetched above
principalId = '<aadPrincipalId>'
az cosmosdb sql role assignment create --account-name $accountName --resource-group $resourceGroupName --scope "/" --principal-id $principalId --role-definition-id $readOnlyRoleDefinitionId

Using Azure Resource Manager templates

See this page for a reference and examples of using Azure Resource Manager templates to create role assignments.

Initialize the SDK with Azure AD

To use the Azure Cosmos DB RBAC in your application, you have to update the way you initialize the Azure Cosmos DB SDK. Instead of passing your account's primary key, you have to pass an instance of a TokenCredential class. This instance provides the Azure Cosmos DB SDK with the context required to fetch an AAD token on behalf of the identity you wish to use.

The way you create a TokenCredential instance is beyond the scope of this article. There are many ways to create such an instance depending on the type of AAD identity you want to use (user principal, service principal, group etc.). Most importantly, your TokenCredential instance must resolve to the identity (principal ID) that you've assigned your roles to. You can find examples of creating a TokenCredential class:

The examples below use a service principal with a ClientSecretCredential instance.

In .NET

The Azure Cosmos DB RBAC is currently supported in the .NET SDK V3.

TokenCredential servicePrincipal = new ClientSecretCredential(
    "<azure-ad-tenant-id>",
    "<client-application-id>",
    "<client-application-secret>");
CosmosClient client = new CosmosClient("<account-endpoint>", servicePrincipal);

In Java

The Azure Cosmos DB RBAC is currently supported in the Java SDK V4.

TokenCredential ServicePrincipal = new ClientSecretCredentialBuilder()
    .authorityHost("https://login.microsoftonline.com")
    .tenantId("<azure-ad-tenant-id>")
    .clientId("<client-application-id>")
    .clientSecret("<client-application-secret>")
    .build();
CosmosAsyncClient Client = new CosmosClientBuilder()
    .endpoint("<account-endpoint>")
    .credential(ServicePrincipal)
    .build();

In JavaScript

The Azure Cosmos DB RBAC is currently supported in the JavaScript SDK V3.

const servicePrincipal = new ClientSecretCredential(
    "<azure-ad-tenant-id>",
    "<client-application-id>",
    "<client-application-secret>");
const client = new CosmosClient({
    "<account-endpoint>",
    aadCredentials: servicePrincipal
});

Authenticate requests on the REST API

When constructing the REST API authorization header, set the type parameter to aad and the hash signature (sig) to the oauth token as shown in the following example:

type=aad&ver=1.0&sig=<token-from-oauth>

Use data explorer

Note

The data explorer exposed in the Azure portal does not support the Azure Cosmos DB RBAC yet. To use your Azure AD identity when exploring your data, you must use the Azure Cosmos DB Explorer instead.

When you access the Azure Cosmos DB Explorer with the specific ?feature.enableAadDataPlane=true query parameter and sign in, the following logic is used to access your data:

  1. A request to fetch the account's primary key is attempted on behalf of the identity signed in. If this request succeeds, the primary key is used to access the account's data.
  2. If the identity signed in isn't allowed to fetch the account's primary key, this identity is directly used to authenticate data access. In this mode, the identity must be assigned with proper role definitions to ensure data access.

Audit data requests

When using the Azure Cosmos DB RBAC, diagnostic logs get augmented with identity and authorization information for each data operation. This lets you perform detailed auditing and retrieve the AAD identity used for every data request sent to your Azure Cosmos DB account.

This additional information flows in the DataPlaneRequests log category and consists of two extra columns:

  • aadPrincipalId_g shows the principal ID of the AAD identity that was used to authenticate the request.
  • aadAppliedRoleAssignmentId_g shows the role assignment that was honored when authorizing the request.

Enforcing RBAC as the only authentication method

In situations where you want to force clients to connect to Azure Cosmos DB through RBAC exclusively, you have the option to disable the account's primary/secondary keys. When doing so, any incoming request using either a primary/secondary key or a resource token will be actively rejected.

Using Azure Resource Manager templates

When creating or updating your Azure Cosmos DB account using Azure Resource Manager templates, set the disableLocalAuth property to true:

"resources": [
    {
        "type": " Microsoft.DocumentDB/databaseAccounts",
        "properties": {
            "disableLocalAuth": true,
            // ...
        },
        // ...
    },
    // ...
 ]

Limits

  • You can create up to 100 role definitions and 2,000 role assignments per Azure Cosmos DB account.
  • You can only assign role definitions to Azure AD identities belonging to the same Azure AD tenant as your Azure Cosmos DB account.
  • Azure AD group resolution is not currently supported for identities that belong to more than 200 groups.
  • The Azure AD token is currently passed as a header with each individual request sent to the Azure Cosmos DB service, increasing the overall payload size.

Frequently asked questions

Which Azure Cosmos DB APIs are supported by RBAC?

Only the SQL API is currently supported.

Is it possible to manage role definitions and role assignments from the Azure portal?

Azure portal support for role management is not available yet.

Which SDKs in Azure Cosmos DB SQL API support RBAC?

The .NET V3, Java V4 and JavaScript V3 SDKs are currently supported.

Is the Azure AD token automatically refreshed by the Azure Cosmos DB SDKs when it expires?

Yes.

Is it possible to disable the usage of the account primary/secondary keys when using RBAC?

Yes, see Enforcing RBAC as the only authentication method.

Next steps