Compartilhar via

使用角色访问控制和 Microsoft Entra ID 连接到 Azure DocumentDB

Azure DocumentDB 支持 Microsoft Entra ID 和原生 DocumentDB 身份验证。 每个群集都启用了本机身份验证,并创建了一个内置管理用户。

基于角色的访问控制提供了一种集中机制,通过Microsoft Entra ID分配和实施权限,确保只有授权身份才能对群集执行操作。 此方法简化了治理,支持最低特权原则,并使审核变得简单-帮助组织在部署增长时保持运营完整性和合规性。 在 Azure DocumentDB 中管理访问涉及两个不同的级别:

  • Azure基于角色的访问,用于管理群集作为Azure资源(例如读取元数据、管理防火墙规则和配置专用终结点)
  • DocumentDB 可以在群集上的数据库和集合中读取和写入数据。

启用Microsoft Entra ID以允许Microsoft Entra 主体(用户、服务主体或托管标识)向群集进行身份验证。 Microsoft Entra ID身份验证是使用 OpenID Connect (OIDC)实现的。 客户端向 MongoDB 驱动程序提供 Entra 颁发的 OIDC 访问令牌。 群集必须启用本机身份验证;支持的配置是仅本机配置或仅Microsoft Entra ID身份验证或本机身份验证和Microsoft Entra ID身份验证。

注释

预配后,可以随时在群集上启用或更改身份验证方法。 更改身份验证方法 不需要 重启群集,并且不中断。 创建群集时,必须启用本机 DocumentDB 身份验证。 可以在群集完成预配后禁用本机身份验证。

使用Microsoft Entra ID进行身份验证的好处包括:

  • 跨Azure服务的统一标识和登录。
  • 集中管理凭据、密码策略和轮换。
  • 支持来自Microsoft Entra ID的无密码和多重身份验证方法。
  • 应用程序的基于令牌的身份验证,消除了存储的密码。

启用Microsoft Entra ID身份验证后,可以将一个或多个Microsoft Entra 主体注册为群集上的管理用户或非管理员用户。 注册的主体在 Microsoft.DocumentDB/mongoClusters/users 下成为Azure资源,并复制到数据库中;将这些主体映射到 MongoDB 数据库角色会授予相应的数据库权限。 这种形式的身份验证支持多种主体类型,包括:人类用户、服务主体(应用)、用户分配的托管标识和系统分配的托管标识。

注释

可以同时将多个Microsoft Entra ID标识和标识类型配置为群集的管理员。 Microsoft Entra ID标识类型包括但不限于:

  • 人的身份
  • 用户分配的托管标识
  • 系统分配的托管标识
  • 工作负载标识

所有标识类型都可以同时成为管理员。

管理用户拥有管理群集及其数据的完整权限。 可以为不需要管理权限的持续生产任务添加非管理用户。 非管理员用户通常持有受限角色,例如对特定数据库的只读或读写访问,但无法执行群集范围的管理操作。

使用此功能之前,请查看以下注意事项:

  • 主群集和副本群集上的身份验证方法 是独立管理的
  • Microsoft Entra 主体在群集元数据中永久存在。 如果主体从Microsoft Entra ID中删除,则相应的群集用户将保留,但无法再获取新令牌。 现有令牌在过期之前保持有效(通常从 令牌颁发起最多 90 分钟)。
  • 若要立即撤销访问,请从群集中删除主体(删除 users/<principal-id> 资源),并删除任何关联的数据库角色,数据库管理员必须负责处理已删除主体的所有权转移或清理。

先决条件

  • Azure订阅

    • 如果没有Azure订阅,请创建 Trial
  • Microsoft Entra ID中的一个或多个现有标识。
  • 如果希望在本地运行 CLI 引用命令,install Azure CLI。 如果在 Windows 或 macOS 上运行,请考虑在 Docker 容器中运行Azure CLI。 有关详细信息,请参阅 如何在 Docker 容器中运行Azure CLI

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

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

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

管理基于角色的Azure access control

Azure角色基于的访问控制指的是在不管理数据的情况下,管理Azure服务资源的能力。 例如,Azure DocumentDB 群集的基于角色的访问可能包括以下能力:

  • 读取所有帐户和资源元数据
  • 读取和重新生成连接字符串
  • 管理数据库和集合
  • 修改帐户属性

Azure DocumentDB 支持 Azure 基于角色的访问控制用于 mongoCluster 资源类型。 资源类型的以下 mongoCluster 可用于 Azure 中的基于角色的访问控制,用于单个分配和自定义基于角色的访问控制角色创建:

Description
Microsoft.DocumentDB/mongoClusters/read 读取mongoCluster资源或列出所有mongoCluster资源。
Microsoft.DocumentDB/mongoClusters/write 创建或更新指定 mongoCluster 资源的属性或标记。
Microsoft.DocumentDB/mongoClusters/delete 删除指定的 mongoCluster 资源。
Microsoft.DocumentDB/mongoClusters/PrivateEndpointConnectionsApproval/action 管理资源的专用终结点连接mongoCluster
Microsoft.DocumentDB/mongoClusters/listConnectionStrings/action 列出给定 mongoCluster 资源的连接字符串
Microsoft.DocumentDB/mongoClusters/firewallRules/read 读取防火墙规则或列出指定 mongoCluster 资源的所有防火墙规则。
Microsoft.DocumentDB/mongoClusters/firewallRules/write 在指定 mongoCluster 资源上创建或更新防火墙规则。
Microsoft.DocumentDB/mongoClusters/firewallRules/delete 删除指定 mongoCluster 资源的现有防火墙规则。
Microsoft.DocumentDB/mongoClusters/privateEndpointConnectionProxies/read 读取指定 mongoCluster 资源的专用终端连接代理。
Microsoft.DocumentDB/mongoClusters/privateEndpointConnectionProxies/write 在指定的 mongoCluster 资源上创建或更新专用终结点连接代理。
Microsoft.DocumentDB/mongoClusters/privateEndpointConnectionProxies/delete 删除指定 mongoCluster 资源的现有专用终结点连接代理。
Microsoft.DocumentDB/mongoClusters/privateEndpointConnectionProxies/validate/action 验证指定 mongoCluster 资源的专用终结点连接代理。
Microsoft.DocumentDB/mongoClusters/privateEndpointConnections/read 读取专用终结点连接或列出指定 mongoCluster 资源的所有专用终结点连接。
Microsoft.DocumentDB/mongoClusters/privateEndpointConnections/write 在指定 mongoCluster 资源上创建或更新专用终结点连接。
Microsoft.DocumentDB/mongoClusters/privateEndpointConnections/delete 删除指定 mongoCluster 资源的现有专用终结点连接。
Microsoft.DocumentDB/mongoClusters/privateLinkResources/read 读取 Private Link 资源或列出指定 mongoCluster 资源的所有 Private Link 资源。
Microsoft.DocumentDB/mongoClusters/users/read 读取用户或列出指定 mongoCluster 资源的所有用户。
Microsoft.DocumentDB/mongoClusters/users/write 在指定 mongoCluster 资源上创建或更新用户。
Microsoft.DocumentDB/mongoClusters/users/delete 删除指定 mongoCluster 资源的现有用户。
  1. 打开新的终端。

  2. 登录到Azure CLI。

  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 DocumentDB RBAC Owner",
      "IsCustom": true,
      "Description": "Can perform all Azure role-based access control actions for Azure DocumentDB clusters.",
      "Actions": [
        "Microsoft.DocumentDb/mongoClusters/*"
      ],
      "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 Azure role-based access control actions for Azure DocumentDB clusters.",
      "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 DocumentDB RBAC Owner",
      "roleType": "CustomRole"
    }
    

    注释

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

  1. 打开新的终端。

  2. 登录到Azure CLI。

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

    Description
    Microsoft.DocumentDb/mongoClusters/* 启用所有可能的作。
    metadata description = 'Create RBAC definition for Azure role-based access control access to Azure DocumentDB.'
    
    @description('Name of the role definition.')
    param roleDefinitionName string = 'Azure DocumentDB RBAC Owner'
    
    @description('Description of the role definition.')
    param roleDefinitionDescription string = 'Can perform all Azure role-based access control actions for Azure DocumentDB clusters.'
    
    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/mongoClusters/*'
            ]
          }
        ]
        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 Azure role-based access control access to Azure DocumentDB.'
    
    @description('Id of the role definition to assign to the targeted principal in the context of the cluster.')
    param roleDefinitionId string
    
    @description('Id of the identity/principal to assign this role in the context of the cluster.')
    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
    
  1. 登录到 Azure portal (https://portal.azure.cn)。

  2. 在global search栏中输入 Resource group

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

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

  5. 在资源组的窗格中,在服务菜单中选择Access control (IAM)

  6. Access control (IAM) 窗格中,选择 Add。 然后选择 “添加自定义角色”。

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

    价值
    自定义角色名称 Azure DocumentDB RBAC Owner
    说明 Can perform all Azure role-based access control actions for Azure DocumentDB clusters.
    基线权限 从头开始
  8. 在“ 权限 ”窗格中,选择“ 添加权限”。 然后,在权限对话框中搜索 DocumentDB 。 最后,选择 Microsoft.DocumentDB/mongoClusters 选项。

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

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

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

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

  13. Access control (IAM) 窗格中,选择 Add,然后选择 Add 角色分配

  14. Role 窗格中,搜索 Azure DocumentDB,然后选择本指南前面创建的 Azure DocumentDB RBAC 所有者角色。 然后选择下一步

    小窍门

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

  15. 在“ 成员 ”窗格中,选择“ 选择成员 ”选项。 在成员对话框中,选择要为 Azure DocumentDB 群集授予此级别access的标识,然后使用 Select 选项确认选择。

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

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

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

  1. 打开新的终端。

  2. 登录到Azure CLI。

  3. 检查目标Azure订阅。

    az account show
    
  4. 创建新的 Terraform 文件以定义角色定义。 将文件 control-plane-role-definition 命名。tf 将以下项 actions 添加到定义:

    Description
    Microsoft.DocumentDb/mongoClusters/* 启用所有可能的作。
    variable "role_definition_name" {
      type        = string
      description = "Name of the role definition."
      default     = "Azure DocumentDB RBAC Owner"
    }
    
    variable "role_definition_description" {
      type        = string
      description = "Description of the role definition."
      default     = "Can perform all Azure role-based access control actions for Azure DocumentDB clusters."
    }
    
    terraform {
      required_providers {
        azurerm = {
          source  = "hashicorp/azurerm"
          version = "~> 4.0"
        }
      }
    }
    
    provider "azurerm" {
      features {}
    }
    
    data "azurerm_client_config" "current" {}
    
    data "azurerm_resource_group" "existing" {
      name = "<name-of-existing-resource-group>"
    }
    
    resource "azurerm_role_definition" "control_plane" {
      name               = var.role_definition_name
      scope              = data.azurerm_resource_group.existing.id
      description        = var.role_definition_description
    
      permissions {
        actions = [
          "Microsoft.DocumentDb/mongoClusters/*"
        ]
      }
    
      assignable_scopes = [
        data.azurerm_resource_group.existing.id
      ]
    }
    
    output "definition_id" {
      value = azurerm_role_definition.control_plane.id
    }
    
  5. 初始化 Terraform 部署。

    terraform init --upgrade
    
  6. 为角色定义创建执行计划,并将其保存到名为 role-definition.tfplan 的文件。

    ARM_SUBSCRIPTION_ID=$(az account show --query id --output tsv) terraform plan --out "role-definition.tfplan"
    
  7. 应用执行计划将角色定义部署到Azure。

    ARM_SUBSCRIPTION_ID=$(az account show --query id --output tsv) terraform apply "role-definition.tfplan"
    
  8. 查看部署的输出。 输出包含属性中 definition_id 角色定义的唯一标识符。 记下此值,因为本指南后面的工作分配步骤需要使用此值。

  9. 创建新的 Terraform 文件以定义角色分配。 将文件 control-plane-role-assignment 命名。tf

    variable "role_definition_id" {
      type        = string
      description = "Id of the role definition to assign to the targeted principal in the context of the cluster."
    }
    
    variable "identity_id" {
      type        = string
      description = "Id of the identity/principal to assign this role in the context of the cluster."
    }
    
    terraform {
      required_providers {
        azurerm = {
          source  = "hashicorp/azurerm"
          version = "~> 4.0"
        }
      }
    }
    
    provider "azurerm" {
      features {}
    }
    
    data "azurerm_resource_group" "existing" {
      name = "<name-of-existing-resource-group>"
    }
    
    resource "azurerm_role_assignment" "control_plane" {
      scope              = data.azurerm_resource_group.existing.id
      role_definition_id = var.role_definition_id
      principal_id       = var.identity_id
    }
    
  10. 创建名为 control-plane-role-assignment.tfvars 的新 Terraform 变量文件。 在此变量文件中;将以前记录的角色定义标识符分配给 role_definition_id 变量,并将标识的唯一标识符分配给 identity_id 变量。

    role_definition_id = "<id-of-new-role-definition>"
    identity_id        = "<id-of-existing-identity>"
    
  11. 初始化并应用此 Terraform 配置。

    terraform init --upgrade
    
    ARM_SUBSCRIPTION_ID=$(az account show --query id --output tsv) terraform plan --var-file="control-plane-role-assignment.tfvars" --out "role-assignment.tfplan"
    
    ARM_SUBSCRIPTION_ID=$(az account show --query id --output tsv) terraform apply "role-assignment.tfplan"
    

启用Microsoft Entra ID身份验证

创建 Azure DocumentDB 群集时,群集配置为默认仅使用本机身份验证。 若要使用Microsoft Entra ID启用身份验证,请启用Microsoft Entra ID身份验证方法,并将Microsoft Entra ID标识添加到群集。

  1. 使用 az ad signed-in-user 获取当前登录帐户的详细信息。

    az ad signed-in-user show
    
  2. 该命令将输出包含各种字段的 JSON 响应。

    {
      "@odata.context": "<https://microsoftgraph.chinacloudapi.cn/v1.0/$metadata#users/$entity>",
      "businessPhones": [],
      "displayName": "Kai Carter",
      "givenName": "Kai",
      "id": "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb",
      "jobTitle": "Senior Sales Representative",
      "mail": "<kai@adventure-works.com>",
      "mobilePhone": null,
      "officeLocation": "Redmond",
      "preferredLanguage": null,
      "surname": "Carter",
      "userPrincipalName": "<kai@adventure-works.com>"
    }
    

    小窍门

    记录id字段的值。 在此示例中,该值为 aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb. 然后,可以在各种脚本中使用该值来授予当前帐户对 Azure 资源的基于角色的访问控制权限。 如果改用托管标识,可以使用 id 命令获取该托管标识的 az identity show

  3. 通过将群集资源更新为在 MicrosoftEntraID 数组中包含 authConfig.allowedModes,在群集上启用Microsoft Entra ID身份验证:

    az resource patch \
        --resource-group "<resource-group>" \
        --name "<cluster-name>" \
        --resource-type "Microsoft.DocumentDB/mongoClusters" \
        --properties '{"authConfig":{"allowedModes":["MicrosoftEntraID","NativeAuth"]}}' \
        --latest-include-preview
    

    注释

    <resource-group><cluster-name> 替换为自定义值。

  4. 使用 authConfig 读取群集上的 az resource show 属性,验证是否已应用更改。

    az resource show \
        --resource-group "<resource-group>" \
        --name "<cluster-name>" \
        --resource-type "Microsoft.DocumentDB/mongoClusters" \
        --query "properties.authConfig" \
        --latest-include-preview
    

    注释

    输出应包含 allowedModes 列表。 如果成功启用Microsoft Entra ID,则数组包含 NativeAuthMicrosoftEntraID

  1. (可选)获取计划在群集上注册的 Microsoft Entra 主体的唯一标识符。 可以使用以下命令之一通过Azure CLI获取它:

    • 当前已登录身份

      az ad signed-in-user show      
      
    • 使用友好名称的另一个个人身份

      az ad user show \
        --id "<user-alias-and-domain>"
      
    • 服务主体使用应用程序标识符

      az ad sp show \
        --id "<application-id>"
      
    • 使用资源组和名称的托管标识

      az identity show \
        --resource-group "<resource-group>" \
        --name "<managed-identity-name>"      
      
  2. 创建一个小型 Bicep 模板,用于更新群集 authConfig以包含Microsoft Entra ID(另存为 enable-entra-id.bicep):

    param clusterName string
    param location string = resourceGroup().location
    
    resource cluster 'Microsoft.DocumentDB/mongoClusters@2025-09-01' = {
      name: clusterName
      location: location
      properties: {
        authConfig: {
          allowedModes: [
            'MicrosoftEntraID'
            'NativeAuth'
          ]
        }
      }
    }
    
  3. 部署模板以更新群集:

    az deployment group create \
        --resource-group "<resource-group>" \
        --template-file enable-entra-id.bicep \
        --parameters clusterName="<cluster-name>"
    
  4. 使用 az resource show 验证群集上的 authConfig 属性。

    az resource show \
        --resource-group "<resource-group>" \
        --name "<cluster-name>" \
        --resource-type "Microsoft.DocumentDB/mongoClusters" \
        --query "properties.authConfig" \
        --latest-include-preview
    

    注释

    输出应包含 allowedModes 列表。 如果成功启用Microsoft Entra ID,则数组包含 NativeAuthMicrosoftEntraID

  1. 在Azure portal的 Home 窗格中,找到并选择 Microsoft Entra ID 选项。

    Azure 门户“主页”中 Microsoft Entra ID 选项的屏幕截图。

    小窍门

    如果未列出此选项,请选择 更多服务,然后使用搜索词 “Entra” 搜索 Microsoft Entra ID

  2. 在Microsoft Entra ID租户的 Overview 窗格中,选择服务菜单 Manage 部分中的 Users

    Microsoft Entra ID 租户的服务菜单中“用户”选项的屏幕截图。

  3. 在用户列表中,选择您要获取更多信息的用户身份。

    Microsoft Entra ID 租户用户列表的屏幕截图,其中突出显示了一个示例用户。

    注释

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

  4. 在特定用户的详细信息窗格中,观察 对象 ID 属性的值。

    用户详细信息窗格的截图,其中“对象 ID”被突出显示。

    小窍门

    记录 对象 ID 属性的值。 在此示例中,该值为 aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb. 然后,可以在各种脚本中使用此值来授予当前帐户角色基于的访问控制对Azure资源的权限。 如果使用托管标识,则步骤类似。

  5. 导航到现有 Azure DocumentDB 群集资源。

  6. 在群集菜单中的 “设置”下,选择“ 身份验证”。

  7. 身份验证方法部分中,选择 Native DocumentDB 和 Microsoft Entra ID 以启用 Microsoft Entra ID 身份验证以及本机身份验证。

  8. 选择 “保存” 以保留更改。

  9. “身份验证方法”部分现在应同时将 NativeAuthMicrosoftEntraID 列为已启用的方法。

  1. (可选)获取计划在群集上注册的 Microsoft Entra 主体的唯一标识符。 可以使用以下命令之一通过Azure CLI获取它:

    • 当前已登录身份

      az ad signed-in-user show      
      
    • 使用友好名称的另一个个人身份

      az ad user show \
        --id "<user-alias-and-domain>"
      
    • 服务主体使用应用程序标识符

      az ad sp show \
        --id "<application-id>"
      
    • 使用资源组和名称的托管标识

      az identity show \
        --resource-group "<resource-group>" \
        --name "<managed-identity-name>"      
      
  2. 创建 Terraform 配置文件,以便在现有群集上启用Microsoft Entra ID身份验证。 将文件另存为 enable-entra-id.tf

    variable "cluster_name" {
      type        = string
      description = "Name of the existing cluster"
    }
    
    variable "resource_group_name" {
      type        = string
      description = "Name of the existing resource group"
    }
    
    terraform {
      required_providers {
        azurerm = {
          source  = "hashicorp/azurerm"
          version = "~> 4.0"
        }
      }
    }
    
    provider "azurerm" {
      features {}
    }
    
    data "azurerm_resource_group" "existing" {
      name = var.resource_group_name
    }
    
    data "azurerm_mongo_cluster" "existing" {
      name                = var.cluster_name
      resource_group_name = data.azurerm_resource_group.existing.name
    }
    
    resource "azurerm_mongo_cluster" "enable_entra" {
      name                   = data.azurerm_mongo_cluster.existing.name
      resource_group_name    = data.azurerm_resource_group.existing.name
      location               = data.azurerm_mongo_cluster.existing.location
      administrator_username = data.azurerm_mongo_cluster.existing.administrator_username
      administrator_password = data.azurerm_mongo_cluster.existing.administrator_password
      shard_count            = data.azurerm_mongo_cluster.existing.shard_count
      compute_tier           = data.azurerm_mongo_cluster.existing.compute_tier
      high_availability_mode = data.azurerm_mongo_cluster.existing.high_availability_mode
      storage_size_in_gb     = data.azurerm_mongo_cluster.existing.storage_size_in_gb
      version                = data.azurerm_mongo_cluster.existing.version
    
      # Enable both Microsoft Entra ID and Native authentication
      authentication_enabled = true
    }
    

    小窍门

    有关使用 azurerm_mongo_cluster 资源的选项的详细信息,请参阅 azurerm Terraform 注册表中的提供程序文档

  3. 使用群集详细信息创建名为 enable-entra-id.tfvars 的 变量文件:

    cluster_name        = "<cluster-name>"
    resource_group_name = "<resource-group>"
    
  4. 初始化并应用 Terraform 配置以启用Microsoft Entra ID身份验证:

    terraform init --upgrade
    
    ARM_SUBSCRIPTION_ID=$(az account show --query id --output tsv) terraform plan --var-file="enable-entra-id.tfvars" --out "enable-entra.tfplan"
    
    ARM_SUBSCRIPTION_ID=$(az account show --query id --output tsv) terraform apply "enable-entra.tfplan"
    
  5. 使用 az resource show 验证群集中的 authConfig 属性。

    az resource show \
        --resource-group "<resource-group>" \
        --name "<cluster-name>" \
        --resource-type "Microsoft.DocumentDB/mongoClusters" \
        --query "properties.authConfig" \
        --latest-include-preview
    

    注释

    输出应包含 allowedModes 列表。 如果成功启用Microsoft Entra ID,则数组包含 NativeAuthMicrosoftEntraID

管理 DocumentDB 管理、Microsoft Entra ID 标识和本机用户的行政操作

在 Azure DocumentDB 集群上启用 Microsoft Entra ID 身份验证时,可以将一个或多个 Microsoft Entra ID 主体添加为 administrator 用户。 Microsoft Entra ID管理员可以是Microsoft Entra ID用户、服务主体或托管标识。 可以随时配置多个Microsoft Entra ID管理员。

管理 Entra ID 用户作为 Microsoft.DocumentDB/mongoClusters/users 下的 Azure 实体对象创建,并将其复制到数据库中。

此外,在启用身份验证Microsoft Entra ID后,可以随时将一个或多个非管理Microsoft Entra ID用户添加到群集。 非管理员用户通常用于不需要管理权限的持续生产任务。

对于 Azure DocumentDB,这种访问权限通过在群集上注册 Microsoft Entra 主体,并将其映射到 MongoDB 数据库角色(例如,数据库上的 readWriteroot 数据库中的 admin)来授予。 注册的主体被创建为类型为 Microsoft.DocumentDB/mongoClusters/users 的 Azure 资源,其名称采用 <cluster-name>/users/<principal-id> 格式。

管理用户具有管理群集及其数据的完整权限,包括完整的用户管理功能。 对于非管理员用户,可以通过特定的 MongoDB 数据库角色授予读写或只读权限。 readWriteAnyDatabaseclusterAdmin 角色共同授予对群集的完整读写权限,包括数据库管理和数据库作的权限。 readAnyDatabase 角色用于授予对群集的只读权限。 不能单独分配 readWriteAnyDatabaseclusterAdmin 角色 - 必须一起授予它们才能进行完整读写访问。

非管理员(辅助)用户和安全主体在群集上被授予有限的用户管理权限,如下表所述:

安全提供程序 角色 创建用户 (CreateUser) DeleteUser UpdateUser 列出用户
Microsoft Entra ID 读写(readWriteAnyDatabase, clusterAdmin) ✔️
Microsoft Entra ID 只读(readAnyDatabase) ✔️
原生 DocumentDB 读写(readWriteAnyDatabase, clusterAdmin) 仅更改自己的密码 ✔️
原生 DocumentDB 只读(readAnyDatabase) 仅更改自己的密码 ✔️
  1. 获取要授予访问权限的 Microsoft Entra 实体的唯一标识符(对象 ID),可以使用以下命令之一:

    • 当前已登录身份

      az ad signed-in-user show      
      
    • 使用友好名称的另一个个人身份

      az ad user show \
        --id "<user-alias-and-domain>"
      
    • 服务主体使用应用程序标识符

      az ad sp show \
        --id "<application-id>"
      
    • 使用资源组和名称的托管标识

      az identity show \
        --resource-group "<resource-group>" \
        --name "<managed-identity-name>"      
      
  2. 在群集上注册主体对象,并将其映射到 MongoDB 数据库角色。 以下示例将主体注册为 readWrite 数据库中的 sales 用户:

    az resource create \
        --resource-group "<resource-group>" \
        --name "<cluster-name>/users/<principal-id>" \
        --resource-type "Microsoft.DocumentDB/mongoClusters/users" \
        --location "<cluster-region>" \
        --properties '{"identityProvider":{"type":"MicrosoftEntraID","properties":{"principalType":"User"}},"roles":[{"db":"sales","role":"readWrite"}]}' \
        --latest-include-preview
    
    • principalType替换为应用/服务主体的servicePrincipal或托管标识的ManagedIdentity
    • 若要授予管理权限,请在 {"db":"admin","role":"root"} 数组中使用 roles
  3. 列出所有已注册主体及其映射角色(群集级别视图):

    az rest \
        --method "GET" \
        --url "https://management.chinacloudapi.cn/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.DocumentDB/mongoClusters/<cluster-name>/users?api-version=2025-09-01"
    
    • 响应包含一组用户资源,每个资源都有 identityProvider 元数据和一个 roles 显示映射的数据库角色的数组。
  4. 获取特定注册主体的详细信息(替换 <principal-id>):

    az resource show \
        --resource-group "<resource-group>" \
        --name "<cluster-name>/users/<principal-id>" \
        --resource-type "Microsoft.DocumentDB/mongoClusters/users" \
        --latest-include-preview
    
  5. 删除已注册的主体(撤销数据平面访问权限):

    az resource delete \
        --resource-group "<resource-group>" \
        --name "<cluster-name>/users/<principal-id>" \
        --resource-type "Microsoft.DocumentDB/mongoClusters/users" \
        --latest-include-preview
    
  1. 创建 Bicep 文件(例如 register-principal.bicep),注册主体和映射数据库角色:

    param clusterName string
    param principalId string
    param location string = resourceGroup().location
    param principalType string = 'User'
    param roles array = [
      {
        db: 'sales'
        role: 'readWrite'
      }
    ]
    
    resource user 'Microsoft.DocumentDB/mongoClusters/users@2025-09-01' = {
      name: '${clusterName}/users/${principalId}'
      location: location
      properties: {
        identityProvider: {
          type: 'Microsoft.EntraID'
          properties: {
            principalType: principalType
          }
        }
        roles: roles
      }
    }
    
  2. 部署 Bicep 模板以注册主体:

    az deployment group create \
        --resource-group "<resource-group>" \
        --template-file register-principal.bicep \
        --parameters clusterName="<cluster-name>" principalId="<principal-id>"
    
  3. 使用 REST API 列出群集的所有已注册主体(在 Bicep 部署后很有用):

    az rest \
        --method GET \
        --url "https://management.chinacloudapi.cn/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.DocumentDB/mongoClusters/<cluster-name>/users?api-version=2025-09-01"
    
  4. 获取 Bicep 创建的特定注册主体的详细信息(替换 <principal-id>):

    az resource show \
        --resource-group "<resource-group>" \
        --name "<cluster-name>/users/<principal-id>" \
        --resource-type "Microsoft.DocumentDB/mongoClusters/users" \
        --latest-include-preview
    
  5. 通过删除资源(或部署没有用户资源的模板)删除主体:

    az resource delete \
        --resource-group "<resource-group>" \
        --name "<cluster-name>/users/<principal-id>" \
        --resource-type "Microsoft.DocumentDB/mongoClusters/users" \
        --latest-include-preview
    
  1. 在Azure portal中打开目标Azure DocumentDB 群集。

  2. 在“设置”下选择“身份验证”

  3. Microsoft Entra ID身份验证部分中,门户按对象 ID 列出已注册的Microsoft Entra 主体。 使用此视图可以:

    • 扫描列表以查找预期的对象标识符。
    • 通过选择列出的条目(或使用门户的搜索功能)检查单个主体的详细信息。
    • 使用条目旁边的Remove以立即撤销该主体的数据平面访问。
  4. 若要获取门户列表中显示的对象标识符的友好名称,请使用 Microsoft Entra ID 节中的 Users 页。 然后,按对象 ID 或友好名称进行搜索。

  1. 获取要授予访问权限的 Microsoft Entra 实体的唯一标识符(对象 ID),可以使用以下命令之一:

    • 当前已登录身份

      az ad signed-in-user show      
      
    • 使用友好名称的另一个个人身份

      az ad user show \
        --id "<user-alias-and-domain>"
      
    • 服务主体使用应用程序标识符

      az ad sp show \
        --id "<application-id>"
      
    • 使用资源组和名称的托管标识

      az identity show \
        --resource-group "<resource-group>" \
        --name "<managed-identity-name>"      
      
  2. 创建 Terraform 文件(例如 register-principal.tf),以使用 AzAPI 提供程序来注册主体并映射数据库角色:

    variable "cluster_name" {
      type        = string
      description = "Name of the existing cluster"
    }
    
    variable "resource_group_name" {
      type        = string
      description = "Name of the existing resource group"
    }
    
    variable "principal_id" {
      type        = string
      description = "Object ID of the Microsoft Entra principal"
    }
    
    variable "principal_type" {
      type        = string
      description = "Type of principal: User, ServicePrincipal, or ManagedIdentity"
      default     = "User"
    }
    
    variable "roles" {
      type = list(object({
        db   = string
        role = string
      }))
      description = "Database roles to assign"
      default = [
        {
          db   = "sales"
          role = "readWrite"
        }
      ]
    }
    
    terraform {
      required_providers {
        azapi = {
          source  = "azure/azapi"
          version = "~> 2.0"
        }
        azurerm = {
          source  = "hashicorp/azurerm"
          version = "~> 4.0"
        }
      }
    }
    
    provider "azurerm" {
      features {}
    }
    
    provider "azapi" {}
    
    data "azurerm_resource_group" "existing" {
      name = var.resource_group_name
    }
    
    data "azurerm_mongo_cluster" "existing" {
      name                = var.cluster_name
      resource_group_name = var.resource_group_name
    }
    
    resource "azapi_resource" "mongo_cluster_user" {
      type      = "Microsoft.DocumentDB/mongoClusters/users@2025-09-01"
      name      = var.principal_id
      parent_id = data.azurerm_mongo_cluster.existing.id
      location  = data.azurerm_resource_group.existing.location
    
      body = {
        properties = {
          identityProvider = {
            type = "MicrosoftEntraID"
            properties = {
              principalType = var.principal_type
            }
          }
          roles = var.roles
        }
      }
    }
    

    小窍门

    有关 AzAPI 提供程序的详细信息,请参阅 Azure AzAPI 提供程序文档

    • principalType替换为应用/服务主体的servicePrincipal或托管标识的ManagedIdentity
    • 若要授予管理权限,请在 {"db":"admin","role":"root"} 数组中使用 roles
  3. 创建名为 : 的 register-principal.tfvars变量文件:

    cluster_name        = "<cluster-name>"
    resource_group_name = "<resource-group>"
    principal_id        = "<principal-id>"
    principal_type      = "User"
    roles = [
      {
        db   = "sales"
        role = "readWrite"
      }
    ]
    
  4. 初始化并应用 Terraform 配置以注册主体:

    terraform init --upgrade
    
    ARM_SUBSCRIPTION_ID=$(az account show --query id --output tsv) terraform plan --var-file="register-principal.tfvars" --out "register-principal.tfplan"
    
    ARM_SUBSCRIPTION_ID=$(az account show --query id --output tsv) terraform apply "register-principal.tfplan"
    
  5. 使用 REST API 列出群集的所有已注册主体(在 Terraform 部署后很有用):

    az rest \
        --method GET \
        --url "https://management.chinacloudapi.cn/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.DocumentDB/mongoClusters/<cluster-name>/users?api-version=2025-09-01"
    
  6. 获取由 Terraform 创建的特定注册主体的详细信息(替换 <principal-id>):

    az resource show \
        --resource-group "<resource-group>" \
        --name "<cluster-name>/users/<principal-id>" \
        --resource-type "Microsoft.DocumentDB/mongoClusters/users" \
        --latest-include-preview
    
  7. 通过销毁 Terraform 资源删除主体:

    ARM_SUBSCRIPTION_ID=$(az account show --query id --output tsv) terraform destroy --var-file="register-principal.tfvars"
    

注释

Azure DocumentDB 群集是使用一个内置管理本机 DocumentDB 用户创建的。 完成群集预配后,可以 添加更多本机管理 DocumentDB 用户 。 Microsoft Entra ID 管理用户将被添加到群集,并与在同一群集上已定义的本机管理 DocumentDB 用户共存。 所有管理的 Microsoft Entra ID 身份都复制到数据库。

在数据库中创建非管理的Microsoft Entra ID标识。 列出数据库中的非管理员用户时,该列表包含所有管理员和非管理员 Microsoft Entra ID 标识以及所有次级(非管理员)原生 DocumentDB 用户。

获取群集凭据

可以使用首选语言的驱动程序中的连接 URI 或自定义设置对象连接到群集。 在任一选项中,必须将 方案 设置为 mongodb+srv 连接到群集。 host位于 *.global.mongocluster.cosmos.azure.cn*.mongocluster.cosmos.azure.cn 域,具体取决于你使用的是 当前群集还是全局读写终结点+srv 方案和 *.global.* 主机可确保客户端在多群集配置中动态连接到适当的可写群集,即使发生区域交换操作,也是如此。 在单群集配置中,可以不分青红皂白地使用connection string。

还必须启用 tls 设置。 其余建议的设置是最佳实践配置。

选项 价值
scheme mongodb+srv
host <cluster-name>.global.mongocluster.cosmos.azure.cn<cluster-name>.mongocluster.cosmos.azure.cn
tls true
authMechanism MONGODB-OIDC
retrywrites false
maxIdleTimeMS 120000

重要

使用 Azure portal 获取连接字符串。

  1. 导航到 Azure DocumentDB 群集。

  2. 选择 连接字符串 导航菜单选项。

  3. Connection string 字段中复制或记录值。

    小窍门

    Microsoft Entra ID连接字符串位于 Microsoft Entra ID 节中。

在 Visual Studio Code 中使用Microsoft Entra ID进行连接

将 Visual Studio Code 与 DocumentDB 扩展配合使用,以使用Microsoft Entra ID标识连接到 Azure DocumentDB 群集。

重要

在具有 DocumentDB 扩展的 Visual Studio Code 中使用 Microsoft Entra ID 对 Azure DocumentDB 群集进行身份验证时,不支持 shell 功能。 如果需要将 MongoDB shell 用于Microsoft Entra ID身份验证,请直接在客户端计算机上使用 MongoDB Shell

  1. 打开Visual Studio代码。

  2. 在侧栏中浏览DocumentDB扩展。

  3. 在“ 连接 ”部分中,选择“ + 新建连接...”

  4. 在连接类型对话框中,选择Connection String

  5. 使用以下连接字符串:

    mongodb+srv://<client-id>@<cluster-name>.global.mongocluster.cosmos.azure.cn/?tls=true&authMechanism=MONGODB-OIDC&retrywrites=false&maxIdleTimeMS=120000
    
  6. 等待自动提示使用Microsoft Entra ID身份验证。 输入您身份类型的相关凭据。

    注释

    例如,如果要使用自己的标识(人工标识)登录,请使用无密码身份验证体验。

  7. 等待连接完成。 然后将新的 DocumentDB 条目添加到群集的 “连接” 部分。

在 MongoDB Compass 或 MongoDB Shell 中使用Microsoft Entra ID进行连接

使用 Microsoft Entra ID 身份,通过MongoDB Compass 应用程序直接连接到 Azure DocumentDB 群集。

  1. 通过创建Azure计算资源(例如Azure虚拟机)来设置用于连接到 Azure DocumentDB 群集的执行环境。

  2. 创建系统分配的托管标识或 用户分配的托管标识,并将其与虚拟机相关联。

    在 Azure 门户上分配托管标识的屏幕截图。

  3. 在 Azure DocumentDB 群集中注册托管标识。

    用于在 Azure 文档数据库集群中注册托管标识的截图。

  4. 在终端中启动 MongoDB Compass 应用程序或 Mongo shell

  5. 在 MongoDB 指南针中,在+菜单中选择以添加新连接。 在使用 shell 时,获取你的 Azure DocumentDB 群集的 名称和目标标识的 客户端 ID

    截图用于查看从 Azure DocumentDB 门户中构造 Entra 连接字符串所需的客户端 ID。

  6. URI 输入框中输入以下凭据。

    mongodb+srv://<client-id>@<cluster-name>.global.mongocluster.cosmos.azure.cn/?tls=true&authMechanism=MONGODB-OIDC&retrywrites=false&maxIdleTimeMS=120000&authMechanismProperties=ENVIRONMENT:azure,TOKEN_RESOURCE:https://ossrdbms-aad.database.chinacloudapi.cn
    
  7. 打开 “高级连接选项 ”对话框。

  8. General 节中,为 Connection String Scheme 选择 mongodb+srv

  9. 导航到 “身份验证 ”部分,确保已选择 “OIDC ”选项。

  10. 导航到“OIDC 选项”部分,并确保还选择了“考虑目标终结点可信”选项。

  11. 选择“ 保存并连接”。

管理 DocumentDB 辅助(非管理员)Microsoft Entra ID标识

使用管理员权限的 Microsoft Entra ID 标识登录到群集,从事对非管理员 Microsoft Entra ID 标识的管理操作。

注释

支持 securityPrincipaluser 主体类型的所有非管理用户管理命令。

非管理员用户未在Azure portal中注册。

  1. 使用管理Microsoft Entra ID标识并使用 MongoDB Shell 等工具登录到群集。

  2. 使用 命令在群集上添加具有 createUser 权限的非管理员Microsoft Entra ID标识:

    db.runCommand(
      {
        createUser: "<entra-id-unique-identifier>",
        roles: [
          { role: "clusterAdmin", db: "admin" },
          { role: "readWriteAnyDatabase", db: "admin" }
        ],
        customData: { "IdentityProvider": { "type": "MicrosoftEntraID", "properties": { "principalType": "user" } } }
      }
    )
    
  3. 在群集上使用 只读权限添加非管理员身份的 Microsoft Entra ID,并设置一组不同的角色。

    db.runCommand(
      {
        createUser: "<entra-id-unique-identifier>",
        roles: [
          { role: "readAnyDatabase", db: "admin" }
        ],
        customData: { "IdentityProvider": { "type": "MicrosoftEntraID", "properties": { "principalType": "user" } } }
      }
    )
    
  4. 使用 dropUser 命令从群集中删除非管理Microsoft Entra ID标识。

    db.runCommand(
      {
        dropUser: "<entra-id-unique-identifier>"
      }
    )
    
  5. 使用 userInfo 列出群集上的所有 Microsoft Entra ID 和本机 DocumentDB 用户。

    db.runCommand(
      {
        usersInfo: 1
      }
    )
    

    注释

    所有 Microsoft Entra 身份标识和本机 DocumentDB 管理用户都被复制到数据库中。 由于此复制,用户列表包括群集上的所有管理和非管理 Microsoft Entra ID 用户,以及本机 DocumentDB 用户。

在代码中使用Microsoft Entra ID进行连接

验证您是否已通过应用程序代码和所选语言的相应客户端库正确授予访问权限。

class AzureIdentityTokenCallback(OIDCCallback):
    def __init__(self, credential):
        self.credential = credential

    def fetch(self, context: OIDCCallbackContext) -> OIDCCallbackResult:
        token = self.credential.get_token(
            "https://ossrdbms-aad.database.chinacloudapi.cn/.default").token
        return OIDCCallbackResult(access_token=token)

clusterName = "<cluster-name>"

credential = DefaultAzureCredential()
authProperties = {"OIDC_CALLBACK": AzureIdentityTokenCallback(credential)}

client = MongoClient(
  f"mongodb+srv://{clusterName}.global.mongocluster.cosmos.azure.cn/",
  connectTimeoutMS=120000,
  tls=True,
  retryWrites=True,
  authMechanism="MONGODB-OIDC",
  authMechanismProperties=authProperties
)
const AzureIdentityTokenCallback = async (params: OIDCCallbackParams, credential: TokenCredential): Promise<OIDCResponse> => {
  const tokenResponse: AccessToken | null = await credential.getToken(['https://ossrdbms-aad.database.chinacloudapi.cn/.default']);
  return {
      accessToken: tokenResponse?.token || '',
      expiresInSeconds: (tokenResponse?.expiresOnTimestamp || 0) - Math.floor(Date.now() / 1000)
  };
};

const clusterName: string = '<cluster-name>';

const credential: TokenCredential = new DefaultAzureCredential();

const client = new MongoClient(
    `mongodb+srv://${clusterName}.global.mongocluster.cosmos.azure.cn/`, {
    connectTimeoutMS: 120000,
    tls: true,
    retryWrites: true,
    authMechanism: 'MONGODB-OIDC',
    authMechanismProperties: {
        OIDC_CALLBACK: (params: OIDCCallbackParams) => AzureIdentityTokenCallback(params, credential),
        ALLOWED_HOSTS: ['*.azure.cn']
    }
  }
);
string tenantId = "<microsoft-entra-tenant-id>";
string clusterName = "<cluster-name>";

DefaultAzureCredential credential = new();
AzureIdentityTokenHandler tokenHandler = new(credential, tenantId);

MongoUrl url = MongoUrl.Create($"mongodb+srv://{clusterName}.global.mongocluster.cosmos.azure.cn/");
MongoClientSettings settings = MongoClientSettings.FromUrl(url);
settings.UseTls = true;
settings.RetryWrites = false;
settings.MaxConnectionIdleTime = TimeSpan.FromMinutes(2);
settings.Credential = MongoCredential.CreateOidcCredential(tokenHandler);
settings.Freeze();

MongoClient client = new(settings);

internal sealed class AzureIdentityTokenHandler(
    TokenCredential credential,
    string tenantId
) : IOidcCallback
{
    private readonly string[] scopes = ["https://ossrdbms-aad.database.chinacloudapi.cn/.default"];

    public OidcAccessToken GetOidcAccessToken(OidcCallbackParameters parameters, CancellationToken cancellationToken)
    {
        AccessToken token = credential.GetToken(
            new TokenRequestContext(scopes, tenantId: tenantId),
            cancellationToken
        );

        return new OidcAccessToken(token.Token, token.ExpiresOn - DateTimeOffset.UtcNow);
    }

    public async Task<OidcAccessToken> GetOidcAccessTokenAsync(OidcCallbackParameters parameters, CancellationToken cancellationToken)
    {
        AccessToken token = await credential.GetTokenAsync(
            new TokenRequestContext(scopes, parentRequestId: null, tenantId: tenantId),
            cancellationToken
        );

        return new OidcAccessToken(token.Token, token.ExpiresOn - DateTimeOffset.UtcNow);
    }
}