Added transit batch encrypt and decrypt support.
We now support batch encryption and decryption via VaultTransitOperations.
List<VaultEncryptionResult> batchEncryption = transitOperations.encrypt("mykey", Arrays.asList(Plaintext.of("hello"), Plaintext.of("world")));
Ciphertext encryptedHello = batchEncryption.get(0).get();
Ciphertext encryptedWorld = batchEncryption.get(1).get();
List<VaultDecryptionResult> batchDecryption = transitOperations.decrypt("mykey", Arrays.asList(encryptedHello, encryptedWorld));
Original pull request: gh-138.
Related ticket: gh-137.
Closes gh-138.
This commit is contained in:
committed by
Mark Paluch
parent
aa8eb13f66
commit
ed920ec0ab
@@ -246,6 +246,7 @@ The following scripts need to be run prior to building the project for the tests
|
||||
|
||||
$ ./src/test/bash/install_vault.sh
|
||||
$ ./src/test/bash/create_certificates.sh
|
||||
$ ./src/test/bash/env.sh
|
||||
$ ./src/test/bash/local_run_vault.sh
|
||||
|
||||
Changes to the documentation should be made to the adocs found under `src/main/asciidoc/`
|
||||
|
||||
@@ -17,18 +17,23 @@ package org.springframework.vault.core;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.vault.support.RawTransitKey;
|
||||
import org.springframework.vault.support.TransitKeyType;
|
||||
import org.springframework.vault.support.VaultDecryptionPayload;
|
||||
import org.springframework.vault.support.VaultDecryptionResult;
|
||||
import org.springframework.vault.support.VaultEncryptionPayload;
|
||||
import org.springframework.vault.support.VaultEncryptionResult;
|
||||
import org.springframework.vault.support.VaultTransitContext;
|
||||
import org.springframework.vault.support.VaultTransitKey;
|
||||
import org.springframework.vault.support.VaultTransitKeyConfiguration;
|
||||
import org.springframework.vault.support.VaultTransitKeyCreationRequest;
|
||||
import org.springframework.vault.support.RawTransitKey;
|
||||
|
||||
/**
|
||||
* Interface that specifies operations using the {@code transit} backend.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author Sven Schürmann
|
||||
* @author Praveendra Singh
|
||||
* @see <a href="https://www.vaultproject.io/docs/secrets/transit/index.html">Transit
|
||||
* Secret Backend</a>
|
||||
*/
|
||||
@@ -122,6 +127,19 @@ public interface VaultTransitOperations {
|
||||
*/
|
||||
String encrypt(String keyName, byte[] plaintext, VaultTransitContext transitRequest);
|
||||
|
||||
/**
|
||||
* Encrypts the provided list of plaintext using the named key and context.
|
||||
* The encryption is done using transit backend's batch operation.
|
||||
*
|
||||
* works with Vault 0.6.5 and later.
|
||||
*
|
||||
* @param keyName must not be empty or {@literal null}.
|
||||
* @param batchRequest a list of VaultEncryptionPayload which includes plaintext and optional context
|
||||
* @return list of cipher text in the same order as in plaintexts.
|
||||
* throws VaultException in case of not matching context found.
|
||||
*/
|
||||
List<VaultEncryptionResult> encrypt(String keyName, List<VaultEncryptionPayload> batchRequest);
|
||||
|
||||
/**
|
||||
* Decrypts the provided plaintext using the named key.
|
||||
*
|
||||
@@ -141,6 +159,19 @@ public interface VaultTransitOperations {
|
||||
*/
|
||||
byte[] decrypt(String keyName, String ciphertext, VaultTransitContext transitRequest);
|
||||
|
||||
/**
|
||||
* Decrypts the provided list of ciphertext using the named key and context.
|
||||
* The decryption is done using transit backend's batch operation.
|
||||
*
|
||||
* works with Vault 0.6.5 and later.
|
||||
*
|
||||
* @param keyName must not be empty or {@literal null}.
|
||||
* @param batchRequest a list of VaultDecryptionPayload which includes plaintext and optional context
|
||||
* @return list of plain text in the same order as in ciphertexts.
|
||||
* throws VaultException in case of not matching context found.
|
||||
*/
|
||||
List<VaultDecryptionResult> decrypt(String keyName, List<VaultDecryptionPayload> batchRequest);
|
||||
|
||||
/**
|
||||
* Rewrap the provided ciphertext using the latest version of the named key. Because
|
||||
* this never returns plaintext, it is possible to delegate this functionality to
|
||||
|
||||
@@ -15,30 +15,38 @@
|
||||
*/
|
||||
package org.springframework.vault.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.Base64Utils;
|
||||
import org.springframework.vault.support.RawTransitKey;
|
||||
import org.springframework.vault.support.TransitKeyType;
|
||||
import org.springframework.vault.support.VaultDecryptionPayload;
|
||||
import org.springframework.vault.support.VaultDecryptionResult;
|
||||
import org.springframework.vault.support.VaultEncryptionDecryptionResultHelper;
|
||||
import org.springframework.vault.support.VaultEncryptionPayload;
|
||||
import org.springframework.vault.support.VaultEncryptionResult;
|
||||
import org.springframework.vault.support.VaultResponse;
|
||||
import org.springframework.vault.support.VaultResponseSupport;
|
||||
import org.springframework.vault.support.VaultTransitContext;
|
||||
import org.springframework.vault.support.VaultTransitKey;
|
||||
import org.springframework.vault.support.VaultTransitKeyConfiguration;
|
||||
import org.springframework.vault.support.VaultTransitKeyCreationRequest;
|
||||
import org.springframework.vault.support.RawTransitKey;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link VaultTransitOperations}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author Sven Schürmann
|
||||
* @author Praveendra Singh
|
||||
*/
|
||||
public class VaultTransitTemplate implements VaultTransitOperations {
|
||||
|
||||
@@ -152,7 +160,7 @@ public class VaultTransitTemplate implements VaultTransitOperations {
|
||||
.write(String.format("%s/encrypt/%s", path, keyName), request).getData()
|
||||
.get("ciphertext");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String encrypt(String keyName, byte[] plaintext,
|
||||
VaultTransitContext transitRequest) {
|
||||
@@ -173,6 +181,37 @@ public class VaultTransitTemplate implements VaultTransitOperations {
|
||||
.get("ciphertext");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<VaultEncryptionResult> encrypt(String keyName, List<VaultEncryptionPayload> batchRequest) {
|
||||
|
||||
Assert.hasText(keyName, "KeyName must not be empty");
|
||||
Assert.notEmpty(batchRequest, "batchRequest must not be null and should have at least one entry");
|
||||
|
||||
List<Map<String, String>> batch = new ArrayList<Map<String, String>>();
|
||||
|
||||
for (VaultEncryptionPayload request : batchRequest) {
|
||||
|
||||
Assert.notNull(request.getPlaintext(), "Plain text must not be null");
|
||||
|
||||
Map<String, String> vaultRequest = new LinkedHashMap<String, String>();
|
||||
|
||||
vaultRequest.put("plaintext", Base64Utils.encodeToString(request.getPlaintext()));
|
||||
|
||||
if (request.getContext() != null) {
|
||||
applyTransitOptions(request.getContext(), vaultRequest);
|
||||
}
|
||||
|
||||
batch.add(vaultRequest);
|
||||
}
|
||||
|
||||
Map<String, List<Map<String, String>>> request = new LinkedHashMap<String, List<Map<String, String>>>();
|
||||
request.put("batch_input", batch);
|
||||
|
||||
VaultResponse vaultResponse = vaultOperations.write(String.format("%s/encrypt/%s", path, keyName), request);
|
||||
|
||||
return VaultEncryptionDecryptionResultHelper.fetchEncryptionResult(vaultResponse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String decrypt(String keyName, String ciphertext) {
|
||||
|
||||
@@ -211,6 +250,37 @@ public class VaultTransitTemplate implements VaultTransitOperations {
|
||||
|
||||
return Base64Utils.decodeFromString(plaintext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<VaultDecryptionResult> decrypt(String keyName, List<VaultDecryptionPayload> batchRequest) {
|
||||
|
||||
Assert.hasText(keyName, "KeyName must not be empty");
|
||||
Assert.notEmpty(batchRequest, "batchRequest must not be null and should have at least one entry");
|
||||
|
||||
List<Map<String, String>> batch = new ArrayList<Map<String, String>>();
|
||||
|
||||
for (VaultDecryptionPayload request : batchRequest) {
|
||||
|
||||
Assert.notNull(request.getCiphertext(), "Cipher text must not be null");
|
||||
|
||||
Map<String, String> vaultRequest = new LinkedHashMap<String, String>();
|
||||
|
||||
vaultRequest.put("ciphertext", request.getCiphertext());
|
||||
|
||||
if (request.getContext() != null) {
|
||||
applyTransitOptions(request.getContext(), vaultRequest);
|
||||
}
|
||||
|
||||
batch.add(vaultRequest);
|
||||
}
|
||||
|
||||
Map<String, List<Map<String, String>>> request = new LinkedHashMap<String, List<Map<String, String>>>();
|
||||
request.put("batch_input", batch);
|
||||
|
||||
VaultResponse vaultResponse = vaultOperations.write(String.format("%s/decrypt/%s", path, keyName), request);
|
||||
|
||||
return VaultEncryptionDecryptionResultHelper.fetchDecryptionResult(vaultResponse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String rewrap(String keyName, String ciphertext) {
|
||||
@@ -303,4 +373,5 @@ public class VaultTransitTemplate implements VaultTransitOperations {
|
||||
|
||||
private String name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package org.springframework.vault.support;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* Decryption Value Object used for encrypt() operations.
|
||||
*
|
||||
* @author Praveendra Singh
|
||||
*
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
public class VaultDecryptionPayload {
|
||||
private String ciphertext;
|
||||
private VaultTransitContext context;
|
||||
|
||||
/**
|
||||
* factory method helps to create decryption value object using ciphertext
|
||||
* in String
|
||||
*
|
||||
* @param ciphertext
|
||||
* to be decrypted
|
||||
* @return decryption value object
|
||||
*/
|
||||
public static VaultDecryptionPayload of(String ciphertext) {
|
||||
|
||||
if (ciphertext == null) {
|
||||
throw new IllegalArgumentException("The ciphertext must not be null");
|
||||
}
|
||||
|
||||
return new VaultDecryptionPayload(ciphertext, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the decryption context to the value object.
|
||||
*
|
||||
* @param context
|
||||
* transit decryption context
|
||||
* @return decryption value object
|
||||
*/
|
||||
public VaultDecryptionPayload with(VaultTransitContext context) {
|
||||
return new VaultDecryptionPayload(this.getCiphertext(), context);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.springframework.vault.support;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.vault.VaultException;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* Holds the response from decryption operation and provides helper methods to
|
||||
* deal with the data.
|
||||
*
|
||||
* @author Praveendra Singh
|
||||
*
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
public class VaultDecryptionResult {
|
||||
|
||||
private byte[] cipherText;
|
||||
private String error;
|
||||
|
||||
/**
|
||||
* returns the list of plaintext or throws VaultException if error
|
||||
* encountered.
|
||||
*
|
||||
* @return plaintext
|
||||
*/
|
||||
public byte[] get() {
|
||||
|
||||
if (!StringUtils.isEmpty(error)) {
|
||||
throw new VaultException(error);
|
||||
}
|
||||
return cipherText;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package org.springframework.vault.support;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.util.Base64Utils;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* Holds the response from encryption/decryption operation and provides helper
|
||||
* methods to generate list of encryption/decryption objects by fetching the
|
||||
* respective fields from VaultResponse.
|
||||
*
|
||||
* @author Praveendra Singh
|
||||
*
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class VaultEncryptionDecryptionResultHelper {
|
||||
|
||||
public static List<VaultEncryptionResult> fetchEncryptionResult(VaultResponse vaultResponse) {
|
||||
|
||||
List<VaultEncryptionResult> result = new ArrayList<VaultEncryptionResult>();
|
||||
|
||||
for (Map<String, String> data : getBatchData(vaultResponse)) {
|
||||
|
||||
VaultEncryptionResult res = new VaultEncryptionResult(data.get("ciphertext"), data.get("error"));
|
||||
result.add(res);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static List<VaultDecryptionResult> fetchDecryptionResult(VaultResponse vaultResponse) {
|
||||
|
||||
List<VaultDecryptionResult> result = new ArrayList<VaultDecryptionResult>();
|
||||
|
||||
for (Map<String, String> data : getBatchData(vaultResponse)) {
|
||||
|
||||
VaultDecryptionResult res = new VaultDecryptionResult(Base64Utils.decodeFromString(data.get("plaintext")),
|
||||
data.get("error"));
|
||||
result.add(res);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected static List<Map<String, String>> getBatchData(VaultResponse vaultResponse) {
|
||||
return (List<Map<String, String>>) vaultResponse.getData().get("batch_results");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package org.springframework.vault.support;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* Encryption Value Object used for encrypt() operations.
|
||||
*
|
||||
* @author Praveendra Singh
|
||||
*
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
public class VaultEncryptionPayload {
|
||||
private byte[] plaintext;
|
||||
private VaultTransitContext context;
|
||||
|
||||
/**
|
||||
* factory method helps to create encryption value object using plaintext in
|
||||
* bytes
|
||||
*
|
||||
* @param plaintext
|
||||
* data to be encrypted
|
||||
*
|
||||
* @return encryption value object
|
||||
*/
|
||||
public static VaultEncryptionPayload of(byte[] plaintext) {
|
||||
|
||||
if ((plaintext == null) || (plaintext.length == 0)) {
|
||||
throw new IllegalArgumentException("The plaintext must not be null or empty");
|
||||
}
|
||||
|
||||
return new VaultEncryptionPayload(plaintext, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* factory method helps to create encryption value object using plaintext in
|
||||
* String
|
||||
*
|
||||
* @param plaintext
|
||||
* data to be encrypted
|
||||
*
|
||||
* @return encryption value object
|
||||
*/
|
||||
public static VaultEncryptionPayload of(String plaintext) {
|
||||
|
||||
if (plaintext == null) {
|
||||
throw new IllegalArgumentException("The plaintext must not be null");
|
||||
}
|
||||
|
||||
return of(plaintext.getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the encryption context to the value object.
|
||||
*
|
||||
* @param context
|
||||
* transit encryption context
|
||||
* @return encryption value object
|
||||
*/
|
||||
public VaultEncryptionPayload with(VaultTransitContext context) {
|
||||
return new VaultEncryptionPayload(this.getPlaintext(), context);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.springframework.vault.support;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.vault.VaultException;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* Holds the response from encryption operation and provides helper methods to
|
||||
* deal with the data.
|
||||
*
|
||||
* @author Praveendra Singh
|
||||
*
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
public class VaultEncryptionResult {
|
||||
|
||||
private String cipherText;
|
||||
private String error;
|
||||
|
||||
/**
|
||||
* returns the list of ciphertexts or throws VaultException if error
|
||||
* encountered.
|
||||
*
|
||||
* @return ciphertexts
|
||||
*/
|
||||
public String get() {
|
||||
|
||||
if (!StringUtils.isEmpty(error)) {
|
||||
throw new VaultException(error);
|
||||
}
|
||||
return cipherText;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,17 +15,26 @@
|
||||
*/
|
||||
package org.springframework.vault.core;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.vault.VaultException;
|
||||
import org.springframework.vault.support.VaultDecryptionPayload;
|
||||
import org.springframework.vault.support.VaultDecryptionResult;
|
||||
import org.springframework.vault.support.VaultEncryptionPayload;
|
||||
import org.springframework.vault.support.VaultEncryptionResult;
|
||||
import org.springframework.vault.support.VaultMount;
|
||||
import org.springframework.vault.support.VaultTransitContext;
|
||||
import org.springframework.vault.support.VaultTransitKey;
|
||||
@@ -34,20 +43,19 @@ import org.springframework.vault.support.VaultTransitKeyCreationRequest;
|
||||
import org.springframework.vault.util.IntegrationTestSupport;
|
||||
import org.springframework.vault.util.Version;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.fail;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link VaultTransitTemplate} through
|
||||
* {@link VaultTransitOperations}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author Praveendra Singh
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration(classes = VaultIntegrationTestConfiguration.class)
|
||||
public class VaultTransitTemplateIntegrationTests extends IntegrationTestSupport {
|
||||
|
||||
private static final String BATCH_INTRODUCED_IN_VERSION = "0.6.5";
|
||||
|
||||
@Autowired
|
||||
private VaultOperations vaultOperations;
|
||||
private VaultTransitOperations transitOperations;
|
||||
@@ -98,7 +106,7 @@ public class VaultTransitTemplateIntegrationTests extends IntegrationTestSupport
|
||||
deleteKey("derived");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void createKeyShouldCreateKey() {
|
||||
|
||||
@@ -277,4 +285,170 @@ public class VaultTransitTemplateIntegrationTests extends IntegrationTestSupport
|
||||
String rewrapped = transitOperations.rewrap("mykey", ciphertext, transitRequest);
|
||||
assertThat(rewrapped).startsWith("vault:v2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void batchEncryptionAndDecryptionTestWithoutContext() {
|
||||
|
||||
if (prepare().getVersion().isLessThan(Version.parse(BATCH_INTRODUCED_IN_VERSION))) {
|
||||
return;
|
||||
}
|
||||
|
||||
transitOperations.createKey("mykey");
|
||||
|
||||
List<String> plaintexts = new ArrayList<String>();
|
||||
plaintexts.add("one");
|
||||
plaintexts.add("two");
|
||||
|
||||
batchEncryptionAndDecryption(plaintexts, null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void batchEncryptionAndDecryptionTestWithMatchingContext() {
|
||||
|
||||
if (prepare().getVersion().isLessThan(Version.parse(BATCH_INTRODUCED_IN_VERSION))) {
|
||||
return;
|
||||
}
|
||||
|
||||
VaultTransitKeyCreationRequest request = VaultTransitKeyCreationRequest.builder() //
|
||||
.derived(true) //
|
||||
.build();
|
||||
|
||||
transitOperations.createKey("mykey", request);
|
||||
|
||||
List<String> plaintexts = new ArrayList<String>();
|
||||
plaintexts.add("one");
|
||||
plaintexts.add("two");
|
||||
|
||||
List<VaultTransitContext> contexts = new ArrayList<VaultTransitContext>();
|
||||
contexts.add(VaultTransitContext.builder().context("oneContext".getBytes()).build());
|
||||
contexts.add(VaultTransitContext.builder().context("twoContext".getBytes()).build());
|
||||
|
||||
batchEncryptionAndDecryption(plaintexts, contexts, contexts);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void batchEncryptionAndDecryptionTestWithNonEqualContext() {
|
||||
|
||||
if (prepare().getVersion().isLessThan(Version.parse(BATCH_INTRODUCED_IN_VERSION))) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
VaultTransitKeyCreationRequest request = VaultTransitKeyCreationRequest.builder() //
|
||||
.derived(true) //
|
||||
.build();
|
||||
|
||||
transitOperations.createKey("mykey", request);
|
||||
|
||||
List<String> plaintexts = new ArrayList<String>();
|
||||
plaintexts.add("one");
|
||||
plaintexts.add("two");
|
||||
|
||||
List<VaultTransitContext> encryptionContexts = new ArrayList<VaultTransitContext>();
|
||||
encryptionContexts.add(VaultTransitContext.builder().context("oneContext".getBytes()).build());
|
||||
encryptionContexts.add(VaultTransitContext.builder().context("twoContext".getBytes()).build());
|
||||
|
||||
List<VaultTransitContext> decryptionContext = new ArrayList<VaultTransitContext>();
|
||||
decryptionContext.add(VaultTransitContext.builder().context("oneContext".getBytes()).build());
|
||||
|
||||
batchEncryptionAndDecryption(plaintexts, encryptionContexts, decryptionContext);
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
return;
|
||||
} catch (VaultException e) {
|
||||
return;
|
||||
}
|
||||
|
||||
Assert.fail();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void batchEncryptionAndDecryptionTestWithNonMatchingContext() {
|
||||
|
||||
if (prepare().getVersion().isLessThan(Version.parse(BATCH_INTRODUCED_IN_VERSION))) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
VaultTransitKeyCreationRequest request = VaultTransitKeyCreationRequest.builder() //
|
||||
.derived(true) //
|
||||
.build();
|
||||
|
||||
transitOperations.createKey("mykey", request);
|
||||
|
||||
List<String> plaintexts = new ArrayList<String>();
|
||||
plaintexts.add("one");
|
||||
plaintexts.add("two");
|
||||
|
||||
List<VaultTransitContext> encryptionContexts = new ArrayList<VaultTransitContext>();
|
||||
encryptionContexts.add(VaultTransitContext.builder().context("oneContext".getBytes()).build());
|
||||
encryptionContexts.add(VaultTransitContext.builder().context("twoContext".getBytes()).build());
|
||||
|
||||
List<VaultTransitContext> decryptionContext = new ArrayList<VaultTransitContext>();
|
||||
decryptionContext.add(VaultTransitContext.builder().context("oneContext".getBytes()).build());
|
||||
decryptionContext.add(VaultTransitContext.builder().context("wrongTwoContext".getBytes()).build());
|
||||
|
||||
batchEncryptionAndDecryption(plaintexts, encryptionContexts, decryptionContext);
|
||||
|
||||
} catch (VaultException e) {
|
||||
return;
|
||||
}
|
||||
|
||||
Assert.fail();
|
||||
}
|
||||
|
||||
private void batchEncryptionAndDecryption(List<String> plaintexts, List<VaultTransitContext> encryptionContexts,
|
||||
List<VaultTransitContext> decryptionContext) {
|
||||
|
||||
List<VaultEncryptionPayload> encryptionBatchRequest = new ArrayList<VaultEncryptionPayload>();
|
||||
|
||||
int index = 0;
|
||||
|
||||
for (String plaintext : plaintexts) {
|
||||
|
||||
VaultEncryptionPayload req = VaultEncryptionPayload.of(plaintext);
|
||||
|
||||
if (encryptionContexts != null) {
|
||||
if (encryptionContexts.size() >= (index + 1)) {
|
||||
req = req.with(encryptionContexts.get(index));
|
||||
}
|
||||
}
|
||||
|
||||
encryptionBatchRequest.add(req);
|
||||
index++;
|
||||
}
|
||||
|
||||
List<VaultEncryptionResult> cipherResult = transitOperations.encrypt("mykey", encryptionBatchRequest);
|
||||
|
||||
List<VaultDecryptionPayload> decryptionBatchRequest = new ArrayList<VaultDecryptionPayload>();
|
||||
|
||||
index = 0;
|
||||
|
||||
for (VaultEncryptionResult cipher : cipherResult) {
|
||||
|
||||
VaultDecryptionPayload req = VaultDecryptionPayload.of(cipher.get());
|
||||
|
||||
if (decryptionContext != null) {
|
||||
if (decryptionContext.size() >= (index + 1)) {
|
||||
req = req.with(decryptionContext.get(index));
|
||||
}
|
||||
}
|
||||
|
||||
decryptionBatchRequest.add(req);
|
||||
index++;
|
||||
}
|
||||
|
||||
List<VaultDecryptionResult> plaintextResult = transitOperations.decrypt("mykey", decryptionBatchRequest);
|
||||
|
||||
Assert.assertEquals(plaintexts.size(), plaintextResult.size());
|
||||
|
||||
int i = 0;
|
||||
|
||||
for (String plaintext : plaintexts) {
|
||||
String decrypted = new String(plaintextResult.get(i++).get());
|
||||
Assert.assertEquals(plaintext, decrypted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,3 +5,8 @@
|
||||
=== What's new in Spring Vault 1.0
|
||||
|
||||
* Initial Vault support.
|
||||
|
||||
[[new-features.1-1-0]]
|
||||
=== What's new in Spring Vault 1.1.0
|
||||
|
||||
* Batch encryption & decryption support.
|
||||
|
||||
Reference in New Issue
Block a user