使用本地和 Azure 上的 Azure Function App 中的托管标识连接 Azure CosmosDB

Pin*_*ong 8 azure azure-functions azure-cosmosdb azure-managed-identity

DocumentDB Account Contributor我为函数应用程序创建了一个托管身份,并按照以下两个部分将其分配给

https://learn.microsoft.com/en-us/azure/cosmos-db/management-identity-based-authentication#assign-a-system-assigned-management-identity-to-a-function-app

https://learn.microsoft.com/en-us/azure/cosmos-db/management-identity-based-authentication#grant-access-to-your-azure-cosmos-account

Microsoft.Azure.Services.AppAuthentication

当我尝试运行以下部分中的代码时出现异常:

https://learn.microsoft.com/en-us/azure/cosmos-db/management-identity-based-authentication#programmatically-access-the-azure-cosmos-db-keys

无法加载文件或程序集“System.Text.Encodings.Web,Version=6.0.0.0,Culture=neutral,PublicKeyToken=cc7b13ffcd2ddd51”。该系统找不到指定的文件。在 System.Text.Json.Serialization.Metadata.JsonPropertyInfo.DeterminePropertyName() 在 System.Text.Json.Serialization.Metadata.JsonPropertyInfo.GetPolicies(Nullable 1 ignoreCondition, Nullable1 declaringTypeNumberHandling) 在 ... System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task任务)位于 C:.ME\MyLab.Code\AzureCode\CosmosDB\azure-cosmos-dotnet- 中的 Cosmos.Samples.AzureFunctions.AzureFunctionsCosmosClientMI.d__7.MoveNext() 处的 System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() v3-usage\AzureFunctions\AzureFunctionsCosmosClientMI.cs:第 85 行

Azure.身份

由于AppAuthenticationMS 不推荐,因此我Azure.Identity通过以下链接转而使用: https://learn.microsoft.com/en-us/dotnet/api/overview/azure/identity-readme ?view=azure-dotnet

https://joonasaijala.com/2021/07/01/how-to-using-management-identities-to-access-cosmos-db-data-via-rbac-and-disabling-authentication-via-keys/

和下面的代码

 static string cosmosUrl = "https://xxx.documents.azure.com:443/";
    private static CosmosClient client = new CosmosClient(cosmosUrl, new DefaultAzureCredential());
   var container = client.GetContainer("FamilyDatabase", "FamilyContainer");
        try
        {
            var result = await container.CreateItemAsync<Item>(data, new PartitionKey(data.LastName));
            return new OkObjectResult(result.Resource.Id);
        }
        catch (CosmosException cosmosException)
        {
            log.LogError("Creating item failed with error {0}", cosmosException.ToString());
            return new BadRequestObjectResult($"Failed to create item. Cosmos Status Code {cosmosException.StatusCode}, Sub Status Code {cosmosException.SubStatusCode}: {cosmosException.Message}.");
        }
Run Code Online (Sandbox Code Playgroud)

但是,我在本地和 Azure 中运行时都遇到了以下异常。

创建项目失败。Cosmos 状态码 Forbidden,Sub 状态码 5301:响应状态码不表示成功:Forbidden (403);子状态:5301;活动ID:xxxx-bf03-4355-8642-5d316f9d3373;原因:(请求被 Auth xxxx 阻止:请求被阻止,因为主体 [xxx-2bff-44e9-97be-9ffeb3aae3ee] 不具备对资源执行操作 [Microsoft.DocumentDB/databaseAccounts/readMetadata] 所需的 RBAC 权限 [/]。学习更多: https: //aka.ms/cosmos-native-rbac .ActivityId:xxx-bf03-4355-8642-5d316f9d3373、Microsoft.Azure.Documents.Common/2.14.0、Windows/10.0.14393 cosmos-netstandard-sdk /3.24.1);。

在本地,我通过链接 https://learn.microsoft.com/en-us/dotnet/api/overview/azure/identity-readme?view=azure-dotnet#authenticating-via-visual-studio登录到 VS

有解决 Azure.Identity 问题的想法吗?

参考:

使用托管身份将 Function App 连接到 CosmosDB

https://github.com/Azure/azure-sdk-for-net/tree/Azure.Identity_1.5.0/sdk/identity/Azure.Identity/samples

小智 10

今天早上,我在设置 CosmosDB 以使用 Azure VM 的托管身份时遇到了同样的错误。该错误消息指出您的主体没有 RBAC 权限Microsoft.DocumentDB/databaseAccounts/readMetadata。一旦您提供了主体,您就可以使用 Azure.Identity 进行权限身份验证。

DocumentDB帐户贡献者没有Microsoft.DocumentDB/databaseAccounts/readMetadata角色,而且我找不到包含该权限的内置 Azure 角色,因此我按照本文中的示例创建了自己的自定义CosmosDBReadWrite角色。

要创建自定义角色定义和分配,您需要安装Azure CLI

配置自定义角色定义

准备 JSON 角色定义文件

首先,您需要创建一个包含角色定义的 json 文件。以下是 2 个不同的自定义角色配置 json 文件,一个用于对 CosmosDB 的只读访问,另一个具有读写角色访问权限。

只读自定义角色的 Json 文件
{
    "RoleName": "CosmosDBReadOnlyRole",
    "Type": "CustomRole",
    "AssignableScopes": ["/"],
    "Permissions": [{
        "DataActions": [
            "Microsoft.DocumentDB/databaseAccounts/readMetadata",
            "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/read",
            "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/executeQuery",
            "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/readChangeFeed"
        ]
    }]
}
Run Code Online (Sandbox Code Playgroud)
读写自定义角色的 Json 文件
{
    "RoleName": "CosmosDBReadWriteRole",
    "Type": "CustomRole",
    "AssignableScopes": ["/"],
    "Permissions": [{
        "DataActions": [
            "Microsoft.DocumentDB/databaseAccounts/readMetadata",
            "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*",
            "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*"
        ]
    }]
}
Run Code Online (Sandbox Code Playgroud)

创建并分配角色定义

使用自定义角色定义保存 json 文件后,我们可以使用 Azure CLI 创建自定义角色,然后将其分配给正确的主体。

使用上面创建的 JSON 文件创建自定义角色

resourceGroupName='<myResourceGroup>'
accountName='<myCosmosAccount>'
az cosmosdb sql role definition create -a $accountName -g $resourceGroupName -b @role-definition.json
Run Code Online (Sandbox Code Playgroud)

创建角色后,应返回所创建角色的定义。如果没有,请使用以下命令查找可以在name属性中找到的roleDefinitionId

az cosmosdb sql role definition list --account-name $accountName -g $resourceGroupName
Run Code Online (Sandbox Code Playgroud)

最后,将自定义角色应用到需要访问 CosmosDB 权限的主体。

resourceGroupName='<myResourceGroup>'
accountName='<myCosmosAccount>'
roleDefinitionId = '<roleDefinitionId>'
principalId = '<ID for the Object that needs access to the CosmosDB>'
az cosmosdb sql role assignment create -a $accountName -g $resourceGroupName -s "/" -p $principalId -d $roleDefinitionId
Run Code Online (Sandbox Code Playgroud)

希望这也能解决您遇到的错误!