我正在尝试使用系统分配的托管标识来访问 Azure Cosmos DB 数据,如 Microsoft 文档中所述: https://learn.microsoft.com/en-us/azure/cosmos-db/management-identity-based-authentication
我已在 Azure 函数中创建了系统分配的 ID,并将“Cosmos DB 内置数据读取器”角色分配给了 Cosmos DB(基本上授予了该函数的读取权限)。
然后,我按照“(可选)在本地运行函数”部分中的代码尝试在本地运行我的函数。
但是它失败并显示以下消息:
Request blocked by Auth <my cosmos account> : Request is blocked because principal [89c3cdb1-438c-4e04-a16d-...........] does not have required RBAC permissions to perform action [Microsoft.DocumentDB/databaseAccounts/readMetadata] on resource [/]
此消息中返回的主体 Id 与我的 azure 函数的主体 Id 不同。
显然发生这种情况是因为我的本地帐户的主体 ID 与我在 Azure 上的函数中的系统分配的主体 ID 不同。
但是我找不到任何关于如何在本地设置相同的系统分配原则 id 的信息。
有人有想法吗?
我能找到的关闭解决方法是:
要部署到 Azure,请使用系统分配的身份
在 Function 应用程序中打开系统分配的身份并复制主体 Id
az cosmosdb sql role assignment create \
--resource-group $resourceGroupName \
--account-name $cosmosName \
--role-definition-name "Cosmos DB Built-in Data Contributor" \
--principal-id <Principal Id from Step 1> \
--scope $scope
命令取自 Microsoft 文档:https://learn.microsoft.com/en-us/azure/cosmos-db/management-identity-based-authentication
DefaultAzureCredential
在本地运行该函数。像这样的东西:
var cosmosDbEndpoint = Environment.GetEnvironmentVariable("CosmosDbEndpoint", EnvironmentVariableTarget.Process);
var cosmosClient = new CosmosClient(accountEndpoint: cosmosDbEndpoint, new DefaultAzureCredential());
Request is blocked because principal [<blocked principal Id>]
az cosmosdb sql role assignment create \
--resource-group $resourceGroupName \
--account-name $cosmosName \
--role-definition-name "Cosmos DB Built-in Data Contributor" \
--principal-id <Principal Id from Step 5> \
--scope $scope
当然你可以为这些命令设置不同的定义,但原理是一样的。
我要补充的一件事是,由于必须检查所有凭证类型,本地运行 Function 需要永远花费时间。
因此,为了最大限度地减少执行时间,最好排除所有不必要的凭证类型。假设您的帐户在本地通过 Azure cli 凭据进行身份验证,那么您将创建如下凭据:
var cosmosDbEndpoint = Environment.GetEnvironmentVariable("CosmosDbEndpoint", EnvironmentVariableTarget.Process);
var localDebugging = Environment.GetEnvironmentVariable("LocalDebugging");
var credentials = localDebugging is null or not "true" ?
new DefaultAzureCredential() : // running on Azure
new DefaultAzureCredential(new DefaultAzureCredentialOptions() // running locally
{
ExcludeManagedIdentityCredential = true,
// ExcludeAzureCliCredential = true,
ExcludeAzureDeveloperCliCredential = true,
ExcludeAzurePowerShellCredential = true,
ExcludeEnvironmentCredential = true,
ExcludeInteractiveBrowserCredential = true,
ExcludeSharedTokenCacheCredential = true,
ExcludeVisualStudioCodeCredential = true,
ExcludeVisualStudioCredential = true,
ExcludeWorkloadIdentityCredential = true,
});
services.AddSingleton<CosmosClient>(sp => new CosmosClient(accountEndpoint: cosmosDbEndpoint, credentials));