适用范围: NoSQL
在本文中,你将设置一个无论是否轮换密钥都能可靠运行的解决方案,以使用托管标识和数据平面基于角色的访问控制来访问 Azure Cosmos DB 密钥。 本文中的示例使用 Azure Functions,但你可以使用任何支持托管标识的服务。
本文将介绍如何创建一个无需复制任何 Azure Cosmos DB 密钥即可访问 Azure Cosmos DB 数据的函数应用。 发出 HTTP 请求时,函数应用将会触发,然后列出所有现有数据库。
适用范围: NoSQL
在本文中,你将设置一个无论是否轮换密钥都能可靠运行的解决方案,以使用托管标识和数据平面基于角色的访问控制来访问 Azure Cosmos DB 密钥。 本文中的示例使用 Azure Functions,但你可以使用任何支持托管标识的服务。
本文将介绍如何创建一个无需复制任何 Azure Cosmos DB 密钥即可访问 Azure Cosmos DB 数据的函数应用。 发出 HTTP 请求时,函数应用将会触发,然后列出所有现有数据库。
具有活动订阅的 Azure 帐户。 免费创建帐户。
现有的 Azure Cosmos DB API for NoSQL 帐户。 创建 Azure Cosmos DB API for NoSQL 帐户
现有的Azure Functions 函数应用。 在 Azure 门户中创建你的第一个函数
若要执行本文中的步骤,需安装 Azure CLI 并登录到 Azure。
在终端或命令窗口中,将 Azure Functions 函数应用、Azure Cosmos DB 帐户和资源组的名称分别存储为名为 functionName
、cosmosName
和 resourceGroupName
的 shell 变量。
# Variable for function app name
functionName="msdocs-function-app"
# Variable for Azure Cosmos DB account name
cosmosName="msdocs-cosmos-app"
# Variable for resource group name
resourceGroupName="msdocs-cosmos-functions-dotnet-identity"
注意
后续步骤中将会重用这些变量。 此示例假设 Azure Cosmos DB 帐户名称为 msdocs-cosmos-app
,函数应用名称为 msdocs-function-app
,资源组名称为 msdocs-cosmos-functions-dotnet-identity
。
使用 az functionapp show
命令查看函数应用的属性。
az functionapp show \
--resource-group $resourceGroupName \
--name $functionName
使用 az webapp identity show
查看函数应用的系统分配托管标识的属性。
az webapp identity show \
--resource-group $resourceGroupName \
--name $functionName
使用 az cosmosdb show
查看 Azure Cosmos DB 帐户的属性。
az cosmosdb show \
--resource-group $resourceGroupName \
--name $cosmosName
在此步骤中,你将创建两个数据库。
在终端或命令窗口中,使用 az cosmosdb sql database create
创建新的 products
数据库。
az cosmosdb sql database create \
--resource-group $resourceGroupName \
--name products \
--account-name $cosmosName
创建新的 customers
数据库。
az cosmosdb sql database create \
--resource-group $resourceGroupName \
--name customers \
--account-name $cosmosName
在此步骤中,你将查询 API for NoSQL 帐户的文档终结点。
使用 az cosmosdb show
并将 query 参数设置为 documentEndpoint
。 记录结果。 在稍后的步骤中会使用此值。
az cosmosdb show \
--resource-group $resourceGroupName \
--name $cosmosName \
--query documentEndpoint
cosmosEndpoint=$(
az cosmosdb show \
--resource-group $resourceGroupName \
--name $cosmosName \
--query documentEndpoint \
--output tsv
)
echo $cosmosEndpoint
注意
此变量将在后面的步骤中重用。
在此步骤中,你将向函数应用的系统分配托管标识分配角色。 Azure Cosmos DB 有多个内置角色,可将这些角色分配到托管标识以进行控制平面访问。 对于数据平面访问,你将创建一个有权读取元数据的新自定义角色。
提示
若要详细了解最小特权访问权限的重要性,请参阅降低特权帐户的泄露风险一文。
使用 az cosmosdb show
并将 query 参数设置为 id
。 将结果存储在名为 scope
的 shell 变量中。
scope=$(
az cosmosdb show \
--resource-group $resourceGroupName \
--name $cosmosName \
--query id \
--output tsv
)
echo $scope
注意
此变量将在后面的步骤中重用。
使用 az webapp identity show
并将 query 参数设置为 principalId
。 将结果存储在名为 principal
的 shell 变量中。
principal=$(
az webapp identity show \
--resource-group $resourceGroupName \
--name $functionName \
--query principalId \
--output tsv
)
echo $principal
使用新自定义角色的配置创建新的 JSON 文件。
{
"RoleName": "Read Azure Cosmos DB Metadata",
"Type": "CustomRole",
"AssignableScopes": ["/"],
"Permissions": [{
"DataActions": [
"Microsoft.DocumentDB/databaseAccounts/readMetadata"
]
}]
}
提示
可以使用 touch <filename>
或内置编辑器 (code .
) 在 Azure Cli 中创建文件。
使用 az cosmosdb sql role definition create
通过自定义 JSON 对象创建名为 Read Azure Cosmos DB Metadata
的新角色定义。
az cosmosdb sql role definition create \
--resource-group $resourceGroupName \
--account-name $cosmosName \
--body @definition.json
注意
在此示例中,角色定义在名为 definition.json 的文件中定义。
使用 az role assignment create
将 Read Azure Cosmos DB Metadata
角色分配到系统分配的托管标识。
az cosmosdb sql role assignment create \
--resource-group $resourceGroupName \
--account-name $cosmosName \
--role-definition-name "Read Azure Cosmos DB Metadata" \
--principal-id $principal \
--scope $scope
现在,我们有了一个使用系统分配的托管标识的函数应用,该标识具有自定义角色。 以下函数应用将在 Azure Cosmos DB 帐户中查询数据库列表。
使用 --dotnet
参数在名为 csmsfunc
的文件夹中创建一个本地函数项目。 更改 shell 的目录
func init csmsfunc --dotnet
cd csmsfunc
创建一个新函数并将 template 参数设置为 httptrigger
,将 name 设置为 readdatabases
。
func new --template httptrigger --name readdatabases
将 Azure.Identity
和 Microsoft.Azure.Cosmos
NuGet 包添加到 .NET 项目。 使用 dotnet build
生成项目。
dotnet add package Azure.Identity
dotnet add package Microsoft.Azure.Cosmos
dotnet build
在集成开发环境 (IDE) 中打开函数代码。
提示
如果在本地使用 Azure CLI,可以打开 Visual Studio Code。
code .
请将 readdatabases.cs 文件中的代码替换为此示例函数实现。 保存更新的文件。
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Azure.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.Cosmos;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
namespace csmsfunc
{
public static class readdatabases
{
[FunctionName("readdatabases")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequest req,
ILogger log)
{
log.LogTrace("Start function");
CosmosClient client = new CosmosClient(
accountEndpoint: Environment.GetEnvironmentVariable("COSMOS_ENDPOINT", EnvironmentVariableTarget.Process),
new DefaultAzureCredential()
);
using FeedIterator<DatabaseProperties> iterator = client.GetDatabaseQueryIterator<DatabaseProperties>();
List<(string name, string uri)> databases = new();
while(iterator.HasMoreResults)
{
foreach(DatabaseProperties database in await iterator.ReadNextAsync())
{
log.LogTrace($"[Database Found]\t{database.Id}");
databases.Add((database.Id, database.SelfLink));
}
}
return new OkObjectResult(databases);
}
}
}
在本地环境中,DefaultAzureCredential
类将使用各种本地凭据来确定当前标识。 虽然本操作指南不要求在本地运行,但你可以使用自己的标识或服务主体进行本地开发。
使用 az ad signed-in-user show
获取本地帐户的主体标识符。
az ad signed-in-user show --query "id"
使用 az cosmosdb sql role assignment create
命令将本地帐户基于角色的访问控制访问权限分配给 Azure Cosmos DB 帐户。 使用 ID 为 00000000-0000-0000-0000-000000000002
的内置“Cosmos DB 数据参与者”角色。
az cosmosdb sql role assignment create \
--resource-group $resourceGroupName \
--account-name $cosmosName \
--role-definition-id "00000000-0000-0000-0000-000000000002" \
--principal-id "<your-principal-id>" \
--scope "/"
在 local.settings.json 文件中的 Values 对象内添加一个名为 COSMOS_ENDPOINT
的新设置。 该设置的值应是前面在本操作指南中记下的文档终结点。
...
"Values": {
...
"COSMOS_ENDPOINT": "https://msdocs-cosmos-app.documents.azure.com:443/",
...
}
...
注意
为简洁起见,此 JSON 对象已缩短。 此 JSON 对象还包含一个示例值,该值假设帐户名称为 msdocs-cosmos-app
。
运行函数应用
func start
发布后,DefaultAzureCredential
类将使用环境中的凭据或使用托管标识。 对于本指南,系统分配的托管标识将用作 CosmosClient
构造函数的凭据。
在已部署到 Azure 的函数应用中指定 COSMOS_ENDPOINT
设置。
az functionapp config appsettings set \
--resource-group $resourceGroupName \
--name $functionName \
--settings "COSMOS_ENDPOINT=$cosmosEndpoint"
通过重用 functionName
shell 变量将函数应用部署到 Azure:
func azure functionapp publish $functionName