配置用户分配的托管标识以信任外部标识提供者

本文介绍如何在 Microsoft Entra ID 中管理用户分配的托管标识的联合标识凭据。 联合标识凭据在用户分配的托管标识与外部标识提供者 (IdP) 之间创建信任关系。 不支持在系统分配的托管标识上配置联合标识凭据。

将用户分配的托管标识配置为信任外部 IdP 后,配置外部软件工作负荷以将来自外部 IdP 的令牌交换为来自 Microsoft 标识平台的访问令牌。 外部工作负荷使用访问令牌来访问 Microsoft Entra 受保护的资源,而无需管理机密(在支持的场景中)。 若要详细了解令牌交换工作流,请阅读工作负荷标识联合验证

本文介绍如何在用户分配的托管标识中创建、列出和删除联合标识凭据。

重要注意事项和限制

最多可以向应用程序或用户分配的托管标识添加 20 个联合标识凭据。

配置联合标识凭据时,需要提供几条重要信息:

  • issuer 和 subject 是建立信任关系所需的关键信息。 issuersubject 的组合在应用中必须唯一。 当外部软件工作负荷请求 Microsoft 标识平台来交换访问令牌的外部令牌时,将针对外部令牌中提供的 issuersubject 声明来检查联合标识凭据的 issuer 和 subject 值。 如果该验证检查通过,Microsoft 标识平台会向外部软件工作负荷发出访问令牌。

  • issuer 是外部身份提供商的 URL,必须与要交换的外部令牌的 issuer 声明相匹配。 必需。 如果 issuer 声明具有值中的前导或尾随空格,则会阻止令牌交换。 此字段的字符限制为 600 个字符。

  • subject 是外部标识提供者的标识符,必须与要交换的外部令牌的 sub (subject) 声明相匹配。 subject 没有固定格式,因为每个 IdP 都使用自己的格式,格式有时是 GUID,有时是冒号分隔的标识符,有时是任意字符串。 此字段的字符限制为 600 个字符。

    重要

    “subject”设置值必须与 GitHub 工作流配置中的配置完全匹配。 否则,Microsoft 标识平台将查看传入的外部令牌,并拒绝交换访问令牌。 你不会收到错误消息,交换失败且没有错误。

    重要

    如果在 subject 设置中意外添加了不正确的外部工作负荷信息,则已成功创建联合标识凭据,且未出现错误。 在令牌交换失败之前,此错误不会变得明显。

  • audiences 列出了可出现在外部令牌中的受众。 必需。 必须添加一个受众值,该值限制为 600 个字符。 建议的值为“api://AzureADTokenExchange”。 它表示 Microsoft 标识平台必须接受传入令牌中的 aud 声明。

  • name 是联合标识凭据的唯一标识符。 必需。 此字段的字符限制为 3-120 个字符,并且必须对 URL 友好。 支持字母数字、短划线或下划线字符,第一个字符必须是字母数字字符。  它在创建后就不可变。

  • description 是用户提供的联合标识凭据的说明。 可选。 Microsoft Entra ID 不会验证或检查说明。 此字段的上限为 600 个字符。

任何联合标识凭据属性值都不支持通配符。

若要详细了解受支持的区域、传播联合凭据更新的时间、支持的颁发者等,请阅读联合标识凭据的重要注意事项和限制

先决条件

在用户分配的托管标识上配置联合标识凭据

Microsoft Entra 管理中心中,导航到你创建的用户分配的托管标识。 在左侧导航栏中的“设置”下,选择“联合凭据”,然后选择“添加凭据”。

在“联合凭据场景”下拉列表框中,选择你的场景。

部署 Azure 资源的 GitHub Actions

要为 GitHub 操作添加联合身份,请执行以下步骤:

  1. 对于“实体类型”,请选择“环境”、“分支”、“拉取请求”或“标记”,并指定值。 值必须与 GitHub 工作流中的配置完全匹配。 有关详细信息,请阅读示例

  2. 为联合凭据添加“名称”

  3. “颁发者”、“受众”和“主题标识符”字段会根据你输入的值自动填充。

  4. 选择“添加”以配置联合凭据。

将你的 Microsoft Entra 托管标识中的以下值用于你的 GitHub 工作流:

  • AZURE_CLIENT_ID,托管标识客户端 ID

  • AZURE_SUBSCRIPTION_ID,订阅 ID

    下面的屏幕截图演示了如何复制托管标识 ID 和订阅 ID。

    演示如何从 Azure 门户复制托管标识 ID 和订阅 ID 的屏幕截图。

  • AZURE_TENANT_ID 目录(租户)ID。 了解如何查找 Microsoft Entra 租户 ID

实体类型示例

分支示例

对于主分支上的推送或拉取请求事件触发的工作流,请执行以下操作:

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

将“实体类型”指定为“分支”,将“GitHub 分支名称”指定为“main”。

环境示例

对于绑定到名为“production”的环境的“作业”,请执行以下操作:

on:
  push:
    branches:
      - main

jobs:
  deployment:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - name: deploy
        # ...deployment-specific steps

将“实体类型”指定为“环境”,将“GitHub 环境名称”指定为“production”。

标记示例

例如,对于目标为标记“v2”的推送触发的工作流,请执行以下操作:

on:
  push:
    # Sequence of patterns matched against refs/heads
    branches:
      - main
      - 'mona/octocat'
      - 'releases/**'
    # Sequence of patterns matched against refs/tags
    tags:
      - v2
      - v1.*

将“实体类型”指定为“标记”,将“GitHub 标记名称”指定为“v2”。

拉取请求示例

对于拉取请求事件触发的工作流,请将“实体类型”指定为“拉取请求”

访问 Azure 资源的 Kubernetes

填写“群集证书颁发者 URL”、“命名空间”、“服务帐户名称”和“名称”字段:

  • “群集证书颁发者 URL”是托管群集的 OIDC 证书颁发者 URL 或自托管群集的 OIDC 证书颁发者 URL
  • “服务帐户名称”是 Kubernetes 服务帐户的名称,它为 Pod 中运行的进程提供标识。
  • “命名空间”是服务帐户命名空间。
  • “Name”是联合凭据的名称,以后将无法更改。

选择“添加”以配置联合凭据。

其他

从下拉菜单中选择“其他证书颁发者”场景。

指定以下字段(以在 Google Cloud 中运行的一个软件工作负载为例):

  • “Name”是联合凭据的名称,以后将无法更改。
  • 主题标识符:必须与外部标识提供者颁发的令牌中的 sub 声明匹配。 在本示例中使用 Google Cloud,subject 是你计划使用的服务帐户的唯一 ID。
  • 证书颁发者:必须与外部标识提供者颁发的令牌中的 iss 声明匹配。 符合 OIDC 发现规范的 URL。Microsoft Entra ID 使用此颁发者 URL 提取验证令牌所需的密钥。 对于 Google Cloud,issuer 为 https://accounts.google.com";

选择“添加”以配置联合凭据。

在用户分配的托管标识上列出联合标识凭据

Microsoft Entra 管理中心中,导航到你创建的用户分配的托管标识。 在左侧导航栏中的“设置”下,选择“联合凭据”。

在该用户分配的托管标识上配置的联合标识凭据已列出。

从用户分配的托管标识中删除联合标识凭据

Microsoft Entra 管理中心中,导航到你创建的用户分配的托管标识。 在左侧导航栏中的“设置”下,选择“联合凭据”。

在该用户分配的托管标识上配置的联合标识凭据已列出。

若要删除特定联合标识凭据,请选择凭据的“删除”图标。

先决条件

在用户分配的托管标识上配置联合标识凭据

运行 az identity federated-credential create 命令,在用户分配的托管标识(由相应名称指定)上创建新的联合标识凭据。 指定 name、issuer、subject 和其他参数。

az login

# set variables
location="centralus"
subscription="{subscription-id}"
rg="fic-test-rg"

# user assigned identity name
uaId="fic-test-ua"

# federated identity credential name
ficId="fic-test-fic-name"

# create prerequisites if required.
# otherwise make sure that existing resources names are set in variables above
az account set --subscription $subscription
az group create --location $location --name $rg
az identity create --name $uaId --resource-group $rg --location $location --subscription $subscription

# Create/update a federated identity credential
az identity federated-credential create --name $ficId --identity-name $uaId --resource-group $rg --issuer 'https://aks.azure.com/issuerGUID' --subject 'system:serviceaccount:ns:svcaccount' --audiences 'api://AzureADTokenExchange'

在用户分配的托管标识上列出联合标识凭据

运行 az identity federated-credential list 命令,读取在用户分配的托管标识上配置的所有联合标识凭据:

az login

# Set variables
rg="fic-test-rg"

# User assigned identity name
uaId="fic-test-ua"

# Read all federated identity credentials assigned to the user-assigned managed identity
az identity federated-credential list --identity-name $uaId --resource-group $rg

在用户分配的托管标识上获取联合标识凭据

运行 az identity federated-credential show 命令,显示联合标识凭据(按 ID):

az login

# Set variables
rg="fic-test-rg"

# User assigned identity name
uaId="fic-test-ua"

# Federated identity credential name
ficId="fic-test-fic-name"

# Show the federated identity credential
az identity federated-credential show --name $ficId --identity-name $uaId --resource-group $rg

从用户分配的托管标识中删除联合标识凭据

运行 az identity federated-credential delete 命令,删除现有用户分配的标识下的联合标识凭据。

az login

# Set variables
# in Linux shell remove $ from set variable statement
$rg="fic-test-rg"

# User assigned identity name
$uaId="fic-test-ua"

# Federated identity credential name
$ficId="fic-test-fic-name"

az identity federated-credential delete --name $ficId --identity-name $uaId --resource-group $rg

先决条件

在本地配置 Azure PowerShell

若要在本文中本地使用 Azure PowerShell 而不是使用 Cloud Shell,请执行以下操作:

  1. 安装最新版本的 Azure PowerShell(如果尚未安装)。

  2. 登录 Azure。

    Connect-AzAccount
    
  3. 安装最新版本的 PowerShellGet

    Install-Module -Name PowerShellGet -AllowPrerelease
    

    在下一步运行此命令后,可能需要 Exit 退出当前 PowerShell 会话。

  4. 安装 Az.ManagedServiceIdentity 模块,以执行本文中用户分配的托管标识操作。

    Install-Module -Name Az.ManagedServiceIdentity
    

在用户分配的托管标识上配置联合标识凭据

运行 New-AzFederatedIdentityCredentials 命令,在用户分配的托管标识(由相应名称指定)上创建新的联合标识凭据。 指定 name、issuer、subject 和其他参数。

New-AzFederatedIdentityCredentials -ResourceGroupName azure-rg-test -IdentityName uai-pwsh01 `
    -Name fic-pwsh01 -Issuer "https://kubernetes-oauth.azure.com" -Subject "system:serviceaccount:ns:svcaccount"

在用户分配的托管标识上列出联合标识凭据

运行 Get-AzFederatedIdentityCredentials 命令,读取在用户分配的托管标识上配置的所有联合标识凭据:

Get-AzFederatedIdentityCredentials -ResourceGroupName azure-rg-test -IdentityName uai-pwsh01

在用户分配的托管标识上获取联合标识凭据

运行 Get-AzFederatedIdentityCredentials 命令,显示联合标识凭据(按名称):

Get-AzFederatedIdentityCredentials -ResourceGroupName azure-rg-test -IdentityName uai-pwsh01 -Name fic-pwsh01

从用户分配的托管标识中删除联合标识凭据

运行 Remove-AzFederatedIdentityCredentials 命令,删除现有用户分配标识下的联合标识凭据。

Remove-AzFederatedIdentityCredentials -ResourceGroupName azure-rg-test -IdentityName uai-pwsh01 -Name fic-pwsh01

先决条件

模板创建和编辑

资源管理器模板有助于部署由 Azure 资源组定义的新资源或已修改资源。 有多种可用于执行模板编辑和部署的方法(包括本地方法和基于门户的方法)。 方法:

在用户分配的托管标识上配置联合标识凭据

联合标识凭据和父级用户分配的标识可通过以下模板创建或更新。 可以从 Azure 门户部署 ARM 模板

所有模板参数都是必需的。

联合标识凭据名称长度限制为 3-120 个字符。 名称必须为字母数字、短划线、下划线。 第一个符号仅为字母数字。

必须向联合标识凭据添加正好 1 名受众。 将在令牌交换期间对该受众进行验证。 使用“api://AzureADTokenExchange”作为默认值。

模板不提供列表、获取和删除操作。 有关这些操作,请参阅 Azure CLI。 默认情况下,所有子级联合标识凭据都并行创建,这会触发并发检测逻辑,并导致部署失败并出现 409 冲突的 HTTP 状态代码。 若要按顺序创建,请使用 dependsOn 属性指定依赖项链。

确保任何类型的自动化都按顺序在同一父标识下创建联合标识凭据。 联合标识凭据可在不同托管标识下并行创建,且没有任何限制。

{

    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "variables": {},
    "parameters": {
        "location": {
            "type": "string",
            "defaultValue": "westcentralus",
            "metadata": {
                "description": "Location for identities resources. FIC should be enabled in this region."
            }
        },
        "userAssignedIdentityName": {
            "type": "string",
            "defaultValue": "FIC_UA",
            "metadata": {
                "description": "Name of the User Assigned identity (parent identity)"
            }
        },
        "federatedIdentityCredential": {
            "type": "string",
            "defaultValue": "testCredential",
            "metadata": {
                "description": "Name of the Federated Identity Credential"
            }
        },
        "federatedIdentityCredentialIssuer": {
            "type": "string",
            "defaultValue": "https://aks.azure.com/issuerGUID",
            "metadata": {
                "description": "Federated Identity Credential token issuer"
            }
        },
        "federatedIdentityCredentialSubject": {
            "type": "string",
            "defaultValue": "system:serviceaccount:ns:svcaccount",
            "metadata": {
                "description": "Federated Identity Credential token subject"
            }
        },
        "federatedIdentityCredentialAudience": {
            "type": "string",
            "defaultValue": " api://AzureADTokenExchange",
            "metadata": {
                "description": "Federated Identity Credential audience. Single value is only supported."
            }
        }
    },
    "resources": [
        {
            "type": "Microsoft.ManagedIdentity/userAssignedIdentities",
            "apiVersion": "2018-11-30",
            "name": "[parameters('userAssignedIdentityName')]",
            "location": "[parameters('location')]",
            "tags": {
                "firstTag": "ficTest"
            },
            "resources": [
                {
                    "type": "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials",
                    "apiVersion": "2022-01-31-PREVIEW",
                    "name": "[concat(parameters('userAssignedIdentityName'), '/', parameters('federatedIdentityCredential'))]",
                    "dependsOn": [
                      "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('userAssignedIdentityName'))]"
                    ],
                    "properties": {
                        "issuer": "[parameters('federatedIdentityCredentialIssuer')]",
                        "subject": "[parameters('federatedIdentityCredentialSubject')]",
                        "audiences": [
                            "[parameters('federatedIdentityCredentialAudience')]"
                        ]
                    }
                }
            ]
        }
    ]
}

先决条件

获取持有者访问令牌

  1. 如果在本地运行,请通过 Azure CLI 登录到 Azure。

    az login
    
  2. 使用 az account get-access-token 获取访问令牌。

    az account get-access-token
    

在用户分配的托管标识上配置联合标识凭据

在用户分配的指定托管标识上创建或更新联合标识凭据

curl 'https://management.azure.com/subscriptions/<SUBSCRIPTION ID>/resourceGroups/<RESOURCE GROUP>/provider
s/Microsoft.ManagedIdentity/userAssignedIdentities/<USER ASSIGNED IDENTITY NAME>/federatedIdenti
tyCredentials/<FEDERATED IDENTITY CREDENTIAL NAME>?api-version=2022-01-31-preview' -X PUT -d '{"properties": "{ "properties": { "issuer": "<ISSUER>", "subject": "<SUBJECT>", "audiences": [ "api://AzureADTokenExchange" ] }}"}' -H "Content-Type: application/json" -H "Authorization: Bearer <ACCESS TOKEN>"
PUT https://management.azure.com/subscriptions/<SUBSCRIPTION ID>/resourceGroups/<RESOURCE GROUP>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<USER ASSIGNED IDENTITY NAME>/federatedIdentityCredentials/<FEDERATED IDENTITY CREDENTIAL NAME>?api-version=2022-01-31-preview

{
 "properties": {
 "issuer": "https://oidc.prod-aks.azure.com/IssuerGUID",
 "subject": "system:serviceaccount:ns:svcaccount",
 "audiences": [
 "api://AzureADTokenExchange"
 ]
 }
}

请求标头

请求标头 说明
Content-Type 必需。 设置为 application/json
授权 必需。 设置为有效的 Bearer 访问令牌。

请求正文

名称 说明
properties.audiences 必需。 可在颁发的令牌中显示的受众列表。
properties.issuer 必需。 要信任的颁发者的 URL。
properties.subject 必需。 外部文件的标识符。

在用户分配的托管标识上列出联合标识凭据

在用户分配的指定托管标识上列出所有联合标识凭据

curl 'https://management.azure.com/subscriptions/<SUBSCRIPTION ID>/resourceGroups/<RESOURCE GROUP>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<USER ASSIGNED IDENTITY NAME>/<RESOURCE NAME>/federatedIdentityCredentials?api-version=2022-01-31-preview' -H "Content-Type: application/json" -X GET -H "Authorization: Bearer <ACCESS TOKEN>"
GET
https://management.azure.com/subscriptions/<SUBSCRIPTION ID>/resourceGroups/<RESOURCE GROUP>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<USER ASSIGNED IDENTITY NAME>/<RESOURCE NAME>/federatedIdentityCredentials?api-version=2022-01-31-preview

请求标头

请求标头 说明
Content-Type 必需。 设置为 application/json
授权 必需。 设置为有效的 Bearer 访问令牌。

在用户分配的托管标识上获取联合标识凭据

在用户分配的指定托管标识上获取联合标识凭据

curl 'https://management.azure.com/subscriptions/<SUBSCRIPTION ID>/resourceGroups/<RESOURCE GROUP>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<USER ASSIGNED IDENTITY NAME>/<RESOURCE NAME>/federatedIdentityCredentials/<FEDERATED IDENTITY CREDENTIAL RESOURCENAME>?api-version=2022-01-31-preview' -X GET -H "Content-Type: application/json" -H "Authorization: Bearer <ACCESS TOKEN>"
GET
https://management.azure.com/subscriptions/<SUBSCRIPTION ID>/resourceGroups/<RESOURCE GROUP>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<USER ASSIGNED IDENTITY NAME>/<RESOURCE NAME>/federatedIdentityCredentials/<FEDERATED IDENTITY CREDENTIAL RESOURCENAME>?api-version=2022-01-31-preview

请求标头

请求标头 说明
Content-Type 必需。 设置为 application/json
授权 必需。 设置为有效的 Bearer 访问令牌。

从用户分配的托管标识中删除联合标识凭据

在用户分配的指定托管标识上删除联合标识凭据

curl 'https://management.azure.com/subscriptions/<SUBSCRIPTION ID>/resourceGroups/<RESOURCE GROUP>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<USER ASSIGNED IDENTITY NAME>/<RESOURCE NAME>/federatedIdentityCredentials/<FEDERATED IDENTITY CREDENTIAL RESOURCENAME>?api-version=2022-01-31-preview' -X DELETE -H "Content-Type: application/json" -H "Authorization: Bearer <ACCESS TOKEN>"
DELETE
https://management.azure.com/subscriptions/<SUBSCRIPTION ID>/resourceGroups/<RESOURCE GROUP>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<USER ASSIGNED IDENTITY NAME>/<RESOURCE NAME>/federatedIdentityCredentials/<FEDERATED IDENTITY CREDENTIAL RESOURCENAME>?api-version=2022-01-31-preview

请求标头

请求标头 说明
Content-Type 必需。 设置为 application/json
授权 必需。 设置为有效的 Bearer 访问令牌。

后续步骤

  • 有关由外部标识提供者创建的 JWT 所需格式的信息,请阅读断言格式