使用 Azure SDK for Python 向 Azure 资源验证 Azure 托管应用的身份

使用 Azure 应用程序服务、Azure 虚拟机或 Azure 容器实例等服务在 Azure 中托管应用时,建议使用托管标识对应用进行身份验证。

托管标识为应用提供一个标识,使应用无需使用机密密钥或其他应用程序机密即可连接到其他 Azure 资源。 在内部,Azure 知道应用的标识以及应用能够连接到哪些资源。 Azure 使用此信息来自动获取应用的 Microsoft Entra 令牌,使应用能够连接到其他 Azure 资源,你无需管理任何应用程序机密。

注意

在 Azure Kubernetes 服务 (AKS) 上运行的应用可以使用工作负荷标识向 Azure 资源进行身份验证。 在 AKS 中,工作负荷标识表示托管标识与 Kubernetes 服务帐户之间的信任关系。 如果部署到 AKS 的应用程序在此类关系中配置了 Kubernetes 服务帐户,则 DefaultAzureCredential 使用托管标识向 Azure 验证该应用。 使用工作负载标识进行身份验证在将 Microsoft Entra 工作负载 ID 与 Azure Kubernetes 服务结合使用中进行了讨论。 有关如何配置工作负荷标识的步骤,请参阅在 Azure Kubernetes 服务 (AKS) 群集上部署和配置工作负荷标识

托管标识类型

托管标识分为两种类型:

  • 系统分配的托管标识 - 这种类型的托管标识由 Azure 资源提供并直接关联到 Azure 资源。 在 Azure 资源上启用托管标识时,你将获得该资源的系统分配的托管标识。 系统分配的托管标识在与其关联的 Azure 资源的生命周期内有效。 当资源被删除时,Azure 会自动为你删除标识。 由于你只需为托管代码的 Azure 资源启用托管标识,因此此方法是最容易使用的托管标识类型。
  • 用户分配的托管标识 - 你也可以将托管标识创建为独立的 Azure 资源。 当解决方案具有在多个 Azure 资源上运行的多个工作负荷时,此方法最常用,因为这些资源都需要共享相同的标识和相同的权限。 例如,如果你的解决方案具有在多个应用程序服务和虚拟机实例上运行的组件,并且这些实例都需要访问同一组 Azure 资源,则在这些资源中使用用户分配的托管标识就有意义。

本文介绍为应用启用和使用系统分配的托管标识的步骤。 如果需要使用用户分配的托管标识,请参阅管理用户分配的托管标识一文来了解如何创建用户分配的托管标识。

1 - 在托管应用的 Azure 资源中启用托管标识

第一步是在托管应用的 Azure 资源上启用托管标识。 例如,如果要使用 Azure 应用程序服务托管 Django 应用程序,则需要为托管应用的应用程序服务 Web 应用启用托管标识。 如果要使用虚拟机来托管应用,则支持 VM 使用托管标识。

可以使用 Azure 门户或 Azure CLI 来启用用于 Azure 资源的托管标识。

Azure CLI 命令可以在 Azure Cloud Shell 中或是安装了 Azure CLI 的工作站上运行。

用于为 Azure 资源启用托管标识的 Azure CLI 命令的格式为 az <command-group> identity --resource-group <resource-group-name> --name <resource-name>。 下面显示了针对常用 Azure 服务的特定命令。

az webapp identity assign --resource-group <resource-group-name> -name <web-app-name>

输出将如下所示。

{
  "principalId": "aaaaaaaa-bbbb-cccc-1111-222222222222",
  "tenantId": "aaaabbbb-0000-cccc-1111-dddd2222eeee",
  "type": "SystemAssigned",
  "userAssignedIdentities": null
}

principalId 值是托管标识的唯一 ID。 请将此输出复制到别处,因为在下一步骤中需要用到这些值。

2 - 将角色分配到托管标识

接下来,需确定应用需要哪些角色(权限),并为托管标识分配 Azure 中的这些角色。 可以在资源、资源组或订阅范围为托管标识分配角色。 此示例演示如何在资源组范围分配角色,因为大多数应用程序将其所有 Azure 资源分组到单个资源组中。

使用 az role assignment create 命令为托管标识分配 Azure 中的角色。 对于被分配人,请使用在步骤 1 中复制的 principalId

az role assignment create --assignee <managedIdentityprincipalId> \
    --scope /subscriptions/<subscriptionId>/resourceGroups/<resourceGroupName> \
    --role "<roleName>" 

若要获取可为服务主体分配的角色名称,请使用 az role definition list 命令。

az role definition list \
    --query "sort_by([].{roleName:roleName, description:description}, &roleName)" \
    --output table

例如,若要允许 ID 为 aaaaaaaa-bbbb-cccc-1111-222222222222 的托管标识在 ID 为 aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e 的订阅中对 msdocs-python-sdk-auth-example 资源组中的所有存储帐户中的 Azure 存储 blob 容器和数据进行读取、写入和删除访问,你可以使用以下命令将应用程序服务主体分配给存储 Blob 数据参与者角色。

az role assignment create --assignee aaaaaaaa-bbbb-cccc-1111-222222222222 \
    --scope /subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/msdocs-python-sdk-auth-example \
    --role "Storage Blob Data Contributor"

有关使用 Azure CLI 在资源或订阅级别分配权限的信息,请参阅使用 Azure CLI 分配 Azure 角色一文。

3 - 在应用程序中实现 DefaultAzureCredential

正在 Azure 中运行代码并在托管应用的 Azure 资源上启用托管标识时,DefaultAzureCredential 确定要按以下顺序使用的凭据:

  1. 检查环境变量 AZURE_CLIENT_IDAZURE_TENANT_ID 以及 AZURE_CLIENT_SECRETAZURE_CLIENT_CERTIFICATE_PATH 和(可选)AZURE_CLIENT_CERTIFICATE_PASSWORD 定义的服务主体的环境。
  2. 检查用户分配的托管标识的关键字参数。 可以通过在 managed_identity_client_id 参数中指定用户分配的托管标识的客户端 ID 来将用户分配的托管标识传入。
  3. 检查用户分配的托管标识的客户端 ID 的 AZURE_CLIENT_ID 环境变量。
  4. 如果已启用,请将系统分配的托管标识用于 Azure 资源。

可以通过设置 exclude_managed_identity_credential 关键字参数 True 从凭据中排除托管标识。

在本文中,我们将为 Azure 应用程序服务 Web 应用使用系统分配的托管标识,因此无需在环境中配置托管标识或将其作为参数传入。 以下步骤演示如何使用 DefaultAzureCredential

首先,将 azure.identity 包添加到应用程序中。

pip install azure-identity

接下来,对于在应用中创建 Azure SDK 客户端对象的任何 Python 代码,你需要:

  1. azure.identity 模块中导入 DefaultAzureCredential 类。
  2. 创建 DefaultAzureCredential 对象。
  3. DefaultAzureCredential 对象传递给 Azure SDK 客户端对象构造函数。

以下代码片段中显示了这些步骤的示例。

from azure.identity import DefaultAzureCredential
from azure.storage.blob import BlobServiceClient

# Acquire a credential object
token_credential = DefaultAzureCredential()

blob_service_client = BlobServiceClient(
        account_url="https://<my_account_name>.blob.core.windows.net",
        credential=token_credential)

Azure SDK for Python 身份验证概述文章中所述,DefaultAzureCredential 支持多种身份验证方法,并确定在运行时使用的身份验证方法。 这种方法的好处是,你的应用可在不同环境中使用不同的身份验证方法,而无需实现特定于环境的代码。 在本地开发期间,在工作站上运行上述代码时,DefaultAzureCredential 将使用应用程序服务主体(由环境设置确定)或开发人员工具凭据,以向其他 Azure 资源进行身份验证。 因此,相同的代码可用于在本地开发期间和部署到 Azure 时向 Azure 资源对应用进行身份验证。