Introduction to VaultTemplate
位于 org.springframework.vault.core
包中的 VaultTemplate
类是 Spring Vault 支持的中心类,它提供了一套丰富的功能与 Vault 进行交互。模板提供了在 Vault 中读写和删除数据的便捷操作,并在您的域对象和 Vault 数据之间提供映射。
配置后, |
Vault 文档和域类之间的映射是通过委托给 RestTemplate
完成的。Spring Web 支持提供映射基础设施。
VaultTemplate
类实现了 VaultOperations
接口。在尽可能多的情况下,VaultOperations
上的方法是以 Vault API 上可用的方法命名的,以使 API 对习惯使用 API 和 CLI 的现有 Vault 开发人员来说变得熟悉。例如,您会找到诸如“write”、“delete”、“read”和“revoke”这样的方法。设计目标是尽可能简化在 Vault API 和 VaultOperations
之间进行转换。这两个 API 之间的主要区别在于 VaultOperations
可以传递域对象,而不是 JSON 键值对。
引用 |
虽然 VaultTemplate
上有很多便利方法可以帮助您轻松执行常见任务,但如果您需要直接访问 Vault API 来访问未 VaultTemplate
明确公开的功能,则可以使用多种执行回调方法来访问底层 API。执行回调将为您提供 RestOperations
对象的引用。有关更多信息,请参见 Execution Callbacks 部分。
现在,让我们来看一个示例,了解如何在 Spring 容器的上下文中使用 Vault。
Registering and configuring Spring Vault beans
使用 Spring Vault 不需要 Spring 上下文。但是,在受管上下文中注册的 VaultTemplate
和 SessionManager
的实例将参与 Spring IoC 容器提供的 {spring-framework-docs}core.html#beans-factory-nature[生命周期事件] 。这有助于在应用程序关闭时释放活动 Vault 会话。您还可以受益于在整个应用程序中重复使用相同的 VaultTemplate
实例。
Spring Vault 带有一个支持配置类,该类提供了在 Spring 上下文中使用的 bean 定义。应用程序配置类通常从 AbstractVaultConfiguration
扩展,并且需要提供特定于环境的附加详细信息。
从 AbstractVaultConfiguration
扩展需要实现` VaultEndpoint vaultEndpoint()` 和 ClientAuthentication clientAuthentication()
方法。
@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
}
}
1 | 创建一个新的 VaultEndpoint ,该令牌默认指向 https://localhost:8200 。 |
2 | 此示例使用 TokenAuthentication 快速入门。请参阅 [vault.core.authentication] 了解受支持的身份验证方法的详细信息。 |
@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
}
}
1 | 可以使用各种工厂方法(如 from(URI uri) 或 VaultEndpoint.create(String host, int port) )构建 VaultEndpoint 。 |
2 | ClientAuthentication 方法的依赖项可以从 AbstractVaultConfiguration 获取,也可以由配置提供。 |
在某些情况下,创建自定义配置类可能很麻烦。了解 |
Session Management
Spring Vault 需要 ClientAuthentication
登录并访问 Vault。有关认证的详细信息,请参见 [vault.core.authentication]。Vault 登录不应在每次经过认证的 Vault 交互中进行,而必须在整个会话中重用。这个方面由 SessionManager
实现处理。一个 SessionManager
决定多久获取令牌一次,以及撤销和续订。Spring Vault 提供了两种实现:
-
SimpleSessionManager
:仅从提供的ClientAuthentication
获取令牌,但不刷新和撤销 -
LifecycleAwareSessionManager
:如果某个令牌可更新,此SessionManager
将计划令牌续订,并在处置时撤销登录令牌。续订计划使用AsyncTaskExecutor
进行。如果使用AbstractVaultConfiguration
,则LifecycleAwareSessionManager
默认进行配置。
Using EnvironmentVaultConfiguration
Spring Vault 包含 EnvironmentVaultConfiguration
配置来自 Spring Environment
的 Vault 客户端,以及一组预定义属性键。EnvironmentVaultConfiguration
支持经常应用的配置。通过从最合适的配置类派生可支持其他配置。将 EnvironmentVaultConfiguration
与 @Import(EnvironmentVaultConfiguration.class)
一起包含到现有的基于 Java 的配置类中,并通过 Spring 的任何 PropertySource
提供配置属性。
@PropertySource("vault.properties")
@Import(EnvironmentVaultConfiguration.class)
public class MyConfiguration{
}
vault.uri=https://localhost:8200
vault.token=00000000-0000-0000-0000-000000000000
Property keys
-
Vault URI:
vault.uri
-
SSL Configuration
-
Keystore resource:
vault.ssl.key-store
(optional) -
Keystore password:
vault.ssl.key-store-password
(optional) -
密钥库类型:
vault.ssl.key-store-type
(可选,通常为jks
,还支持pem
) -
Truststore resource:
vault.ssl.trust-store
(optional) -
Truststore password:
vault.ssl.trust-store-password
(optional) -
信任库类型:
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
)
Authentication-specific property keys
-
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`一起使用。
-
AppRole 路径:
vault.app-role.app-role-path
(默认为approle
) -
RoleId:
vault.app-role.role-id
-
SecretId:
vault.app-role.secret-id
(optional)
-
AWS EC2 路径:
vault.aws-ec2.aws-ec2-path
(默认为aws-ec2
) -
Role:
vault.aws-ec2.role
-
RoleId:
vault.aws-ec2.role-id
(*deprecated:*使用 `vault.aws-ec2.role`代替) -
身份文档网址:
vault.aws-ec2.identity-document
(默认为http://169.254.169.254/latest/dynamic/instance-identity/pkcs7
)
-
Role:
vault.aws-iam.role
-
Azure MSI 路径:
vault.azure-msi.azure-path
(默认为azure
) -
Role:
vault.azure-msi.role
-
元数据服务网址:
vault.azure-msi.metadata-service
(默认为http://169.254.169.254/metadata/instance?api-version=2017-08-01
) -
身份令牌服务网址:
vault.azure-msi.identity-token-service
(默认为http://169.254.169.254/metadata/identity/oauth2/token?resource=https://vault.hashicorp.com&api-version=2018-02-01
)
没有配置选项。
-
Initial Vault Token:
vault.token
-
Kubernetes 路径:
vault.kubernetes.kubernetes-path
(默认为kubernetes
) -
Role:
vault.kubernetes.role
-
服务帐户令牌文件路径:
vault.kubernetes.service-account-token-file
(默认为/var/run/secrets/kubernetes.io/serviceaccount/token
)
Execution callbacks
所有 Spring 模板类的常见设计特点就是所有功能都发送至其中一个模板执行回调方法。这样有助于确保以一致的方式执行异常以及可能所需的任何资源管理。虽然这在 JDBC 和 JMS 的情况下比在 Vault 的情况下需要更多,但它仍然为访问和记录提供一个地点。因此,使用 execute 回调是访问 Vault API 的首选方法,以便执行我们未在 VaultTemplate
上公开为方法的不常见操作。
这里列出了一些 execute 回调方法。
-
<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();
}
});