该版本仍在开发中,尚未被视为稳定版本。如需获取最新的稳定版本,请使用Spring Vault 4.0.1spring-doc.cadn.net.cn

Vault Secrets Engines

Spring Vault 提供了多个扩展来支持 Vault 的各种密钥引擎。spring-doc.cadn.net.cn

Spring Vault 特别附带了以下扩展:spring-doc.cadn.net.cn

你可以通过 VaultTemplate 上的方法直接使用所有其他密钥引擎(VaultTemplate.read(…)VaultTemplate.write(…))。spring-doc.cadn.net.cn

键值版本 1(“未版本化的密钥”)

kv secrets 引擎用于在 Vault 配置的物理存储中存储任意密钥。spring-doc.cadn.net.cn

当以非版本化方式运行 kv secrets 引擎时,只会保留最近一次写入的键值。 非版本化 kv 的好处是每个键的存储大小减少了,因为没有存储额外的元数据或历史记录。 此外,发送到以此方式配置的 secrets 引擎的请求性能更高,因为存储调用更少,并且任何给定请求都不会发生锁定。spring-doc.cadn.net.cn

Spring Vault 提供了一个专用的键值(Key-Value)API,以封装不同键值 API 实现之间的差异。 VaultKeyValueOperations 遵循 Vault CLI 的设计。 这是 Vault 的主要命令行工具,提供了诸如 vault kv getvault kv put 等命令。spring-doc.cadn.net.cn

您可以通过指定版本和挂载路径,将此 API 与键值引擎的两个版本一起使用。 以下示例使用键值版本 1:spring-doc.cadn.net.cn

VaultOperations operations = new VaultTemplate(new VaultEndpoint());
VaultKeyValueOperations keyValueOperations = operations.opsForKeyValue("secret",
							VaultKeyValueOperationsSupport.KeyValueBackend.KV_1);

keyValueOperations.put("elvis", Collections.singletonMap("password", "409-52-2002"));

VaultResponse read = keyValueOperations.get("elvis");
read.getRequiredData().get("social-security-number");

VaultKeyValueOperations 支持所有的键值操作,例如 putgetdeletelistspring-doc.cadn.net.cn

或者,可以通过VaultTemplate使用API,因为它具有直接映射和简单使用的特性,键和响应可以直接映射到输入和输出键。 以下示例展示了在mykey处写入和读取秘密的方法。 kv secrets引擎挂载在secretspring-doc.cadn.net.cn

VaultOperations operations = new VaultTemplate(new VaultEndpoint());

operations.write("secret/elvis", Collections.singletonMap("social-security-number", "409-52-2002"));

VaultResponse read = operations.read("secret/elvis");
read.getRequiredData().get("social-security-number");

你可以在 Vault 参考文档中找到更多关于 Vault 键值版本 1 API 的详细信息。spring-doc.cadn.net.cn

Vault 通过 Vault 的 sys/internal/ui/mounts/… 端点确定挂载路径。确保您的策略允许访问该路径,否则您将无法使用键值 API。

键值版本2(“带版本的密钥”)

您可以运行 kv secrets 引擎的两个版本之一。 本节介绍如何使用版本 2。当运行版本 2 的 kv 引擎时,一个密钥可以保留可配置数量的版本。 您可以检索旧版本的元数据和数据。 此外,您可以使用检查并设置操作来避免意外覆盖数据。spring-doc.cadn.net.cn

Similar to 键值版本 1(“未版本化的密钥”),Spring Vault 提供了一个专用的键值 API,用于封装不同键值 API 实现之间的差异。 Spring Vault 提供了一个专用的键值 API,用于封装不同键值 API 实现之间的差异。 VaultKeyValueOperations 遵循 Vault CLI 的设计。 这是 Vault 的主要命令行工具,提供诸如 vault kv getvault kv put 等命令。spring-doc.cadn.net.cn

您可以通过指定版本和挂载路径,将此 API 与键值引擎的两个版本一起使用。 以下示例使用键值版本 2:spring-doc.cadn.net.cn

VaultOperations operations = new VaultTemplate(new VaultEndpoint());
VaultKeyValueOperations keyValueOperations = operations.opsForKeyValue("secret",
							VaultKeyValueOperationsSupport.KeyValueBackend.KV_2);

keyValueOperations.put("elvis", Collections.singletonMap("social-security-number", "409-52-2002"));

VaultResponse read = keyValueOperations.get("elvis");
read.getRequiredData().get("social-security-number");

VaultKeyValueOperations 支持所有的键值操作,例如 putgetdeletelistspring-doc.cadn.net.cn

您还可以与版本化的键值 API 的具体细节进行交互。如果您想获取特定的秘密或需要访问元数据,这将非常有用。spring-doc.cadn.net.cn

VaultOperations operations = new VaultTemplate(new VaultEndpoint());
VaultVersionedKeyValueOperations versionedOperations = operations.opsForVersionedKeyValue("secret");

Versioned.Metadata metadata = versionedOperations.put("elvis",							(1)
					Collections.singletonMap("social-security-number", "409-52-2002"));

Version version = metadata.getVersion();												(2)

Versioned<Object> ssn = versionedOperations.get("elvis", Version.from(42));				(3)

Versioned<SocialSecurityNumber> mappedSsn = versionedOperations.get("elvis",			(4)
											Version.from(42), SocialSecurityNumber.class);

Versioned<Map<String,String>> versioned = Versioned.create(Collections					(5)
						.singletonMap("social-security-number", "409-52-2002"),
						Version.from(42));

versionedOperations.put("elvis", version);
1 将密钥存储在 elvis 中,该密钥在 secret/ 挂载下可用。
2 将数据存储在带版本控制的密钥引擎中时,会返回诸如版本号之类的元数据。
3 版本化的键值 API 允许通过版本号检索特定版本。
4 带有版本控制的键值秘密可以映射到值对象中。
5 使用 CAS 更新带版本的密钥时,输入必须引用之前获取的版本。

虽然可以通过VaultTemplate使用kvv2版本的密钥引擎是可行的。 但这并不是最方便的方法,因为API对上下文路径以及输入/输出的表示方式提供了不同的处理方法。 具体来说,与实际密钥的交互需要对数据部分进行封装和解封,并在挂载点和密钥键之间引入一个data/路径段。spring-doc.cadn.net.cn

VaultOperations operations = new VaultTemplate(new VaultEndpoint());

operations.write("secret/data/elvis", Collections.singletonMap("data",
			Collections.singletonMap("social-security-number", "409-52-2002")));

VaultResponse read = operations.read("secret/data/ykey");
Map<String,String> data = (Map<String, String>) read.getRequiredData().get("data");
data.get("social-security-number");

你可以在 Vault 参考文档中找到更多关于 Vault 键值版本 2 API 的详细信息。spring-doc.cadn.net.cn

Vault 通过 Vault 的 sys/internal/ui/mounts/… 端点确定挂载路径。确保您的策略允许访问该路径,否则您将无法使用键值 API。

公钥基础设施(PKI)

pki 密钥引擎通过实现证书颁发机构的操作,代表了一个用于证书的密钥引擎。spring-doc.cadn.net.cn

PKI secrets 引擎生成动态的 X.509 证书。 通过此 secrets 引擎,服务可以获取证书,而无需经历通常的手动流程:生成私钥和 CSR、提交给 CA,并等待验证和签名过程完成。 Vault 内置的身份验证和授权机制提供了验证功能。spring-doc.cadn.net.cn

Spring Vault 支持通过 VaultPkiOperations 发放、签署、吊销证书以及 CRL 检索。 所有其他 PKI 功能可以通过 VaultOperations 使用。spring-doc.cadn.net.cn

以下示例简要说明了如何颁发和吊销证书的用法:spring-doc.cadn.net.cn

VaultOperations operations = new VaultTemplate(new VaultEndpoint());
VaultPkiOperations pkiOperations = operations.opsForPki("pki");

VaultCertificateRequest request = VaultCertificateRequest.builder()								(1)
			.ttl(Duration.ofHours(48))
			.altNames(Arrays.asList("prod.dc-1.example.com", "prod.dc-2.example.com"))
			.withIpSubjectAltName("1.2.3.4")
			.commonName("hello.example.com")
			.build();

VaultCertificateResponse response = pkiOperations.issueCertificate("production", request); 		(2)
CertificateBundle certificateBundle = response.getRequiredData();

KeyStore keyStore = certificateBundle.createKeyStore("my-keystore");							(3)

KeySpec privateKey = certificateBundle.getPrivateKeySpec();										(4)
X509Certificate certificate = certificateBundle.getX509Certificate();
X509Certificate caCertificate = certificateBundle.getX509IssuerCertificate();

pkiOperations.revoke(certificateBundle.getSerialNumber());										(5)
1 通过使用VaultCertificateRequest构建器来构建证书请求。
2 向 Vault 请求证书。 Vault 充当证书颁发机构,并返回一个已签名的 X.509 证书。 实际的响应是一个 CertificateBundle
3 您可以直接获取生成的证书作为 Java KeyStore,其中包含公钥和私钥以及颁发者证书。KeyStore 具有广泛的用途,这使得该格式适合用于配置(例如 HTTP 客户端、数据库驱动程序或 SSL 加密的 HTTP 服务器)。
4 CertificateBundle 允许通过 Java 加密扩展 API 直接访问私钥以及公钥和颁发者证书。
5 一旦证书不再使用(或已被泄露),您可以通过其序列号将其吊销。 Vault 会将其吊销的证书包含在其 CRL 中。

你可以在 Vault 参考文档中找到更多关于 Vault PKI secrets API 的详细信息。spring-doc.cadn.net.cn

Tokens认证方法

这是一种不与实际密钥交互的认证方法。 相反,它提供对访问Tokens管理的访问。 你可以阅读更多关于基于Tokens的认证的信息,在认证方法章节中。spring-doc.cadn.net.cn

内置的 token 认证方法在 /auth/token 处自动可用。 它允许用户使用Tokens进行身份验证,还可以创建新Tokens、通过Tokens撤销密钥等更多功能。spring-doc.cadn.net.cn

当任何其他身份验证方法返回身份时,Vault 核心将调用Tokens方法为该身份创建一个新的唯一Tokens。spring-doc.cadn.net.cn

您还可以使用Tokens存储来绕过任何其他身份验证方法。您可以直接创建Tokens,还可以对Tokens执行各种其他操作,例如续订和吊销。spring-doc.cadn.net.cn

Spring Vault 使用此后端来续订和撤销由配置的身份验证方法提供的会话Tokens。spring-doc.cadn.net.cn

以下示例展示了如何在应用程序中请求、续订和吊销 Vault Tokens:spring-doc.cadn.net.cn

VaultOperations operations = new VaultTemplate(new VaultEndpoint());
VaultTokenOperations tokenOperations = operations.opsForToken();

VaultTokenResponse tokenResponse = tokenOperations.create();                          (1)
VaultToken justAToken = tokenResponse.getToken();

VaultTokenRequest tokenRequest = VaultTokenRequest.builder().withPolicy("policy-for-myapp")
									.displayName("Access tokens for myapp")
									.renewable()
									.ttl(Duration.ofHours(1))
									.build();

VaultTokenResponse appTokenResponse = tokenOperations.create(tokenRequest);          (2)
VaultToken appToken = appTokenResponse.getToken();

tokenOperations.renew(appToken);                                                     (3)

tokenOperations.revoke(appToken);                                                    (4)
1 通过应用角色默认值创建一个Tokens。
2 使用构建器 API,您可以为请求的Tokens定义细粒度的设置。 请求Tokens将返回一个 VaultToken,它用作 Vault Tokens的值对象。
3 你可以通过 Token API 更新Tokens。通常,这是通过 SessionManager 来跟踪 Vault 会话Tokens完成的。
4 如果需要,可以通过 Token API 撤销Tokens。通常,这是由 SessionManager 完成的,以跟踪 Vault 会话Tokens。

你可以在 Vault 参考文档中找到更多关于 Vault Token 身份验证方法 API 的详细信息。spring-doc.cadn.net.cn

后端传输

传输秘密引擎处理传输中数据的加密功能。 Vault 不会存储发送到该秘密引擎的数据。 它也可以被视为“加密即服务”或“加密作为服务”。 传输秘密引擎还可以签名和验证数据、生成数据的哈希值和 HMAC,并充当随机字节源。spring-doc.cadn.net.cn

主要的使用场景是通过传输加密应用程序的数据,同时将这些加密后的数据存储在某些主要的数据存储中。 这减轻了应用程序开发人员正确加密和解密的负担,并将该负担转移给 Vault 的操作员。spring-doc.cadn.net.cn

Spring Vault 支持广泛的 Transit 操作:spring-doc.cadn.net.cn

所有在 transit 中的操作都围绕密钥进行。 Transit 引擎支持密钥的版本控制和 多种密钥类型。 请注意,密钥类型可能会对可使用的操作施加限制。spring-doc.cadn.net.cn

以下示例展示了如何创建密钥以及如何加密和解密数据:spring-doc.cadn.net.cn

VaultOperations operations = new VaultTemplate(new VaultEndpoint());
VaultTransitOperations transitOperations = operations.opsForTransit("transit");

transitOperations.createKey("my-aes-key", VaultTransitKeyCreationRequest.ofKeyType("aes128-gcm96"));	(1)

String ciphertext = transitOperations.encrypt("my-aes-key", "plaintext to encrypt");					(2)

String plaintext = transitOperations.decrypt("my-aes-key", ciphertext);									(3)
1 首先,我们需要一个密钥来开始。 每个密钥都需要指定类型。aes128-gcm96 支持加密、解密、密钥派生和收敛加密,其中在本例中我们需要加密和解密功能。
2 接下来,我们加密一个包含应被加密的纯文本的String。 输入String使用默认的Charset将字符串编码为其二进制表示形式。 请求Tokens会返回一个VaultToken,它作为VaultTokens的值对象使用。 encrypt方法返回Base64编码的密文,通常以vault:开头。
3 要将密文解密为明文,请调用 decrypt 方法。 它会解密密文并返回使用默认字符集解码的 String

前面的示例在加密操作中使用了简单的字符串。虽然这种方法简单,但它存在字符集配置错误的风险,并且不是二进制安全的。当明文使用二进制表示数据(例如图像、压缩数据或二进制数据结构)时,需要二进制安全。spring-doc.cadn.net.cn

要加密和解密二进制数据,请使用可以保存二进制值的PlaintextCiphertext 值对象:spring-doc.cadn.net.cn

byte [] plaintext = "plaintext to encrypt".getBytes();

Ciphertext ciphertext = transitOperations.encrypt("my-aes-key", Plaintext.of(plaintext));			(1)

Plaintext decrypttedPlaintext = transitOperations.decrypt("my-aes-key", ciphertext);				(2)
1 假设键my-aes-key已经就位,我们正在加密Plaintext对象。 作为返回,encrypt方法返回一个Ciphertext对象。
2 Ciphertext 对象可直接用于解密,并返回一个 Plaintext 对象。

PlaintextCiphertext 带有一个上下文对象,VaultTransitContext。 它用于为收敛加密提供一个随机数(nonce)值,并为利用密钥派生提供上下文值。spring-doc.cadn.net.cn

Transit允许对明文进行签名并验证给定明文的签名。 签名操作需要使用非对称密钥,通常采用椭圆曲线加密(ECC)或RSA算法。spring-doc.cadn.net.cn

签名使用公钥/私钥分离来确保真实性。
签名者使用其私钥创建签名。否则,任何人都能以你的名义签署消息。 验证者使用公钥部分来验证签名。实际的签名通常是一个哈希值。

内部地,使用私钥计算和加密哈希以生成最终签名。验证过程解密签名消息,为明文计算自己的哈希值,并比较两个哈希值以检查签名是否有效。
byte [] plaintext = "plaintext to sign".getBytes();

transitOperations.createKey("my-ed25519-key", VaultTransitKeyCreationRequest.ofKeyType("ed25519"));	(1)

Signature signature = transitOperations.sign("my-ed25519-key", Plaintext.of(plaintext));			(2)

boolean valid = transitOperations.verify("my-ed25519-key", Plaintext.of(plaintext), signature);		(3)
1 签名需要一个非对称密钥。您可以使用任何椭圆曲线加密或RSA密钥类型。创建密钥后,您就具备了创建签名的所有前提条件。
2 签名是为纯文本消息创建的。返回的 Signature 包含使用 Base64 字符的 ASCII 安全字符串。
3 为了验证签名,验证过程需要一个Signature对象以及纯文本消息。作为返回值,您将得到签名是否有效的结果。

你可以在 Vault 参考文档中找到有关 Vault Transit 后端 的更多详细信息。spring-doc.cadn.net.cn