此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring Vault 3.2.0! |
支持 Vault 的秘密引擎
Spring Vault 附带了多个扩展来支持 Vault 的各种秘密引擎。
具体来说,Spring Vault 附带了以下扩展:
-
转换(企业功能)
-
系统后端
您可以通过以下方法使用所有其他后端VaultTemplate
直接 (VaultTemplate.read(…)
,VaultTemplate.write(…)
).
键值版本 1(“未版本化密钥”)
这kv
secrets 引擎用于在为 Vault 配置的物理存储中存储任意密钥。
运行kv
secrets 引擎,仅保留密钥的最新写入值。
非版本控制 kv 的好处是减小了每个键的存储大小,因为不会存储额外的元数据或历史记录。
此外,发送到以这种方式配置的后端的请求性能更高,因为存储调用更少,并且任何给定请求都没有锁定。
Spring Vault 附带一个专用的键值 API,用于封装各个键值 API 实现之间的差异。VaultKeyValueOperations
遵循 Vault CLI 设计。
这是 Vault 的主要命令行工具,提供诸如vault kv get
,vault kv put
等等。
您可以通过指定版本和挂载路径,将此 API 与键值引擎版本一起使用。 以下示例使用键值版本 1:
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
支持所有键值作,例如put
,get
,delete
,list
.
或者,可以通过VaultTemplate
由于其直接映射和简单使用,AS 键和响应直接映射到输入和输出键。
以下示例说明了在mykey
.
这kv
secrets 引擎安装在secret
:
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 的更多详细信息。
Vault 确定通过 Vault 的sys/internal/ui/mounts/… 端点。请确保您的策略允许访问该路径,否则您将无法使用键值 API。 |
键值版本 2(“版本控制的密钥”)
您可以运行kv
secrets 引擎中的两个版本之一。
本节介绍使用版本 2。当运行kv
后端密钥可以保留可配置数量的版本。
您可以检索旧版本的元数据和数据。
此外,您可以使用检查和设置作来避免无意中覆盖数据。
与键值版本 1(“未版本控制的密钥”)类似,Spring Vault 附带一个专用的键值 API,用于封装各个键值 API 实现之间的差异。
Spring Vault 附带一个专用的键值 API,用于封装各个键值 API 实现之间的差异。VaultKeyValueOperations
遵循 Vault CLI 设计。
这是 Vault 的主要命令行工具,提供诸如vault kv get
,vault kv put
,依此类推。
您可以通过指定版本和挂载路径,将此 API 与键值引擎版本一起使用。 以下示例使用键值版本 2:
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
支持所有键值作,例如put
,get
,delete
,list
.
您还可以与版本化键值 API 的详细信息进行交互。如果您想获取特定密钥或需要访问元数据,这将非常有用。
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 更新版本控制的密钥时,输入必须引用以前获取的版本。 |
使用kv
v2 secrets 引擎通过VaultTemplate
是可能的。
这不是最方便的方法,因为 API 提供了一种不同的上下文路径方法以及输入/输出的表示方式。
具体来说,与实际密钥的交互需要包装和解包数据部分,并引入一个data/
挂载和密钥之间的路径段。
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 的更多详细信息。
Vault 确定通过 Vault 的sys/internal/ui/mounts/… 端点。请确保您的策略允许访问该路径,否则您将无法使用键值 API。 |
PKI(公钥基础设施)
这pki
secrets 引擎通过实现证书颁发机构作来表示证书的后端。
PKI 密钥引擎生成动态 X.509 证书。使用此密钥引擎,服务可以获取证书,而无需经历生成私钥和 CSR、提交给 CA 以及等待验证和签名过程完成的常规手动过程。Vault 的内置身份验证和授权机制提供了验证功能。
Spring Vault 支持通过VaultPkiOperations
. 所有其他 PKI 功能都可以通过VaultOperations
.
以下示例简要说明了如何颁发和吊销证书的用法:
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 Cryptography Extension API 访问私钥以及公共证书和颁发者证书。 |
5 | 一旦证书不再使用(或已泄露),您可以通过其序列号吊销它。Vault 将吊销的证书包含在其 CRL 中。 |
您可以在 Vault 参考文档中找到有关 Vault PKI 密钥 API 的更多详细信息。
Tokens认证后端
此后端是不与实际密钥交互的身份验证后端。 相反,它提供了对访问Tokens管理的访问权限。 您可以在身份验证方法一章中阅读有关基于Tokens的身份验证的更多信息。
这token
身份验证方法是内置的,并在/auth/token
.
它允许用户使用Tokens进行身份验证,以及创建新Tokens、按Tokens撤销机密等。
当任何其他身份验证方法返回身份时,Vault 核心会调用Tokens方法为该身份创建新的唯一Tokens。
您还可以使用Tokens存储绕过任何其他身份验证方法。您可以直接创建Tokens,也可以对Tokens执行各种其他作,例如续订和吊销。
Spring Vault 使用此后端来续订和撤销配置的身份验证方法提供的会话Tokens。
以下示例演示了如何从应用程序中请求、续订和撤销 Vault Tokens:
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 | 您可以通过Tokens API 续订Tokens。通常,这是通过SessionManager 以跟踪 Vault 会话Tokens。 |
4 | 如果需要,可以通过Tokens API 撤销Tokens。通常,这是通过SessionManager 以跟踪 Vault 会话Tokens。 |
您可以在 Vault 参考文档中找到有关 Vault Tokens身份验证方法 API 的更多详细信息。
中转后端
传输密钥引擎处理传输中数据的加密功能。 Vault 不存储发送到此密钥引擎的数据。 也可以看作是“密码即服务”或“加密即服务”。 传输机密引擎还可以对数据进行签名和验证,生成数据的哈希值和 HMAC,并充当随机字节源。
传输的主要用例是加密来自应用程序的数据,同时仍将加密数据存储在某些主数据存储中。 这减轻了应用程序开发人员正确加密和解密的负担,并将负担推给了 Vault 的运营商。
Spring Vault 支持广泛的 Transit作:
-
密钥创建
-
密钥重新配置
-
加密/解密/重新包装
-
HMAC 计算
-
签名和签名验证
内部所有作transit
以键为中心。
Transit 引擎支持键和各种键类型的版本控制。
请注意,键类型可能会对可以使用的作施加限制。
以下示例演示如何创建密钥以及如何加密和解密数据:
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 ,用作 Vault Tokens的值对象。
这encrypt 方法返回 Base64 编码的密文,通常以vault: . |
3 | 要将密文解密为纯文本,请调用decrypt 方法。
它解密密文并返回一个String 使用默认字符集进行解码。 |
前面的示例使用简单字符串进行加密作。 虽然这是一种简单的方法,但它存在字符集配置错误的风险,并且不是二进制安全的。 当纯文本对图像、压缩数据或二进制数据结构等数据使用二进制表示时,需要二进制安全性。
要加密和解密二进制数据,请使用Plaintext
和Ciphertext
value 对象,可以保存二进制值:
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 object 可以直接用于解密,并返回一个Plaintext 对象。 |
Plaintext
和Ciphertext
带有上下文对象,VaultTransitContext
.
它用于为收敛加密提供随机数值,并为上下文值提供使用密钥派生。
Transit 允许对纯文本进行签名并验证给定纯文本的签名。 签名作需要非对称密钥,通常使用椭圆曲线加密或 RSA。
签名使用公钥/私钥拆分来确保真实性。 签名者使用其私钥创建签名。否则,任何人都可以以您的名义签署消息。 验证者使用公钥部分来验证签名。实际签名通常是哈希值。 在 内部,使用私钥计算和加密哈希值以创建最终签名。验证解密签名消息,计算自己的纯文本哈希值,并比较两个哈希值以检查签名是否有效。 |
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)
您可以在 Vault 参考文档中找到有关 Vault Transit 后端的更多详细信息。