Vault Secret Engines 支援

Spring Vault 隨附多個擴充功能,以支援 Vault 各種 Secret Engines。

具體來說,Spring Vault 隨附以下項目的擴充功能:

您可以透過 VaultTemplate 上的方法直接使用所有其他後端 (VaultTemplate.read(…)VaultTemplate.write(…))。

Key-Value Version 1 ("未版本控制的密碼")

kv Secret Engine 用於在 Vault 的已配置實體儲存空間中儲存任意密碼。

當以非版本控制方式執行 kv Secret Engine 時,只會保留金鑰最近寫入的值。非版本控制 kv 的優點是每個金鑰的儲存大小減少,因為不會儲存額外的中繼資料或歷史記錄。此外,前往以此方式配置的後端的請求效能更高,因為儲存呼叫次數較少,且任何給定請求都沒有鎖定。

Spring Vault 隨附專用的 Key-Value API,以封裝個別 Key-Value API 實作之間的差異。VaultKeyValueOperations 遵循 Vault CLI 設計。這是 Vault 的主要命令列工具,提供 vault kv getvault kv put 等命令。

您可以透過指定版本和掛載路徑,將此 API 與 Key-Value Engine 版本搭配使用。以下範例使用 Key-Value version 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 支援所有 Key-Value 作業,例如 putgetdeletelist

或者,API 可以透過 VaultTemplate 使用,因為它直接對應且易於使用,因為金鑰和回應直接對應到輸入和輸出金鑰。以下範例說明在 mykey 寫入和讀取密碼。kv Secret Engine 掛載在 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 Key-Value version 1 API 的更多詳細資訊。

Key-Value Version 2 ("已版本控制的密碼")

您可以使用兩個版本之一執行 kv Secret Engine。本節說明如何使用 version 2。當執行 kv 後端的 version 2 時,金鑰可以保留可配置的版本數。您可以擷取舊版本的中繼資料和資料。此外,您可以使用檢查和設定作業來避免意外覆寫資料。

Key-Value Version 1 ("未版本控制的密碼") 類似,Spring Vault 隨附專用的 Key-Value API,以封裝個別 Key-Value API 實作之間的差異。Spring Vault 隨附專用的 Key-Value API,以封裝個別 Key-Value API 實作之間的差異。VaultKeyValueOperations 遵循 Vault CLI 設計。這是 Vault 的主要命令列工具,提供 vault kv getvault kv put 等命令。

您可以透過指定版本和掛載路徑,將此 API 與 Key-Value Engine 版本搭配使用。以下範例使用 Key-Value version 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 支援所有 Key-Value 作業,例如 putgetdeletelist

您也可以與版本控制的 Key-Value 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 版本控制的 Key-Value API 允許擷取由版本號碼識別的特定版本。
4 版本控制的 Key-Value 密碼可以對應到值物件中。
5 當使用 CAS 更新版本控制的密碼時,輸入必須參考先前取得的版本。

雖然可以透過 VaultTemplate 使用 kv v2 Secret Engine。但這不是最方便的方法,因為 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 Key-Value version 2 API 的更多詳細資訊。

PKI (公開金鑰基礎架構)

pki Secret Engine 代表憑證的後端,方法是實作憑證授權單位作業。

PKI Secret Engine 產生動態 X.509 憑證。透過此 Secret Engine,服務可以取得憑證,而無需經歷產生私密金鑰和 CSR、提交至 CA 以及等待驗證和簽署程序完成的通常手動程序。Vault 的內建驗證和授權機制提供驗證功能。

Spring Vault 支援透過 VaultPkiOperations 發行、簽署、撤銷憑證和 CRL 擷取。所有其他 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 Builder 建構憑證請求。
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 Secret API 的更多詳細資訊。

Token 驗證後端

此後端是驗證後端,不會與實際密碼互動。相反地,它提供對存取 Token 管理的存取權限。您可以在 Token 基礎驗證 中的 驗證方法章節 中閱讀更多相關資訊。

token 驗證方法是內建的,並且在 /auth/token 中自動可用。它讓使用者可以使用 Token 進行驗證,以及建立新的 Token、依 Token 撤銷密碼等等。

當任何其他驗證方法傳回身分時,Vault 核心會叫用 Token 方法,以針對該身分建立新的唯一 Token。

您也可以使用 Token 儲存區來略過任何其他驗證方法。您可以直接建立 Token,以及對 Token 執行各種其他作業,例如續約和撤銷。

Spring Vault 使用此後端來續約和撤銷已配置的 驗證方法 所提供的會期 Token。

以下範例顯示如何從您的應用程式內請求、續約和撤銷 Vault Token

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 透過套用角色預設值來建立 Token。
2 使用 Builder API,您可以為要請求的 Token 定義精細的設定。請求 Token 會傳回 VaultToken,其用作 Vault Token 的值物件。
3 您可以透過 Token API 續約 Token。通常,這是由 SessionManager 完成,以追蹤 Vault 會期 Token。
4 如果需要,可以透過 Token API 撤銷 Token。通常,這是由 SessionManager 完成,以追蹤 Vault 會期 Token。

您可以在 Vault 參考文件中找到關於 Vault Token 驗證方法 API 的更多詳細資訊。

Transit 後端

Transit Secret Engine 處理傳輸中資料的加密功能。Vault 不會儲存傳送至此 Secret Engine 的資料。它也可以視為「密碼編譯即服務」或「加密即服務」。Transit Secret Engine 也可以簽署和驗證資料、產生資料的雜湊和 HMAC,以及充當隨機位元組來源。

Transit 的主要使用案例是加密來自應用程式的資料,同時仍將該加密資料儲存在某些主要資料儲存區中。這減輕了應用程式開發人員正確加密和解密的負擔,並將負擔轉移到 Vault 的營運商身上。

Spring Vault 支援廣泛的 Transit 作業

  • 金鑰建立

  • 金鑰重新配置

  • 加密/解密/重新包裝

  • HMAC 計算

  • 簽署和簽名驗證

transit 內的所有作業都以金鑰為中心。Transit Engine 支援金鑰的版本控制和 各種金鑰類型。請注意,金鑰類型可能會對可以使用哪些作業施加限制。

以下範例顯示如何建立金鑰以及如何加密和解密資料

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 將字串編碼為其二進位表示法。請求 Token 會傳回 VaultToken,其用作 Vault Token 的值物件。encrypt 方法會傳回 Base64 編碼的密文,通常以 vault: 開頭。
3 若要將密文解密為純文字,請呼叫 decrypt 方法。它會解密密文並傳回使用預設字元集解碼的 String

先前的範例使用簡單字串進行密碼編譯作業。雖然這是一種簡單的方法,但它帶有字元集配置錯誤的風險,並且不是二進位安全。當純文字使用二進位表示法表示資料 (例如影像、壓縮資料或二進位資料結構) 時,就需要二進位安全性。

若要加密和解密二進位資料,請使用 PlaintextCiphertext 值物件,這些物件可以保存二進位值

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 值,並為內容值提供以使用金鑰衍生。

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)
1 簽署需要非對稱金鑰。您可以使用任何橢圓曲線密碼編譯或 RSA 金鑰類型。建立金鑰後,您就已具備建立簽名的所有先決條件。
2 簽名是為純文字訊息建立的。傳回的 Signature 包含使用 Base64 字元的 ASCII 安全字串。
3 若要驗證簽名,驗證需要 Signature 物件和純文字訊息。作為傳回值,您會取得簽名是否有效。

您可以在 Vault 參考文件中找到關於 Vault Transit 後端 的更多詳細資訊。