当我尝试使用用户分配的托管标识从 Azure Key Vault 为我的 API 管理实例获取自定义 TLS/SSL 证书时遇到问题,如下所述:获取 API 管理实例的自定义 TLS/SSL 证书从 Azure Key Vault。与文档的不同之处在于我的 Key Vault 启用了网络访问规则。特别是用户分配的托管标识和密钥保管库的防火墙的组合很麻烦。
脚步:
- 为 APIM 创建 vnet + 子网
- 创建用户分配的托管标识
- 创建密钥保管库。允许从 APIM 的子网进行网络访问,并为用户分配的托管身份的机密创建 GET/LIST 访问策略
- 生成自签名证书并将其导入密钥保管库
- 部署 APIM(开发人员 SKU,内部 vnet 模式,具有用户分配的托管标识,使用来自密钥库的 ssl 证书的自定义主机名配置)
错误
这会导致以下错误消息。该消息具有误导性,因为给定的身份确实具有 GET 权限。
Failed to access KeyVault Secret https://kv-xxx.vault.azure.net/secrets/gateway-certificate/58542d0de4094c60856f97482a9b2e69 using Managed Service Identity (http://aka.ms/apimmsi) of Api Management service. Check if Managed Identity of Type: UserAssigned, ClientId: 2fa6db22-xxxx-xxxx-xxxx-xxxxxxxxxxxx and ObjectId: 91f8fa07-xxxx-xxxx-xxxx-xxxxxxxxxxxx has GET permissions on secrets in the KeyVault Access Policies.
成功场景
如前所述,似乎特别是用户分配的托管身份和具有网络访问规则的密钥库的这种组合很麻烦。以下确实有效:
- 系统分配的托管标识 + 密钥保管库上的防火墙
- 用户分配的托管标识 + 密钥保管库上没有防火墙
部署
我使用 Bicep 部署我的资源,但我通过 Portal 遇到了同样的问题。
APIM 的二头肌模块:
@description('Name of APIM service')
param apimName string
@description('Location')
param location string = resourceGroup().location
@allowed([
'Basic'
'Consumption'
'Developer'
'Isolated'
'Premium'
'Standard'
])
@description('SKU name of APIM')
param skuName string
@description('Capacity of the SKU (number of deployed units of the SKU)')
param skuCapacity int
@description('Id of the subnet')
param subnetId string
@description('Publisher email')
param publisherEmail string
@description('Publisher name')
param publisherName string
@description('Id of the managed identity')
param managedIdentityId string
@description('Client id of the managed identity')
param managedIdentityClientId string
@description('Reference to the Key Vault certificate')
param certificateKeyVaultId string
@description('Reference to the Key Vault certificate')
@secure()
param certificateKeyVaultPassword string
@description('Hostname of the gateway')
param gatewayHostname string
resource apim 'Microsoft.ApiManagement/service@2021-08-01' = {
name: apimName
location: location
sku: {
capacity: skuCapacity
name: skuName
}
identity: {
type: 'UserAssigned'
userAssignedIdentities: {
'${managedIdentityId}': {}
}
}
properties: {
hostnameConfigurations: [
{
type: 'Proxy'
hostName: gatewayHostname
defaultSslBinding: true
certificateSource: 'KeyVault'
identityClientId: managedIdentityClientId
keyVaultId: certificateKeyVaultId
certificatePassword: certificateKeyVaultPassword
}
]
publisherEmail: publisherEmail
publisherName: publisherName
virtualNetworkConfiguration: {
subnetResourceId: subnetId
}
virtualNetworkType: 'Internal'
}
}
链接:
- https://github.com/MicrosoftDocs/azure-docs/issues/86983
- https://docs.microsoft.com/en-us/azure/api-management/api-management-howto-integrate-internal-vnet-appgateway#set-up-custom-domain-names-in-api-management
- https://docs.microsoft.com/en-us/azure/api-management/api-management-howto-use-managed-service-identity#use-ssl-tls-certificate-from-azure-key-vault- UA