将基于角色的访问控制与 Azure Cosmos DB for Table(预览版)配合使用

适用对象:

此图显示部署指南序列中的当前位置(“基于角色的访问控制”)。

部署指南序列图,包括以下位置,顺序为:概述、概念、准备、基于角色的访问控制、参考。 当前突出显示了“基于角色的访问控制”位置。

本文介绍授予管理 Azure Cosmos DB for Table 帐户中数据的标识访问权限的步骤。 本文中的步骤仅介绍对单个项执行操作和运行查询的数据平面访问。

先决条件

  • 具有活动订阅的 Azure 帐户。 创建帐户
  • 现有 Azure Cosmos DB for Table 帐户。
  • Microsoft Entra ID 中的一个或多个现有标识。

可以使用本地 Azure CLI。

  • 如果需要,请安装 Azure CLI 来运行 CLI 参考命令。

  • 本地 Azure CLI,请了解如何安装 Azure CLI。 如果在 Windows 或 macOS 上运行,请考虑在 Docker 容器中运行 Azure CLI。 有关详细信息,请参阅如何在 Docker 容器中运行 Azure CLI

    • 通过使用 az login 命令登录到 Azure CLI。 若要完成身份验证过程,请遵循终端中显示的步骤。 有关其他登录选项,请参阅使用 Azure CLI 登录

    • 出现提示时,请在首次使用时安装 Azure CLI 扩展。 有关扩展详细信息,请参阅使用 Azure CLI 的扩展

    • 运行 az version 以查找安装的版本和依赖库。 若要升级到最新版本,请运行 az upgrade

准备角色定义

首先,必须准备一个角色定义,其中包含 dataActions 的列表,以授予读取、查询和管理 Azure Cosmos DB for Table 中数据的访问权限。

首先,使用 az cosmsodb show 获取现有 Azure Cosmos DB for Table 帐户的资源标识符,并将其存储在变量中。 然后,使用 az rest 列出与 Azure Cosmos DB for Table 帐户关联的所有角色定义。 最后,查看输出并找到名为 Cosmos DB 内置数据参与者的角色定义。 输出包含属性中 id 角色定义的唯一标识符。 记下此值,因为本指南后面的工作分配步骤需要使用此值。

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
[
  ...,
  {
    "id": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/msdocs-identity-example/providers/Microsoft.DocumentDB/databaseAccounts/msdocs-identity-example-nosql/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-nosql"
      ],
      "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-nosql/tableRoleDefinitions/00000000-0000-0000-0000-000000000002。 此示例使用虚构数据,而你的标识符与此示例不同。 此示例输出会被截断。

使用 Get-AzCosmosDBAccount 获取现有 Azure Cosmos DB for Table 帐户的资源标识符,并将其存储在变量中。 然后,使用 Invoke-AzRestMethod 列出与 Azure Cosmos DB for Table 帐户关联的所有角色定义。 查看输出并找到名为 Cosmos DB 内置数据参与者的角色定义。 输出包含属性中 Id 角色定义的唯一标识符。 记下此值,因为本指南后面的工作分配步骤需要使用此值。

$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
StatusCode : 200
Content    : {
               "value": [
                ...,
                {
                  "id": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/msdocs-identity-example/providers/Microsoft.DocumentDB/databaseAccounts/msdocs-identity-example-nosql/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-nosql"
                    ],
                    "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-nosql/tableRoleDefinitions/00000000-0000-0000-0000-000000000002。 此示例使用虚构数据,而你的标识符与此示例不同。 此示例输出会被截断。

将角色分配给标识

现在,将新定义的角色分配给标识,以便应用程序可以访问 Azure Cosmos DB for Table 中的数据。

重要

此分配任务要求拥有要授予基于角色的访问控制权限的任何标识的唯一标识符。 如果没有标识的唯一标识符,请按照创建托管标识获取登录标识指南中的说明执行操作。

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

    az cosmosdb show \
        --resource-group "<name-of-existing-resource-group>" \
        --name "<name-of-existing-resource-group>" \
        --query "{id:id}"
    
  2. 观察上一命令的输出。 记录此帐户的 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。 此示例使用虚构数据,而你的标识符与此示例不同。

  3. 创建名为 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。

  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/tableRoleAssignments/e4e4e4e4-ffff-aaaa-bbbb-c5c5c5c5c5c5?api-version=2023-04-15 \
        --body @role-assignment.json
    

    注意

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

  1. 创建另一个 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
    
  2. 创建名为 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>'
    
  3. 使用 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
    
  4. 重复这些步骤,从要使用的任何其他标识授予对帐户的访问权限。

    提示

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

  1. 使用 `Get-AzCosmosDBAccount 获取当前帐户的唯一标识符。

    $parameters = @{
        ResourceGroupName = "<name-of-existing-resource-group>"
        Name = "<name-of-existing-nosql-account>"
    }
    Get-AzCosmosDBAccount @parameters | Select -Property Id
    
  2. 观察上一命令的输出。 记录此帐户的 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。 此示例使用虚构数据,而你的标识符与此示例不同。

  3. 现在,将 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 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>"
);

重要

此代码示例使用 NuGet 中的 Azure.Data.TablesAzure.Identity 库。

警告

如果要使用用户分配的托管标识,则需要在创建凭据对象时指定托管标识的唯一标识符。