Edit

Share via


Connect to Azure Cosmos DB for NoSQL using role-based access control and Microsoft Entra ID

Role-based access control refers to a method to manage access to resources in Azure. This method is based on specific identities being assigned roles that manage what level of access they have to one or more resources. Role-based access control provides a flexible system of fine-grained access management that ensures identities only have the least privileged level of access they need to perform their task.

For more information, see role-based access control.

Prerequisites

  • An Azure account with an active subscription. Create an account for free.

  • An existing Azure Cosmos DB for NoSQL account.

  • One or more existing identities in Microsoft Entra ID.

Disable key-based authentication

Disabling key-based authorization prevents your account from being used without the more secure Microsoft Entra ID authentication method. This procedure is a step that should be performed on new accounts in secure workloads. Alternatively, perform this procedure on existing accounts being migrated to a secure workload pattern.

First, disable key-based authentication to your existing account so that applications are required to use Microsoft Entra ID authentication. Use az resource update to modify properties.disableLocalAuth of the existing account.

az resource update \
    --resource-group "<name-of-existing-resource-group>" \
    --name "<name-of-existing-account>" \
    --resource-type "Microsoft.DocumentDB/databaseAccounts" \
    --set properties.disableLocalAuth=true

First, create a new account with key-based authentication disabled so that applications are required to use Microsoft Entra authentication.

  1. Create a new Bicep file to deploy your new account with key-based authentication disabled. Name the file deploy-new-account.bicep.

    metadata description = 'Deploys a new Azure Cosmos DB account with key-based auth disabled.'
    
    @description('Name of the Azure Cosmos DB account.')
    param name string = 'csms-${uniqueString(resourceGroup().id)}'
    
    @description('Primary ___location for the Azure Cosmos DB account.')
    param ___location string = resourceGroup().___location
    
    resource account 'Microsoft.DocumentDB/databaseAccounts@2024-05-15' = {
      name: name
      ___location: ___location
      kind: 'GlobalDocumentDB'
      properties: {
        databaseAccountOfferType: 'Standard'
        locations: [
          {
            locationName: ___location
          }
        ]
        disableLocalAuth: true
      }
    }
    
  2. Use az deployment group create to deploy the Bicep file with the new account.

    az deployment group create \
        --resource-group "<name-of-existing-resource-group>" \
        --template-file deploy-new-account.bicep
    

First, disable key-based authentication to your existing account so that applications are required to use Microsoft Entra authentication. Use Get-AzResource and Set-AzResource to respectively read and update the existing account.

$parameters = @{
    ResourceGroupName = "<name-of-existing-resource-group>"
    ResourceName = "<name-of-existing-account>"
    ResourceType = "Microsoft.DocumentDB/databaseAccounts"
}
$resource = Get-AzResource @parameters

$resource.Properties.DisableLocalAuth = $true

$resource | Set-AzResource -Force

Use these steps to create a new Azure Cosmos DB for NoSQL account with key-based authentication disabled so that applications are required to only use Microsoft Entra authentication.

  1. When setting up a new Azure Cosmos DB for NoSQL account, navigate to the Security section of the account creation process.

  2. Then, select Disable for the Key-based authentication option.

    Screenshot of the option to disable key-based authentication when creating a new account in the Azure portal.

Important

Modifying an Azure Cosmos DB account requires an Azure role with at least the Microsoft.DocumentDb/databaseAccounts/*/write permission. For more information, see permissions for Azure Cosmos DB.

Validate that key-based authentication is disabled

To validate that key-based access is disabled, attempt to use the Azure SDK to connect to Azure Cosmos DB for NoSQL using a resource-owner password credential (ROPC). This attempt should fail. If necessary, code samples for common programming languages are provided here.

using Microsoft.Azure.Cosmos;

string connectionString = "AccountEndpoint=<nosql-endpoint>;AccountKey=<key>;";

CosmosClient client = new(connectionString);
const { CosmosClient } = require('@azure/cosmos');

const connectionString = 'AccountEndpoint=<nosql-endpoint>;AccountKey=<key>;';

const client = new CosmosClient(connectionString);
import { CosmosClient } from '@azure/cosmos'

let connectionString: string = 'AccountEndpoint=<nosql-endpoint>;AccountKey=<key>;';

const client: CosmosClient = new CosmosClient(connectionString);
from azure.cosmos import CosmosClient

connection_string = "AccountEndpoint=<nosql-endpoint>;AccountKey=<key>;"

client = CosmosClient(connection_string)
package main

import (
    "github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos"
)

const connectionString = "AccountEndpoint=<nosql-endpoint>;AccountKey=<key>;"

func main() {
    client, _ := azcosmos.NewClientFromConnectionString(connectionString, nil)
}
import com.azure.cosmos.CosmosClient;
import com.azure.cosmos.CosmosClientBuilder;

public class NoSQL{
    public static void main(String[] args){
        CosmosClient client = new CosmosClientBuilder()
            .endpoint("<nosql-endpoint>")
            .key("<key>")
            .buildClient();
    }
}
use azure_data_cosmos::CosmosClient;

fn main() {
    let client = CosmosClient::new_with_access_key(
        "<account-endpoint>",
        "<account-key>",
        None,
    ).unwrap();

    let container = client.database_client("<database-name>").container_client("<container-name>");

    let response = container.read_item("<partition-key>", "<item-id>", None);
    tokio::runtime::Runtime::new().unwrap().block_on(response).unwrap();
}

Grant control plane role-based access

Control plane access refers to the ability to manage resources for an Azure service without managing data. For example, Azure Cosmos DB control plane access could include the ability to:

  • Read all account and resource metadata
  • Read and regenerate account keys and connection strings
  • Perform account backups and restore
  • Start and track data transfer jobs
  • Manage databases and containers
  • Modify account properties

Important

In Azure Cosmos DB, you need control plane access to manage native data-plane role-based access control definitions and assignments. Since Azure Cosmos DB's data plane role-based access control mechanism is native, you need control plane access to create definitions and assignments and store them as resources within an Azure Cosmos DB account.

First, you must prepare a role definition with a list of actions to grant access to manage account resources in Azure Cosmos DB. In this guide, you prepare a built-in and custom role. Then, assign the newly defined role[s] to an identity so that your applications can access resources in Azure Cosmos DB.

  1. List all of the role definitions associated with your Azure Cosmos DB account using az role definition list.

    az role definition list \
        --name "Cosmos DB Operator"
    
  2. Review the output and locate the role definition named Cosmos DB Operator. The output contains the unique identifier of the role definition in the id property. Record this value as it is required to use in the assignment step later in this guide.

    [
      {
        "assignableScopes": [
          "/"
        ],
        "description": "Lets you manage Azure Cosmos DB accounts, but not access data in them. Prevents access to account keys and connection strings.",
        "id": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/providers/Microsoft.Authorization/roleDefinitions/230815da-be43-4aae-9cb4-875f7bd000aa",
        "name": "230815da-be43-4aae-9cb4-875f7bd000aa",
        "permissions": [
          {
            "actions": [
              "Microsoft.DocumentDb/databaseAccounts/*",
              "Microsoft.Insights/alertRules/*",
              "Microsoft.Authorization/*/read",
              "Microsoft.ResourceHealth/availabilityStatuses/read",
              "Microsoft.Resources/deployments/*",
              "Microsoft.Resources/subscriptions/resourceGroups/read",
              "Microsoft.Support/*",
              "Microsoft.Network/virtualNetworks/subnets/joinViaServiceEndpoint/action"
            ],
            "condition": null,
            "conditionVersion": null,
            "dataActions": [],
            "notActions": [
              "Microsoft.DocumentDB/databaseAccounts/dataTransferJobs/*",
              "Microsoft.DocumentDB/databaseAccounts/readonlyKeys/*",
              "Microsoft.DocumentDB/databaseAccounts/regenerateKey/*",
              "Microsoft.DocumentDB/databaseAccounts/listKeys/*",
              "Microsoft.DocumentDB/databaseAccounts/listConnectionStrings/*",
              "Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions/write",
              "Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions/delete",
              "Microsoft.DocumentDB/databaseAccounts/sqlRoleAssignments/write",
              "Microsoft.DocumentDB/databaseAccounts/sqlRoleAssignments/delete",
              "Microsoft.DocumentDB/databaseAccounts/mongodbRoleDefinitions/write",
              "Microsoft.DocumentDB/databaseAccounts/mongodbRoleDefinitions/delete",
              "Microsoft.DocumentDB/databaseAccounts/mongodbUserDefinitions/write",
              "Microsoft.DocumentDB/databaseAccounts/mongodbUserDefinitions/delete"
            ],
            "notDataActions": []
          }
        ],
        "roleName": "Cosmos DB Operator",
        "roleType": "BuiltInRole",
        "type": "Microsoft.Authorization/roleDefinitions",
      }
    ]
    

    Note

    In this example, the id value would be /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/providers/Microsoft.Authorization/roleDefinitions/230815da-be43-4aae-9cb4-875f7bd000aa. This example uses fictitious data and your identifier would be distinct from this example. However, the identifier (230815da-be43-4aae-9cb4-875f7bd000aa) is globally unique across all role definitions in Azure.

  3. Use az group show to get the metadata for your current resource group.

    az group show \
        --name "<name-of-existing-resource-group>"
    
  4. Observe the output of the previous command. Record the value of the id property for this resource group as it is required to use in the next step.

    {
      "id": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example",
      "___location": "westus",
      "name": "msdocs-identity-example",
      "type": "Microsoft.Resources/resourceGroups"
    }
    

    Note

    In this example, the id value would be /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example. This example uses fictitious data and your identifier would be distinct from this example. This string is a truncated example of the output.

  5. Create a new JSON file named role-definition.json. In the file, create this resource definition specifying the values listed here. For the AssignableScopes list, add the id property of the resource group recorded in the previous step.

    {
      "Name": "Azure Cosmos DB Control Plane Owner",
      "IsCustom": true,
      "Description": "Can perform all control plane actions for an Azure Cosmos DB account.",
      "Actions": [
        "Microsoft.DocumentDb/*"
      ],
      "AssignableScopes": [
        "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example"
      ]
    }
    

    Note

    This example uses the /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example value recorded from the previous step. Your actual resource identifier could be different.

  6. Create a new role definition using az role definition create. Use the role-definition.json file as the input for the --role-definition argument.

    az role definition create \
        --role-definition role-definition.json
    
  7. Review the output from the definition creation command. The output contains the unique identifier of the role definition in the id property. Record this value as it is required to use in the assignment step later in this guide.

    {
      "assignableScopes": [
        "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example"
      ],
      "description": "Can perform all control plane actions for an Azure Cosmos DB account.",
      "id": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example/providers/Microsoft.Authorization/roleDefinitions/a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1",
      "name": "e4e4e4e4-ffff-aaaa-bbbb-c5c5c5c5c5c5",
      "permissions": [
        {
          "actions": [
            "Microsoft.DocumentDb/*"
          ]
        }
      ],
      "roleName": "Azure Cosmos DB Control Plane Owner",
      "roleType": "CustomRole"
    }
    

    Note

    In this example, the id value would be /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example/providers/Microsoft.Authorization/roleDefinitions/a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1. This example uses fictitious data and your identifier would be distinct from this example. This example is a subset of the typical JSON outputted from the deployment for clarity.

  8. Use az group show to get the metadata for your current resource group again.

    az group show \
        --name "<name-of-existing-resource-group>"
    
  9. Observe the output of the previous command. Record the value of the id property for this resource group as it is required to use in the next step.

    {
      "id": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example",
      "___location": "westus",
      "name": "msdocs-identity-example",
      "type": "Microsoft.Resources/resourceGroups"
    }
    

    Note

    In this example, the id value would be /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example. This example uses fictitious data and your identifier would be distinct from this example. This string is a truncated example of the output.

  10. Assign the new role using az role assignment create. Use your resource group's identifier for the --scope argument, the role's identifier for the -role argument, and the unique identifier for your identity to the --assignee argument.

    az role assignment create \
        --assignee "<your-principal-identifier>" \
        --role "subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example/providers/Microsoft.Authorization/roleDefinitions/a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1" \
        --scope "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example"
    

    Note

    In this example command, the scope was set to the fictitious example /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example from the previous step's example. Your resource group's identifier would be distinct from this example. The role was also set to the fictitious /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example/providers/Microsoft.Authorization/roleDefinitions/a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1. Again, your role identifier would be distinct.

  11. Observe the output from the command. The output includes a unique identifier for the assignment in the id property.

    {
      "id": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example/providers/Microsoft.Authorization/roleAssignments/a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1",
      "name": "ffffffff-5555-6666-7777-aaaaaaaaaaaa",
      "principalId": "aaaaaaaa-bbbb-cccc-1111-222222222222",
      "resourceGroup": "msdocs-identity-example",
      "roleDefinitionId": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example/providers/Microsoft.Authorization/roleDefinitions/a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1",
      "scope": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example",
      "type": "Microsoft.Authorization/roleAssignments"
    }
    

    Note

    In this example, the id property is /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example/providers/Microsoft.Authorization/roleAssignments/a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1, which is another fictitious example.

  12. Repeat these steps to grant access to the account from any other identities you would like to use.

    Tip

    You can repeat these steps for as many identities as you'd like. Typically, these steps are at least repeated to allow developers access to an account using their human identity and to allow applications access to the data using a managed identity.

  1. List all of the role definitions associated with your Azure Cosmos DB account using az role definition list.

    az role definition list \
        --name "Cosmos DB Operator"
    
  2. Review the output and locate the role definition named Cosmos DB Operator. The output contains the unique identifier of the role definition in the id property. Record this value as it is required to use in the assignment step later in this guide.

    [
      {
        "assignableScopes": [
          "/"
        ],
        "description": "Lets you manage Azure Cosmos DB accounts, but not access data in them. Prevents access to account keys and connection strings.",
        "id": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/providers/Microsoft.Authorization/roleDefinitions/230815da-be43-4aae-9cb4-875f7bd000aa",
        "name": "230815da-be43-4aae-9cb4-875f7bd000aa",
        "permissions": [
          {
            "actions": [
              "Microsoft.DocumentDb/databaseAccounts/*",
              "Microsoft.Insights/alertRules/*",
              "Microsoft.Authorization/*/read",
              "Microsoft.ResourceHealth/availabilityStatuses/read",
              "Microsoft.Resources/deployments/*",
              "Microsoft.Resources/subscriptions/resourceGroups/read",
              "Microsoft.Support/*",
              "Microsoft.Network/virtualNetworks/subnets/joinViaServiceEndpoint/action"
            ],
            "condition": null,
            "conditionVersion": null,
            "dataActions": [],
            "notActions": [
              "Microsoft.DocumentDB/databaseAccounts/dataTransferJobs/*",
              "Microsoft.DocumentDB/databaseAccounts/readonlyKeys/*",
              "Microsoft.DocumentDB/databaseAccounts/regenerateKey/*",
              "Microsoft.DocumentDB/databaseAccounts/listKeys/*",
              "Microsoft.DocumentDB/databaseAccounts/listConnectionStrings/*",
              "Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions/write",
              "Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions/delete",
              "Microsoft.DocumentDB/databaseAccounts/sqlRoleAssignments/write",
              "Microsoft.DocumentDB/databaseAccounts/sqlRoleAssignments/delete",
              "Microsoft.DocumentDB/databaseAccounts/mongodbRoleDefinitions/write",
              "Microsoft.DocumentDB/databaseAccounts/mongodbRoleDefinitions/delete",
              "Microsoft.DocumentDB/databaseAccounts/mongodbUserDefinitions/write",
              "Microsoft.DocumentDB/databaseAccounts/mongodbUserDefinitions/delete"
            ],
            "notDataActions": []
          }
        ],
        "roleName": "Cosmos DB Operator",
        "roleType": "BuiltInRole",
        "type": "Microsoft.Authorization/roleDefinitions",
      }
    ]
    

    Note

    In this example, the id value would be /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/providers/Microsoft.Authorization/roleDefinitions/230815da-be43-4aae-9cb4-875f7bd000aa. This example uses fictitious data and your identifier would be distinct from this example. However, the identifier (230815da-be43-4aae-9cb4-875f7bd000aa) is globally unique across all role definitions in Azure.

  3. Create a new Bicep file to define your role definition. Name the file control-plane-role-definition.bicep. Add these actions to the definition:

    Description
    Microsoft.DocumentDb/* Enables all possible actions.
    metadata description = 'Create RBAC definition for control plane access to Azure Cosmos DB.'
    
    @description('Name of the role definition.')
    param roleDefinitionName string = 'Azure Cosmos DB Control Plane Owner'
    
    @description('Description of the role definition.')
    param roleDefinitionDescription string = 'Can perform all control plane actions for an Azure Cosmos DB account.'
    
    resource definition 'Microsoft.Authorization/roleDefinitions@2022-04-01' = {
      name: guid(subscription().id, resourceGroup().id, roleDefinitionName)
      scope: resourceGroup()
      properties: {
        roleName: roleDefinitionName
        description: roleDefinitionDescription
        type: 'CustomRole'
        permissions: [
          {
            actions: [
              'Microsoft.DocumentDb/*'
            ]
          }
        ]
        assignableScopes: [
          resourceGroup().id
        ]
      }
    }
    
    output definitionId string = definition.id
    
  4. Deploy the Bicep template using az deployment group create. Specify the name of the Bicep template and Azure resource group.

    az deployment group create \
        --resource-group "<name-of-existing-resource-group>" \
        --template-file control-plane-role-definition.bicep
    
  5. Review the output from the deployment. The output contains the unique identifier of the role definition in the properties.outputs.definitionId.value property. Record this value as it is required to use in the assignment step later in this guide.

    {
      "properties": {
        "outputs": {
          "definitionId": {
            "type": "String",
            "value": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example/providers/Microsoft.Authorization/roleDefinitions/a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1"
          }
        }
      }
    }
    

    Note

    In this example, the id value would be /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example/providers/Microsoft.Authorization/roleDefinitions/a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1. This example uses fictitious data and your identifier would be distinct from this example. This example is a subset of the typical JSON outputted from the deployment for clarity.

  6. Create a new Bicep file to define your role assignment. Name the file control-plane-role-assignment.bicep.

    metadata description = 'Assign RBAC role for control plane access to Azure Cosmos DB.'
    
    @description('Id of the role definition to assign to the targeted principal in the context of the account.')
    param roleDefinitionId string
    
    @description('Id of the identity/principal to assign this role in the context of the account.')
    param identityId string
    
    resource assignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
      name: guid(subscription().id, resourceGroup().id, roleDefinitionId, identityId)
      scope: resourceGroup()
      properties: {
        roleDefinitionId: roleDefinitionId
        principalId: identityId
      }
    }
    
  7. Create a new Bicep parameters file named control-plane-role-assignment.bicepparam. In this parameters file; assign the previously recorded role definition identifiers to the roleDefinitionId parameter, and the unique identifier for your identity to the identityId parameter.

    using './control-plane-role-assignment.bicep'
    
    param roleDefinitionId = '<id-of-new-role-definition>'
    param identityId = '<id-of-existing-identity>'
    
  8. Deploy this Bicep template using az deployment group create.

    az deployment group create \
        --resource-group "<name-of-existing-resource-group>" \
        --parameters control-plane-role-assignment.bicepparam \
        --template-file control-plane-role-assignment.bicep
    
  9. Repeat these steps to grant access to the account from any other identities you would like to use.

    Tip

    You can repeat these steps for as many identities as you'd like. Typically, these steps are at least repeated to allow developers access to an account using their human identity and to allow applications access to the data using a managed identity.

  1. Sign in to the Azure portal (https://portal.azure.com).

  2. Enter Resource group in the global search bar.

    Screenshot of the global search bar in the Azure portal.

  3. Within Services, select Resource groups.

    Screenshot of the 'Resource groups' option selected in the search menu.

  4. In the Resource groups pane, select your existing resource group.

    Screenshot of an existing resource group in the list of resource groups for the subscription.

    Note

    This example screenshot includes the msdocs-identity-example resource group. Your actual resource group name could be different.

  5. Within the pane for the resource group, select Access control (IAM) in the service menu.

    Screenshot of the 'Access Control (IAM)' option in the service menu for a resource group.

  6. In the Access control (IAM) pane, select Roles.

    Screenshot of the 'Roles' option in the 'Access Control (IAM)' pane.

  7. In the Roles section, use the search phrase Cosmos DB and locate the Cosmos DB Operator role definition. Then, select the View option associated with that definition.

    Screenshot of a list of role definitions at the current assignable scope filtered to include only definitions with 'Cosmos DB' in the title.

  8. In the Cosmos DB Operator role definition dialog, observe the actions assigned as part of this role definition.

    Screenshot of the 'Cosmos DB Operator' dialog with details about the built-in role definition.

  9. Close the Cosmos DB Operator role definition dialog.

  10. Back in the Access control (IAM) pane, select Add. Then select Add custom role.

    Screenshot of the 'Add custom role' option in the 'Access Control (IAM)' menu for the 'Add' option.

  11. Within the Basics pane, configure the following options, and then select Next:

    Value
    Custom role name Azure Cosmos DB Control Plane Owner
    Description Can perform all control plane actions for an Azure Cosmos DB account.
    Baseline permissions Start from scratch

    Screenshot of the 'Basics' pane for adding a custom role.

  12. In the Permissions pane, select Add permissions. Then, search for DocumentDB in the permissions dialog. Finally, select the Microsoft.DocumentDB option.

    Screenshot of the 'Permissions' pane for adding a custom role.

    Screenshot of the 'Add permissions' dialog filtered to permissions related to 'DocumentDB' for adding a custom role.

  13. In the permissions dialog, select all Actions for Microsoft.DocumentDB. Then, select Add to return to the *Permissions pane.

    Screenshot of all permissions selected for 'DocumentDB' in a dialog for a custom role.

  14. Back in the Permissions pane, observe the list of permissions. Then, select Review + create.

    Screenshot of the 'Permissions' pane with multiple permissions added to the list for a custom role.

  15. In the Review + create pane, review the specified options for the new role definition. Finally, select Create.

    Screenshot of the 'Review + create' pane for adding a custom role.

  16. Wait for the portal to finish creating the role definition.

  17. In the Access control (IAM) pane, select Add and then Add role assignment.

    Screenshot of the 'Add role assignment' option in the 'Access Control (IAM)' menu for the 'Add' option.

  18. In the Role pane, search for Azure Cosmos DB and then select the Azure Cosmos DB Control Plane Owner role created earlier in this guide. Then, select Next.

    Screenshot of the 'Role' pane for adding a role assignment.

    Tip

    You can optionally filter the list of roles to only include custom roles.

  19. In the Members pane, select the Select members option. In the members dialog, select the identity you wish to grant this level of access for your Azure Cosmos DB account and then use the Select option to confirm your choice.

    Screenshot of the 'Members' pane for adding a role assignment.

    Screenshot of the identity selection dialog for adding a role assignment.

    Note

    This screenshot illustrates an example user named "Kai Carter" with a principal of kai@adventure-works.com.

  20. Back in the Members pane, review the selected member[s] and then select Review + assign.

    Screenshot of the 'Members' pane with a selected identity for a role assignment.

  21. In the Review + assign pane, review the specified options for the new role assignment. Finally, select Review + assign.

    Screenshot of the 'Review + create' pane for a role assignment.

  22. Wait for the portal to finish creating the role assignment.

  1. Use Get-AzRoleDefinition to list all of the role definitions associated with your Azure Cosmos DB account.

    $parameters = @{
        Name = "Cosmos DB Operator"
    }
    Get-AzRoleDefinition @parameters
    
  2. Review the output and locate the role definition named Cosmos DB Built-in Data Contributor. The output contains the unique identifier of the role definition in the Id property. Record this value as it is required to use in the assignment step later in this guide.

    Name             : Cosmos DB Operator
    Id               : 230815da-be43-4aae-9cb4-875f7bd000aa
    IsCustom         : False
    Description      : Lets you manage Azure Cosmos DB accounts, but not access data in them. Prevents access to account keys and connection strings.
    Actions          : {Microsoft.DocumentDb/databaseAccounts/*, Microsoft.Insights/alertRules/*, Microsoft.Authorization/*/read, Microsoft.ResourceHealth/availabilityStatuses/read…}
    NotActions       : {Microsoft.DocumentDB/databaseAccounts/dataTransferJobs/*, Microsoft.DocumentDB/databaseAccounts/readonlyKeys/*, Microsoft.DocumentDB/databaseAccounts/regenerateKey/*, Microsoft.DocumentDB/databaseAccounts/listKeys/*…}
    DataActions      : {}
    NotDataActions   : {}
    AssignableScopes : {/}
    

    Note

    In this example, the Id value would be 230815da-be43-4aae-9cb4-875f7bd000aa. The identifier is globally unique across all role definitions in Azure.

  3. Use Get-AzResourceGroup to get the metadata for your current resource group.

    $parameters = @{
        Name = "<name-of-existing-resource-group>"
    }
    Get-AzResourceGroup @parameters
    
  4. Observe the output of the previous command. Record the value of the ResourceId property for this resource group as it is required to use in the next step.

    ResourceGroupName : msdocs-identity-example
    Location          : westus
    ProvisioningState : Succeeded
    ResourceId        : /subscriptions/a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1/resourcegroups/msdocs-identity-example
    

    Note

    In this example, the ResourceId value would be /subscriptions/a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1/resourcegroups/msdocs-identity-example. This example uses fictitious data and your identifier would be distinct from this example. This string is a truncated example of the typical output.

  5. First, import the Az.Resources module. Then, Create a new Microsoft.Azure.Commands.Resources.Models.Authorization.PSRoleDefinition object. In the object, create this resource definition specifying the values listed here. For the AssignableScopes list, add the ResourceId property of the resource group recorded in the previous step. Finally, use the role definition object as the input for the -Role parameter of New-AzRoleDefinition.

    Import-Module Az.Resources
    
    $parameters = @{
        TypeName = "Microsoft.Azure.Commands.Resources.Models.Authorization.PSRoleDefinition"
        Property = @{
            Name = "Azure Cosmos DB Control Plane Owner"
            Description = "Can perform all control plane actions for an Azure Cosmos DB account."
            IsCustom = $true
            Actions = @(
                "Microsoft.DocumentDb/*"
            )
            AssignableScopes = @(
                "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example"
            )
        }
    }
    $role = New-Object @parameters
    
    New-AzRoleDefinition -Role $role
    

    Note

    This example uses the /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example value recorded from the previous step. Your actual resource identifier could be different.

  6. Review the output from the definition creation command. The output contains the unique identifier of the role definition in the Name property. Record this value as it is required to use in the assignment step later in this guide.

    Name             : Azure Cosmos DB Control Plane Owner
    Id               : e4e4e4e4-ffff-aaaa-bbbb-c5c5c5c5c5c5
    IsCustom         : True
    Description      : Can perform all control plane actions for an Azure Cosmos DB account.
    Actions          : {Microsoft.DocumentDb/*}
    AssignableScopes : {/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example}
    

    Note

    In this example, the Name value would be Azure Cosmos DB Control Plane Owner. This example is a subset of the typical output of the deployment for clarity.

  7. Assign the new role using New-AzRoleAssignment. Use the role's name for the RoleDefinitionName parameter and the unique identifier for your identity to the ObjectId parameter.

    $parameters = @{
        ResourceGroupName = "<name-of-existing-resource-group>"
        ObjectId = "<your-principal-identifier>"
        RoleDefinitionName = "Azure Cosmos DB Control Plane Owner"
    }
    New-AzRoleAssignment @parameters
    
  8. Observe the output from the command. The output includes a unique identifier for the assignment in the RoleAssignmentId property.

    RoleAssignmentName : ffffffff-5555-6666-7777-aaaaaaaaaaaa
    RoleAssignmentId   : /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example/providers/Microsoft.Authorization/roleAssignments/a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1
    Scope              : /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example
    DisplayName        : Kai Carter
    SignInName         : <kai@adventure-works.com>
    RoleDefinitionName : Azure Cosmos DB Control Plane Owner
    RoleDefinitionId   : e4e4e4e4-ffff-aaaa-bbbb-c5c5c5c5c5c5
    

    Note

    In this example, the RoleAssignmentId property is /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example/providers/Microsoft.Authorization/roleAssignments/a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1, which is another fictitious example. This example is a subset of the typical output of the deployment for clarity.

  9. Repeat these steps to grant access to the account from any other identities you would like to use.

    Tip

    You can repeat these steps for as many identities as you'd like. Typically, these steps are at least repeated to allow developers access to an account using their human identity and to allow applications access to the data using a managed identity.

Important

Assigning a role definition requires you to already have the unique identifier of any identity you want to grant role-based access control permissions.

Validate control plane role-based access in code

Validate that you correctly granted access using application code and the Azure Management SDK.

using Azure.Identity;
using Azure.ResourceManager;

DefaultAzureCredential credential = new();

ArmClient client = new(credential);
const { CosmosDBManagementClient } = require('@azure/arm-cosmosdb');
const { DefaultAzureCredential } = require('@azure/identity');

const subscriptionId = "<subscription-id>";

const credential = new DefaultAzureCredential();

const client = new CosmosDBManagementClient(credential, subscriptionId);
import { CosmosDBManagementClient } from '@azure/arm-cosmosdb';
import { TokenCredential, DefaultAzureCredential } from '@azure/identity';

let subscriptionId: string = "<subscription-id>";

let credential: TokenCredential = new DefaultAzureCredential();

const client: CosmosDBManagementClient = new CosmosDBManagementClient(credential, subscriptionId);
from azure.mgmt.cosmosdb import CosmosDBManagementClient
from azure.identity import DefaultAzureCredential

subscription_id = "<subscription-id>"

credential = DefaultAzureCredential()

client = CosmosDBManagementClient(credential=credential, subscription=subscription_id)
package main

import (
    "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
    "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/cosmos/armcosmos"
)

const subscriptionId = "<subscription-id>"

func main() {
    credential, _ := azidentity.NewDefaultAzureCredential(nil)
    
    client, _ := armcosmos.NewDatabaseClient(subscriptionId, credential, nil)
}
package com.example;

import com.azure.core.management.profile.AzureProfile;
import com.azure.core.management.AzureEnvironment;
import com.azure.identity.DefaultAzureCredential;
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.resourcemanager.cosmos.CosmosManager;

public class CosmosDB {
    public static void main(String[] args) {
        AzureProfile profile = new AzureProfile(AzureEnvironment.AZURE);
        DefaultAzureCredential credential = new DefaultAzureCredentialBuilder()
          .build();

        CosmosManager manager = CosmosManager.authenticate(credential, profile);
    }
}

Grant data plane role-based access

Data plane access refers to the ability to read and write data within an Azure service without the ability to manage resources in the account. For example, Azure Cosmos DB data plane access could include the ability to:

  • Read some account and resource metadata
  • Create, read, update, patch, and delete items
  • Execute NoSQL queries
  • Read from a container's change feed
  • Execute stored procedures
  • Manage conflicts in the conflict feed

First, you must prepare a role definition with a list of dataActions to grant access to read, query, and manage data in Azure Cosmos DB for NoSQL. In this guide, you prepare a built-in and custom role. Then, assign the newly defined role[s] to an identity so that your applications can access data in Azure Cosmos DB for NoSQL.

Important

Obtaining an existing data plane role definition requires these control plane permissions:

  • Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions/read

Creating a new data plane role definition requires these control plane permissions:

  • Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions/read
  • Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions/write

Creating a new data plane role assignment requires these control plane permissions:

  • Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions/read
  • Microsoft.DocumentDB/databaseAccounts/sqlRoleAssignments/read
  • Microsoft.DocumentDB/databaseAccounts/sqlRoleAssignments/write

Warning

Azure Cosmos DB for NoSQL's native role-based access control doesn't support the notDataActions property. Any action that isn't specified as an allowed dataAction is excluded automatically.

  1. List all of the role definitions associated with your Azure Cosmos DB for NoSQL account using az cosmosdb sql role definition list.

    az cosmosdb sql role definition list \
        --resource-group "<name-of-existing-resource-group>" \
        --account-name "<name-of-existing-nosql-account>"
    
  2. Review the output and locate the role definition named Cosmos DB Built-in Data Contributor. The output contains the unique identifier of the role definition in the id property. Record this value as it is required to use in the assignment step later in this guide.

    [
      ...,
      {
        "assignableScopes": [
          "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/msdocs-identity-example/providers/Microsoft.DocumentDB/databaseAccounts/msdocs-identity-example-nosql"
        ],
        "id": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/msdocs-identity-example/providers/Microsoft.DocumentDB/databaseAccounts/msdocs-identity-example-nosql/sqlRoleDefinitions/00000000-0000-0000-0000-000000000002",
        "name": "00000000-0000-0000-0000-000000000002",
        "permissions": [
          {
            "dataActions": [
              "Microsoft.DocumentDB/databaseAccounts/readMetadata",
              "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*",
              "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*"
            ],
            "notDataActions": []
          }
        ],
        "resourceGroup": "msdocs-identity-example",
        "roleName": "Cosmos DB Built-in Data Contributor",
        "type": "Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions",
        "typePropertiesType": "BuiltInRole"
      }
      ...
    ]
    

    Note

    In this example, the id value would be /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/msdocs-identity-example/providers/Microsoft.DocumentDB/databaseAccounts/msdocs-identity-example-nosql/sqlRoleDefinitions/00000000-0000-0000-0000-000000000002. This example uses fictitious data and your identifier would be distinct from this example.

  3. Create a new JSON file named role-definition.json. In this file, create a resource definition specifying the data actions listed here:

    Description
    Microsoft.DocumentDB/databaseAccounts/readMetadata Can read account-level metadata
    Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/* Can perform any container-level data operations
    Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/* Can perform any operation on items with containers
    {
      "RoleName": "Azure Cosmos DB for NoSQL Data Plane Owner",
      "Type": "CustomRole",
      "AssignableScopes": [
        "/"
      ],
      "Permissions": [
        {
          "DataActions": [
            "Microsoft.DocumentDB/databaseAccounts/readMetadata",
            "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*",
            "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*"
          ]
        }
      ]
    }
    
  4. Next, use az cosmosdb sql role definition create to create the role definition. Use the role-definition.json as the input for the --body argument.

    az cosmosdb sql role definition create \
        --resource-group "<name-of-existing-resource-group>" \
        --account-name "<name-of-existing-nosql-account>" \
        --body "@role-definition.json"
    
  5. Now, list all of the role definitions associated with your Azure Cosmos DB for NoSQL account using az cosmosdb sql role definition list.

    az cosmosdb sql role definition list \
        --resource-group "<name-of-existing-resource-group>" \
        --account-name "<name-of-existing-nosql-account>"
    
  6. Review the output from the previous command. Locate the role definition you just created named Azure Cosmos DB for NOSQL Data Plane Owner. The output contains the unique identifier of the role definition in the id property. Record this value as it is required to use in the assignment step later in this guide.

    {
      "assignableScopes": [
        "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example/providers/Microsoft.DocumentDB/databaseAccounts/msdocs-identity-example-nosql"
      ],
      "id": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example/providers/Microsoft.DocumentDB/databaseAccounts/msdocs-identity-example-nosql/sqlRoleDefinitions/bbbbbbbb-1111-2222-3333-cccccccccccc",
      "name": "bbbbbbbb-1111-2222-3333-cccccccccccc",
      "permissions": [
        {
          "dataActions": [
            "Microsoft.DocumentDB/databaseAccounts/readMetadata",
            "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*",
            "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*"
          ],
          "notDataActions": []
        }
      ],
      "resourceGroup": "msdocs-identity-example",
      "roleName": "Azure Cosmos DB for NoSQL Data Plane Owner",
      "type": "Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions",
      "typePropertiesType": "CustomRole"
    }
    

    Note

    In this example, the id value would be /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example/providers/Microsoft.DocumentDB/databaseAccounts/msdocs-identity-example-nosql/sqlRoleDefinitions/bbbbbbbb-1111-2222-3333-cccccccccccc. This example uses fictitious data and your identifier would be distinct from this example.

  7. Use az cosmosdb show to get the unique identifier for your current account.

    az cosmosdb show \
        --resource-group "<name-of-existing-resource-group>" \
        --name "<name-of-existing-nosql-account>" \
        --query "{id:id}"
    
  8. Observe the output of the previous command. Record the value of the id property for this account as it is required to use in the next step.

    {
      "id": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/msdocs-identity-example/providers/Microsoft.DocumentDB/databaseAccounts/msdocs-identity-example-nosql"
    }
    

    Note

    In this example, the id value would be /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/msdocs-identity-example/providers/Microsoft.DocumentDB/databaseAccounts/msdocs-identity-example-nosql. This example uses fictitious data and your identifier would be distinct from this example.

  9. Assign the new role using az cosmosdb sql role assignment create. Use the previously recorded role definition identifiers to the --role-definition-id argument, and the unique identifier for your identity to the --principal-id argument. Finally, use your account's identifier for the --scope argument.

    az cosmosdb sql role assignment create \
        --resource-group "<name-of-existing-resource-group>" \
        --account-name "<name-of-existing-nosql-account>" \
        --role-definition-id "<id-of-new-role-definition>" \
        --principal-id "<id-of-existing-identity>" \
        --scope "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/msdocs-identity-example/providers/Microsoft.DocumentDB/databaseAccounts/msdocs-identity-example-nosql"
    

    Tip

    If you're attempting to grant data plane role-based access control to your own identity, you can use this command to get the identity:

    az ad signed-in-user show
    

    For more information, see az ad signed-in-user.

    Tip

    In Azure Cosmos DB's native implementation of role-based access control, scope refers to the granularity of resources within an account for which you want permission applied. At the highest level, you can scope a data plane role-based access control assignment to the entire account using the largest scope. This scope includes all databases and containers within the account:

    /subscriptions/<subscription-id>/resourcegroups/<resource-group-name>/providers/Microsoft.DocumentDB/databaseAccounts/<account-name>/
    

    Or, you can scope your data plane role assignment to a specific database:

    /subscriptions/<subscription-id>/resourcegroups/<resource-group-name>/providers/Microsoft.DocumentDB/databaseAccounts/<account-name>/dbs/<database-name>
    

    Finally, you can scope the assignment to a single container, the most granular scope:

    /subscriptions/<subscription-id>/resourcegroups/<resource-group-name>/providers/Microsoft.DocumentDB/databaseAccounts/<account-name>/dbs/<database-name>/colls/<container-name>
    

    In many cases, you can use the relative scope instead of the fully qualified scope. For example, you can use this relative scope to grant data plane role-based access control permissions to a specific database and container from an Azure CLI command:

    /dbs/<database-name>/colls/<container-name>
    

    You can also grant universal access to all databases and containers using the relative scope:

    /
    
  10. Use az cosmosdb sql role assignment list to list all role assignments for your Azure Cosmos DB for NoSQL account. Review the output to ensure your role assignment was created.

    az cosmosdb sql role assignment list \
        --resource-group "<name-of-existing-resource-group>" \
        --account-name "<name-of-existing-nosql-account>"
    
  1. List all of the role definitions associated with your Azure Cosmos DB for NoSQL account using az cosmosdb sql role definition list.

    az cosmosdb sql role definition list \
        --resource-group "<name-of-existing-resource-group>" \
        --account-name "<name-of-existing-nosql-account>"
    
  2. Review the output and locate the role definition named Cosmos DB Built-in Data Contributor. The output contains the unique identifier of the role definition in the id property. Record this value as it is required to use in the assignment step later in this guide.

    [
      ...,
      {
        "assignableScopes": [
          "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/msdocs-identity-example/providers/Microsoft.DocumentDB/databaseAccounts/msdocs-identity-example-nosql"
        ],
        "id": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/msdocs-identity-example/providers/Microsoft.DocumentDB/databaseAccounts/msdocs-identity-example-nosql/sqlRoleDefinitions/00000000-0000-0000-0000-000000000002",
        "name": "00000000-0000-0000-0000-000000000002",
        "permissions": [
          {
            "dataActions": [
              "Microsoft.DocumentDB/databaseAccounts/readMetadata",
              "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*",
              "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*"
            ],
            "notDataActions": []
          }
        ],
        "resourceGroup": "msdocs-identity-example",
        "roleName": "Cosmos DB Built-in Data Contributor",
        "type": "Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions",
        "typePropertiesType": "BuiltInRole"
      }
      ...
    ]
    

    Note

    In this example, the id value would be /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/msdocs-identity-example/providers/Microsoft.DocumentDB/databaseAccounts/msdocs-identity-example-nosql/sqlRoleDefinitions/00000000-0000-0000-0000-000000000002. This example uses fictitious data and your identifier would be distinct from this example.

  3. Create a new Bicep file to define your role definition. Name the file data-plane-role-definition.bicep. Add these dataActions to the definition:

    Description
    Microsoft.DocumentDB/databaseAccounts/readMetadata Can read account-level metadata
    Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/* Can perform any container-level data operations
    Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/* Can perform any operation on items with containers
    metadata description = 'Create RBAC definition for data plane access to Azure Cosmos DB for NoSQL.'
    
    @description('Name of the Azure Cosmos DB for NoSQL account.')
    param accountName string
    
    @description('Name of the role definition.')
    param roleDefinitionName string = 'Azure Cosmos DB for NoSQL Data Plane Owner'
    
    resource account 'Microsoft.DocumentDB/databaseAccounts@2024-05-15' existing = {
      name: accountName
    }
    
    resource definition 'Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions@2024-05-15' = {
      name: guid(account.id, roleDefinitionName)
      parent: account
      properties: {
        roleName: roleDefinitionName
        type: 'CustomRole'
        assignableScopes: [
          account.id
        ]
        permissions: [
          {
            dataActions: [
              'Microsoft.DocumentDB/databaseAccounts/readMetadata'
              'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*'
              'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*'
            ]
          }
        ]
      }
    }
    
    output definitionId string = definition.id
    

    Tip

    In Azure Cosmos DB's native implementation of role-based access control, scope refers to the granularity of resources within an account for which you want permission applied. At the highest level, you can scope a data plane role-based access control assignment to the entire account using the largest scope. This scope includes all databases and containers within the account:

    /subscriptions/<subscription-id>/resourcegroups/<resource-group-name>/providers/Microsoft.DocumentDB/databaseAccounts/<account-name>/
    

    Or, you can scope your data plane role assignment to a specific database:

    /subscriptions/<subscription-id>/resourcegroups/<resource-group-name>/providers/Microsoft.DocumentDB/databaseAccounts/<account-name>/dbs/<database-name>
    

    Finally, you can scope the assignment to a single container, the most granular scope:

    /subscriptions/<subscription-id>/resourcegroups/<resource-group-name>/providers/Microsoft.DocumentDB/databaseAccounts/<account-name>/dbs/<database-name>/colls/<container-name>
    

    In many cases, you can use the relative scope instead of the fully qualified scope. For example, you can use this relative scope to grant data plane role-based access control permissions to a specific database and container from an Azure CLI command:

    /dbs/<database-name>/colls/<container-name>
    

    You can also grant universal access to all databases and containers using the relative scope:

    /
    
  4. Create a new Bicep parameters file named data-plane-role-definition.bicepparam. In this parameters file, assign the name of your existing Azure Cosmos DB for NoSQL account to the accountName parameter.

    using './data-plane-role-definition.bicep'
    
    param accountName = '<name-of-existing-nosql-account>'
    
  5. Deploy the Bicep template using az deployment group create.

    az deployment group create \
        --resource-group "<name-of-existing-resource-group>" \
        --parameters data-plane-role-definition.bicepparam \
        --template-file data-plane-role-definition.bicep
    
  6. Create a new Bicep file to define your role assignment. Name the file data-plane-role-assignment.bicep.

    metadata description = 'Assign RBAC role for data plane access to Azure Cosmos DB for NoSQL.'
    
    @description('Name of the Azure Cosmos DB for NoSQL account.')
    param accountName string
    
    @description('Id of the role definition to assign to the targeted principal in the context of the account.')
    param roleDefinitionId string
    
    @description('Id of the identity/principal to assign this role in the context of the account.')
    param identityId string = deployer().objectId
    
    resource account 'Microsoft.DocumentDB/databaseAccounts@2024-05-15' existing = {
      name: accountName
    }
    
    resource assignment 'Microsoft.DocumentDB/databaseAccounts/sqlRoleAssignments@2024-05-15' = {
      name: guid(roleDefinitionId, identityId, account.id)
      parent: account
      properties: {
        principalId: identityId
        roleDefinitionId: roleDefinitionId
        scope: account.id
      }
    }
    
    output assignmentId string = assignment.id
    
  7. Create a new Bicep parameters file named data-plane-role-assignment.bicepparam. In this parameters file, assign the name of your existing Azure Cosmos DB for NoSQL account to the accountName parameter, the previously recorded role definition identifiers to the roleDefinitionId parameter, and the unique identifier for your identity to the identityId parameter.

    using './data-plane-role-assignment.bicep'
    
    param accountName = '<name-of-existing-nosql-account>'
    param roleDefinitionId = '<id-of-new-role-definition>'
    param identityId = '<id-of-existing-identity>'
    

    Tip

    If you're attempting to grant data plane role-based access control to your own identity, you can omit the identityId parameter. The Bicep template then uses deployer().objectId to get the identity of the principal that deployed the template. For more information, see deployer.

  8. Deploy the Bicep template using az deployment group create.

    az deployment group create \
        --resource-group "<name-of-existing-resource-group>" \
        --parameters data-plane-role-assignment.bicepparam \
        --template-file data-plane-role-assignment.bicep
    
  9. Repeat these steps to grant access to the account from any other identities you would like to use.

    Tip

    You can repeat these steps for as many identities as you'd like. Typically, these steps are at least repeated to allow developers access to an account using their human identity. You can also repeat these steps to allow applications to access resources using a managed identity.

  1. Use Get-AzCosmosDBSqlRoleDefinition to list all of the role definitions associated with your Azure Cosmos DB for NoSQL account.

    $parameters = @{
        ResourceGroupName = "<name-of-existing-resource-group>"
        AccountName = "<name-of-existing-nosql-account>"
    }
    Get-AzCosmosDBSqlRoleDefinition @parameters
    
  2. Review the output and locate the role definition named Cosmos DB Built-in Data Contributor. The output contains the unique identifier of the role definition in the Id property. Record this value as it is required to use in the assignment step later in this guide.

    Id                         : /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/msdocs-identity-example/providers/Microsoft.DocumentDB/databaseAccounts/msdocs-identity-example-nosql/sqlRoleDefinitions/00000000-0000-0000-0000-000000000002
    RoleName                   : Cosmos DB Built-in Data Contributor
    Type                       : BuiltInRole
    AssignableScopes           : {/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/msdocs-identity-example/providers/Microsoft.DocumentDB/databaseAccountsmsdocs-identity-example-nosql}
    Permissions.DataActions    : {Microsoft.DocumentDB/databaseAccounts/readMetadata, Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*, Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*}
    Permissions.NotDataActions : 
    

    Note

    In this example, the Id value would be /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/msdocs-identity-example/providers/Microsoft.DocumentDB/databaseAccounts/msdocs-identity-example-nosql/sqlRoleDefinitions/00000000-0000-0000-0000-000000000002. This example uses fictitious data and your identifier would be distinct from this example. However, the identifier (00000000-0000-0000-0000-000000000002) is unique across all role definitions in your account.

  3. Create a new role definition using New-AzCosmosDBSqlRoleDefinition. For the DataAction parameter, specify the data actions listed here:

    Description
    Microsoft.DocumentDB/databaseAccounts/readMetadata Can read account-level metadata
    Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/* Can perform any container-level data operations
    Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/* Can perform any operation on items with containers
    $parameters = @{
        ResourceGroupName = "<name-of-existing-resource-group>"
        AccountName = "<name-of-existing-nosql-account>"
        RoleName = "Azure Cosmos DB for NoSQL Data Plane Owner"
        Type = "CustomRole"
        AssignableScope = @(
            "/"
        )
        DataAction = @(
            "Microsoft.DocumentDB/databaseAccounts/readMetadata",
            "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*",
            "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*"
        )
    }
    New-AzCosmosDBSqlRoleDefinition @parameters
    

    Tip

    In Azure Cosmos DB's native implementation of role-based access control, scope refers to the granularity of resources within an account for which you want permission applied. At the highest level, you can scope a data plane role-based access control assignment to the entire account using the largest scope. This scope includes all databases and containers within the account:

    /subscriptions/<subscription-id>/resourcegroups/<resource-group-name>/providers/Microsoft.DocumentDB/databaseAccounts/<account-name>/
    

    Or, you can scope your data plane role assignment to a specific database:

    /subscriptions/<subscription-id>/resourcegroups/<resource-group-name>/providers/Microsoft.DocumentDB/databaseAccounts/<account-name>/dbs/<database-name>
    

    Finally, you can scope the assignment to a single container, the most granular scope:

    /subscriptions/<subscription-id>/resourcegroups/<resource-group-name>/providers/Microsoft.DocumentDB/databaseAccounts/<account-name>/dbs/<database-name>/colls/<container-name>
    

    In many cases, you can use the relative scope instead of the fully qualified scope. For example, you can use this relative scope to grant data plane role-based access control permissions to a specific database and container from an Azure CLI command:

    /dbs/<database-name>/colls/<container-name>
    

    You can also grant universal access to all databases and containers using the relative scope:

    /
    
  4. Use Get-AzCosmosDBSqlRoleDefinition to list all of the role definitions associated with your Azure Cosmos DB for NoSQL account.

    $parameters = @{
        ResourceGroupName = "<name-of-existing-resource-group>"
        AccountName = "<name-of-existing-nosql-account>"
    }
    Get-AzCosmosDBSqlRoleDefinition @parameters    
    
  5. Review the output from the previous command. Locate the role definition you just created named Azure Cosmos DB for NOSQL Data Plane Owner. The output contains the unique identifier of the role definition in the Id property. Record this value as it is required to use in the assignment step later in this guide.

    Id                         : /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example/providers/Microsoft.DocumentDB/databaseAccounts/msdocs-identity-example-nosql/sqlRoleDefinitions/bbbbbbbb-1111-2222-3333-cccccccccccc
    RoleName                   : Azure Cosmos DB for NoSQL Data Plane Owner
    Type                       : CustomRole
    AssignableScopes           : {/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example/providers/Microsoft.DocumentDB/databaseAccounts/msdocs-identity-example-nosql}
    Permissions.DataActions    : {Microsoft.DocumentDB/databaseAccounts/readMetadata, Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*, Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*}
    Permissions.NotDataActions :
    

    Note

    In this example, the Id value would be /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example/providers/Microsoft.DocumentDB/databaseAccounts/msdocs-identity-example-nosql/sqlRoleDefinitions/bbbbbbbb-1111-2222-3333-cccccccccccc. This example uses fictitious data and your identifier would be distinct from this example.

  6. Use Get-AzCosmosDBAccount to get the metadata for your current account.

    $parameters = @{
        ResourceGroupName = "<name-of-existing-resource-group>"
        Name = "<name-of-existing-nosql-account>"
    }    
    Get-AzCosmosDBAccount @parameters | Select -Property Id
    
  7. Observe the output of the previous command. Record the value of the Id property for this account as it is required to use in the next step.

    Id
    --    
    /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/msdocs-identity-example/providers/Microsoft.DocumentDB/databaseAccounts/msdocs-identity-example-nosql
    

    Note

    In this example, the Id value would be /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/msdocs-identity-example/providers/Microsoft.DocumentDB/databaseAccounts/msdocs-identity-example-nosql. This example uses fictitious data and your identifier would be distinct from this example.

  8. Use New-AzCosmosDBSqlRoleAssignment to assign the new role. Use the previously recorded role definition identifiers to the RoleDefinitionId parameter, and the unique identifier for your identity to the PrincipalId parameter. Finally, use your account's identifier for the Scope parameter.

    $parameters = @{
        ResourceGroupName = "<name-of-existing-resource-group>"
        AccountName = "<name-of-existing-nosql-account>"
        RoleDefinitionId = "<id-of-new-role-definition>"
        PrincipalId = "<id-of-existing-identity>"
        Scope = "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/msdocs-identity-example/providers/Microsoft.DocumentDB/databaseAccounts/msdocs-identity-example-nosql"
    }    
    New-AzCosmosDBSqlRoleAssignment @parameters
    

    Tip

    If you're attempting to grant data plane role-based access control to your own identity, you can use this command to get the identity:

    Get-AzADUser -SignedIn | Format-List `
        -Property Id, DisplayName, Mail, UserPrincipalName
    

    For more information, see Get-AzADUser.

  9. List all role assignments for your Azure Cosmos DB for NoSQL account using Get-AzCosmosDBSqlRoleAssignment. Review the output to ensure your role assignment was created.

    $parameters = @{
        ResourceGroupName = "<name-of-existing-resource-group>"
        AccountName = "<name-of-existing-nosql-account>"
    }
    Get-AzCosmosDBSqlRoleAssignment @parameters
    

Warning

Managing data plane role-based access control isn't supported in the Azure portal.

Validate data plane role-based access in code

Validate that you correctly granted access using application code and the Azure SDK.

using Azure.Core;
using Azure.Identity;
using Microsoft.Azure.Cosmos;

string endpoint = "<account-endpoint>";

TokenCredential credential = new DefaultAzureCredential();

CosmosClient client = new(endpoint, credential);

Container container = client.GetContainer("<database-name>", "<container-name>");

await container.ReadItemAsync<dynamic>("<item-id>", new PartitionKey("<partition-key>"));
const { CosmosClient } = require('@azure/cosmos');
const { DefaultAzureCredential } = require('@azure/identity');

const endpoint = '<account-endpoint>';

const credential = new DefaultAzureCredential();

const client = new CosmosClient({ endpoint, aadCredentials:credential});

const container = client.database('<database-name>').container('<container-name>');

await container.item('<item-id>', '<partition-key>').read<String>();
import { Container, CosmosClient, CosmosClientOptions } from '@azure/cosmos'
import { TokenCredential, DefaultAzureCredential } from '@azure/identity'

let endpoint: string = '<account-endpoint>';

let credential: TokenCredential = new DefaultAzureCredential();

let options: CosmosClientOptions = {
  endpoint: endpoint,
  aadCredentials: credential
};

const client: CosmosClient = new CosmosClient(options);

const container: Container = client.database('<database-name>').container('<container-name>');

await container.item('<item-id>', '<partition-key>').read<String>();
from azure.cosmos import CosmosClient
from azure.identity import DefaultAzureCredential

endpoint = "<account-endpoint>"

credential = DefaultAzureCredential()

client = CosmosClient(endpoint, credential=credential)

container = client.get_database_client("<database-name>").get_container_client("<container-name>")

container.read_item(
    item="<item-id>",
    partition_key="<partition-key>",
)
import (
    "context"
    
    "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
    "github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos"
)

const endpoint = "<account-endpoint>"

func main() {
    credential, _ := azidentity.NewDefaultAzureCredential(nil)
    client, _ := azcosmos.NewClient(endpoint, credential, nil)
    
    database, _ := client.NewDatabase("<database-name>")
    container, _ := database.NewContainer("<container-name>")
    
    _, err := container.ReadItem(context.TODO(), azcosmos.NewPartitionKeyString("<partition-key>"), "<item-id>", nil)
    if err != nil {
        panic(err)
    }
}
import com.azure.cosmos.CosmosClient;
import com.azure.cosmos.CosmosClientBuilder;
import com.azure.cosmos.CosmosContainer;
import com.azure.cosmos.models.PartitionKey;
import com.azure.identity.DefaultAzureCredential;
import com.azure.identity.DefaultAzureCredentialBuilder;

public class NoSQL {
    public static void main(String[] args) {   
        DefaultAzureCredential credential = new DefaultAzureCredentialBuilder()
            .build();
            
        CosmosClient client = new CosmosClientBuilder()
            .endpoint("<account-endpoint>")
            .credential(credential)
            .buildClient();

        CosmosContainer container = client.getDatabase("<database-name>").getContainer("<container-name>");

        container.readItem("<item-id>", new PartitionKey("<partition-key>"), Object.class);
    }
}
use azure_data_cosmos::CosmosClient;
use azure_identity::DefaultAzureCredential;

fn main() {
    let credential = DefaultAzureCredential::new().unwrap();
    let client = CosmosClient::new("<account-endpoint>", credential, None).unwrap();

    let container = client.database_client("<database-name>").container_client("<container-name>");

    let response = container.read_item("<partition-key>", "<item-id>", None);
    tokio::runtime::Runtime::new().unwrap().block_on(response).unwrap();
}