Spring Boot应用在Vault生成MongoDB动态凭证后认证失败
Spring Cloud Vault动态MongoDB凭证启动后30秒内认证失败,过滤器层返回不友好异常
问题概述
- 基于Spring Cloud Vault对接HCP Vault,实现MongoDB动态凭证生成
- 应用启动成功,但启动后30秒内发起请求会触发MongoDB认证失败,30秒后自动恢复正常
- 直接通过Vault API生成的凭证,1秒内即可在mongosh中正常使用
- 认证异常在过滤器层抛出,无法流转到Controller,返回的错误信息冗长且不友好
报错日志
2022-10-25 19:35:36,882 ERROR org.springframework.core.log.CompositeLog [boundedElastic-1] [8f31d431-2] 500 Server Error for HTTP PUT "/v1/demo/123" org.springframework.data.mongodb.UncategorizedMongoDbException: Exception authenticating MongoCredential{mechanism=SCRAM-SHA-1, userName='user', source='source', password=<hidden>, mechanismProperties=<hidden>}; nested exception is com.mongodb.MongoSecurityException: Exception authenticating MongoCredential{mechanism=SCRAM-SHA-1, userName='user', source='admin', password=<hidden>, mechanismProperties=<hidden>} at org.springframework.data.mongodb.core.MongoExceptionTranslator.translateExceptionIfPossible(MongoExceptionTranslator.java:140)
应用配置
spring.cloud.vault: enabled: true application-name: APPLICATION_NAME host: ${VAULT_HOST} port: 8200 scheme: https namespace: admin fail-fast: true config: lifecycle: enabled: true min-renewal: 10s expiry-threshold: 1m authentication: APPROLE app-role: role-id: ${VAULT_ROLE_ID} secret-id: ${VAULT_SECRET_ID} role: ${VAULT_ROLE} app-role-path: approle kv: enabled: true default-context: database: enabled: true role: ${VAULT_DB_ROLE} backend: database spring.config.import: vault://
解决方案建议
1. 配置MongoDB客户端认证重试机制
在MongoDB客户端配置中添加认证失败的重试逻辑,让客户端在凭证未生效时自动重试,直到超时或成功。可以通过代码自定义客户端配置:
@Bean public MongoClient mongoClient(MongoProperties mongoProperties) { MongoClientSettings settings = MongoClientSettings.builder() .applyConnectionString(new ConnectionString(mongoProperties.getUri())) .retryWrites(true) .retryReads(true) .applyToSocketSettings(builder -> builder.connectTimeout(Duration.ofSeconds(10)) .readTimeout(Duration.ofSeconds(10))) .build(); return MongoClients.create(settings); }
也可通过Spring Boot配置参数简化:
spring.data.mongodb.retry-writes=true spring.data.mongodb.connect-timeout=10s spring.data.mongodb.read-timeout=10s
2. 自定义全局异常处理器捕获过滤器层异常
实现ErrorController,捕获MongoDB认证相关异常,返回友好的业务提示:
@RestController public class CustomErrorController extends AbstractErrorController { public CustomErrorController(ErrorAttributes errorAttributes) { super(errorAttributes); } @RequestMapping("/error") public ResponseEntity<Map<String, Object>> handleError(HttpServletRequest request) { Throwable throwable = getError(request); if (throwable instanceof UncategorizedMongoDbException && throwable.getCause() instanceof MongoSecurityException) { Map<String, Object> response = new HashMap<>(); response.put("code", "SERVICE_INITIALIZING"); response.put("message", "服务初始化中,请稍后重试"); return new ResponseEntity<>(response, HttpStatus.SERVICE_UNAVAILABLE); } Map<String, Object> errorAttributes = getErrorAttributes(request, ErrorAttributeOptions.defaults()); return new ResponseEntity<>(errorAttributes, HttpStatus.INTERNAL_SERVER_ERROR); } @Override public String getErrorPath() { return "/error"; } }
3. 调整Spring Cloud Vault凭证初始化逻辑
Spring Cloud Vault默认在启动阶段获取凭证,可能存在凭证生成到MongoDB同步的延迟。可调整租赁续约配置,或关闭fail-fast让应用等待凭证生效:
spring.cloud.vault.database: lease-renewal: enabled: true init-delay: 5s fixed-delay: 10s spring.cloud.vault.fail-fast: false
4. 检查Vault MongoDB引擎配置
确认HCP Vault的MongoDB数据库引擎角色配置,确保用户创建语句为即时生效,避免异步同步逻辑。可通过Vault CLI验证:
vault read database/roles/${VAULT_DB_ROLE}
内容的提问来源于stack exchange,提问作者eyal tamsot
相关产品推荐
相关产品推荐

