VaultTemplate 简介
VaultTemplate 类位于 org.springframework.vault.core
包中,是 Spring Vault 支持的核心类,提供了丰富的功能集来与 Vault 进行交互。该模板提供了便捷的操作来读取、写入和删除 Vault 中的数据,并在您的领域对象和 Vault 数据之间提供了映射。
一旦配置完成,VaultTemplate 是线程安全的,并且可以在多个实例中重复使用。
Vault 文档与领域类之间的映射是通过委托给 RestTemplate
来完成的。Spring Web 支持提供了映射基础设施。
VaultTemplate 类实现了 VaultOperations 接口。在尽可能的情况下,VaultOperations 上的方法命名与 Vault API 上的可用方法一致,以便让熟悉 Vault API 和 CLI 的现有 Vault 开发者更容易上手。例如,你会发现诸如 "write"、"delete"、"read" 和 "revoke" 等方法。设计目标是尽可能简化从使用 Vault API 到 VaultOperations
的过渡。这两个 API 之间的一个主要区别是,VaultOperations
可以传递领域对象,而不是 JSON 键值对。
引用 VaultTemplate 实例上的操作的首选方式是通过其接口 VaultOperations。
虽然 VaultTemplate
上有许多便捷方法可以帮助你轻松执行常见任务,但如果你需要直接访问 Vault API 以访问 VaultTemplate
未明确公开的功能,你可以使用多个执行回调方法之一来访问底层 API。这些执行回调方法将为你提供一个 RestOperations
对象的引用。有关更多信息,请参阅 执行回调 部分。
现在让我们来看一些在 Spring 容器中使用 Vault 的示例。
注册和配置 Spring Vault beans
使用 Spring Vault 并不需要 Spring 上下文。然而,在受管理的上下文中注册的 VaultTemplate
和 SessionManager 实例将参与由 Spring IoC 容器提供的生命周期事件。这在应用程序关闭时处理活动的 Vault 会话时非常有用。此外,您还可以在应用程序中重用相同的 VaultTemplate
实例,从而受益。
Spring Vault 附带了一个支持配置类,该类提供了在 Spring 上下文中使用的 bean 定义。应用程序配置类通常继承自 AbstractVaultConfiguration,并且需要提供特定于环境的额外详细信息。
从 AbstractVaultConfiguration 扩展需要实现 VaultEndpoint vaultEndpoint()
和 ClientAuthentication clientAuthentication()
方法。
示例 1. 使用基于 Java 的 bean 元数据注册 Spring Vault 对象
@Configuration
public class AppConfig extends AbstractVaultConfiguration {
/**
* Specify an endpoint for connecting to Vault.
*/
@Override
public VaultEndpoint vaultEndpoint() {
return new VaultEndpoint(); 1
}
/**
* Configure a client authentication.
* Please consider a more secure authentication method
* for production use.
*/
@Override
public ClientAuthentication clientAuthentication() {
return new TokenAuthentication("…"); 2
}
}
创建一个新的 VaultEndpoint,默认指向
https://localhost:8200
。此示例使用 TokenAuthentication 来快速开始。有关支持的认证方法的详细信息,请参阅 [vault.core.authentication]。
示例 2. 注册 Spring Vault 应用注入的属性
@Configuration
public class AppConfig extends AbstractVaultConfiguration {
@Value("${vault.uri}")
URI vaultUri;
/**
* Specify an endpoint that was injected as URI.
*/
@Override
public VaultEndpoint vaultEndpoint() {
return VaultEndpoint.from(vaultUri); 1
}
/**
* Configure a Client Certificate authentication.
* {@link RestOperations} can be obtained from {@link #restOperations()}.
*/
@Override
public ClientAuthentication clientAuthentication() {
return new ClientCertificateAuthentication(restOperations()); 2
}
}
VaultEndpoint 可以通过多种工厂方法进行构造,例如
from(URI uri)
或VaultEndpoint.create(String host, int port)
。ClientAuthentication
方法的依赖项可以从AbstractVaultConfiguration
中获取,或者由你的配置提供。
在某些情况下,创建自定义配置类可能会比较繁琐。可以查看 EnvironmentVaultConfiguration,它允许使用现有属性源中的属性和 Spring 的 Environment
进行配置。更多内容请参阅 使用 EnvironmentVaultConfiguration。
会话管理
Spring Vault 需要一个 ClientAuthentication
来进行登录并访问 Vault。有关身份验证的详细信息,请参阅 [vault.core.authentication]。Vault 登录不应在每次经过身份验证的 Vault 交互时发生,而必须在整个会话期间重复使用。这一方面由 SessionManager
实现处理。SessionManager
决定获取令牌的频率、撤销和续订。Spring Vault 提供了两种实现:
-
SimpleSessionManager: 仅从提供的
ClientAuthentication
中获取令牌,不进行刷新和撤销操作。 -
LifecycleAwareSessionManager: 该
SessionManager
会在令牌可续期的情况下安排续期,并在销毁时撤销登录令牌。续期操作通过AsyncTaskExecutor
进行调度。如果使用AbstractVaultConfiguration
,默认会配置LifecycleAwareSessionManager
。
使用 EnvironmentVaultConfiguration
Spring Vault 包含了 EnvironmentVaultConfiguration,用于从 Spring 的 Environment
和一组预定义的属性键来配置 Vault 客户端。EnvironmentVaultConfiguration 支持常见的配置。其他配置可以通过从最合适的配置类派生来支持。通过 @Import(EnvironmentVaultConfiguration.class)
将 EnvironmentVaultConfiguration 包含到现有的基于 Java 的配置类中,并通过 Spring 的任何 PropertySource
提供配置属性。
示例 3. 使用带有属性文件的 EnvironmentVaultConfiguration
@PropertySource("vault.properties")
@Import(EnvironmentVaultConfiguration.class)
public class MyConfiguration{
}
vault.uri=https://localhost:8200
vault.token=00000000-0000-0000-0000-000000000000
属性键
-
Vault URI:
vault.uri
-
SSL 配置
-
Keystore 资源:
vault.ssl.key-store
(可选) -
Keystore 密码:
vault.ssl.key-store-password
(可选) -
Keystore 类型:
vault.ssl.key-store-type
(可选, 通常为jks
, 也支持pem
) -
Truststore 资源:
vault.ssl.trust-store
(可选) -
Truststore 密码:
vault.ssl.trust-store-password
(可选) -
Truststore 类型:
vault.ssl.trust-store-type
(可选, 通常为jks
, 也支持pem
) -
启用的 SSL/TLS 协议:
vault.ssl.enabled-protocols
(自 2.3.2 起, 可选, 协议以逗号分隔) -
启用的 SSL/TLS 加密套件:
vault.ssl.enabled-cipher-suites
(自 2.3.2 起, 可选, 加密套件以逗号分隔)
-
-
认证方法:
vault.authentication
(默认为TOKEN
, 支持的认证方法有:TOKEN
,APPID
,APPROLE
,AWS_EC2
,AWS_IAM
,AZURE
,CERT
,CUBBYHOLE
,KUBERNETES
)
身份验证特定的属性键
- Vault Token:
vault.token
-
AppId 路径:
vault.app-id.app-id-path
(默认为app-id
) -
AppId:
vault.app-id.app-id
-
UserId:
vault.app-id.user-id
.MAC_ADDRESS
和IP_ADDRESS
使用MacAddressUserId
和IpAddressUserId
用户 ID 机制。其他任何值都使用StaticUserId
。
[vault.authentication.approle]
-
AppRole 路径:
vault.app-role.app-role-path
(默认为approle
) -
RoleId:
vault.app-role.role-id
-
SecretId:
vault.app-role.secret-id
(可选)
-
AWS EC2 路径:
vault.aws-ec2.aws-ec2-path
(默认为aws-ec2
) -
角色:
vault.aws-ec2.role
-
角色ID:
vault.aws-ec2.role-id
(已弃用: 请使用vault.aws-ec2.role
代替) -
身份文档 URL:
vault.aws-ec2.identity-document
(默认为[169.254.169.254/latest/dynamic/instance-identity/pkcs7](http://169.254.169.254/latest/dynamic/instance-identity/pkcs7)
)
- 角色:
vault.aws-iam.role
[vault.authentication.azuremsi]
-
Azure MSI 路径:
vault.azure-msi.azure-path
(默认为azure
) -
角色:
vault.azure-msi.role
-
元数据服务 URL:
vault.azure-msi.metadata-service
(默认为[169.254.169.254/metadata/instance?api-version=2017-08-01](http://169.254.169.254/metadata/instance?api-version=2017-08-01)
) -
身份令牌服务 URL:
vault.azure-msi.identity-token-service
(默认为[169.254.169.254/metadata/identity/oauth2/token?resource=https://vault.hashicorp.com&api-version=2018-02-01](http://169.254.169.254/metadata/identity/oauth2/token?resource=https://vault.hashicorp.com&api-version=2018-02-01)
)
[vault.authentication.clientcert]
无配置选项。
[vault.authentication.cubbyhole]
- 初始 Vault Token:
vault.token
[vault.authentication.kubernetes]
-
Kubernetes 路径:
vault.kubernetes.kubernetes-path
(默认为kubernetes
) -
角色:
vault.kubernetes.role
-
服务账户令牌文件路径:
vault.kubernetes.service-account-token-file
(默认为/var/run/secrets/kubernetes.io/serviceaccount/token
)
执行回调
所有 Spring 模板类的一个常见设计特性是,所有功能都被路由到模板的 execute
回调方法之一。这有助于确保异常处理和任何可能需要的资源管理能够一致地执行。尽管在 JDBC 和 JMS 的情况下,这种需求比在 Vault 中更为重要,但它仍然为访问和日志记录提供了一个单一的位置。因此,使用 execute
回调是访问 Vault API 的首选方式,以执行那些我们没有在 VaultTemplate 上暴露为方法的不常见操作。
以下是执行回调方法的列表。
-
<T> T
doWithVault(RestOperationsCallback<T> callback)
执行给定的RestOperationsCallback
,允许在不需会话的情况下使用RestOperations
与 Vault 进行交互。 -
<T> T
doWithSession(RestOperationsCallback<T> callback)
执行给定的RestOperationsCallback
,允许在已认证的会话中与 Vault 进行交互。
以下是一个使用 ClientCallback
初始化 Vault 的示例:
vaultOperations.doWithVault(new RestOperationsCallback<VaultInitializationResponse>() {
@Override
public VaultInitializationResponse doWithRestOperations(RestOperations restOperations) {
ResponseEntity<VaultInitializationResponse> exchange = restOperations
.exchange("/sys/init", HttpMethod.PUT,
new HttpEntity<Object>(request),
VaultInitializationResponse.class);
return exchange.getBody();
}
});