azure-spring-boot-starter-keyvault-certificates是否支持Azure AD Workload Identity?
- 技术栈:Kotlin + Spring,部署在Azure Kubernetes Service(AKS)
- 使用依赖:
com.azure.spring:azure-spring-boot-starter-keyvault-certificates:3.14.0 - 获取密钥库代码:
KeyStore.getInstance("AzureKeyVault").load(KeyVaultLoadStoreParameter(keyVaultUri)) - 异常情况:原本用Azure AD Pod Identity时运行正常,切换到Azure AD Workload Identity后抛出空指针异常:
Caused by: java.lang.NullPointerException: Cannot invoke "com.azure.security.keyvault.jca.implementation.model.AccessToken.getAccessToken()" because "this.accessToken" is null
at com.azure.security.keyvault.jca.implementation.KeyVaultClient.getAccessToken(KeyVaultClient.java:195) ~[azure-security-keyvault-jca-2.6.0.jar!/:2.6.0]
at com.azure.security.keyvault.jca.implementation.KeyVaultClient.getAliases(KeyVaultClient.java:233) ~[azure-security-keyvault-jca-2.6.0.jar!/:2.6.0]
at com.azure.security.keyvault.jca.implementation.certificates.KeyVaultCertificates.refreshCertificates(KeyVaultCertificates.java:142) ~[azure-security-keyvault-jca-2.6.0.jar!/:2.6.0]
at com.azure.security.keyvault.jca.implementation.certificates.KeyVaultCertificates.refreshCertificatesIfNeeded(KeyVaultCertificates.java:130) ~[azure-security-keyvault-jca-2.6.0.jar!/:2.6.0]
at com.azure.security.keyvault.jca.implementation.certificates.KeyVaultCertificates.getCertificateKeys(KeyVaultCertificates.java:122) ~[azure-security-keyvault-jca-2.6.0.jar!/:2.6.0]
- 对比现象:用
WorkloadIdentityCredentialBuilder().build()连接CosmosDB、ServiceBus完全正常,推测问题出在Key Vault JCA Provider的令牌获取流程未适配Workload Identity。
1. 升级依赖版本
当前依赖的azure-security-keyvault-jca:2.6.0版本较老,对Workload Identity的支持不完善。建议升级到最新稳定版,示例配置如下:
<!-- Maven配置 --> <dependency> <groupId>com.azure.spring</groupId> <artifactId>azure-spring-boot-starter-keyvault-certificates</artifactId> <version>4.14.0</version> <!-- 可替换为更高稳定版 --> </dependency>
// Gradle Kotlin DSL配置 implementation("com.azure.spring:azure-spring-boot-starter-keyvault-certificates:4.14.0")
新版本的JCA Provider已经适配了Workload Identity的令牌获取逻辑,能自动识别Pod中的环境变量配置。
2. 显式配置Workload Identity凭证
如果升级后问题仍存在,可直接指定Key Vault JCA使用WorkloadIdentityCredential:
- 新建Spring配置类,创建WorkloadIdentityCredential Bean:
import com.azure.identity.WorkloadIdentityCredential import com.azure.identity.WorkloadIdentityCredentialBuilder import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration @Configuration class AzureIdentityConfig { @Bean fun workloadIdentityCredential(): WorkloadIdentityCredential { return WorkloadIdentityCredentialBuilder() .clientId(System.getenv("AZURE_CLIENT_ID")) .tenantId(System.getenv("AZURE_TENANT_ID")) .tokenFilePath(System.getenv("AZURE_FEDERATED_TOKEN_FILE")) .build() } }
- 在
application.properties中指定凭证Bean名称:
azure.keyvault.jca.credential-bean-name=workloadIdentityCredential
这样Key Vault JCA会直接复用你配置的凭证获取令牌,绕过内部可能存在的兼容问题。
3. 验证Pod环境变量
确认AKS Pod中已正确注入以下Workload Identity必需的环境变量:
AZURE_CLIENT_ID:工作负载标识的客户端IDAZURE_TENANT_ID:Azure租户IDAZURE_FEDERATED_TOKEN_FILE:令牌文件路径(由AKS自动注入)
可通过在Pod内执行printenv命令检查变量是否存在且值正确。
4. 检查Key Vault权限
确保工作负载标识对应的Azure AD应用已被授予Key Vault的Certificate Reader或Certificate User权限,避免因权限不足导致令牌获取后无法访问证书资源。
内容的提问来源于stack exchange,提问作者user1610362

