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

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

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

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

注意

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

创建系统分配的托管标识

Azure 门户

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

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

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

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

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

Azure PowerShell

注意

若要与 Azure 交互,建议使用 Azure Az PowerShell 模块。 请参阅安装 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 属性标识该标识所属的 Azure AD 租户。 principalId 属性是实例的新标识的唯一标识符。 在 Azure AD 中,服务主体的名称与你为 API 管理实例提供的名称相同。

注意

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

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

请参阅 API 管理从 Key Vault 访问机密和证书所需的以下配置。

配置 Key Vault 访问策略

若要使用门户配置访问策略,请执行以下操作:

  1. 在 Azure 门户中,导航到你的密钥保管库。
  2. 选择“设置”>“访问策略”>“+添加访问策略”。
  3. 选择“机密权限”,然后选择“获取”和“列出”。
  4. 在“选择主体”中,选择你的托管标识的资源名称。 如果你使用系统分配的标识,则主体为你的 API 管理实例的名称。
  5. 选择 添加

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 事件中心 Trused-access-to-azure-event-hub

创建用户分配的托管标识

注意

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

Azure 门户

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

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

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

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

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

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

Azure PowerShell

注意

若要与 Azure 交互,建议使用 Azure Az PowerShell 模块。 请参阅安装 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 属性是用于 Azure AD 管理的标识的唯一标识符。 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 管理将自动获取该版本。

有关完整的模板,请参阅使用基于 Key Vault 的 SSL 和用户分配标识的 API 管理

在此模板中,将部署:

  • Azure API 管理实例
  • Azure 用户分配的托管标识
  • 用于存储 SSL/TLS 证书的 Azure Key Vault

若要自动运行部署,请选择以下按钮:

部署到 Azure

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

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

注意

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

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

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

删除标识

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

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

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

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

重要

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

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

后续步骤

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