配置防火墙限制后Azure App Service无法访问Key Vault获取证书的问题排查
解决Key Vault防火墙限制下App Service无法拉取证书的问题
我来帮你拆解这个问题,其实是两个层面的权限和访问限制导致的:
先看错误里的0.0.0.0和防火墙拒绝问题
这个报错本质是Terraform自身在访问Key Vault时被防火墙拦截了,不是App Service直接访问的问题。当你创建azurerm_app_service_certificate资源时,Terraform需要从Key Vault读取证书的secret_id来完成资源创建,但你的Key Vault防火墙设置了default_action = "Deny",且没把Terraform执行环境的IP(比如你的本地机器IP、CI/CD服务器IP)加入ip_rules列表,所以直接被拒绝了。
再看App Service的证书访问权限配置
你当前添加的是"Microsoft Azure App Service"这个通用服务主体的访问策略,但实际上,当App Service通过托管标识访问Key Vault时,需要给App Service自身的托管标识(系统分配或用户分配)配置访问权限,而不是这个通用服务主体。那个通用服务主体只适用于少数平台级操作,完全不适用于托管标识的场景。
具体解决方案
1. 允许Terraform执行IP访问Key Vault
把Terraform运行所在环境的公网IP添加到Key Vault的ip_rules里,比如:
network_acls { default_action = "Deny" bypass = "AzureServices" # 把你的本地/CI IP加到allowed_ip数组里,或者直接拼接 ip_rules = concat(local.allowed_ip, ["192.168.1.100"]) # 替换成实际的Terraform执行IP }
2. 给App Service的托管标识添加Key Vault访问策略
你需要给App Service的系统分配标识和用户分配标识分别配置访问权限,确保它们能读取证书、密钥和机密(证书在Key Vault里会关联密钥和机密对象):
resource "azurerm_key_vault" "keyvault-name" { name = "keyvault" location = var.location resource_group_name = azurerm_resource_group.rgrp.name tenant_id = data.azurerm_client_config.current.tenant_id # 保留原有的网络ACL配置,加上Terraform的IP network_acls { default_action = "Deny" bypass = "AzureServices" ip_rules = concat(local.allowed_ip, ["<your-terraform-ip>"]) } # 给App Service系统分配标识的访问策略 access_policy { object_id = azurerm_app_service.app_service.identity[0].principal_id tenant_id = data.azurerm_client_config.current.tenant_id certificate_permissions = ["Get", "List"] secret_permissions = ["Get", "List"] key_permissions = ["Get", "List"] } # 给用户分配标识的访问策略(如果你用这个标识访问Key Vault) access_policy { object_id = data.azurerm_user_identity.user-identity.principal_id tenant_id = data.azurerm_client_config.current.tenant_id certificate_permissions = ["Get", "List"] secret_permissions = ["Get", "List"] key_permissions = ["Get", "List"] } # 原来的通用App Service服务主体可以保留,但其实不是必须的,建议测试后移除 access_policy { object_id = "..." # 你之前获取的服务主体ID tenant_id = "..." certificate_permissions = ["Get", "List"] secret_permissions = ["Get", "List"] key_permissions = ["Get", "List"] } }
3. 补充说明
bypass = "AzureServices"并不是万能的:它只允许少数受信任的Azure服务绕过防火墙,App Service的托管标识访问并不在这个受信任列表里,所以必须通过访问策略+IP允许(或虚拟网络)来授权。- 错误里的
Caller信息里的oid其实是Terraform使用的服务主体ID,或者是App Service的托管标识ID,你可以通过az ad sp show --id <appid>来查看具体是哪个标识,确认是否已经添加到访问策略里。
验证步骤
- 先把Terraform执行IP加入Key Vault的IP允许列表,重新运行Terraform,看是否还会出现403错误。
- 确认App Service的托管标识已经在Key Vault的访问策略里,并且权限正确。
- 等待几分钟让权限生效,然后测试自定义域名绑定是否正常。
内容的提问来源于stack exchange,提问作者Mukesh Jha




