Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
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.
An existing Azure Cosmos DB for Table account.
One or more existing identities in Microsoft Entra ID.
You can use the local Azure CLI.
If you prefer, install the Azure CLI to run CLI reference commands.
Local Azure CLI, see how to install the Azure CLI. If you're running on Windows or macOS, consider running Azure CLI in a Docker container. For more information, see How to run the Azure CLI in a Docker container.
Sign in to the Azure CLI by using the az login command. To finish the authentication process, follow the steps displayed in your terminal. For other sign-in options, see Sign in with the Azure CLI.
When you're prompted, install the Azure CLI extension on first use. For more information about extensions, see Use extensions with the Azure CLI.
Run az version to find the version and dependent libraries that are installed. To upgrade to the latest version, run az upgrade.
- If you choose to use Azure PowerShell locally:
- Install the latest version of the Az PowerShell module.
- Connect to your Azure account using the Connect-AzAccount -Environment AzureChinaCloud cmdlet.
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.
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 } }
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.
When setting up a new Azure Cosmos DB for NoSQL account, navigate to the Security section of the account creation process.
Then, select Disable for the Key-based authentication option.
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 Table using a resource-owner password credential (ROPC). This attempt should fail. If necessary, code samples for common programming languages are provided here.
using Azure.Data.Tables;
using Azure.Core;
string connectionString = "AccountEndpoint=<table-endpoint>;AccountKey=<key>;";
TableServiceClient client = new(connectionString);
const { TableServiceClient } = require('@azure/data-tables');
const connectionString = 'AccountEndpoint=<table-endpoint>;AccountKey=<key>;';
const client = new TableServiceClient(connectionString);
import { TableServiceClient } from '@azure/data-tables';
let connectionString: string = 'AccountEndpoint=<table-endpoint>;AccountKey=<key>;';
const client: TableServiceClient = new TableServiceClient(connectionString);
from azure.data.tables import TableServiceClient
connection_string = "AccountEndpoint=<table-endpoint>;AccountKey=<key>;"
client = TableServiceClient(endpoint, connection_string)
package main
import (
"github.com/Azure/azure-sdk-for-go/sdk/data/aztables"
)
const connectionString = "AccountEndpoint=<table-endpoint>;AccountKey=<key>;"
func main() {
client, _ := aztables.NewServiceClientFromConnectionString(connectionString, nil)
}
import com.azure.data.tables.TableServiceClient;
import com.azure.data.tables.TableServiceClientBuilder;
public class Table{
public static void main(String[] args){
TableServiceClient tableServiceClient = new TableServiceClientBuilder()
.connectionString("AccountEndpoint=<table-endpoint>;AccountKey=<key>;")
.buildClient();
}
}
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.
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"
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.Use
az group show
to get the metadata for your current resource group.az group show \ --name "<name-of-existing-resource-group>"
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": "chinanorth3", "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.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 theid
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.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
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.Use
az group show
to get the metadata for your current resource group again.az group show \ --name "<name-of-existing-resource-group>"
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.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. Therole
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.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.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.
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"
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.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
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
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.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 } }
Create a new Bicep parameters file named control-plane-role-assignment.
bicepparam
. In this parameters file; assign the previously recorded role definition identifiers to theroleDefinitionId
parameter, and the unique identifier for your identity to theidentityId
parameter.using './control-plane-role-assignment.bicep' param roleDefinitionId = '<id-of-new-role-definition>' param identityId = '<id-of-existing-identity>'
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
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.
Sign in to the Azure portal (https://portal.azure.cn).
Enter Resource group in the global search bar.
Within Services, select Resource groups.
In the Resource groups pane, select your existing resource group.
Note
This example screenshot includes the
msdocs-identity-example
resource group. Your actual resource group name could be different.Within the pane for the resource group, select Access control (IAM) in the service menu.
In the Access control (IAM) pane, select Roles.
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.
In the Cosmos DB Operator role definition dialog, observe the actions assigned as part of this role definition.
Close the Cosmos DB Operator role definition dialog.
Back in the Access control (IAM) pane, select Add. Then select Add custom role.
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 In the Permissions pane, select Add permissions. Then, search for
DocumentDB
in the permissions dialog. Finally, select the Microsoft.DocumentDB option.In the permissions dialog, select all Actions for
Microsoft.DocumentDB
. Then, select Add to return to the *Permissions pane.Back in the Permissions pane, observe the list of permissions. Then, select Review + create.
In the Review + create pane, review the specified options for the new role definition. Finally, select Create.
Wait for the portal to finish creating the role definition.
In the Access control (IAM) pane, select Add and then Add role assignment.
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.Tip
You can optionally filter the list of roles to only include custom roles.
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.
Note
This screenshot illustrates an example user named "Kai Carter" with a principal of
kai@adventure-works.com
.Back in the Members pane, review the selected member[s] and then select Review + assign.
In the Review + assign pane, review the specified options for the new role assignment. Finally, select Review + assign.
Wait for the portal to finish creating the role assignment.
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
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 be230815da-be43-4aae-9cb4-875f7bd000aa
. The identifier is globally unique across all role definitions in Azure.Use
Get-AzResourceGroup
to get the metadata for your current resource group.$parameters = @{ Name = "<name-of-existing-resource-group>" } Get-AzResourceGroup @parameters
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.First, import the
Az.Resources
module. Then, Create a newMicrosoft.Azure.Commands.Resources.Models.Authorization.PSRoleDefinition
object. In the object, create this resource definition specifying the values listed here. For theAssignableScopes
list, add theResourceId
property of the resource group recorded in the previous step. Finally, use the role definition object as the input for the-Role
parameter ofNew-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.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 beAzure Cosmos DB Control Plane Owner
. This example is a subset of the typical output of the deployment for clarity.Assign the new role using
New-AzRoleAssignment
. Use the role's name for theRoleDefinitionName
parameter and the unique identifier for your identity to theObjectId
parameter.$parameters = @{ ResourceGroupName = "<name-of-existing-resource-group>" ObjectId = "<your-principal-identifier>" RoleDefinitionName = "Azure Cosmos DB Control Plane Owner" } New-AzRoleAssignment @parameters
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.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 Table 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 Table. 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 Table.
First, get the resource identifier of the existing Azure Cosmos DB for Table account using
az cosmsodb show
and store it in a variable.resourceId=$( \ az cosmosdb show \ --resource-group "<name-of-existing-resource-group>" \ --name "<name-of-existing-table-account>" \ --query "id" \ --output tsv \ ) az rest \ --method "GET" \ --url $resourceId/tableRoleDefinitions?api-version=2023-04-15
Then, list all of the role definitions associated with your Azure Cosmos DB for Table account using
az rest
. Finally, 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 theid
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-table/tableRoleDefinitions/00000000-0000-0000-0000-000000000002", "name": "00000000-0000-0000-0000-000000000002", "properties": { "assignableScopes": [ "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/msdocs-identity-example/providers/Microsoft.DocumentDB/databaseAccounts/msdocs-identity-example-table" ], "permissions": [ { "dataActions": [ "Microsoft.DocumentDB/databaseAccounts/readMetadata", "Microsoft.DocumentDB/databaseAccounts/tables/*", "Microsoft.DocumentDB/databaseAccounts/tables/containers/entities/*" ], "notDataActions": [] } ], "roleName": "Cosmos DB Built-in Data Contributor", "type": "BuiltInRole" }, "type": "Microsoft.DocumentDB/databaseAccounts/tableRoleDefinitions" } ... ]
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-table/tableRoleDefinitions/00000000-0000-0000-0000-000000000002
. This example uses fictitious data and your identifier would be distinct from this example. This example output is truncated.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 { "properties": { "roleName": "Azure Cosmos DB for Table Data Plane Owner", "type": "CustomRole", "assignableScopes": [ "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/sidandrews-rbac/providers/Microsoft.DocumentDB/databaseAccounts/sidandrews-rbac-table/" ], "permissions": [ { "dataActions": [ "Microsoft.DocumentDB/databaseAccounts/readMetadata", "Microsoft.DocumentDB/databaseAccounts/tables/*", "Microsoft.DocumentDB/databaseAccounts/tables/containers/entities/*" ] } ] } }
Now create or update a role definition using
az cosmosdb show
andaz rest
together to issue an HTTPPUT
request. As part of this request, specify a unique GUID for your role definition.resourceId=$( \ az cosmosdb show \ --resource-group "<name-of-existing-resource-group>" \ --name "<name-of-existing-table-account>" \ --query "id" \ --output tsv \ ) az rest \ --method "PUT" \ --url $resourceId/tableRoleDefinitions/d3d3d3d3-eeee-ffff-aaaa-b4b4b4b4b4b4?api-version=2023-04-15 \ --body @role-definition.json
Note
In this example, the unique GUID specified was
d3d3d3d3-eeee-ffff-aaaa-b4b4b4b4b4b4
. You can specify any unique GUID for your own role definition.The output should now indicate that the request is queued. Now, wait for the enqueued role definition deployment to finish. This task can take a few minutes.
{ "status": "Enqueued" }
Finally, check the list of role definitions using
az rest
again.resourceId=$( \ az cosmosdb show \ --resource-group "<name-of-existing-resource-group>" \ --name "<name-of-existing-table-account>" \ --query "id" \ --output tsv \ ) az rest \ --method "GET" \ --url $resourceId/tableRoleDefinitions?api-version=2023-04-15
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-resource-group>" \ --query "{id:id}"
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-table" }
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-table
. This example uses fictitious data and your identifier would be distinct from this example.Create a new JSON file named role-assignment.json. In the JSON file, add the unique identifier for your identity and unique identifier for the account resource.
{ "properties": { "roleDefinitionId": "<account-resource-id>/tableRoleDefinitions/d3d3d3d3-eeee-ffff-aaaa-b4b4b4b4b4b4", "scope": "<account-resource-id>", "principalId": "<id-of-existing-identity>" } }
Note
In this example, the unique GUID specified was
d3d3d3d3-eeee-ffff-aaaa-b4b4b4b4b4b4
. You can use the unique GUID you used previously for your own role definition.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:
/
Now create or update a role assignment using
az cosmosdb show
andaz rest
together to issue an HTTPPUT
request. As part of this request, specify a unique GUID for your role assignment.resourceId=$( \ az cosmosdb show \ --resource-group "<name-of-existing-resource-group>" \ --name "<name-of-existing-table-account>" \ --query "id" \ --output tsv \ ) az rest \ --method "PUT" \ --url $resourceId/tableRoleAssignments/e4e4e4e4-ffff-aaaa-bbbb-c5c5c5c5c5c5?api-version=2023-04-15 \ --body @role-assignment.json
Note
In this example, the unique GUID specified was
e4e4e4e4-ffff-aaaa-bbbb-c5c5c5c5c5c5
. You can specify any unique GUID for your own role assignment.
First, get the resource identifier of the existing Azure Cosmos DB for Table account using
az cosmsodb show
and store it in a variable.resourceId=$( \ az cosmosdb show \ --resource-group "<name-of-existing-resource-group>" \ --name "<name-of-existing-table-account>" \ --query "id" \ --output tsv \ ) az rest \ --method "GET" \ --url $resourceId/tableRoleDefinitions?api-version=2023-04-15
Then, list all of the role definitions associated with your Azure Cosmos DB for Table account using
az rest
. Finally, 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 theid
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-table/tableRoleDefinitions/00000000-0000-0000-0000-000000000002", "name": "00000000-0000-0000-0000-000000000002", "properties": { "assignableScopes": [ "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/msdocs-identity-example/providers/Microsoft.DocumentDB/databaseAccounts/msdocs-identity-example-table" ], "permissions": [ { "dataActions": [ "Microsoft.DocumentDB/databaseAccounts/readMetadata", "Microsoft.DocumentDB/databaseAccounts/tables/*", "Microsoft.DocumentDB/databaseAccounts/tables/containers/entities/*" ], "notDataActions": [] } ], "roleName": "Cosmos DB Built-in Data Contributor", "type": "BuiltInRole" }, "type": "Microsoft.DocumentDB/databaseAccounts/tableRoleDefinitions" } ... ]
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-table/tableRoleDefinitions/00000000-0000-0000-0000-000000000002
. This example uses fictitious data and your identifier would be distinct from this example. This example output is truncated.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
Microsoft.DocumentDB/databaseAccounts/tables/*
Microsoft.DocumentDB/databaseAccounts/tables/containers/entities/*
metadata description = 'Create RBAC definition for data plane access to Azure Cosmos DB for Table.' @description('Name of the Azure Cosmos DB for Table account.') param accountName string @description('Name of the role definition.') param roleDefinitionName string = 'API for Table Data Plane Owner' resource account 'Microsoft.DocumentDB/databaseAccounts@2023-04-15' existing = { name: accountName } resource definition 'Microsoft.DocumentDB/databaseAccounts/tableRoleDefinitions@2023-04-15' = { name: guid('table-role-definition', account.id) parent: account properties: { roleName: roleDefinitionName type: 'CustomRole' assignableScopes: [ account.id ] permissions: [ { dataActions: [ 'Microsoft.DocumentDB/databaseAccounts/readMetadata' 'Microsoft.DocumentDB/databaseAccounts/tables/*' 'Microsoft.DocumentDB/databaseAccounts/tables/containers/entities/*' ] } ] } } 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:
/
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 Table account to theaccountName
parameter.using './data-plane-role-definition.bicep' param accountName = '<name-of-existing-table-account>'
Deploy the Bicep template using
az deployment group create
. Specify the name of the Bicep template, parameters file, and Azure resource group.az deployment group create \ --resource-group "<name-of-existing-resource-group>" \ --parameters data-plane-role-definition.bicepparam \ --template-file data-plane-role-definition.bicep
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.DocumentDB/databaseAccounts/msdocs-identity-example-table-account/tableRoleDefinitions/dddddddd-9999-0000-1111-eeeeeeeeeeee" } } } }
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-table-account/tableRoleDefinitions/dddddddd-9999-0000-1111-eeeeeeeeeeee
. 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.Create another Bicep file to assign a role to an identity. Name this file data-plane-role-assignment.bicep.
metadata description = 'Assign RBAC role for data plane access to Azure Cosmos DB for Table.' @description('Name of the Azure Cosmos DB for Table 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 resource account 'Microsoft.DocumentDB/databaseAccounts@2023-04-15' existing = { name: accountName } resource assignment 'Microsoft.DocumentDB/databaseAccounts/tableRoleAssignments@2023-04-15' = { name: guid(roleDefinitionId, identityId, account.id) parent: account properties: { principalId: identityId roleDefinitionId: roleDefinitionId scope: account.id } } output id string = assignment.id
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 Table account to theaccountName
parameter, the previously recorded role definition identifiers to theroleDefinitionId
parameter, and the unique identifier for your identity to theidentityId
parameter.using './data-plane-role-assignment.bicep' param accountName = '<name-of-existing-table-account>' param roleDefinitionId = '<id-of-new-role-definition>' param identityId = '<id-of-existing-identity>'
Deploy this 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
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 data using a managed identity.
Use
Get-AzCosmosDBAccount
to get the resource identifier of the existing Azure Cosmos DB for Table account and store it in a variable.$parameters = @{ ResourceGroupName = "<name-of-existing-resource-group>" Name = "<name-of-existing-table-account>" } $resourceId = ( Get-AzCosmosDBAccount @parameters | Select-Object -Property Id -First 1 ).Id $parameters = @{ Path = "$resourceId/tableRoleDefinitions?api-version=2023-04-15" Method = "GET" } Invoke-AzRestMethod @parameters
Then, use
Invoke-AzRestMethod
to list all of the role definitions associated with your Azure Cosmos DB for Table 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 theId
property. Record this value as it is required to use in the assignment step later in this guide.StatusCode : 200 Content : { "value": [ ..., { "id": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/msdocs-identity-example/providers/Microsoft.DocumentDB/databaseAccounts/msdocs-identity-example-table/tableRoleDefinitions/00000000-0000-0000-0000-000000000002", "name": "00000000-0000-0000-0000-000000000002", "properties": { "assignableScopes": [ "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/msdocs-identity-example/providers/Microsoft.DocumentDB/databaseAccounts/msdocs-identity-example-table" ], "permissions": [ { "dataActions": [ "Microsoft.DocumentDB/databaseAccounts/readMetadata", "Microsoft.DocumentDB/databaseAccounts/tables/*", "Microsoft.DocumentDB/databaseAccounts/tables/containers/entities/*" ], "notDataActions": [] } ], "roleName": "Cosmos DB Built-in Data Contributor", "type": "BuiltInRole" }, "type": "Microsoft.DocumentDB/databaseAccounts/tableRoleDefinitions" } ... ] }, ... ] }
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-table/tableRoleDefinitions/00000000-0000-0000-0000-000000000002
. This example uses fictitious data and your identifier would be distinct from this example. This example output is truncated.Create or update your role definition using
Get-AzCosmosDBAccount
andInvoke-AzRestMethod
together to issue an HTTPPUT
request. Also, as part of this request, specify a unique GUID for your role definition. Finally, create a resource definition payload 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 $parameters = @{ ResourceGroupName = "<name-of-existing-resource-group>" Name = "<name-of-existing-table-account>" } $resourceId = ( Get-AzCosmosDBAccount @parameters | Select-Object -Property Id -First 1 ).Id $payload = @{ properties = @{ roleName = "Azure Cosmos DB for Table Data Plane Owner" type = "CustomRole" assignableScopes = @( "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/sidandrews-rbac/providers/Microsoft.DocumentDB/databaseAccounts/sidandrews-rbac-table/" ) permissions = @( @{ dataActions = @( "Microsoft.DocumentDB/databaseAccounts/readMetadata", "Microsoft.DocumentDB/databaseAccounts/tables/*", "Microsoft.DocumentDB/databaseAccounts/tables/containers/entities/*" ) } ) } } $parameters = @{ Path = "$resourceId/tableRoleDefinitions/d3d3d3d3-eeee-ffff-aaaa-b4b4b4b4b4b4?api-version=2023-04-15" Method = "PUT" Payload = $payload | ConvertTo-Json -Depth 4 } Invoke-AzRestMethod @parameters
Note
In this example, the unique GUID specified was
d3d3d3d3-eeee-ffff-aaaa-b4b4b4b4b4b4
. You can specify any unique GUID for your own role definition.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:
/
The output should return with a status code of 200. Now, wait for the enqueued role definition deployment to finish. This task can take a few minutes.
StatusCode : 200 ...
Finally, check the list of role definitions using
Invoke-AzRestMethod
again.$parameters = @{ ResourceGroupName = "<name-of-existing-resource-group>" Name = "<name-of-existing-table-account>" } $resourceId = ( Get-AzCosmosDBAccount @parameters | Select-Object -Property Id -First 1 ).Id $parameters = @{ Path = "$resourceId/tableRoleDefinitions?api-version=2023-04-15" Method = "GET" } Invoke-AzRestMethod @parameters
Use `Get-AzCosmosDBAccount to get the unique identifier for your current account.
$parameters = @{ ResourceGroupName = "<name-of-existing-resource-group>" Name = "<name-of-existing-table-account>" } Get-AzCosmosDBAccount @parameters | Select -Property Id
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-table
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-table
. This example uses fictitious data and your identifier would be distinct from this example.Now create or update a role assignment using
Get-AzCosmosDBAccount
andInvoke-AzRestMethod
together to issue an HTTPPUT
request. As part of this request, specify a unique GUID for your role assignment. Finally, create a resource assignment payload specifying the unique identifier for your identity.$parameters = @{ ResourceGroupName = "<name-of-existing-resource-group>" Name = "<name-of-existing-table-account>" } $resourceId = ( Get-AzCosmosDBAccount @parameters | Select-Object -Property Id -First 1 ).Id $payload = @{ properties = @{ roleDefinitionId = "$resourceId/tableRoleDefinitions/00000000-0000-0000-0000-000000000002" scope = "$resourceId" principalId = "<id-of-existing-identity>" } } $parameters = @{ Path = "$resourceId/tableRoleAssignments/e4e4e4e4-ffff-aaaa-bbbb-c5c5c5c5c5c5?api-version=2023-04-15" Method = "PUT" Payload = $payload | ConvertTo-Json -Depth 2 } Invoke-AzRestMethod @parameters
Note
In this example, the unique GUID specified was
e4e4e4e4-ffff-aaaa-bbbb-c5c5c5c5c5c5
. You can specify any unique GUID for your own role assignment.
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.Identity;
using Azure.Data.Tables;
string endpoint = "<account-endpoint>";
DefaultAzureCredential credential = new();
TableServiceClient client = new(
endpoint: new Uri(endpoint),
tokenCredential: credential
);
TableClient table = client.GetTableClient(
tableName: "<name-of-table>"
);
await table.GetEntityAsync<TableEntity>(
partitionKey: "<partition-key>",
rowKey: "<row-key>"
);
const { TableServiceClient, TableClient } = require('@azure/data-tables');
const { DefaultAzureCredential } = require('@azure/identity');
const endpoint = '<account-endpoint>';
let credential = new DefaultAzureCredential();
let client = new TableServiceClient(endpoint, credential);
let table = new TableClient(endpoint, "<table-name>", credential);
await table.getEntity("<partition-key>", "<row-key>");
import { TableServiceClient, TableClient } from '@azure/data-tables';
import { TokenCredential, DefaultAzureCredential } from '@azure/identity';
const endpoint: string = '<account-endpoint>';
let credential: TokenCredential = new DefaultAzureCredential();
let client: TableServiceClient = new TableServiceClient(endpoint, credential);
let table: TableClient = new TableClient(endpoint, "<table-name>", credential);
await table.getEntity("<partition-key>", "<row-key>");
from azure.data.tables import TableServiceClient
from azure.identity import DefaultAzureCredential
endpoint = "<account-endpoint>"
credential = DefaultAzureCredential()
client = TableServiceClient(endpoint, credential=credential)
table = client.get_table_client("<table-name>")
table.get_entity(
row_key="<row-key>",
partition_key="<partition-key>"
)
import (
"context"
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
"github.com/Azure/azure-sdk-for-go/sdk/data/aztables"
)
const endpoint = "<account-endpoint>"
func main() {
credential, _ := azidentity.NewDefaultAzureCredential(nil)
client, _ := aztables.NewServiceClient(endpoint, credential, nil)
table := client.NewClient("<table-name>")
_, err := table.GetEntity(context.TODO(), "<partition-key>", "<row-key>", nil)
if err != nil {
panic(err)
}
}
import com.azure.data.tables.TableClient;
import com.azure.data.tables.TableServiceClient;
import com.azure.data.tables.TableServiceClientBuilder;
import com.azure.identity.DefaultAzureCredential;
import com.azure.identity.DefaultAzureCredentialBuilder;
public class Table{
public static void main(String[] args){
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder()
.build();
TableServiceClient client = new TableServiceClientBuilder()
.endpoint("<table-endpoint>")
.credential(credential)
.buildClient();
TableClient table = client
.getTableClient("<table-name>");
table.getEntity("<partition-key>", "<row-key>");
}
}