使用角色为基础的访问控制和 Microsoft Entra ID 来连接 Azure Cosmos DB for Table

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

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

先决条件

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

  • 用于表的现有 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 Table。 此尝试应失败。 如有必要,此处提供了常见编程语言的代码示例。

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

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

控制平面访问是指无需管理数据即可管理 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 数据平面访问可能包括:

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

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

  1. 首先,获取现有 Azure Cosmos DB for Table 帐户 az cosmsodb show 的资源标识符,并将其存储在变量中。

    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
    
  2. 然后,使用 az rest 列出与 Azure Cosmos DB 表帐户关联的所有角色定义。 最后,查看输出并找到名为 Cosmos DB 内置数据参与者的角色定义。 输出包含属性中 id 角色定义的唯一标识符。 记下此值,因为本指南后面的工作分配步骤需要使用此值。

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

    注释

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

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

    Description
    Microsoft.DocumentDB/databaseAccounts/readMetadata 可以读取帐户级元数据
    Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/* 可以执行任何容器级数据作业
    Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/* 可以对带有容器的项执行任何操作
    {
      "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/*"
            ]
          }
        ]
      }
    }
    
  4. 现在,使用 az cosmosdb showaz rest 一起创建或更新角色定义来发出 HTTP PUT 请求。 作为此请求的一部分,请为角色定义指定唯一的 GUID。

    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
    

    注释

    在此示例中,指定的唯一 GUID 为 d3d3d3d3-eeee-ffff-aaaa-b4b4b4b4b4b4。 可以为自己的角色定义指定任何唯一的 GUID。

  5. 现在输出应显示请求已排队。 现在,等待已排队的角色定义部署完成。 此任务可能需要几分钟时间。

    {
      "status": "Enqueued"
    }
    
  6. 使用 az rest 再次检查角色定义列表。

    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
    
  7. 使用 az cosmosdb show 获取当前帐户的唯一标识符。

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

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

    注释

    在此示例中,该值 id/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/msdocs-identity-example/providers/Microsoft.DocumentDB/databaseAccounts/msdocs-identity-example-table. 此示例使用虚构数据,标识符与此示例不同。

  9. 创建名为 role-assignment.json的新 JSON 文件。 在 JSON 文件中,添加您的身份的唯一标识符以及帐户资源的唯一标识符。

    {
      "properties": {
        "roleDefinitionId": "<account-resource-id>/tableRoleDefinitions/d3d3d3d3-eeee-ffff-aaaa-b4b4b4b4b4b4",
        "scope": "<account-resource-id>",
        "principalId": "<id-of-existing-identity>"
      }
    }
    

    注释

    在此示例中,指定的唯一 GUID 为 d3d3d3d3-eeee-ffff-aaaa-b4b4b4b4b4b4。 可以使用以前用于自己的角色定义的唯一 GUID。

    小窍门

    在 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 showaz rest 一起创建或更新角色分配来发出 HTTP PUT 请求。 作为此请求的一部分,请为您的角色分配指定一个唯一的 GUID。

    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
    

    注释

    在此示例中,指定的唯一 GUID 为 e4e4e4e4-ffff-aaaa-bbbb-c5c5c5c5c5c5。 您可以为自己的角色分配任何唯一的 GUID。

  1. 首先,获取现有 Azure Cosmos DB for Table 帐户 az cosmsodb show 的资源标识符,并将其存储在变量中。

    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
    
  2. 然后,使用 az rest 列出与 Azure Cosmos DB 表帐户关联的所有角色定义。 最后,查看输出并找到名为 Cosmos DB 内置数据参与者的角色定义。 输出包含属性中 id 角色定义的唯一标识符。 记下此值,因为本指南后面的工作分配步骤需要使用此值。

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

    注释

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

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

    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
    

    小窍门

    在 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.bicepparam 的新 Bicep 参数文件。 在此参数文件中,将现有 Azure Cosmos DB for Table 帐户的名称分配给该 accountName 参数。

    using './data-plane-role-definition.bicep'
    
    param accountName = '<name-of-existing-table-account>'
    
  5. 使用 az deployment group create 部署 Bicep 模板。 指定 Bicep 模板、参数文件和 Azure 资源组的名称。

    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. 查看部署的输出。 输出包含属性中 properties.outputs.definitionId.value 角色定义的唯一标识符。 记下此值,因为本指南后面的工作分配步骤需要使用此值。

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

    注释

    在此示例中,该值 id/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. 此示例使用虚构数据,标识符与此示例不同。 此示例是部署中输出的典型 JSON 的子集,为清楚起见。

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

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

    小窍门

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

  1. 用于 Get-AzCosmosDBAccount 获取现有 Azure Cosmos DB for Table 帐户的资源标识符,并将其存储在变量中。

    $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
    
  2. 然后,用于 Invoke-AzRestMethod 列出与 Azure Cosmos DB for Table 帐户关联的所有角色定义。 查看输出并找到名为 Cosmos DB 内置数据参与者的角色定义。 输出包含属性中 Id 角色定义的唯一标识符。 记下此值,因为本指南后面的工作分配步骤需要使用此值。

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

    注释

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

  3. 使用 Get-AzCosmosDBAccountInvoke-AzRestMethod 一起创建或更新角色定义来发出 HTTP PUT 请求。 此外,作为此请求的一部分,请为角色定义指定唯一的 GUID。 最后,创建一个资源定义有效负载,指定所列的数据操作:

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

    注释

    在此示例中,指定的唯一 GUID 为 d3d3d3d3-eeee-ffff-aaaa-b4b4b4b4b4b4。 可以为自己的角色定义指定任何唯一的 GUID。

    小窍门

    在 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. 输出应返回状态代码 为 200。 现在,等待已排队的角色定义部署完成。 此任务可能需要几分钟时间。

    StatusCode : 200
    ...
    
  5. 使用 Invoke-AzRestMethod 再次检查角色定义列表。

    $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
    
  6. 使用“Get-AzCosmosDBAccount”命令来获取当前帐户的唯一标识符。

    $parameters = @{
        ResourceGroupName = "<name-of-existing-resource-group>"
        Name = "<name-of-existing-table-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-table
    

    注释

    在此示例中,该值 Id/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/msdocs-identity-example/providers/Microsoft.DocumentDB/databaseAccounts/msdocs-identity-example-table. 此示例使用虚构数据,标识符与此示例不同。

  8. 现在,使用 Get-AzCosmosDBAccountInvoke-AzRestMethod 一起创建或更新角色分配来发出 HTTP PUT 请求。 作为此请求的一部分,请为您的角色分配指定一个唯一的 GUID。 最后,创建一个资源分配数据载荷,指定您的标识的唯一标识符。

    $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
    

    注释

    在此示例中,指定的唯一 GUID 为 e4e4e4e4-ffff-aaaa-bbbb-c5c5c5c5c5c5。 您可以为自己的角色分配任何唯一的 GUID。

警告

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

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

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