|
该版本仍在开发中,尚未被视为稳定版本。如需获取最新的稳定版本,请使用Spring Vault 4.0.1! |
凭据轮换
Vault的全面凭证轮换功能支持自动更新和轮换密钥,例如数据库凭证。 通过将密钥的有效性与应用实例的生命周期绑定,您的应用能够在无需人工干预的情况下保持对有效凭证的访问。 受损的凭证仅在有限的时间内有效,并且影响范围被隔离到单个应用实例。
当一个密钥具有租约时,Spring Vault 会在其到期前续订该租约,从而在整个应用程序生命周期中保持凭证的有效性。
以下部分介绍了诸如属性源等组件所使用的凭据轮换基础设施。
秘钥租约容器
SecretLeaseContainer 管理租用密钥的生命周期。 它会在到期前续订租约,并在必要时轮换凭证,监听租约事件并触发适当的操作。
作为 Spring Lifecycle 组件,该容器支持在应用程序运行时进行动态密钥管理。 它接受 RequestedSecret 实例,表示被管理的密钥。
SecretLeaseContainerSecretLeaseContainer container = new SecretLeaseContainer(vaultOperations, (1)
taskScheduler);
RequestedSecret requestedSecret = container (2)
.requestRotatingSecret("mysql/creds/my-role");
container.addLeaseListener(new LeaseListenerAdapter() { (3)
@Override
public void onLeaseEvent(SecretLeaseEvent secretLeaseEvent) {
if (requestedSecret.equals(secretLeaseEvent.getSource())) {
if (secretLeaseEvent instanceof SecretLeaseCreatedEvent) {
// …
}
if (secretLeaseEvent instanceof SecretLeaseExpiredEvent) {
// …
}
}
}
});
container.afterPropertiesSet();
container.start(); // events are triggered after starting the container
| 1 | 使用 VaultOperations 和 TaskScheduler 进行初始化以用于续订调度。 |
| 2 | 从 Vault 路径请求一个轮换的密钥。 |
| 3 | 注册一个LeaseListener用于租约事件。 注册顺序很重要:在容器启动或密钥请求之后添加的监听器可能会错过早期事件。 在启动容器之前设置监听器以捕获所有事件。 |
当您的配置类是 AbstractVaultConfiguration 的子类时,通常会注册 SecretLaseContainer,这通常适用于非 Spring Boot 应用程序。 使用 Spring Boot 时,可以考虑 Spring Cloud Vault,它通过自动配置来处理注册。 |
事件
常规活动
-
AfterSecretLeaseRenewedEvent: 租约续订成功。 -
AfterSecretLeaseRevocationEvent: 租约已成功撤销。 -
BeforeSecretLeaseRevocationEvent: 在租约撤销之前,允许执行预撤销操作。 -
SecretLeaseCreatedEvent: 创建了新租约,通常是在初始请求时。 -
SecretLeaseRotatedEvent:SecretLeaseCreatedEvent在租约到期后进行密钥轮换的专用化。 -
SecretLeaseExpiredEvent: 检测到租约已过期,可能是由于TTL到期或评估导致的到期Predicate<Lease>。 -
SecretNotFoundEvent: 在初始请求或续期时,未在 Vault 路径找到密钥。
错误事件
-
SecretLeaseErrorEvent: Vault 错误响应或通信期间的 I/O 错误。
使用 SecretLeaseContainer 并结合其监听器可以直接对密钥的生命周期和租约事件的处理进行细粒度的控制。 在典型的应用场景中,您可能希望使用更高级别的抽象来简化密钥及其租约的管理。
ManagedSecret 和 SecretRegistrar
ManagedSecret API 提供了声明式的密钥生命周期管理。ManagedSecret 是一个更高级的抽象,它会向 SecretLeaseContainer 注册并代表您处理租约事件。 作为 SecretRegistrar 的实现,注册器 bean 会在启动之前通过 AbstractVaultConfiguration 向容器注册。
ManagedSecret@Configuration
class MyConfiguration {
@Bean
ManagedSecret mysqlCredentials(HikariDataSource dataSource) {
return ManagedSecret.rotating("mysql/creds/my-role", secrets -> secrets.as(UsernamePassword::from)
.applyTo((username, password) -> {
connectionPool.setUsername(username);
connectionPool.setPassword(password);
}));
}
}
Managed Secrets 允许在密钥管理与使用这些密钥的应用程序组件之间建立直接连接,从而在请求或轮换密钥时更容易将凭据传播到应用程序组件。 请注意,SecretLeaseContainers 生命周期的特性通常会推迟密钥的可用性,直到容器启动并且密钥被请求时才会提供,这可能不同于在 InitializingBean.afterPropertiesSet() 或 @PostConstruct 阶段需要凭据的组件。 AbstractVaultConfiguration 有意在 Bean 创建期间就启动容器,以允许提前访问凭据。 在任何情况下,您都应确保组件的依赖顺序,以保证在需要时正确初始化并提供密钥。
证书容器
CertificateContainer 管理由 Vault 的 PKI 机密引擎颁发的证书。证书通常不与租约相关联(事实上,避免租约是一项性能优化建议),因此它们不需要续订,但在到期时可以进行轮换。证书轮换实际上是一种重新颁发。
Vault PKI 提供了多种证书类型:
-
X.509 证书包
-
TLS 加密
-
客户端认证
-
-
X.509 证书
-
信任锚点
-
容器是一个 Spring Lifecycle 组件,可以启动和停止,从而允许在应用程序运行时动态管理证书。 它接受 RequestedCertificate 实例,这些实例代表需要管理的证书。 以下代码示例展示了如何设置 CertificateContainer 并监听事件:
CertificateContainerCertificateContainer container = new CertificateContainer(vaultOperations.opsForPki()); (1)
RequestedCertificate cert = container
.register(RequestedCertificate.trustAnchor("vault-ca")); (2)
RequestedCertificate bundle = RequestedCertificateBundle.issue("www.example.com", (3)
"testrole", VaultCertificateRequest.builder()
.commonName("www.example.com")
.ttl(Duration.ofHours(12)).build());
container.addCertificateListener(new CertificateListenerAdapter() { (4)
@Override
public void onCertificateEvent(CertificateEvent event) {
if (cert.equals(event.getSource())) {
if (event instanceof CertificateBundleIssuedEvent) {
// Certificate bundle issued initially or rotated
}
if (event instanceof CertificateObtainedEvent) {
// initial certificate obtained
}
}
}
});
container.afterPropertiesSet();
container.start(); // events are triggered after starting the container
| 1 | 使用 VaultPkiOperations 进行初始化。 如果没有提供 TaskScheduler,容器会创建一个默认实例。 |
| 2 | 通过 RequestedCertificate 请求颁发者证书(支持默认或命名的颁发者)。 |
| 3 | 通过 RequestedCertificateBundle 使用证书请求来申请托管的证书包。 |
| 4 | 注册一个CertificateListener用于证书事件。 注册顺序很重要:在容器启动或证书请求之后添加的监听器可能会错过早期事件。 在启动容器之前设置监听器以捕获所有事件。 |
当您的配置类是 AbstractVaultConfiguration 的子类时,通常会注册 CertificateContainer,这通常适用于非 Spring Boot 应用程序。 使用 Spring Boot 时,可以考虑 Spring Cloud Vault,它通过自动配置来处理注册。 |
事件
常规活动
-
CertificateObtainedEvent: 证书已颁发。 -
CertificateRotatedEvent:CertificateObtainedEvent的证书轮换专用化。 -
CertificateBundleIssuedEvent:CertificateObtainedEvent的证书捆绑发行专业化。 -
CertificateBundleRotatedEvent:CertificateBundleIssuedEvent的证书捆绑轮换特化。 -
CertificateExpiredEvent: 检测到证书已过期。
错误事件
-
CertificateErrorEvent: 如果在与 Vault 通信期间发生 Vault 错误响应或 I/O 错误。
使用 CertificateContainer 并结合其监听器可以直接对证书的生命周期和事件处理进行细粒度的控制。 在典型的应用场景中,您可能希望使用更高级别的抽象来简化证书的管理。
ManagedCertificate 和 CertificateRegistrar
ManagedCertificate API 提供了声明式的证书生命周期管理。ManagedCertificate 是一个更高级的抽象,它会注册到 CertificateContainer 并代表您处理证书事件。 它是 CertificateRegistrar 的实现。 注册器 bean 会被 AbstractVaultConfiguration 检测到,并在容器启动之前注册到 CertificateContainer。
ManagedCertificate@Configuration
class MyConfiguration {
@Bean
ManagedCertificate serverCertificate(SslBundles bundles) {
VaultCertificateRequest request = VaultCertificateRequest.builder()
.commonName("www.example.com")
.ttl(Duration.ofHours(12)).build();
return ManagedCertificate.issue("my-bundle", "my-role", request, bundle -> {
bundles.register("my-bundle", bundle.createKeyStore("my-alias"));
});
}
}
Managed Certificates 允许在证书管理与使用证书的应用组件之间建立直接连接,从而使将凭证传播到应用组件更加容易。 请注意,CertificateContainer 生命周期的性质通常会将证书的可用性推迟到容器启动并且证书被请求时,这可能不同于在 InitializingBean.afterPropertiesSet() 或 @PostConstruct 阶段需要凭证的组件。 AbstractVaultConfiguration 会在 bean 创建期间刻意提前启动容器,以允许早期访问证书。 在任何情况下,您都应该确保组件的依赖顺序,以保证在需要时正确初始化并提供证书。