在 Azure API 管理中使用托管标识

适用于:所有 API 管理层级

本文说明如何创建 Azure API 管理实例的托管标识以及如何使用它来访问其他资源。 借助 Microsoft Entra ID 生成的托管标识,API Management 实例可以轻松、安全地访问其他受 Microsoft Entra 保护的资源,例如 Azure Key Vault。 Azure 管理此标识,因此无需预配或轮换任何机密。 有关托管标识的详细信息,请参阅什么是 Azure 资源托管标识?

可以向 API 管理实例授予两种类型的标识:

  • 系统分配的标识与你的服务绑定,如果删除服务,标识也会被删除。 服务只能有一个系统分配的标识。
  • 用户分配的标识是可以分配给服务的独立 Azure 资源。 服务可以有多个用户分配的标识。

注意

托管标识特定于托管 Azure 订阅的 Microsoft Entra 租户。 如果将订阅移动到其他目录,则托管标识不会更新。 如果订阅移动,则需要重新创建和配置标识。

创建系统分配的托管标识

Azure 门户

若要在 Azure 门户中设置托管标识,需先创建 API 管理实例,然后启用该功能。

  1. 按常规在门户中创建 API 管理实例。 在门户中浏览到它。

  2. 在左侧菜单中,在“安全性”下,选择“托管标识”。

  3. 在“系统分配”选项卡中,将“状态”切换为“启用” 。 选择“保存” 。

    用于启用系统分配的托管标识的选项

Azure PowerShell

注意

建议使用 Azure Az PowerShell 模块与 Azure 交互。 请参阅安装 Azure PowerShell 以开始使用。 若要了解如何迁移到 Az PowerShell 模块,请参阅 将 Azure PowerShell 从 AzureRM 迁移到 Az

以下步骤将指导你完成使用 Azure PowerShell 创建 API 管理实例并为其分配标识的操作。

  1. 如果需要,请按照 Azure PowerShell 指南中的说明安装 Azure PowerShell。 然后运行 Connect-AzAccount 以创建与 Azure 的连接。

  2. 使用以下代码创建具有系统分配的托管标识的实例。 有关如何将 Azure PowerShell 与 API 管理实例配合使用的更多示例,请参阅 API 管理 PowerShell 示例

    # Create a resource group.
    New-AzResourceGroup -Name $resourceGroupName -Location $location
    
    # Create an API Management Consumption Sku service.
    New-AzApiManagement -ResourceGroupName $resourceGroupName -Name consumptionskuservice -Location $location -Sku Consumption -Organization contoso -AdminEmail contoso@contoso.com -SystemAssignedIdentity
    

你还可以更新现有实例以创建标识:

# Get an API Management instance
$apimService = Get-AzApiManagement -ResourceGroupName $resourceGroupName -Name $apiManagementName

# Update an API Management instance
Set-AzApiManagement -InputObject $apimService -SystemAssignedIdentity

Azure 资源管理器模板

在资源定义中包括以下属性,可以创建具有系统分配的标识的 API 管理实例:

"identity" : {
    "type" : "SystemAssigned"
}

此属性将告知 Azure 为 API 管理实例创建和管理标识。

例如,完整的 Azure 资源管理器模板可能如下所示:

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "0.9.0.0",
    "resources": [{
        "apiVersion": "2021-08-01",
        "name": "contoso",
        "type": "Microsoft.ApiManagement/service",
        "location": "[resourceGroup().location]",
        "tags": {},
        "sku": {
            "name": "Developer",
            "capacity": "1"
        },
        "properties": {
            "publisherEmail": "admin@contoso.com",
            "publisherName": "Contoso"
        },
        "identity": {
            "type": "systemAssigned"
        }
    }]
}

创建实例后,它具有以下附加属性:

"identity": {
    "type": "SystemAssigned",
    "tenantId": "<TENANTID>",
    "principalId": "<PRINCIPALID>"
}

tenantId 属性标识该标识所属的 Microsoft Entra 租户。 principalId 属性是实例的新标识的唯一标识符。 在 Microsoft Entra ID 中,服务主体的名称与你为 API 管理实例提供的名称相同。

注意

API 管理实例可以同时具有系统分配的标识和用户分配的标识。 在这种情况下,type 属性将为 SystemAssigned,UserAssigned

使用托管标识配置 Key Vault 访问

API 管理需要以下配置才能从 Azure 密钥保管库访问机密和证书。

配置对密钥保管库的访问权限

  1. 在门户中导航到你的密钥保管库。

  2. 在左侧菜单中,选择“访问配置”,并记下配置的权限模型

  3. 根据权限模型,为 API 管理托管标识配置密钥保管库访问策略Azure RBAC 访问

    添加密钥保管库访问策略:

    1. 在左侧菜单中,选择“访问策略”。
    2. 在“访问策略”页上,选择“+ 创建”。
    3. 在“权限”选项卡上的“机密权限”下,选中“获取”和“列出”,然后选择“下一步”。
    4. 在“主体”选项卡上的“选择主体”中,搜索托管标识的资源名称,然后选择“下一步”。 如果你使用系统分配的标识,则主体为你的 API 管理实例的名称。
    5. 再次选择“下一步”。 在“查看 + 创建”选项卡上,选择“创建”。

    配置 Azure RBAC 访问:

    1. 在左侧菜单中,选择“访问控制(IAM)”。
    2. 在“访问控制(IAM)”页上,选择“添加角色分配”。
    3. 在“角色”选项卡上,选择“密钥保管库机密用户”。
    4. 在“成员”选项卡上,选择“托管标识”>“+ 选择成员”。
    5. 在“选择托管标识”页上,选择系统分配的托管标识或与 API 管理实例关联的用户分配的托管标识,然后选择“选择”。
    6. 选择“查看 + 分配”。

Key Vault 防火墙要求

如果在密钥保管库上启用了 Key Vault 防火墙,则具有以下附加要求:

  • 必须使用 API 管理实例的“系统分配的”托管标识来访问密钥保管库。

  • 在 Key Vault 防火墙中,启用“允许受信任的 Microsoft 服务绕过此防火墙”选项。

  • 在选择要添加到 Azure API 管理的证书或机密时,请确保允许本地客户端 IP 地址临时访问密钥保管库。 有关详细信息,请参阅配置 Azure Key Vault 网络设置

    完成配置后,可以在密钥保管库防火墙中阻止客户端地址。

虚拟网络要求

如果 API 管理实例部署在虚拟网络中,则还应配置下列网络设置:

  • 在 API 管理子网上,启用 Azure Key Vault 的服务终结点
  • 配置一个网络安全组 (NSG) 规则,以允许指向 AzureKeyVault 和 AzureActiveDirectory 服务标记的出站流量。

有关详细信息,请参阅在 VNET 中设置 Azure API 管理时使用的网络配置

使用系统分配标识的受支持方案

从 Azure 密钥保管库获取 API 管理实例的自定义 TLS/SSL 证书

可以使用 API 管理实例的系统分配标识来检索存储在 Azure 密钥保管库中的自定义 TLS/SSL 证书。 然后,可以将这些证书分配给 API 管理实例中的自定义域。 请记住以下注意事项:

  • 机密的内容类型必须是 application/x-pkcs12。 详细了解自定义域证书要求
  • 使用包含机密的密钥保管库证书机密终结点。

重要

如果未提供证书的对象版本,在将证书的较新版本上传到密钥保管库后的四小时内,API 管理将自动获取该版本。

以下示例演示了一个 Azure 资源管理器模板,该模板使用 API 管理服务实例的系统分配托管标识从 Key Vault 检索自定义域证书。

先决条件

  • 使用系统分配的托管标识配置的 API 管理服务实例。 若要创建实例,可以使用 Azure 快速入门模板
  • 同一资源组中的 Azure Key Vault 实例,托管将用作 API 管理中的自定义域证书的证书。

以下模板包含以下步骤。

  1. 更新 Azure Key Vault 实例的访问策略,并允许 API 管理实例从中获取机密。
  2. 通过 Key Vault 实例中的证书设置自定义域名来更新 API 管理实例。

运行模板时,请提供适合环境的参数值。

{
	"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
	"contentVersion": "1.0.0.0",
	"parameters": {
        "apiManagementServiceName": {
            "type": "string",
            "minLength": 8,
            "metadata":{
                "description": "The name of the API Management service"
            }
        },
		"publisherEmail": {
			"type": "string",
			"minLength": 1,
			"metadata": {
				"description": "The email address of the owner of the service"
			}
		},
		"publisherName": {
			"type": "string",
			"minLength": 1,
			"metadata": {
				"description": "The name of the owner of the service"
			}
		},
		"sku": {
			"type": "string",
			"allowedValues": ["Developer",
			"Standard",
			"Premium"],
			"defaultValue": "Developer",
			"metadata": {
				"description": "The pricing tier of this API Management service"
			}
		},
		"skuCount": {
			"type": "int",
			"defaultValue": 1,
			"metadata": {
				"description": "The instance size of this API Management service."
			}
		},
        "keyVaultName": {
            "type": "string",
            "metadata": {
                "description": "Name of the key vault"
            }
        },
		"proxyCustomHostname1": {
			"type": "string",
			"metadata": {
				"description": "Gateway custom hostname 1. Example: api.contoso.com"
			}
		},
		"keyVaultIdToCertificate": {
			"type": "string",
			"metadata": {
				"description": "Reference to the key vault certificate. Example: https://contoso.vault.azure.cn/secrets/contosogatewaycertificate"
			}
		}
	},
	 "variables": {
        "apimServiceIdentityResourceId": "[concat(resourceId('Microsoft.ApiManagement/service', parameters('apiManagementServiceName')),'/providers/Microsoft.ManagedIdentity/Identities/default')]"
		    },
	"resources": [ 
   {
        "apiVersion": "2021-08-01",
        "name": "[parameters('apiManagementServiceName')]",
        "type": "Microsoft.ApiManagement/service",
        "location": "[resourceGroup().location]",
        "tags": {
        },
        "sku": {
            "name": "[parameters('sku')]",
            "capacity": "[parameters('skuCount')]"
        },
        "properties": {
            "publisherEmail": "[parameters('publisherEmail')]",
            "publisherName": "[parameters('publisherName')]"
        },
        "identity": {
            "type": "systemAssigned"
        }
    },
    {
        "type": "Microsoft.KeyVault/vaults/accessPolicies",
        "name": "[concat(parameters('keyVaultName'), '/add')]",
        "apiVersion": "2018-02-14",
        "properties": {
            "accessPolicies": [{
                "tenantId": "[reference(variables('apimServiceIdentityResourceId'), '2018-11-30').tenantId]",
                "objectId": "[reference(variables('apimServiceIdentityResourceId'), '2018-11-30').principalId]",
                "permissions": {
                     "secrets": ["get", "list"]
                }
            }]
        }
    },
	{
        "apiVersion": "2021-04-01",
		"type": "Microsoft.Resources/deployments",
        "name": "apimWithKeyVault",
		 "dependsOn": [
        "[resourceId('Microsoft.ApiManagement/service', parameters('apiManagementServiceName'))]"
        ],
        "properties": {
            "mode": "incremental",
            "template": {
                "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
				"contentVersion": "1.0.0.0",
				"parameters": {},			
				"resources": [{
					"apiVersion": "2021-08-01",
					"name": "[parameters('apiManagementServiceName')]",
					"type": "Microsoft.ApiManagement/service",
					"location": "[resourceGroup().location]",
					"tags": {
					},
					"sku": {
						"name": "[parameters('sku')]",
						"capacity": "[parameters('skuCount')]"
					},
					"properties": {
						"publisherEmail": "[parameters('publisherEmail')]",
						"publisherName": "[parameters('publisherName')]",
						"hostnameConfigurations": [{
							"type": "Proxy",
							"hostName": "[parameters('proxyCustomHostname1')]",
							"keyVaultId": "[parameters('keyVaultIdToCertificate')]"
						}]
					},
					"identity": {
						"type": "systemAssigned"
					}
				}]
		}
		}
	}
]
}

存储和管理 Azure Key Vault 中的命名值

可以使用系统分配的托管标识访问 Azure Key Vault 来存储和管理用于 API 管理策略的机密。 有关详细信息,请参阅在 Azure API 管理策略中使用命名值

使用 API 管理标识向后端进行身份验证

可以使用系统分配的标识通过 authentication-managed-identity 策略向后端服务进行身份验证。

使用系统分配的托管标识连接到 IP 防火墙后面的 Azure 资源

API 管理是针对以下资源的受信任 Microsoft 服务。 这允许服务连接到防火墙后面的以下资源。 在为该资源实例的系统分配的托管标识显式分配适当的 Azure 角色之后,该实例的访问范围将与分配给托管标识的 Azure 角色相对应。

Azure 服务 链接
Azure Key Vault Trusted-access-to-azure-key-vault
Azure 存储 Trusted-access-to-azure-storage
Azure 服务总线 Trusted-access-to-azure-service-bus
Azure 事件中心 Trusted-access-to-azure-event-hub

将事件记录到事件中心

可以配置和使用系统分配的托管标识来访问事件中心,以便从API 管理实例记录事件。 如需了解更多信息,请参阅如何在 Azure API 管理中将事件记录到 Azure 事件中心

创建用户分配的托管标识

注意

可以将一个 API 管理实例与最多 10 个用户分配的托管标识相关联。

Azure 门户

若要在门户中设置托管标识,需先创建 API 管理实例,然后创建用户分配的标识。 然后启用此功能。

  1. 按常规在门户中创建 API 管理实例。 在门户中浏览到它。

  2. 在左侧菜单中,在“安全性”下,选择“托管标识”。

  3. 在“用户分配”选项卡上,选择“添加”。

  4. 搜索之前创建的标识并选择它。 选择“添加” 。

    用于启用用户分配的托管标识的选项

Azure PowerShell

注意

建议使用 Azure Az PowerShell 模块与 Azure 交互。 请参阅安装 Azure PowerShell 以开始使用。 若要了解如何迁移到 Az PowerShell 模块,请参阅 将 Azure PowerShell 从 AzureRM 迁移到 Az

以下步骤将指导你完成使用 Azure PowerShell 创建 API 管理实例并为其分配标识的操作。

  1. 如果需要,请按照 Azure PowerShell 指南中的说明安装 Azure PowerShell。 然后运行 Connect-AzAccount 以创建与 Azure 的连接。

  2. 使用以下代码创建实例。 有关如何将 Azure PowerShell 与 API 管理实例配合使用的更多示例,请参阅 API 管理 PowerShell 示例

    # Create a resource group.
    New-AzResourceGroup -Name $resourceGroupName -Location $location
    
    # Create a user-assigned identity. This requires installation of the "Az.ManagedServiceIdentity" module.
    $userAssignedIdentity = New-AzUserAssignedIdentity -Name $userAssignedIdentityName -ResourceGroupName $resourceGroupName
    
    # Create an API Management Consumption Sku service.
    $userIdentities = @($userAssignedIdentity.Id)
    
    New-AzApiManagement -ResourceGroupName $resourceGroupName -Location $location -Name $apiManagementName -Organization contoso -AdminEmail admin@contoso.com -Sku Consumption -UserAssignedIdentity $userIdentities
    

还可以更新现有服务以向服务分配标识:

# Get an API Management instance
$apimService = Get-AzApiManagement -ResourceGroupName $resourceGroupName -Name $apiManagementName

# Create a user-assigned identity. This requires installation of the "Az.ManagedServiceIdentity" module.
$userAssignedIdentity = New-AzUserAssignedIdentity -Name $userAssignedIdentityName -ResourceGroupName $resourceGroupName

# Update an API Management instance
$userIdentities = @($userAssignedIdentity.Id)
Set-AzApiManagement -InputObject $apimService -UserAssignedIdentity $userIdentities

Azure Resource Manager 模板

在资源定义中包括以下属性,可以创建具有标识的 API 管理实例:

"identity": {
    "type": "UserAssigned",
    "userAssignedIdentities": {
        "<RESOURCEID>": {}
    }
}

添加用户分配的类型即告知 Azure 使用为实例指定的用户分配标识。

例如,完整的 Azure 资源管理器模板可能如下所示:

{
    "$schema": "https://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json#",
    "contentVersion": "0.9.0.0",
    "resources": [{
        "apiVersion": "2021-08-01",
        "name": "contoso",
        "type": "Microsoft.ApiManagement/service",
        "location": "[resourceGroup().location]",
        "tags": {},
        "sku": {
            "name": "Developer",
            "capacity": "1"
        },
        "properties": {
            "publisherEmail": "admin@contoso.com",
            "publisherName": "Contoso"
        },
        "identity": {
            "type": "UserAssigned",
             "userAssignedIdentities": {
                "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('identityName'))]": {}
             }
        },
         "dependsOn": [
          "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('identityName'))]"
        ]
    }]
}

创建服务后,它具有以下附加属性:

"identity": {
    "type": "UserAssigned",
    "userAssignedIdentities": {
        "<RESOURCEID>": {
            "principalId": "<PRINCIPALID>",
            "clientId": "<CLIENTID>"
        }
    }
}

principalId 属性是用于 Microsoft Entra 管理的标识的唯一标识符。 clientId 属性是应用程序的新标识的唯一标识符,用于指定在运行时调用期间要使用的标识。

备注

API 管理实例可以同时具有系统分配的标识和用户分配的标识。 在这种情况下,type 属性将为 SystemAssigned,UserAssigned

使用用户分配的托管标识的受支持方案

从 Azure 密钥保管库获取 API 管理实例的自定义 TLS/SSL 证书

你可以使用用户分配的标识在 API 管理实例和 Azure Key Vault 之间建立信任。 然后,可以借助这种信任关系检索存储在 Azure Key Vault 中的自定义 TLS/SSL 证书。 然后,可以将这些证书分配给 API 管理实例中的自定义域。

重要

如果密钥保管库上启用了 Key Vault 防火墙,则无法使用用户分配的标识从 API 管理进行访问。 可以改用系统分配的标识。 在 Key Vault 防火墙中,还必须启用“允许受信任的 Microsoft 服务绕过此防火墙”选项。

请记住以下注意事项:

  • 机密的内容类型必须是 application/x-pkcs12。
  • 使用包含机密的密钥保管库证书机密终结点。

重要

如果未提供证书的对象版本,在将证书的较新版本上传到密钥保管库后的四小时内,API 管理将自动获取该版本。

存储和管理 Azure Key Vault 中的命名值

可以使用用户分配的托管标识访问 Azure Key Vault 来存储和管理用于 API 管理策略的机密。 有关详细信息,请参阅在 Azure API 管理策略中使用命名值

注意

如果密钥保管库上启用了 Key Vault 防火墙,则无法使用用户分配的标识从 API 管理进行访问。 可以改用系统分配的标识。 在 Key Vault 防火墙中,还必须启用“允许受信任的 Microsoft 服务绕过此防火墙”选项。

使用用户分配的标识向后端进行身份验证

可以使用用户分配的标识通过 authentication-managed-identity 策略向后端服务进行身份验证。

将事件记录到事件中心

可以配置和使用用户分配的托管标识来访问事件中心,以便从API 管理实例记录事件。 如需了解更多信息,请参阅如何在 Azure API 管理中将事件记录到 Azure 事件中心

删除标识

可以通过在门户中禁用功能或通过 Azure 资源管理器模板(和创建标识的方法相同)来删除系统分配的标识。 可以单独删除用户分配的标识。 若要删除所有标识,请将标识类型设置为 "None"

以这种方式删除系统分配的标识也会将它从 Microsoft Entra ID 中删除。 删除 API 管理实例时,也将自动从 Microsoft Entra ID 中删除系统分配的标识。

若要使用 Azure 资源管理器模板删除所有标识,请更新此部分:

"identity": {
    "type": "None"
}

重要

如果使用密钥保管库中的自定义 SSL 证书配置了 API 管理实例,并尝试禁用托管标识,则请求将失败。

可以通过从 Azure 密钥保管库证书切换到内联编码证书,然后禁用托管标识来取消阻止自己。 有关详细信息,请参阅配置自定义域名

后续步骤

详细了解 Azure 资源的托管标识: