Use control plane role-based access control with Azure Cosmos DB for NoSQL

APPLIES TO: NoSQL

Diagram of the current location ('Role-based access control') in the sequence of the deployment guide.

Diagram of the sequence of the deployment guide including these locations, in order: Overview, Concepts, Prepare, Role-based access control, Network, and Reference. The 'Role-based access control' location is currently highlighted.

This article walks through the steps to grant an identity access to manage an Azure Cosmos DB for NoSQL account and its resources.

Important

The steps in this article only cover control plane access to perform operations on the account itself of any resources in the account's hierarchy. To learn how to manage items and execute queries for the data plane, see grant data plane role-based access.

Prerequisites

  • An Azure account with an active subscription. Create an account for free.
  • An existing Azure Cosmos DB account.
  • One or more existing identities in Microsoft Entra ID.

Prepare role definition

First, you must prepare a role definition with a list of actions to grant access to manage account resources in Azure Cosmos DB.

List all of the role definitions associated with your Azure Cosmos DB account using az role definition list. 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.

az role definition list \
    --name "Cosmos DB Operator"
[
  {
    "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.

  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 may 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.

Use Get-AzRoleDefinition to list all of the role definitions associated with your Azure Cosmos DB account. 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.

$parameters = @{
    Name = "Cosmos DB Operator"
}
Get-AzRoleDefinition @parameters
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.

Assign role to identity

Now, assign the newly defined role to an identity so that your applications can access resources in Azure Cosmos DB.

Important

This assignment task requires you to already have the unique identifier of any identity you want to grant role-based access control permissions.

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

    az group show \
        --name "<name-of-existing-resource-group>"
    
  2. 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 is a truncated example of the output.

  3. 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/ffffffff-eeee-dddd-cccc-bbbbbbbbbbb0" \
        --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/ffffffff-eeee-dddd-cccc-bbbbbbbbbbb0. Again, your role identifier would be distinct.

  4. 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/ffffffff-eeee-dddd-cccc-bbbbbbbbbbb0",
      "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/ffffffff-eeee-dddd-cccc-bbbbbbbbbbb0",
      "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/ffffffff-eeee-dddd-cccc-bbbbbbbbbbb0 which is another fictitious example.

  5. 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 using a managed identity.

  1. 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
      }
    }
    
  2. 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>'
    
  3. 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
    
  4. 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 using a managed identity.

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

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

  1. 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
    
  2. 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/ffffffff-eeee-dddd-cccc-bbbbbbbbbbb0
    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/ffffffff-eeee-dddd-cccc-bbbbbbbbbbb0 which is another fictitious example. This is a subset of the typical output of the deployment for clarity.

  3. 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 using a managed identity.

Validate control plane access in code

Finally, validate that you correctly granted access using application code and the Azure Management SDK in your preferred programming language.

using Azure.Identity;
using Azure.ResourceManager;

DefaultAzureCredential credential = new();

ArmClient client = new(credential);

Important

This code sample uses the Azure.ResourceManager.CosmosDB and Azure.Identity libraries from NuGet.

Next step