# Spring 保险库-参考文献
# 序言
Spring Vault 项目将核心 Spring 概念应用于使用 HashiCorpVault 的解决方案的开发。我们提供了一个“模板”作为存储和查询文档的高级抽象。你将注意到与 Spring 框架中的 REST 支持的相似之处。
这份文件是 Spring Vault 的参考指南。它解释了 Vault 的概念、语义和语法。
参考文档的这一部分解释了 Spring Vault 提供的核心功能。
[保险库支持](#vault.core)介绍了 Vault 模块功能集。
## 1.文件结构
这一部分提供了 Spring 和 Vault 的基本介绍。它包含有关后续开发和如何获得支持的详细信息。
文档的其余部分引用了 Spring Vault 特性,并假定用户熟悉[HashiCorp 保险库](https://www.vaultproject.io)以及 Spring 概念。
## 2.知道 Spring
Spring Vault 使用 Spring Framework 的[core](https://docs.spring.io/spring/docs/5.3.4/spring-framework-reference/core.html)功能,例如[IoC](https://docs.spring.io/spring/docs/5.3.4/spring-framework-reference//core.html)容器。虽然了解 Spring API 并不重要,但了解它们背后的概念是重要的。至少,对于你选择使用的任何 IOC 容器,IOC 背后的思想应该是熟悉的。
Vault 支持的核心功能可以直接使用,而不需要调用 Spring 容器的 IoC 服务。这很像`RestTemplate`,它可以在没有 Spring 容器的任何其他服务的情况下“独立”使用。为了利用 Spring Vault 文档的所有特性,例如会话支持,你将需要使用 Spring 配置库的某些部分。
要了解有关 Spring 的更多信息,你可以参考详细解释 Spring 框架的全面(有时是解除武装)文档。有很多关于这个问题的文章、博客条目和书籍--看看 Spring 框架[home page ](https://spring.io/docs),了解更多信息。
## 3.知道保险库
安全性和处理秘密是每个处理数据库、用户凭据或 API 密钥的开发人员关心的问题。Vault 通过提供与访问控制、撤销、密钥滚动和审计相结合的安全存储来介入。简而言之:Vault 是一种安全访问和存储秘密的服务。秘密是你想要严格控制访问权限的任何东西,例如 API 密钥、密码、证书等等。
学习跳马的起点是[WWW,VaultProject.io。](https://www.vaultproject.io)。以下是一些有用的资源:
* 该手册介绍了 Vault,并包含入门指南、参考文档和教程的链接。
* Online Shell 结合在线教程提供了一种方便的方式来与 Vault 实例交互。
* [HashiCorp 保险库介绍](https://www.vaultproject.io/intro/index.html)
* [HashiCorp 保险库文档](https://www.vaultproject.io/docs/index.html)
Spring Vault 提供了用于访问、存储和撤销秘密的客户端支持。有了[HashiCorp 的保险库](https://www.vaultproject.io),你就有了一个中心位置来管理跨所有环境的应用程序的外部秘密数据。Vault 可以管理静态和动态秘密,例如应用程序数据、远程应用程序/资源的用户名/密码,并为外部服务(例如 MySQL、PostgreSQL、 Apache Cassandra、Consul、AWS 等)提供凭据。
## 4.所需经费
Spring Vault2.x 二进制文件要求 JDK 级别为 8.0 及以上,并且[Spring Framework](https://spring.io/docs)5.3.4 及以上。
就保险库而言,[Vault](https://www.vaultproject.io/)至少为 0.6.
## 5.额外的帮助资源
学习一个新的框架并不总是直截了当的。在这一部分中,我们试图提供一种我们认为易于遵循的指南,用于从 Spring Vault 模块开始。然而,如果你遇到问题或你只是在寻求建议,请使用以下链接之一:
### 5.1.支持
有几个可用的支持选项:
#### 5.1.1.社区论坛
在[StackOverflow](https://stackoverflow.com/questions/tagged/spring-vault)上发布有关 Spring Vault 的问题,以共享信息并相互帮助。请注意,需要注册**只有**才能发布。
#### 5.1.2.专业支持
Spring Vault 和 Spring 背后的公司[Pivotal Software,Inc.](https://pivotal.io/)提供专业的、源代码支持,并保证响应时间。
### 5.2.后续发展
有关 Spring Vault 源代码库、夜间构建和快照工件的信息,请参见[Spring Vault homepage](https://projects.spring.io/spring-vault/)。通过在[StackOverflow](https://stackoverflow.com/questions/tagged/spring-vault)上通过社区与开发人员进行交互,你可以帮助使 Spring Vault 最好地满足 Spring 社区的需求。如果你遇到错误或希望提出改进建议,请在 Spring vault 问题[tracker](https://github.com/spring-projects/spring-vault/issues)上创建一个票证。要了解 Spring 生态系统中的最新消息和公告,请订阅 Spring 社区[Portal](https://spring.io)。最后,你可以关注 Spring [blog ](https://spring.io/blog)或 Twitter 上的项目团队([SpringCentral](https://twitter.com/springcentral))。
## 6.新的和值得注意的
### 6.1.最新更新在 Spring Vault2.3 中
* 支持用于密钥库和信任库使用的 PEM 编码证书。
* `ReactiveVaultEndpointProvider`用于`VaultEndpoint`的非阻塞查找。
* `VaultKeyValueMetadataOperations`用于键值元数据交互。
* 支持`transform`后端(Enterprise 功能)。
* [如何使用保险库秘密后端](#vault.core.secret-engines)的文档。
* 每次登录尝试都会重新加载 Kubernetes 和 PCF 身份验证的登录凭据。
* `SecretLeaseContainer`在成功的秘密旋转时发布`SecretLeaseRotatedEvent`而不是`SecretLeaseExpiredEvent`和`SecretLeaseCreatedEvent`。
* `AbstractVaultConfiguration.threadPoolTaskScheduler()` Bean 类型更改为`TaskSchedulerWrapper`而不是`ThreadPoolTaskScheduler`。
### 6.2.最新更新在 Spring Vault2.2 中
* 通过`@VaultPropertySource`支持键值 v2(版本控制的后端)秘密。
* spel 支持`@Secret`。
* 添加对 Jetty 的支持作为反应性 HttpClient。
* `LifecycleAwareSessionManager`和`ReactiveLifecycleAwareSessionManager`现在发射`AuthenticationEvent`s。
* [PCF 认证](#vault.authentication.pcf).
* 反对`AppIdAuthentication`。使用`AppRoleAuthentication`,而不是按照 HashiCorp 保险库的建议。
* `CubbyholeAuthentication`和 wrapped`AppRoleAuthentication`现在默认使用`sys/wrapping/unwrap`端点。
* Kotlin 协程支持`ReactiveVaultOperations`。
### 6.3.最新更新在 Spring Vault2.1 中
* [GCP 计算](#vault.authentication.gcpgce),[GCP IAM](#vault.authentication.gcpiam),以及[Azure](#vault.authentication.azuremsi)身份验证。
* 模板 API 支持版本控制和非版本控制的键/值后端和 Vault 包装操作。
* 在反应式认证中支持完全拉动模式.
* 改进了保险库登录失败的异常层次结构。
### 6.4.最新更新在 Spring Vault2.0 中
* 身份验证步骤 dsl 到[组合认证流](#vault.authentication.steps)。
* [反应式保险库客户端](#vault.core.reactive.template)via`ReactiveVaultOperations`。
* 基于 Spring 数据键值的[保险库存储库支持](#vault.repositories)。
* 支持传输批加密和解密.
* 存储为 JSON 的策略的策略管理。
* 支持 CSR 签名、证书撤销和 CRL 检索。
* [Kubernetes 认证](#vault.authentication.kubernetes).
* roleid/secretid 展开[Approle 身份验证](#vault.authentication.approle)。
* [Spring Security integration](#vault.misc.spring-security)基于传输后端的`BytesKeyGenerator`和`BytesEncryptor`。
### 6.5.最新更新在 Spring Vault1.1.0 中
* [AWS IAM 身份验证](#vault.authentication.awsiam).
* 为传输密钥配置加密/解密版本。
* [Approle 身份验证](#vault.authentication.approle)的拉动模式。
* 支持传输批加密和解密.
* 基于 TTL 的通用秘密旋转。
### 6.6.最新更新在 Spring Vault1.0 中
* 最初的保险库支持。
# 参考文献
## 7.保险库支持
Vault 支持包含一系列广泛的功能,这些功能概述如下。
* Spring 使用基于 Java 的配置支持 @Configuration Classes
* `VaultTemplate`帮助类,用于提高执行公共保险库操作的生产率。包括保险库响应和 POJO 之间的集成对象映射。
对于大多数任务,你会发现自己正在使用`VaultTemplate`,它利用了丰富的通信功能。`VaultTemplate`是查找访问功能(例如从 Vault 读取数据或发出管理命令)的位置。`VaultTemplate`还提供了回调方法,这样你就可以轻松地获得低级 API 工件,例如`RestTemplate`,从而直接与 Vault 通信。
### 7.1.依赖关系
查找 Spring Vault 依赖关系的兼容版本的最简单的方法是依赖于我们提供的 Spring Vault BOM 以及定义的兼容版本。在 Maven 项目中,你将在你的`pom.xml`的``部分中声明此依赖项:
例 1.使用 Spring 保险库 BOM
```
org.springframework.vault
spring-vault-dependencies
2.3.1
import
pom
```
目前的版本是`2.3.1`。版本名遵循以下模式:`${version}`用于 GA 和服务版本,`${version}-${release}`用于快照和里程碑。`release`可以是下列情况之一:
* `SNAPSHOT`-当前快照
* `M1`,`M2`等-里程碑
* `RC1`,`RC2`等-释放候选项
例 2.声明对 Spring Vault 的依赖关系
```
org.springframework.vault
spring-vault-core
```
### 7.2. Spring 框架
Spring Vault 的当前版本需要版本 5.3.4 或更好的 Spring 框架。这些模块还可以与该小版本的旧 Bugfix 版本一起工作。但是,强烈建议你在这一代中使用最新的版本。
## 8.开始
Spring Vault 支持需要 Vault0.6 或更高版本和 Java SE6 或更高版本。引导设置工作环境的一种简单方法是在[STS](https://spring.io/tools/sts)中创建一个基于 Spring 的项目。
首先,你需要设置一个运行的保险库服务器。有关如何启动 Vault 实例的说明,请参阅[Vault](https://www.vaultproject.io/intro/)。
要在 STS 中创建 Spring 项目,请转到文件 New Spring Template Project Simple Spring Utility Project,在提示时按 Yes。然后输入一个项目和一个包名,如`org.spring.vault.example`。
然后将以下内容添加到`pom.xml`依赖关系部分。
例 3.添加 Spring 保险库依赖项
```
org.springframework.vault
spring-vault-core
2.3.1
```
如果你正在使用一个里程碑或候选版本,那么你还需要将 Spring 里程碑存储库的位置添加到你的 Maven `pom.xml`中,该位置与你的``元素处于同一级别。
```
spring-milestone
Spring Maven MILESTONE Repository
https://repo.spring.io/libs-milestone
```
存储库也是[在这里可浏览](https://repo.spring.io/milestone/org/springframework/vault/)。
如果正在使用快照,还需要将 Spring 快照库的位置添加到你的 Maven `pom.xml`中,该位置与你的``元素处于同一级别。
```
spring-snapshot
Spring Maven SNAPSHOT Repository
https://repo.spring.io/libs-snapshot
```
存储库也是[在这里可浏览](https://repo.spring.io/snapshot/org/springframework/vault/)。
创建一个简单的`Secrets`类以持久存在:
例 4.映射数据对象
```
package org.spring.vault.example;
public class Secrets {
String username;
String password;
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
}
```
以及要运行的主应用程序
例 5.使用 Spring Vault 的示例应用程序
```
package org.springframework.vault.example;
import org.springframework.vault.authentication.TokenAuthentication;
import org.springframework.vault.client.VaultEndpoint;
import org.springframework.vault.core.VaultTemplate;
import org.springframework.vault.support.VaultResponseSupport;
public class VaultApp {
public static void main(String[] args) {
VaultTemplate vaultTemplate = new VaultTemplate(new VaultEndpoint(),
new TokenAuthentication("00000000-0000-0000-0000-000000000000"));
Secrets secrets = new Secrets();
secrets.username = "hello";
secrets.password = "world";
vaultTemplate.write("secret/myapp", secrets);
VaultResponseSupport response = vaultTemplate.read("secret/myapp", Secrets.class);
System.out.println(response.getData().getUsername());
vaultTemplate.delete("secret/myapp");
}
}
```
即使在这个简单的例子中,也没有什么值得注意的地方。
* 可以使用`org.springframework.vault.client.VaultEndpoint`对象和`ClientAuthentication`实例化 Spring Vault 的中心类[`VaultTemplate`](#vault.core.template)。你不需要旋转 Spring 上下文来使用 Spring vault。
* Vault 将被配置为使用`00000000-0000-0000-0000-000000000000`的根令牌来运行此应用程序。
* 该映射器针对标准的 POJO 对象工作,而不需要任何额外的元数据(尽管你可以选择提供该信息)。
* 映射约定可以使用字段访问。注意`Secrets`类只有 getter。
* 如果构造函数参数名称与存储文档的字段名称匹配,则将使用它们实例化对象。
## 9.VaultTemplate 简介
类`VaultTemplate`位于包`org.springframework.vault.core`中,是 Spring 的 Vault 支持的中心类,提供了与 Vault 交互的丰富功能集。该模板提供了在 Vault 中读、写和删除数据的方便操作,并提供了域对象和 Vault 数据之间的映射。
| |一旦配置完成,`VaultTemplate`是线程安全的,并且可以在
多个实例中重用。|
|---|------------------------------------------------------------------------------------------------|
Vault 文档和域类之间的映射是通过委托给`RestTemplate`来完成的。 Spring Web 支持提供了映射基础设施。
`VaultTemplate`类实现了接口`VaultOperations`。在尽可能多的情况下,`VaultOperations`上的方法是以 Vault API 上可用的方法命名的,以使熟悉 API 和 CLI 的现有 Vault 开发人员熟悉该 API。例如,你将找到诸如“write”、“delete”、“read”和“revoke”等方法。设计目标是使 Vault API 的使用和`VaultOperations`之间的转换变得尽可能容易。这两个 API 之间的一个主要区别是,`VaultOperations`可以传递域对象,而不是 JSON 键-值对。
| |引用`VaultTemplate`实例
上的操作的首选方法是通过其接口`VaultOperations`。|
|---|---------------------------------------------------------------------------------------------------------------------|
虽然在`VaultTemplate`上有许多方便的方法可以帮助你轻松地执行常见任务,如果你需要直接访问 Vault API 以访问`VaultTemplate`未显式暴露的功能,则可以使用几种执行回调方法中的一种来访问底层 API。Execute 回调将为你提供对`RestOperations`对象的引用。有关更多信息,请参见[执行回调](#vault.core.executioncallback)一节。
现在,让我们来看看如何在 Spring 容器的上下文中使用 Vault 的示例。
### 9.1.注册和配置 Spring Vault bean
使用 Spring Vault 不需要 Spring 上下文。但是,在托管上下文中注册的`VaultTemplate`和`SessionManager`实例将参与由 Spring IOC 容器提供的[生命周期事件](https://docs.spring.io/spring/docs/5.3.4/spring-framework-reference/core.html#beans-factory-nature)。这对于在应用程序关闭时处理活动的 Vault 会话非常有用。你还可以在应用程序中重用相同的`VaultTemplate`实例。
Spring Vault 附带了一个支持配置类,该配置类提供了 Bean 用于在 Spring 上下文中使用的定义。应用程序配置类通常从`AbstractVaultConfiguration`扩展,并且需要提供环境特定的附加细节。
从`AbstractVaultConfiguration`扩展需要实现` VaultEndpoint vaultEndpoint()`和`ClientAuthentication clientAuthentication()`方法。
例 6.使用基于 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)
}
}
```
|**1**|创建一个新的`VaultEndpoint`,默认情况下指向`https://localhost:8200`。|
|-----|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|**2**|此示例使用`TokenAuthentication`快速启动。
有关支持的身份验证方法的详细信息,请参见[认证方法](#vault.core.authentication)。|
例 7.使用注入的财产登记 Spring 保险库
```
@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**|`VaultEndpoint`可以使用各种工厂方法构建,例如`from(URI uri)`或`VaultEndpoint.create(String host, int port)`。|
|-----|------------------------------------------------------------------------------------------------------------------------------------------|
|**2**|`ClientAuthentication`方法的依赖关系可以从`AbstractVaultConfiguration`获得,也可以由配置提供。|
| |在某些情况下,创建自定义配置类可能很麻烦。
看看`EnvironmentVaultConfiguration`,它允许使用现有属性源的
属性和 Spring 的`Environment`进行配置。在[using`EnvironmentVaultConfiguration`](#vault.core.environment-vault-configuration)中阅读更多
。|
|---|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
### 9.2.会话管理
Spring Vault 需要`ClientAuthentication`才能登录和访问 Vault。有关身份验证的详细信息,请参见[认证方法](#vault.core.authentication)。Vault 登录不应该发生在每个经过身份验证的 Vault 交互上,而是必须在整个会话中重用。该方面由`SessionManager`实现来处理。a`SessionManager`决定它获得令牌的频率,关于撤销和更新。 Spring Vault 有两种实现方式:
* `SimpleSessionManager`:只需从提供的`ClientAuthentication`获取令牌,而无需刷新和撤销
* `LifecycleAwareSessionManager`:如果令牌是可更新的,则此`SessionManager`调度令牌更新,并在处置时撤销登录令牌。更新计划使用`AsyncTaskExecutor`。如果使用`AbstractVaultConfiguration`,则默认配置`LifecycleAwareSessionManager`。
### 9.3.使用`EnvironmentVaultConfiguration`
Spring Vault 包括从 Spring 的`Environment`中配置 Vault 客户端的`EnvironmentVaultConfiguration`和一组预定义的属性键。`EnvironmentVaultConfiguration`支持经常应用的配置。从最合适的配置类派生支持其他配置。将`EnvironmentVaultConfiguration`与`@Import(EnvironmentVaultConfiguration.class)`一起包含到现有的基于 Java 的配置类中,并通过 Spring 的`PropertySource`s 中的任何一个提供配置属性。
例 8.对属性文件使用 EnvironmentVaultConfiguration
基于 Java 的配置类
```
@PropertySource("vault.properties")
@Import(EnvironmentVaultConfiguration.class)
public class MyConfiguration{
}
```
Vault.Properties
```
vault.uri=https://localhost:8200
vault.token=00000000-0000-0000-0000-000000000000
```
**属性键**
* Vault URI:`vault.uri`
* SSL 配置
* 密钥存储库资源:`vault.ssl.key-store`(可选)
* 密钥存储库密码:`vault.ssl.key-store-password`(可选)
* 密钥存储库类型:`vault.ssl.key-store-type`(可选的,通常`jks`,还支持`pem`)
* 信任存储资源:`vault.ssl.trust-store`(可选)
* 信任存储库密码:`vault.ssl.trust-store-password`(可选)
* 信任存储类型:`vault.ssl.trust-store-type`(可选的,通常`jks`,也支持`pem`)
* 认证方法:`vault.authentication`(默认为`TOKEN`,支持的认证方法有:`TOKEN`,`APPID`,`APPROLE`,`AWS_EC2`,`AZURE`,`CUBBYHOLE`,`KUBERNETES`)
**特定于身份验证的属性密钥**
**[令牌认证](#vault.authentication.token)**
* 金库令牌:`vault.token`
**[APPID 身份验证](#vault.authentication.appid)**
* 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.authentication.approle)**
* 路径:`vault.app-role.app-role-path`(默认为`approle`)
* ROLEID:`vault.app-role.role-id`
* secretID:`vault.app-role.secret-id`(可选)
**[AWS-EC2 身份验证](#vault.authentication.awsec2)**
* AWS EC2 路径:`vault.aws-ec2.aws-ec2-path`(默认为`aws-ec2`)
* 角色:`vault.aws-ec2.role`
* ROLEID:`vault.aws-ec2.role-id`(** 不推荐:** 用`vault.aws-ec2.role`代替)
* 身份证件网址:`vault.aws-ec2.identity-document`(默认为`[http://169.254.169.254/latest/dynamic/instance-identity/pkcs7](http://169.254.169.254/latest/dynamic/instance-identity/pkcs7)`)
**[Azure(MSI)认证](#vault.authentication.azuremsi)**
* Azure MSI 路径:`vault.azure-msi.azure-path`(默认为`azure`)
* 角色:`vault.azure-msi.role`
* 元数据服务 URL:`vault.azure-msi.metadata-service`(默认为`[http://169.254.169.254/metadata/instance?api-version=2017-08-01](http://169.254.169.254/metadata/instance?api-version=2017-08-01)`)
* Identity TokenService URL:`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](http://169.254.169.254/metadata/identity/oauth2/token?resource=https://vault.hashicorp.com&api-version=2018-02-01)`)
**[TLS 证书认证](#vault.authentication.clientcert)**
没有配置选项。
**[空穴身份验证](#vault.authentication.cubbyhole)**
* 初始保险库令牌:`vault.token`
**[Kubernetes 认证](#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`)
### 9.4.执行回调
所有 Spring 模板类的一个常见设计特征是,所有功能都被路由到一个模板执行回调方法。这有助于确保执行异常和可能需要的任何资源管理的一致性。虽然在 JDBC 和 JMS 的情况下,这比 Vault 的需要大得多,但它仍然为访问和日志记录的发生提供了一个单一的位置。因此,使用 Execute Callback 是访问 Vault API 的首选方式,以执行我们尚未作为`VaultTemplate`上的方法公开的不常见操作。
下面是执行回调方法的列表。
* ` T`**DowithVault**`(RestOperationsCallback callback)`执行给定的`RestOperationsCallback`,允许使用`RestOperations`与 Vault 进行交互,而不需要会话。
* ` T`**首次会议**`(RestOperationsCallback callback)`执行给定的`RestOperationsCallback`,允许在经过身份验证的保险库中进行交互会话。
下面是一个使用`ClientCallback`初始化 Vault 的示例:
```
vaultOperations.doWithVault(new RestOperationsCallback() {
@Override
public VaultInitializationResponse doWithRestOperations(RestOperations restOperations) {
ResponseEntity exchange = restOperations
.exchange("/sys/init", HttpMethod.PUT,
new HttpEntity