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

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

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

托管标识类型

托管标识分为两种类型:

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

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

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

第一步是在托管应用的 Azure 资源上启用托管标识。 例如,如果要使用 Azure App 服务 托管 Django 应用程序,则需要为托管应用的 App 服务 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": "99999999-9999-9999-9999-999999999999",
  "tenantId": "33333333-3333-3333-3333-333333333333",
  "type": "SystemAssigned",
  "userAssignedIdentities": null
}

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

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

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

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

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 为99999999-9999-9999-9999-999999999999读取、写入和删除对订阅中 msdocs-python-sdk-auth-example 资源组11111111-1111-1111-1111-111111111111中所有存储帐户中Azure 存储 blob 容器和数据进行读取、写入和删除的托管标识,请使用以下命令将应用程序服务主体分配给 存储 Blob 数据参与者角色。

az role assignment create --assignee 99999999-9999-9999-9999-999999999999 \
    --scope /subscriptions/11111111-1111-1111-1111-111111111111/resourceGroups/msdocs-python-sdk-auth-example \
    --role "Storage Blob Data Contributor"

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

3 - 在应用程序中实现 DefaultAzureCredential

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

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

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

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

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

pip install azure-identity

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

  1. DefaultAzureCredentialazure.identity模块导入类。
  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 资源验证应用。