问题描述
在 Azure China 中,Function App 通过 Key Vault Reference 在应用设置中引用 Key Vault Secret。由于 Secret 即将过期,本次在 Key Vault 中更新了 Secret 值,也就是生成了一个新的 Secret 版本。
更新后,Function App 侧出现如下错误:
Key Vault reference was not able to be resolved because site was denied access to Key Vault reference's vault.
在报错写着 denied access,第一反应当然是权限问题,可再想想:真的是权限问题,那么轮换之前怎么一直正常呢?而且重启就好/或直接把Secret的内容写进Function App的环境变量设置中就能正常运行。
所以,这个问题到底是什么情况呢?
问题解答
Function App 使用 Key Vault Reference 时,并不是每次读取环境变量都实时访问 Key Vault。
App Service / Azure Functions 会缓存 Key Vault Reference 的解析结果。
根据官方文档,如果 Key Vault Reference 中没有指定 Secret 版本,应用会使用 Key Vault 中存在的最新版本。
但当 Secret 产生新版本后,应用不会立刻实时刷新,而是会在后续刷新周期中更新。
(参考文档:https://learn.microsoft.com/zh-cn/azure/app-service/app-service-key-vault-references?tabs=azure-cli)
所以,本次问题发生的原因就是:Key Vault Reference缓存刷新的问题。
需要注意:这并不代表所有 denied access 都是缓存问题,它也可能是真正的权限、网络、引用语法或 Secret 状态问题。可以通过重启应用后,观察应用是否恢复作为判断标准。
问题排查思路
核心思路:先用“重启 / 刷新”排除缓存问题,再去查权限和网络
1. 先确认是否刚刚轮换 Secret
如果报错发生在 Secret 更新之后,且 Function App 之前一直可以正常读取 Key Vault,则优先怀疑缓存未刷新。
此时可以先执行:
- 重启 Function App;
- 或调用 Key Vault Reference refresh API;
- 再观察应用是否恢复。
- 如果恢复,说明主要问题就是引用缓存刷新。
2. 检查引用是否锁定旧版本
检查 Function App 应用设置中的 Key Vault Reference:
- 如果使用 VaultName + SecretName,通常不锁定版本。如:@Microsoft.KeyVault(VaultName=<your key vault name>;SecretName=<secret name>)
- 如果使用 SecretUri,确认 URI 末尾是否带 Secret 版本号。如: @Microsoft.KeyVault(SecretUri=https://<your key vault name>.vault.azure.cn/secrets/<secret name> )
- 如果业务希望跟随最新 Secret,URI 不要带版本号。
- 如果业务必须固定版本,才使用带版本号的 URI。
3. 如果仍然失败,再查权限和网络
如果重启或 refresh 后仍然报错,就不能继续假设是缓存问题,需要进入权限和网络排查。
重点检查:
- Function App 是否启用了 Managed Identity;
- Managed Identity 是否具备读取 Secret 的权限;
- 使用 RBAC 时,是否分配了类似 Key Vault Secrets User 的角色;
- 使用 Access Policy 时,是否包含 Secret Get 权限;
- Key Vault 防火墙、Private Endpoint、VNet 集成是否允许 Function App 访问;
- Secret 是否被删除、禁用或名称写错;
- Key Vault Reference 语法是否正确。
最后,打开Key Vault的诊断日志,查看报错日志进一步分析(https://learn.microsoft.com/zh-cn/azure/key-vault/general/logging?tabs=Vault)。
总结
Function App 在 Key Vault Secret 轮换后报 Key Vault reference was not able to be resolved,不一定是真实权限被拒绝。
- 如果权限和网络近期没有变化,先通过重启或 refresh API 刷新 Key Vault Reference。
- 如果仍失败,再用 Key Vault 的 SecretGet 日志定位权限、网络、Secret 状态或引用语法问题。
常见问题(FAQ)
Q:为什么 Key Vault 里更新了 Secret,Function App 还是拿到旧值?
A:因为 App Service / Functions 会缓存 Key Vault Reference 的解析结果。如果引用不指定版本号,轮换后最多需要约 24 小时才会自动刷新。想立即生效,可以重启 Function App 或调用 refresh API。
Q:报 denied access 是不是一定是权限问题?
A:不一定。denied access 是 Key Vault Reference 解析失败的统一提示。如果是在 Secret 轮换后出现,且重启后恢复,那通常是缓存刷新问题,而不是权限真的被撤。
Q:怎么让 Function App 不用等 24 小时就拿到新 Secret?
A:三种方式:重启 Function App、修改一个应用设置触发重启、或调用 config/configreferences/appsettings/refresh 的 refresh API。自动化场景推荐在轮换流程里直接调 refresh API。
Q:为什么轮换后 Secret 反而不生效,是不是引用写错了?
A:检查引用是否锁定了 Secret 版本号。如果 SecretUri 末尾带了版本号,Function App 会固定引用那个版本,不会跟随最新 Secret。想跟随最新版本,就不要带版本号,或使用 VaultName + SecretName。
参考资料
在 App Service 和 Azure Functions 中使用 Key Vault 引用 : https://learn.microsoft.com/zh-cn/azure/app-service/app-service-key-vault-references?tabs=azure-cli
Key Vault 日志记录与监控(Diagnostic settings / Insights): https://learn.microsoft.com/zh-cn/azure/key-vault/general/logging?tabs=Vault
当在复杂的环境中面临问题,格物之道需:浊而静之徐清,安以动之徐生。 云中,恰是如此!