迁移应用程序以将无密码连接用于 Azure Cosmos DB for NoSQL
必须对 Azure Cosmos DB for NoSQL 的应用程序请求进行身份验证。 尽管有多个选项可用于对 Azure Cosmos DB 进行身份验证,但应尽可能优先考虑应用程序中的无密码连接。 使用连接字符串(包含密码或密钥)的传统身份验证方法会产生安全风险和复杂性。 访问 Azure 服务中心的无密码连接,详细了解迁移到无密码连接的优势。
以下教程说明了如何迁移现有应用程序,以使用无密码连接(而不是基于密钥的解决方案)来连接到 Azure Cosmos DB for NoSQL。
使用无密码身份验证进行本地开发时,请确保为连接到 COSMOS DB 的用户帐户分配的角色有权执行数据操作。 目前,Azure Cosmos DB for NoSQL 不包括用于数据操作的内置角色,但你可以使用 Azure CLI 或 PowerShell 创建自己的角色。
角色包含一组权限或是允许用户执行的一组操作(如读取、写入和删除)。
创建自定义角色
使用 az role definition create
命令创建角色。 传入 Cosmos DB 帐户名和资源组,然后是用于定义自定义角色的 JSON 主体。 以下示例创建一个名为 PasswordlessReadWrite
的角色,该角色具有在 Cosmos DB 容器中读取和写入项的权限。 使用 /
将角色的范围限定为帐户级别。
az cosmosdb sql role definition create \
--account-name <cosmosdb-account-name> \
--resource-group <resource-group-name> \
--body '{
"RoleName": "PasswordlessReadWrite",
"Type": "CustomRole",
"AssignableScopes": ["/"],
"Permissions": [{
"DataActions": [
"Microsoft.DocumentDB/databaseAccounts/readMetadata",
"Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*",
"Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*"
]
}]
}'
命令完成后,从 name
字段中复制 ID 值,并将其粘贴到某个位置供以后使用。
将创建的角色分配给将连接到 Cosmos DB 的用户帐户或服务主体。 在本地开发期间,这通常是登录到开发工具(例如 Visual Studio 或 Azure CLI)的自身帐户。 使用 az ad user
命令检索帐户的详细信息。
az ad user show --id "<your-email-address>"
从结果中复制 id
属性的值,并将其粘贴到某个位置以供以后使用。
使用 az cosmosdb sql role assignment create
命令和先前复制的 ID 将创建的自定义角色分配给用户帐户。
az cosmosdb sql role assignment create \
--account-name <cosmosdb-account-name> \
--resource-group <resource-group-name> \
--scope "/" \
--principal-id <your-user-id> \
--role-definition-id <your-custom-role-id>
在本地登录到 Azure
对于本地开发,请确保使用分配了该角色的同一 Microsoft Entra 帐户进行身份验证。 可以通过常用的开发工具(如 Azure CLI 或 Azure PowerShell)进行身份验证。 可用于进行身份验证的开发工具因语言而异。
使用以下命令通过 Azure CLI 登录到 Azure:
az login
选择 Visual Studio 右上角的“登录”按钮。
使用你之前为其分配角色的 Microsoft Entra 帐户登录。
需要安装 Azure CLI 才能通过 Visual Studio Code 使用 DefaultAzureCredential
。
在 Visual Studio Code 的主菜单上,导航到“终端”>“新建终端”。
使用以下命令通过 Azure CLI 登录到 Azure:
az cloud set -n AzureChinaCloud
az login
通过以下命令使用 PowerShell 登录到 Azure:
Connect-AzAccount -Environment AzureChinaCloud
迁移应用代码以使用无密码连接
若要在 .NET 应用程序中使用 DefaultAzureCredential
,请安装 Azure.Identity
包:
dotnet add package Azure.Identity
在文件的顶部,添加以下代码:
using Azure.Identity;
确定代码中创建 CosmosClient
对象以连接到 Azure Cosmos DB 的位置。 更新代码,使之与以下示例一致。
DefaultAzureCredential credential = new();
using CosmosClient client = new(
accountEndpoint: Environment.GetEnvironmentVariable("COSMOS_ENDPOINT"),
tokenCredential: credential
);
若要在 Go 应用程序中使用 DefaultAzureCredential
,请安装 azidentity
模块:
go get -u github.com/Azure/azure-sdk-for-go/sdk/azidentity
在文件的顶部,添加以下代码:
import (
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
)
确定代码中创建 Client
实例以连接到 Azure Cosmos DB 的位置。 更新代码,使之与以下示例一致:
cred, err := azidentity.NewDefaultAzureCredential(nil)
if err != nil {
// handle error
}
endpoint := os.Getenv("COSMOS_ENDPOINT")
client, err := azblob.NewClient(endpoint, cred, nil)
if err != nil {
// handle error
}
若要在 Java 应用程序中使用 DefaultAzureCredential
,请通过以下方法之一安装 azure-identity
包:
- 包括 BOM 文件。
- 包括直接依赖项。
在文件的顶部,添加以下代码:
import com.azure.identity.DefaultAzureCredentialBuilder;
确定代码中创建 CosmosClient
或 CosmosAsyncClient
对象以连接到 Azure Cosmos DB 的位置。 更新代码,使之与以下示例一致:
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder()
.build();
String endpoint = System.getenv("COSMOS_ENDPOINT");
CosmosClient client = new CosmosClientBuilder()
.endpoint(endpoint)
.credential(credential)
.consistencyLevel(ConsistencyLevel.EVENTUAL)
.buildClient();
若要在 Node.js 应用程序中使用 DefaultAzureCredential
,请安装 @azure/identity
包:
npm install --save @azure/identity
在文件的顶部,添加以下代码:
import { DefaultAzureCredential } from "@azure/identity";
确定代码中创建 CosmosClient
对象以连接到 Azure Cosmos DB 的位置。 更新代码,使之与以下示例一致:
const credential = new DefaultAzureCredential();
const endpoint = process.env.COSMOS_ENDPOINT;
const cosmosClient = new CosmosClient({
endpoint,
aadCredentials: credential
});
若要在 Python 应用程序中使用 DefaultAzureCredential
,请安装 azure-identity
包:
pip install azure-identity
在文件的顶部,添加以下代码:
from azure.identity import DefaultAzureCredential
确定代码中创建 BlobServiceClient
对象以连接到 Azure Blob 存储的位置。 更新代码,使之与以下示例一致:
credential = DefaultAzureCredential()
endpoint = os.environ["COSMOS_ENDPOINT"]
client = CosmosClient(
url = endpoint,
credential = credential
)
在本地运行应用
进行这些代码更改后,在本地运行应用程序。 新配置应选取本地凭据,例如 Azure CLI、Visual Studio 或 IntelliJ。 你在 Azure 中分配给本地开发用户的角色将允许应用在本地连接到 Azure 服务。
将应用程序配置为使用无密码连接并在本地运行后,相同的代码可以在应用程序部署到 Azure 后向 Azure 服务进行身份验证。 以下各部分介绍了如何配置已部署的应用程序,以使用托管标识连接到 Azure Cosmos DB。
创建托管标识
你可以使用 Azure 门户或 Azure CLI 创建用户分配的托管标识。 应用程序将使用该标识向其他服务进行身份验证。
- 在 Azure 门户顶部搜索“托管标识”。 选择“托管标识”结果。
- 选择“托管标识”概述页面顶部的“+ 创建”。
- 在“基本信息”选项卡中,输入以下值:
- “订阅”:选择所需的订阅。
- “资源组”:选择所需的资源组。
- 区域:选择你所在位置附近的区域。
- “名称”:输入标识的可识别名称,例如“MigrationIdentity”。
- 在页面底部选择“查看 + 创建”。
- 验证检查完成后,选择“创建”。 Azure 将创建新的用户分配的标识。
创建资源后,选择“转到资源”以查看托管标识的详细信息。
使用 az identity create 命令创建用户分配的托管标识:
az identity create --name MigrationIdentity --resource-group <your-resource-group>
将托管标识与 Web 应用相关联
你需要将 Web 应用配置为使用自己创建的托管标识。 使用 Azure 门户或 Azure CLI 将标识分配给应用。
在 Azure 门户中完成以下步骤,从而将标识与应用相关联。 这些步骤同样也适用于以下 Azure 服务:
- Azure Spring Apps
- Azure Container Apps
- Azure 虚拟机
- Azure Kubernetes 服务
导航到 Web 应用的概述页面。
从左侧导航菜单中,选择“标识”。
在“标识”页面上,切换到“用户分配的”选项卡。
选择“+ 添加”,打开“添加用户分配的托管标识”浮出控件。
选择之前用于创建标识的订阅。
按名称搜索“MigrationIdentity”,并从搜索结果中选择该标识。
选择“添加”,以将该标识与应用相关联。
使用以下 Azure CLI 命令将标识与应用相关联:
使用 az identity show 命令检索创建的托管标识的 ID。 复制输出值以在下一步中使用。
az identity show --name MigrationIdentity -g <your-identity-resource-group-name> --query id
可以使用 az webapp identity assign 命令将托管标识分配给 Azure 应用服务实例。
az webapp identity assign \
--resource-group <resource-group-name> \
--name <webapp-name>
--identities <managed-identity-id>
可以使用 az spring app identity assign 命令将托管标识分配给 Azure Spring Apps 实例。
az spring app identity assign \
--resource-group <resource-group-name> \
--name <app-name> \
--service <service-name>
--user-assigned <managed-identity-id>
可以使用 az vm identity assign 命令将托管标识分配给虚拟机。
az vm identity assign \
--resource-group <resource-group-name> \
--name <virtual-machine-name>
--identities <managed-identity-id>
可以使用 az aks update 命令将托管标识分配给 Azure Kubernetes 服务 (AKS) 实例。
az aks update \
--resource-group <resource-group-name> \
--name <cluster-name> \
--enable-managed-identity \
--assign-identity <managed-identity-id> \
--assign-kubelet-identity <managed-identity-id>
为托管标识分配角色
通过为托管标识分配你创建的自定义角色来向其授予权限,就像对本地开发用户的操作一样。
使用 Azure CLI 的 az role assignment
命令分配角色。
az cosmosdb sql role assignment create \
--account-name <cosmosdb-account-name> \
--resource-group <resource-group-name> \
--scope "/" \
--principal-id <managed-identity-id> \
--role-definition-id <your-custom-role-id>
更新应用程序代码
需要配置应用程序代码,以查找在部署到 Azure 时创建的特定托管标识。 在某些情况下,显式设置应用的托管标识还可以防止其他环境标识被意外检测到并自动使用。
在托管标识概述页面上,将客户端 ID 值复制到剪贴板。
应用以下特定于语言的更改:
创建一个 DefaultAzureCredentialOptions
对象并将其传递给 DefaultAzureCredential
。 将 ManagedIdentityClientId 属性设置为客户端 ID。
DefaultAzureCredential credential = new(
new DefaultAzureCredentialOptions
{
ManagedIdentityClientId = managedIdentityClientId
});
将 AZURE_CLIENT_ID
环境变量设置为托管标识客户端 ID。 DefaultAzureCredential
读取此环境变量。
调用 managedIdentityClientId 方法。 将客户端 ID 传递给它。
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder()
.managedIdentityClientId(managedIdentityClientId)
.build();
创建一个 DefaultAzureCredentialClientIdOptions
对象,其 managedIdentityClientId 属性设置为客户端 ID。 将该对象传递给 DefaultAzureCredential
构造函数。
const credential = new DefaultAzureCredential({
managedIdentityClientId
});
将 DefaultAzureCredential
构造函数的 managed_identity_client_id 参数设置为客户端 ID。
credential = DefaultAzureCredential(
managed_identity_client_id = managed_identity_client_id
)
进行此更改后,将代码重新部署到 Azure,以便应用配置更新。
测试应用程序
部署更新后的代码后,请在浏览器中导航到你的托管应用程序。 应用应该可以成功连接到 Cosmos DB。 请记住,角色分配通过 Azure 环境传播最长可能需要五分钟的时间。 应用程序现在配置为在本地和生产环境中运行,开发人员无需管理应用程序本身的机密。
后续步骤
本教程介绍了如何将应用程序迁移到无密码连接。
可以阅读以下资源,更深入地了解本文中讨论的概念: