Azure 容器应用中的托管标识

Microsoft Entra ID 中的托管标识允许容器应用访问其他受 Microsoft Entra 保护的资源。 有关 Microsoft Entra ID 中的托管标识的详细信息,请参阅 Azure 资源的托管标识

可为容器应用授予两种类型的标识:

  • 系统分配的标识与容器应用相关联,删除该容器应用也会删除该标识。 一个应用只能具有一个系统分配的标识。
  • 用户分配的标识是可以分配给容器应用和其他资源的独立 Azure 资源。 一个容器应用可以有多个用户分配的标识。 用户分配的标识存在,直到删除它们。

为什么使用托管标识?

可以在正在运行的容器应用中使用托管标识向支持 Microsoft Entra 身份验证的任何服务进行身份验证。

使用托管标识:

常见用例

系统分配的标识最适合用于具有以下特征的工作负载:

  • 包含在单个资源中
  • 需要独立的标识

用户分配的标识非常适合用于具有以下特征的工作负载:

  • 在多个资源上运行并可共享单个标识
  • 需要预先获取对安全资源的授权

限制

初始化容器无法访问仅限消耗环境专用工作负载配置文件环境中的托管标识

配置托管标识

可通过以下方式配置托管标识:

  • Azure 门户
  • Azure CLI
  • Azure 资源管理器 (ARM) 模板

在正在运行的容器应用中添加、删除或修改托管标识时,该应用不会自动重启,且不会创建新的修订版。

备注

将托管标识添加到在 2022 年 4 月 11 日之前部署的容器应用时,必须创建新的修订版。

添加系统分配的标识

运行 az containerapp identity assign 命令以创建系统分配标识:

az containerapp identity assign --name myApp --resource-group myResourceGroup --system-assigned

添加用户分配的标识

为容器应用配置用户分配的标识需要先创建该标识,然后将其资源标识符添加到该容器应用的配置。 可以通过 Azure 门户或 Azure CLI 创建用户分配的标识。 有关创建和管理用户分配的标识的信息,请参阅管理用户分配的托管标识

  1. 创建用户分配的标识。

    az identity create --resource-group <GROUP_NAME> --name <IDENTITY_NAME> --output json
    

    记下新标识的 id 属性。

  2. 运行 az containerapp identity assign 命令以将标识分配给应用。 identities 参数是一个空格分隔列表。

    az containerapp identity assign --resource-group <GROUP_NAME> --name <APP_NAME> \
        --user-assigned <IDENTITY_RESOURCE_ID>
    

    请将 <IDENTITY_RESOURCE_ID> 替换为标识的 id 属性。 若要分配多个用户分配的标识,请在 --user-assigned 参数中提供标识 ID 的空格分隔列表。

配置目标资源

对于某些资源,需要为应用的托管标识配置角色分配以授予访问权限。 否则,即使对该标识使用有效令牌,应用对服务(例如 Azure 密钥保管库和 Azure SQL 数据库)的调用也会被拒绝。 若要详细了解 Azure 基于角色的访问控制 (Azure RBAC),请参阅什么是 RBAC?。 若详细了解支持 Microsoft Entra 令牌的资源,请参阅支持 Microsoft Entra 身份验证的 Azure 服务

重要

用于托管标识的后端服务将为每个资源 URI 维护缓存约 24 小时。 如果你更新特定目标资源的访问策略并立即检索该资源的令牌,则可以继续获取具有过时权限的缓存令牌,直到该令牌过期。 不支持强制刷新令牌。

在应用代码中连接到 Azure 服务

使用托管标识,应用可以获取令牌来访问使用 Microsoft Entra ID 的 Azure 资源,例如 Azure SQL 数据库、Azure Key Vault 和 Azure 存储。 这些令牌代表访问资源的应用程序,而不是应用程序的任何特定用户。

容器应用提供内部可访问的 REST 终结点用于检索令牌。 REST 终结点可从具有标准 HTTP GET请求的应用内使用,可以使用首选语言的通用 HTTP 客户端发送该请求。 对于 .NET、JavaScript、Java 和 Python,Azure 标识客户端库提供基于此 REST 终结点的抽象。 可以将凭据对象添加到特定于服务的客户端,以连接到其他 Azure 服务。

备注

使用 Azure 标识客户端库时,需要明确指定用户分配的托管标识客户端 ID。

原始 HTTP GET请求如以下示例所示。

IDENTITY_ENDPOINT 环境变量获取令牌终结点 URL。 x-identity-header 包含存储在 IDENTITY_HEADER 环境变量中的 GUID。

GET http://localhost:42356/msi/token?resource=https://vault.azure.cn&api-version=2019-08-01 HTTP/1.1
x-identity-header: 853b9a84-5bfa-4b22-a3f3-0b9a43d9ad8a

响应如以下示例所示:

HTTP/1.1 200 OK
Content-Type: application/json

{
    "access_token": "eyJ0eXAi…",
    "expires_on": "1586984735",
    "resource": "https://vault.azure.cn",
    "token_type": "Bearer",
    "client_id": "5E29463D-71DA-4FE0-8E69-999B57DB23B0"
}

此响应与Microsoft Entra 服务到服务访问令牌请求的响应相同。 要访问密钥保管库,请将access_token的值添加到客户端与保管库的连接。

REST 终结点参考

使用托管标识的容器应用通过定义两个环境变量来公开标识终结点:

  • IDENTITY_ENDPOINT:容器应用可从中请求令牌的本地 URL。
  • IDENTITY_HEADER:用于帮助缓解服务器端请求伪造 (SSRF) 攻击的标头。 该值由平台轮换。

要获取资源的令牌,请对该终结点发起 HTTP GET请求,并包括以下参数:

参数名称 In 说明
resource 查询 应获取其令牌的资源的 Microsoft Entra 资源 URI。 该资源可以是支持 Microsoft Entra 身份验证的 Azure 服务或任何其他资源 URI 之一。
api-version 查询 要使用的令牌 API 版本。 使用“2019-08-01”或更高版本。
X-IDENTITY-HEADER 标头 IDENTITY_HEADER 环境变量的值。 此标头可以缓解服务器端请求伪造 (SSRF) 攻击。
client_id 查询 (可选)要使用的用户分配的标识的客户端 ID。 不能在包含 principal_idmi_res_idobject_id 的请求中使用。 如果省略所有 ID 参数(client_idprincipal_idobject_idmi_res_id),则使用系统分配的标识。
principal_id 查询 (可选)要使用的用户分配的标识的主体 ID。 object_id 是可以改用的别名。 不能在包含 client_id、mi_res_id 或 object_id 的请求中使用。 如果省略所有 ID 参数(client_idprincipal_idobject_idmi_res_id),则使用系统分配的标识。
mi_res_id 查询 (可选)要使用的用户分配的标识的 Azure 资源 ID。 不能在包含 principal_idclient_idobject_id 的请求中使用。 如果省略所有 ID 参数(client_idprincipal_idobject_idmi_res_id),则使用系统分配的标识。

重要

如果你要尝试获取用户分配的标识的令牌,必须包含一个可选属性。 否则,令牌服务将尝试为系统分配的标识获取令牌,而该令牌不一定存在。

将托管标识用于缩放规则

可以在缩放规则中使用托管标识向支持托管标识的 Azure 服务进行身份验证。 要在缩放规则中使用托管标识,请在缩放规则中使用 identity 属性,而不是 auth 属性。 identity 属性的可接受值是用户分配的标识的 Azure 资源 ID,或 system(用于使用系统分配的标识)。

备注

缩放规则中的托管标识身份验证目前为公共预览版。 它在 API 版本 2024-02-02-preview 中提供。

以下 ARM 模板示例演示如何将托管标识与 Azure 队列存储缩放规则结合使用:

队列存储帐户使用 accountName 属性来标识存储帐户,而 identity 属性指定要使用的托管标识。 无需使用 auth 属性。

"scale": {
    "minReplicas": 1,
    "maxReplicas": 10,
    "rules": [{
        "name": "myQueueRule",
        "azureQueue": {
            "accountName": "mystorageaccount",
            "queueName": "myqueue",
            "queueLength": 2,
            "identity": "<IDENTITY1_RESOURCE_ID>"
        }
    }]
}

要详细了解如何将托管标识与缩放规则配合使用,请参阅在 Azure 容器应用中设置缩放规则

控制托管标识可用性

容器应用允许指定 Init 容器和主容器。 默认情况下,消耗工作负载配置文件环境中的主容器和 Init 容器都可以使用托管标识来访问其他 Azure 服务。 在仅消耗环境和专用工作负载配置文件环境中,只有主容器可以使用托管标识。 托管标识访问令牌适用于容器应用上配置的每个托管标识。 但是,在某些情况下,只有 Init 容器或主容器需要托管标识的访问令牌。 其他情况下,可能仅使用托管标识访问 Azure 容器注册表来拉取容器映像,而应用程序本身不需要访问 Azure 容器注册表。

从 API 版本 2024-02-02-preview 开始,可以控制在 Init 阶段和主要阶段可供容器应用使用的托管标识,以遵循最小特权安全原则。 可以使用以下选项:

  • Init:仅适用于 Init 容器。 如果要执行一些需要托管标识的初始化工作,但不再需要主容器中的托管标识,请使用此选项。 此选项目前仅在工作负载配置文件消耗环境中受支持
  • Main:仅适用于主容器。 如果 Init 容器不需要托管标识,请使用此选项。
  • All:适用于所有容器。 此值为默认设置。
  • None:不适用于任何容器。 当托管标识仅用于 ACR 映像拉取、缩放规则或 Key Vault 机密,并且不需要对容器中运行的代码可用时,请使用此选项。

以下 ARM 模板示例演示如何在工作负载配置文件消耗环境中配置容器应用,该环境具有以下特性:

  • 将容器应用的系统分配标识仅限于主容器。
  • 将用户分配的特定标识仅限于 Init 容器。
  • 使用用户分配的特定标识进行 Azure 容器注册表映像拉取,而不允许容器中的代码使用该托管标识来访问注册表。 在此示例中,容器本身不需要访问注册表。

如果恶意行动者未经授权访问容器,此方法可限制可以访问的资源。

{
    "location": "chinaeast2",
    "identity":{
    "type": "SystemAssigned, UserAssigned",
        "userAssignedIdentities": {
            "<IDENTITY1_RESOURCE_ID>":{},
            "<ACR_IMAGEPULL_IDENTITY_RESOURCE_ID>":{}
         }
     },
    "properties": {
        "workloadProfileName":"Consumption",
        "environmentId": "<CONTAINER_APPS_ENVIRONMENT_ID>",
        "configuration": {
            "registries": [
            {
                "server": "myregistry.azurecr.cn",
                "identity": "ACR_IMAGEPULL_IDENTITY_RESOURCE_ID"
            }],
            "identitySettings":[
            {
                "identity": "ACR_IMAGEPULL_IDENTITY_RESOURCE_ID",
                "lifecycle": "None"
            },
            {
                "identity": "<IDENTITY1_RESOURCE_ID>",
                "lifecycle": "Init"
            },
            {
                "identity": "system",
                "lifecycle": "Main"
            }]
        },
        "template": {
            "containers":[
                {
                    "image":"myregistry.azurecr.cn/main:1.0",
                    "name":"app-main"
                }
            ],
            "initContainers":[
                {
                    "image":"myregistry.azurecr.cn/init:1.0",
                    "name":"app-init",
                }
            ]
        }
    }
}

查看托管标识

可以使用以下 Azure CLI 命令显示系统分配的托管标识和用户分配的托管标识。 输出会显示分配给容器应用的所有托管标识的托管标识类型、租户 ID 和主体 ID。

az containerapp identity show --name <APP_NAME> --resource-group <GROUP_NAME>

删除托管标识

删除系统分配的标识时,会从 Microsoft Entra ID 中删除标识。 删除容器应用资源本身时,系统分配的标识也会从 Microsoft Entra ID 中自动删除。 从容器应用中删除用户分配的托管标识不会导致从 Microsoft Entra ID 中删除这些标识。

若要删除系统分配的标识,请执行以下操作:

az containerapp identity remove --name <APP_NAME> --resource-group <GROUP_NAME> --system-assigned

要删除一个或多个用户分配的标识:

az containerapp identity remove --name <APP_NAME> --resource-group <GROUP_NAME> \
    --user-assigned <IDENTITY1_RESOURCE_ID> <IDENTITY2_RESOURCE_ID>

若要删除所有用户分配的标识,请执行以下操作:

az containerapp identity remove --name <APP_NAME> --resource-group <GROUP_NAME> \
    --user-assigned <IDENTITY1_RESOURCE_ID> <IDENTITY2_RESOURCE_ID>