다음을 통해 공유

使用基于角色的访问控制和Microsoft Entra ID 连接到 Azure Cosmos DB for NoSQL

基于角色的访问控制是指管理对 Azure 中资源的访问的方法。 此方法基于为特定身份分配角色,以管理他们对一个或多个资源的访问权限级别。 基于角色的访问控制提供了一个灵活的精细访问管理系统,可确保标识仅具有执行其任务所需的最低特权级别访问权限。

有关详细信息,请参阅 基于角色的访问控制

先决条件

  • 拥有有效订阅的 Azure 帐户。 创建账户

  • 一个现有的适用于 NoSQL 的 Azure Cosmos DB 帐户。

  • Microsoft Entra ID 中的一个或多个现有标识。

可以使用本地 Azure CLI。

禁用基于密钥的身份验证

禁用基于密钥的授权可以防止在不使用更安全的 Microsoft Entra ID 身份验证方法的情况下使用您的帐户。 此过程是应在安全工作负荷中的新帐户上执行的步骤。 或者,对迁移到安全工作负荷模式的现有帐户执行此过程。

首先,对现有帐户禁用基于密钥的身份验证,以便应用程序需要使用 Microsoft Entra ID 身份验证。 请用 az resource update 修改现有帐户的 properties.disableLocalAuth

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

首先,创建禁用基于密钥的身份验证的新帐户,以便应用程序需要使用 Microsoft Entra 身份验证。

  1. 创建一个新的 Bicep 文件,以在禁用基于密钥的身份验证的情况下部署新帐户。 将文件命名为 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. 使用 az deployment group create 部署 Bicep 文件同时启用新帐户。

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

首先,对现有帐户禁用基于密钥的身份验证,以便应用程序需要使用 Microsoft Entra 身份验证。 分别使用 Get-AzResourceSet-AzResource 来读取和更新现有账号。

$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

使用以下步骤创建禁用基于密钥的身份验证的新 Azure Cosmos DB for NoSQL 帐户,以便应用程序仅使用 Microsoft Entra 身份验证。

  1. 设置新的 Azure Cosmos DB for NoSQL 帐户时,导航到帐户创建过程 的安全 部分。

  2. 然后,为基于密钥的身份验证选项选择“禁用”。

    在 Azure 门户中创建新帐户时禁用基于密钥的身份验证的选项的屏幕截图。

重要

要修改 Azure Cosmos DB 帐户,需要至少具备 Microsoft.DocumentDb/databaseAccounts/*/write 权限的 Azure 角色。 有关详细信息,请参阅 Azure Cosmos DB 的权限

验证是否已禁用基于密钥的身份验证

若要验证是否已禁用基于密钥的访问,请尝试使用 Azure SDK 通过资源所有者密码凭据(ROPC)连接到 Azure Cosmos DB for NoSQL。 此尝试应失败。 如有必要,此处提供了常见编程语言的代码示例。

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();
}

授予控制平面基于角色的访问控制

控制平面访问是指无需管理数据即可管理 Azure 服务的资源。 例如,Azure Cosmos DB 控制平面访问可能包括:

  • 读取所有帐户和资源元数据
  • 读取和重新生成帐户密钥和连接字符串
  • 执行帐户备份和还原
  • 启动和跟踪数据传输作业
  • 管理数据库和容器
  • 修改帐户属性

重要

在 Azure Cosmos DB 中,您需要控制平面访问权限来管理本地数据平面基于角色的访问控制定义和分配。 由于 Azure Cosmos DB 的数据平面角色为基础的访问控制机制是原生的,因此需要控制平面访问来创建定义和分配,并将这些定义和分配作为资源存储在 Azure Cosmos DB 帐户中。

首先,必须准备一个角色定义,其中包含用于授予访问权限以管理 Azure Cosmos DB 中的帐户资源的权限的列表 actions 。 在本指南中,您将设置内置和自定义角色。 然后,将新定义的角色分配给身份,以确保你的应用程序可以访问 Azure Cosmos DB 中的资源。

  1. 使用 az role definition list 列出与 Azure Cosmos DB 帐户关联的所有角色定义。

    az role definition list \
        --name "Cosmos DB Operator"
    
  2. 查看输出并找到名为 Cosmos DB 运算符的角色定义。 输出包含属性中 id 角色定义的唯一标识符。 记下此值,因为本指南后面的工作分配步骤需要使用此值。

    [
      {
        "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",
      }
    ]
    

    注释

    在此示例中,该值 id/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/providers/Microsoft.Authorization/roleDefinitions/230815da-be43-4aae-9cb4-875f7bd000aa. 此示例使用虚构数据,标识符与此示例不同。 但是,标识符(230815da-be43-4aae-9cb4-875f7bd000aa)在 Azure 中的所有角色定义中全局唯一。

  3. 使用 az group show 来获取当前资源组的元数据。

    az group show \
        --name "<name-of-existing-resource-group>"
    
  4. 观察上一命令的输出。 记录此资源组的属性 id 值,因为下一步需要使用此属性。

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

    注释

    在此示例中,该值 id/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example. 此示例使用虚构数据,标识符与此示例不同。 此字符串是输出的截断示例。

  5. 创建名为 role-definition.json的新 JSON 文件。 在文件中,创建此资源定义,指定此处列出的值。 在AssignableScopes列表中,添加上一步中记录的资源组的id属性。

    {
      "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"
      ]
    }
    

    注释

    此示例使用 /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example 上一步中记录的值。 实际资源标识符可能有所不同。

  6. 使用 az role definition create. 创建一个新的角色定义。 使用 role-definition.json 文件作为 --role-definition 参数的输入。

    az role definition create \
        --role-definition role-definition.json
    
  7. 查看定义创建命令的输出。 输出包含属性中 id 角色定义的唯一标识符。 记下此值,因为本指南后面的工作分配步骤需要使用此值。

    {
      "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"
    }
    

    注释

    在此示例中,该值 id/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example/providers/Microsoft.Authorization/roleDefinitions/a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1. 此示例使用虚构数据,标识符与此示例不同。 此示例是部署中输出的典型 JSON 的子集,为清楚起见。

  8. 使用 az group show 再次获取当前资源组的元数据。

    az group show \
        --name "<name-of-existing-resource-group>"
    
  9. 观察上一命令的输出。 记录此资源组的属性 id 值,因为下一步需要使用此属性。

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

    注释

    在此示例中,该值 id/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example. 此示例使用虚构数据,标识符与此示例不同。 此字符串是输出的截断示例。

  10. 使用 az role assignment create 分配新角色。 使用资源组的标识符作为--scope参数,角色的标识符作为-role参数,您的标识的唯一标识符作为--assignee参数。

    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"
    

    注释

    在这个示例命令中,scope 被设置为上一个步骤中示例的虚构示例 /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example。 资源组的标识符与此示例不同。 role 也被设置为虚构的 /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example/providers/Microsoft.Authorization/roleDefinitions/a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1。 同样,角色标识符将不同。

  11. 观察命令的输出。 输出中包含分配的唯一标识符在 id 属性中。

    {
      "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"
    }
    

    注释

    在此示例中,该 id 属性是 /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example/providers/Microsoft.Authorization/roleAssignments/a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1,另一个虚构示例。

  12. 重复这些步骤,从您希望使用的任何其他身份授予帐户访问权限。

    小窍门

    可以根据需要为任意数量身份重复这些步骤。 通常,这些步骤至少重复一次,以允许开发人员使用人工标识访问帐户,并允许应用程序使用托管标识访问数据。

  1. 使用 az role definition list 列出与 Azure Cosmos DB 帐户关联的所有角色定义。

    az role definition list \
        --name "Cosmos DB Operator"
    
  2. 查看输出并找到名为 Cosmos DB 运算符的角色定义。 输出包含属性中 id 角色定义的唯一标识符。 记下此值,因为本指南后面的工作分配步骤需要使用此值。

    [
      {
        "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",
      }
    ]
    

    注释

    在此示例中,该值 id/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/providers/Microsoft.Authorization/roleDefinitions/230815da-be43-4aae-9cb4-875f7bd000aa. 此示例使用虚构数据,标识符与此示例不同。 但是,标识符(230815da-be43-4aae-9cb4-875f7bd000aa)在 Azure 中的所有角色定义中全局唯一。

  3. 创建新的 Bicep 文件以定义角色定义。 将文件 control-plane-role-definition.bicep 命名。 将以下项 actions 添加到定义:

    Description
    Microsoft.DocumentDb/* 启用所有可能的作。
    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. 使用 az deployment group create 部署 Bicep 模板。 指定 Bicep 模板和 Azure 资源组的名称。

    az deployment group create \
        --resource-group "<name-of-existing-resource-group>" \
        --template-file control-plane-role-definition.bicep
    
  5. 查看部署的输出。 输出包含属性中 properties.outputs.definitionId.value 角色定义的唯一标识符。 记下此值,因为本指南后面的工作分配步骤需要使用此值。

    {
      "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"
          }
        }
      }
    }
    

    注释

    在此示例中,该值 id/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example/providers/Microsoft.Authorization/roleDefinitions/a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1. 此示例使用虚构数据,标识符与此示例不同。 此示例是部署中输出的典型 JSON 的子集,为清楚起见。

  6. 创建新的 Bicep 文件以定义角色分配。 将文件命名为 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. 创建名为 control-plane-role-assignment 的新 Bicep 参数文件。bicepparam 在此参数文件中。将以前记录的角色定义标识符分配给参数 roleDefinitionId,将您身份的唯一标识符分配给参数 identityId

    using './control-plane-role-assignment.bicep'
    
    param roleDefinitionId = '<id-of-new-role-definition>'
    param identityId = '<id-of-existing-identity>'
    
  8. 使用 az deployment group create 部署此 Bicep 模板。

    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. 重复这些步骤,从您希望使用的任何其他身份授予帐户访问权限。

    小窍门

    可以根据需要为任意数量身份重复这些步骤。 通常,这些步骤至少重复一次,以允许开发人员使用人工标识访问帐户,并允许应用程序使用托管标识访问数据。

  1. 登录到 Azure 门户 (https://portal.azure.cn)。

  2. 在全局搜索栏中输入 资源组

    Azure 门户中全局搜索栏的屏幕截图。

  3. “服务”中,选择 “资源组”。

    搜索菜单中选择“资源组”选项的屏幕截图。

  4. 在“ 资源组 ”窗格中,选择现有的资源组。

    订阅资源组列表中的现有资源组的屏幕截图。

    注释

    此示例屏幕截图包括 msdocs-identity-example 资源组。 实际的资源组名称可能不同。

  5. 在资源组的窗格中,在服务菜单中选择 访问控制(IAM )。

    资源组的服务菜单中的“访问控制(IAM)”选项的屏幕截图。

  6. “访问控制”(IAM) 窗格中,选择“ 角色”。

    “访问控制(IAM)”窗格中“角色”选项的屏幕截图。

  7. “角色 ”部分中,使用搜索短语 Cosmos DB 并找到 Cosmos DB 操作员 角色定义。 然后,选择与该定义关联的 “视图 ”选项。

    在当前可分配范围中角色定义列表的屏幕截图,仅筛选出标题中包含“Cosmos DB”的定义。

  8. Cosmos DB 操作员 角色定义对话框中,查看分配给此角色定义的一部分的操作。

    “Cosmos DB 操作员”对话框的屏幕截图,其中包含有关内置角色定义的详细信息。

  9. 关闭 Cosmos DB 操作员 角色定义对话框。

  10. 返回 “访问控制”(IAM) 窗格,选择“ 添加”。 然后选择 “添加自定义角色”。

    “访问控制 (IAM)”菜单中的“添加”选项的“添加自定义角色”选项的屏幕截图。

  11. “基本信息 ”窗格中,配置以下选项,然后选择“ 下一步” :

    价值
    自定义角色名称 Azure Cosmos DB Control Plane Owner
    说明 Can perform all control plane actions for an Azure Cosmos DB account.
    基线权限 从头开始

    用于添加自定义角色的“基本信息”窗格的屏幕截图。

  12. 在“ 权限 ”窗格中,选择“ 添加权限”。 然后,在权限对话框中搜索 DocumentDB 。 最后,选择 Microsoft.DocumentDB 选项。

    用于添加自定义角色的“权限”窗格的屏幕截图。

    筛选为与“DocumentDB”相关的权限以添加自定义角色的“添加权限”对话框的屏幕截图。

  13. 在“权限”对话框中,为 选择所有 Microsoft.DocumentDB。 然后选择 “添加 ”以返回到“权限 ”窗格。

    自定义角色对话框中为“DocumentDB”选择的所有权限的屏幕截图。

  14. 返回“ 权限 ”窗格,观察权限列表。 然后选择 “查看 + 创建”。

    “权限”窗格的屏幕截图,其中已将多个权限添加到自定义角色的列表。

  15. “审阅 + 创建 ”窗格中,查看新角色定义的指定选项。 最后,选择“ 创建”。

    用于添加自定义角色的“审阅 + 创建”窗格的屏幕截图。

  16. 等待门户完成角色定义创建。

  17. “访问控制”(IAM) 窗格中,选择“ 添加 ”,然后选择 “添加角色分配”。

    “访问控制(IAM)”菜单中“添加”选项的“添加角色分配”选项的屏幕截图。

  18. “角色 ”窗格中,搜索 Azure Cosmos DB 并选择本指南前面创建的 Azure Cosmos DB 控制平面所有者 角色。 然后选择下一步

    用于添加角色分配的“角色”窗格的屏幕截图。

    小窍门

    可以选择筛选角色列表,以仅包含自定义角色。

  19. 在“ 成员 ”窗格中,选择“ 选择成员 ”选项。 在成员对话框中,选择要为 Azure Cosmos DB 帐户授予此级别访问权限的标识,然后使用 “选择” 选项确认选择。

    用于添加角色分配的“成员”窗格的屏幕截图。

    用于添加角色分配的标识选择对话框的屏幕截图。

    注释

    此屏幕截图演示了一个名为 “Kai Carter” 和主体 kai@adventure-works.com的示例用户。

  20. 返回“ 成员 ”窗格,查看所选成员[s],然后选择“ 审阅 + 分配”。

    “成员”窗格的屏幕截图,其中选择了用于角色分配的身份。

  21. “审阅 + 分配 ”窗格中,查看新角色分配的指定选项。 最后,选择“ 审阅 + 分配”。

    角色分配的“审阅 + 创建”窗格的屏幕截图。

  22. 等待门户完成创建角色分配。

  1. 用于 Get-AzRoleDefinition 列出与 Azure Cosmos DB 帐户关联的所有角色定义。

    $parameters = @{
        Name = "Cosmos DB Operator"
    }
    Get-AzRoleDefinition @parameters
    
  2. 查看输出并找到名为 Cosmos DB 内置数据参与者的角色定义。 输出包含属性中 Id 角色定义的唯一标识符。 记下此值,因为本指南后面的工作分配步骤需要使用此值。

    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 : {/}
    

    注释

    在此示例中,该值 Id230815da-be43-4aae-9cb4-875f7bd000aa. 该标识符在 Azure 中的所有角色定义中全局唯一。

  3. 使用 Get-AzResourceGroup 来获取当前资源组的元数据。

    $parameters = @{
        Name = "<name-of-existing-resource-group>"
    }
    Get-AzResourceGroup @parameters
    
  4. 观察上一命令的输出。 记录此资源组的属性 ResourceId 值,因为下一步需要使用此属性。

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

    注释

    在此示例中,该值 ResourceId/subscriptions/a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1/resourcegroups/msdocs-identity-example. 此示例使用虚构数据,标识符与此示例不同。 此字符串是典型输出的截断示例。

  5. 首先,导入 Az.Resources 模块。 然后,创建新 Microsoft.Azure.Commands.Resources.Models.Authorization.PSRoleDefinition 对象。 在对象中,创建此资源定义,指定此处列出的值。 在AssignableScopes列表中,添加上一步中记录的资源组的ResourceId属性。 最后,使用角色定义对象作为-RoleNew-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
    

    注释

    此示例使用 /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example 上一步中记录的值。 实际资源标识符可能有所不同。

  6. 查看定义创建命令的输出。 输出包含属性中 Name 角色定义的唯一标识符。 记下此值,因为本指南后面的工作分配步骤需要使用此值。

    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}
    

    注释

    在此示例中,该值 NameAzure Cosmos DB Control Plane Owner. 此示例是部署的典型输出的子集,以便清楚起见。

  7. 使用 New-AzRoleAssignment 分配新角色。 对于 RoleDefinitionName 参数使用角色名称,而对于 ObjectId 参数则使用您的标识唯一标识符。

    $parameters = @{
        ResourceGroupName = "<name-of-existing-resource-group>"
        ObjectId = "<your-principal-identifier>"
        RoleDefinitionName = "Azure Cosmos DB Control Plane Owner"
    }
    New-AzRoleAssignment @parameters
    
  8. 观察命令的输出。 输出中包含分配的唯一标识符在 RoleAssignmentId 属性中。

    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
    

    注释

    在此示例中,该 RoleAssignmentId 属性是 /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourcegroups/msdocs-identity-example/providers/Microsoft.Authorization/roleAssignments/a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1,另一个虚构示例。 此示例是部署的典型输出的子集,以便清楚起见。

  9. 重复这些步骤,从您希望使用的任何其他身份授予帐户访问权限。

    小窍门

    可以根据需要为任意数量身份重复这些步骤。 通常,这些步骤至少重复一次,以允许开发人员使用人工标识访问帐户,并允许应用程序使用托管标识访问数据。

重要

分配角色定义要求你已拥有要授予基于角色的访问控制权限的任何标识的唯一标识符。

在代码中验证基于角色的控制平面访问

验证是否已使用应用程序代码和 Azure 管理 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);
    }
}

授予数据平面基于角色的访问控制

数据平面访问是指能够在 Azure 服务中读取和写入数据,而无需管理帐户中的资源。 例如,Azure Cosmos DB 数据平面访问可能包括:

  • 读取一些帐户和资源元数据
  • 创建、读取、更新、修补和删除项目
  • 执行 NoSQL 查询
  • 从容器的更改源读取
  • 执行存储过程
  • 管理冲突源中的冲突

首先,必须准备一个角色定义,其中包含授予对 Azure Cosmos DB for NoSQL 中读取、查询和管理数据的访问权限的列表 dataActions 。 在本指南中,您将设置内置和自定义角色。 然后,将新定义的角色[s]分配给身份,以便应用程序可以访问 Azure Cosmos DB for NoSQL 中的数据。

重要

获取现有数据平面角色定义需要以下控制平面权限:

  • Microsoft.DocumentDB/databaseAccounts/sqlRoleDefinitions/read

创建新的数据平面角色定义需要以下控制平面权限:

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

创建新的数据平面角色分配需要以下控制平面权限:

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

警告

Azure Cosmos DB for NoSQL 的原生角色访问控制不支持该 notDataActions 属性。 自动排除未被指定为允许的任何操作。

  1. 使用 az cosmosdb sql role definition list 列出与 Azure Cosmos DB for NoSQL 帐户关联的所有角色定义。

    az cosmosdb sql role definition list \
        --resource-group "<name-of-existing-resource-group>" \
        --account-name "<name-of-existing-nosql-account>"
    
  2. 查看输出并找到名为 Cosmos DB 内置数据参与者的角色定义。 输出包含属性中 id 角色定义的唯一标识符。 记下此值,因为本指南后面的工作分配步骤需要使用此值。

    [
      ...,
      {
        "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"
      }
      ...
    ]
    

    注释

    在此示例中,该值 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. 此示例使用虚构数据,标识符与此示例不同。

  3. 创建名为 role-definition.json的新 JSON 文件。 在此文件中,创建一个资源定义,指定此处列出的数据操作:

    Description
    Microsoft.DocumentDB/databaseAccounts/readMetadata 可以读取帐户级元数据
    Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/* 可以执行任何容器级数据作业
    Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/* 可以对带有容器的项执行任何操作
    {
      "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. 接下来,使用az cosmosdb sql role definition create创建角色定义。 请使用 role-definition.json 作为 --body 参数的输入。

    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. 现在,使用 az cosmosdb sql role definition list 列出与 Azure Cosmos DB for NoSQL 帐户关联的所有角色定义。

    az cosmosdb sql role definition list \
        --resource-group "<name-of-existing-resource-group>" \
        --account-name "<name-of-existing-nosql-account>"
    
  6. 查看上一命令的输出。 找到刚刚为 NOSQL 数据平面所有者创建的名为 Azure Cosmos DB 的角色定义。 输出包含属性中 id 角色定义的唯一标识符。 记下此值,因为本指南后面的工作分配步骤需要使用此值。

    {
      "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"
    }
    

    注释

    在此示例中,该值 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. 此示例使用虚构数据,标识符与此示例不同。

  7. 使用 az cosmosdb show 获取当前帐户的唯一标识符。

    az cosmosdb show \
        --resource-group "<name-of-existing-resource-group>" \
        --name "<name-of-existing-nosql-account>" \
        --query "{id:id}"
    
  8. 观察上一命令的输出。 记录此帐户的属性 id 值,因为下一步需要使用此属性。

    {
      "id": "/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. 此示例使用虚构数据,标识符与此示例不同。

  9. 使用 az cosmosdb sql role assignment create 分配新角色。 将以前记录的角色定义标识符用于 --role-definition-id 参数,并将标识的唯一标识符用于 --principal-id 参数。 最后,使用帐户的标识符作为 --scope 参数。

    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"
    

    小窍门

    如果尝试向数据平面基于角色的访问控制授予自己的标识,可以使用此命令获取标识:

    az ad signed-in-user show
    

    有关详细信息,请参阅 az ad signed-in-user

    小窍门

    在 Azure Cosmos DB 的基于角色的访问控制的本机实现中, 范围 是指想要应用权限的帐户中的资源的粒度。 在最高级别,可以使用最大作用域将数据平面基于角色的访问控制分配限定到整个帐户。 此范围包括帐户中的所有数据库和容器:

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

    或者,可以将数据平面角色分配的范围限定为特定的数据库:

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

    最后,可以将分配范围限定为单个容器,这是最精细的范围:

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

    在许多情况下,可以使用相对范围而不是完全限定的范围。 例如,可以使用此相对范围从 Azure CLI 命令向特定数据库和容器授予基于角色的数据平面访问控制权限:

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

    还可以使用相对范围授予对所有数据库和容器的通用访问权限:

    /
    
  10. 使用az cosmosdb sql role assignment list列出 Azure Cosmos DB for NoSQL 帐户的所有角色分配。 查看输出以确保已创建角色分配。

    az cosmosdb sql role assignment list \
        --resource-group "<name-of-existing-resource-group>" \
        --account-name "<name-of-existing-nosql-account>"
    
  1. 使用 az cosmosdb sql role definition list 列出与 Azure Cosmos DB for NoSQL 帐户关联的所有角色定义。

    az cosmosdb sql role definition list \
        --resource-group "<name-of-existing-resource-group>" \
        --account-name "<name-of-existing-nosql-account>"
    
  2. 查看输出并找到名为 Cosmos DB 内置数据参与者的角色定义。 输出包含属性中 id 角色定义的唯一标识符。 记下此值,因为本指南后面的工作分配步骤需要使用此值。

    [
      ...,
      {
        "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"
      }
      ...
    ]
    

    注释

    在此示例中,该值 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. 此示例使用虚构数据,标识符与此示例不同。

  3. 创建新的 Bicep 文件以定义角色定义。 将文件 命名为 data-plane-role-definition.bicep。 将以下项 dataActions 添加到定义:

    Description
    Microsoft.DocumentDB/databaseAccounts/readMetadata 可以读取帐户级元数据
    Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/* 可以执行任何容器级数据作业
    Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/* 可以对带有容器的项执行任何操作
    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
    

    小窍门

    在 Azure Cosmos DB 的基于角色的访问控制的本机实现中, 范围 是指想要应用权限的帐户中的资源的粒度。 在最高级别,可以使用最大作用域将数据平面基于角色的访问控制分配限定到整个帐户。 此范围包括帐户中的所有数据库和容器:

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

    或者,可以将数据平面角色分配的范围限定为特定的数据库:

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

    最后,可以将分配范围限定为单个容器,这是最精细的范围:

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

    在许多情况下,可以使用相对范围而不是完全限定的范围。 例如,可以使用此相对范围从 Azure CLI 命令向特定数据库和容器授予基于角色的数据平面访问控制权限:

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

    还可以使用相对范围授予对所有数据库和容器的通用访问权限:

    /
    
  4. 创建名为 data-plane-role-definition 的新 Bicep 参数文件。bicepparam 在此参数文件中,将现有 Azure Cosmos DB for NoSQL 帐户的名称分配给该 accountName 参数。

    using './data-plane-role-definition.bicep'
    
    param accountName = '<name-of-existing-nosql-account>'
    
  5. 使用 az deployment group create 部署 Bicep 模板。

    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. 创建新的 Bicep 文件以定义角色分配。 请将文件命名为 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. 创建名为 data-plane-role-assignment 的新 Bicep 参数文件。bicepparam 在此参数文件中,将现有的 Azure Cosmos DB for NoSQL 帐户名称分配给 accountName 参数,将之前记录的角色定义标识符分配给 roleDefinitionId 参数,并将您身份的唯一标识符分配给 identityId 参数。

    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>'
    

    小窍门

    如果您尝试对数据平面的基于角色的访问控制授予您自己的身份,可以省略该 identityId 参数。 然后,Bicep 模板使用 deployer().objectId 获取部署模板的主体身份。 有关详细信息,请参阅 deployer

  8. 使用 az deployment group create 部署 Bicep 模板。

    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. 重复这些步骤,从您希望使用的任何其他身份授予帐户访问权限。

    小窍门

    可以根据需要为任意数量身份重复这些步骤。 通常,这些步骤至少重复一次,以允许开发人员使用其人工标识访问帐户。 还可以重复这些步骤,以允许应用程序使用托管标识访问资源。

  1. 用于 Get-AzCosmosDBSqlRoleDefinition 列出与 Azure Cosmos DB for NoSQL 帐户关联的所有角色定义。

    $parameters = @{
        ResourceGroupName = "<name-of-existing-resource-group>"
        AccountName = "<name-of-existing-nosql-account>"
    }
    Get-AzCosmosDBSqlRoleDefinition @parameters
    
  2. 查看输出并找到名为 Cosmos DB 内置数据参与者的角色定义。 输出包含属性中 Id 角色定义的唯一标识符。 记下此值,因为本指南后面的工作分配步骤需要使用此值。

    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 : 
    

    注释

    在此示例中,该值 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. 此示例使用虚构数据,标识符与此示例不同。 但是,标识符 (00000000-0000-0000-0000-000000000002) 在帐户中的所有角色定义中都是唯一的。

  3. 使用 New-AzCosmosDBSqlRoleDefinition. 创建一个新的角色定义。 对于DataAction参数,请指定此处列出的数据操作:

    Description
    Microsoft.DocumentDB/databaseAccounts/readMetadata 可以读取帐户级元数据
    Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/* 可以执行任何容器级数据作业
    Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/* 可以对带有容器的项执行任何操作
    $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
    

    小窍门

    在 Azure Cosmos DB 的基于角色的访问控制的本机实现中, 范围 是指想要应用权限的帐户中的资源的粒度。 在最高级别,可以使用最大作用域将数据平面基于角色的访问控制分配限定到整个帐户。 此范围包括帐户中的所有数据库和容器:

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

    或者,可以将数据平面角色分配的范围限定为特定的数据库:

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

    最后,可以将分配范围限定为单个容器,这是最精细的范围:

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

    在许多情况下,可以使用相对范围而不是完全限定的范围。 例如,可以使用此相对范围从 Azure CLI 命令向特定数据库和容器授予基于角色的数据平面访问控制权限:

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

    还可以使用相对范围授予对所有数据库和容器的通用访问权限:

    /
    
  4. 用于 Get-AzCosmosDBSqlRoleDefinition 列出与 Azure Cosmos DB for NoSQL 帐户关联的所有角色定义。

    $parameters = @{
        ResourceGroupName = "<name-of-existing-resource-group>"
        AccountName = "<name-of-existing-nosql-account>"
    }
    Get-AzCosmosDBSqlRoleDefinition @parameters    
    
  5. 查看上一命令的输出。 找到刚刚为 NOSQL 数据平面所有者创建的名为 Azure Cosmos DB 的角色定义。 输出包含属性中 Id 角色定义的唯一标识符。 记下此值,因为本指南后面的工作分配步骤需要使用此值。

    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 :
    

    注释

    在此示例中,该值 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. 此示例使用虚构数据,标识符与此示例不同。

  6. 使用 Get-AzCosmosDBAccount 来获取您当前帐户的元数据。

    $parameters = @{
        ResourceGroupName = "<name-of-existing-resource-group>"
        Name = "<name-of-existing-nosql-account>"
    }    
    Get-AzCosmosDBAccount @parameters | Select -Property Id
    
  7. 观察上一命令的输出。 记录此帐户的属性 Id 值,因为下一步需要使用此属性。

    Id
    --    
    /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. 此示例使用虚构数据,标识符与此示例不同。

  8. 使用New-AzCosmosDBSqlRoleAssignment分配新角色。 将先前记录的角色定义标识符用于 RoleDefinitionId 参数,并将您的身份的唯一标识符用于 PrincipalId 参数。 最后,将帐户的标识符用于 Scope 参数。

    $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
    

    小窍门

    如果尝试向数据平面基于角色的访问控制授予自己的标识,可以使用此命令获取标识:

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

    有关详细信息,请参阅 Get-AzADUser

  9. 使用 Get-AzCosmosDBSqlRoleAssignment列出 Azure Cosmos DB for NoSQL 帐户的所有角色分配。 查看输出以确保已创建角色分配。

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

警告

Azure 门户中不支持管理基于角色的数据平面访问控制。

在代码中验证基于角色的数据平面访问

验证是否已使用应用程序代码和 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();
}