使用托管身份将函数应用程序连接到 CosmosDB

问题描述 投票:0回答:3

我正在尝试在函数应用程序中编写一个函数来操作 CosmosDB 中的数据。如果我将读写键放入环境变量中,我就能正常工作。为了使其更加强大,我希望它能够作为托管身份应用程序运行。该应用程序在 Cosmos DB 上具有“DocumentDB 帐户贡献者”角色。

但是,CosmosClient 构造函数不接受 Credential,并且需要读写密钥。我一直在寻找 azure.mgmt.cosmosdb.operations 的兔子洞,其中有一个带有

DatabaseAccountsOperations
方法的
list_keys()
类。但我找不到访问该功能的简洁方法。如果我尝试创建该对象(这需要从我的 dbmgmt 对象中窃取配置、序列化器和反序列化器),它仍然需要
resourceGroupName
accountName

我情不自禁地认为我在某个地方走错了方向,因为这必须以更直接的方式实现。特别是考虑到 JavaScript SDK 引用了一个与 SubscriptionClient 一致的更符合逻辑的类 CosmosDBManagementClient。但是,我在 python 端的任何地方都找不到该类。 有什么指点吗?

from azure.identity import DefaultAzureCredential
from azure.cosmos import CosmosClient
from azure.mgmt.resource import SubscriptionClient
from azure.mgmt.cosmosdb import CosmosDB
from .cred_wrapper import CredentialWrapper

def main(req: func.HttpRequest) -> func.HttpResponse:
    request_body = req.get_body()
    # credential = DefaultAzureCredential()
    # https://gist.github.com/lmazuel/cc683d82ea1d7b40208de7c9fc8de59d
    credential = CredentialWrapper()  

    uri = os.environ.get('cosmos-db-uri')
    # db = CosmosClient(url=uri, credential=credential)  # Doesn't work, wants a credential that is a RW/R key
    # Does work if I replace it with my primary / secondary key but the goal is to remove dependence on that.

    subscription_client = SubscriptionClient(credential)
    subscription = next(subscription_client.subscriptions.list())

    dbmgmt = CosmosDB(credential, subscription.subscription_id)  # This doesn't accept the DB URI??
    operations = list(dbmgmt.operations.list())  # I see the list_keys() Operation there...

编辑

一个乐于助人的灵魂在这里提供了回应,但在我做出反应或接受它作为答案之前将其删除。他们指出有一个等效的 python SDK 并且

from azure.mgmt.cosmosdb import CosmosDBManagementClient
可以解决问题。

从那时起,我就只能靠自己了,因为这导致了

ImportError: cannot import name 'CosmosDBManagementClient' from 'azure.mgmt.cosmosdb'

我相信问题的根源在于软件包不兼容

azure-mgmt
。从我的
azure-mgmt
中删除
requirements.txt
并仅加载cosmos和identiy相关包后,导入错误已解决。

这解决了90%的问题。

dbmgmt  = CosmosDBManagementClient(credential, subscription.subscription_id, c_uri)
print(dbmgmt.database_accounts.list_keys())
TypeError: list_keys() missing 2 required positional arguments: 'resource_group_name' and 'account_name'

真的需要收集这些参数吗?与从 Vault 读取秘密的示例相比,它看起来非常复杂。

python azure azure-functions azure-cosmosdb
3个回答
1
投票
对于其他希望通过托管身份访问 CosmosDB 的不幸者来说,截至 2021 年 5 月,这似乎还不可能。

来源:

Github上的讨论


0
投票

更新 12/05/2021 - 我来这里寻找 Javascript/Typescript 的解决方案。所以把答案留给其他人。我认为类似的方法也适用于 Python。

您可以使用 RBAC 通过托管身份进行数据平面操作。查找文档很困难。

使用托管身份进行 Cosmos DB 数据平面操作的 RBAC

重要 - 如果您收到错误请求被 Auth mydb 阻止:请求被阻止,因为主体 [xxxxxx-6fad-44e4-98bc-2d423a88b65f] 不具备在 Microsoft.DocumentDB/databaseAccounts/readMetadata 上执行操作所需的 RBAC 权限资源 [/]。 不要使用门户分配角色,请使用 Azure CLI for CosmosDB。 如何 - 使用 Azure CosmosDB CLI 为用户/系统 MSI/用户 MSI 创建角色分配

# Find the role ID: resourceGroupName='<myResourceGroup>' accountName='<myCosmosAccount>' az cosmosdb sql role definition list --account-name $accountName --resource-group $resourceGroupName # Assign to the MSI or user managed MSI: readOnlyRoleDefinitionId = '<roleDefinitionId>' # as fetched above principalId = '<aadPrincipalId>' az cosmosdb sql role assignment create --account-name $accountName --resource-group $resourceGroupName --scope "/" --principal-id $principalId --role-definition-id $readOnlyRoleDefinitionId
完成这一步后,连接的代码就非常简单了。使用 @azure/identity 包的默认凭据。 

这适用于具有托管身份的 Azure Function App 以及具有 VS 代码或 az login

 的笔记本电脑。

@azure/identity sdk 的文档

使用 @azure/identity 进行身份验证以获取凭据对象的示例

Azure identity default credential

import { CosmosClient } from "@azure/cosmos"; import { DefaultAzureCredential, ManagedIdentityCredential, ChainedTokenCredential } from "@azure/identity"; const defaultCredentials = new DefaultAzureCredential(); const managedCredentials = new ManagedIdentityCredential(); const aadCredentials = new ChainedTokenCredential(managedCredentials, defaultCredentials); client = new CosmosClient({ endpoint: "https://mydb.documents.azure.com:443/", aadCredentials });


0
投票
截至 2023 年 12 月,有一个几乎合并的 PR。但仍然不可用。

https://github.com/microsoft/AzureTRE/issues/345

© www.soinside.com 2019 - 2024. All rights reserved.