Provide transit backend support #1

This commit is contained in:
Mark Paluch
2016-09-15 06:02:26 +02:00
parent 4d870ed4ff
commit fa9c21f6bb
12 changed files with 855 additions and 30 deletions

View File

@@ -13,8 +13,6 @@
<description>Spring Vault Core Components</description>
<packaging>jar</packaging>
<url>http://projects.spring.io/spring-vault/</url>
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>

View File

@@ -59,6 +59,19 @@ public interface VaultOperations {
*/
VaultTokenOperations opsForToken();
/**
* @return the operations interface to interact with the Vault transit backend.
*/
VaultTransitOperations opsForTransit();
/**
* Returns {@link VaultTransitOperations} if the transit backend is mounted on a different path than {@code transit}.
*
* @param path the mount path
* @return the operations interface to interact with the Vault transit backend.
*/
VaultTransitOperations opsForTransit(String path);
/**
* Read from a secret backend. Reading data using this method is suitable for secret backends that do not require a
* request body.
@@ -102,7 +115,8 @@ public interface VaultOperations {
void delete(String path);
/**
* Executes a Vault {@link ClientCallback}. Allows to interact with Vault using {@link VaultClient} without requiring a session.
* Executes a Vault {@link ClientCallback}. Allows to interact with Vault using {@link VaultClient} without requiring
* a session.
*
* @param clientCallback the request.
* @return the {@link ClientCallback} return value.

View File

@@ -119,14 +119,24 @@ public class VaultTemplate implements InitializingBean, VaultOperations {
Assert.notNull(sessionManager, "SessionManager must not be null");
}
@Override
public VaultSysOperations opsForSys() {
return new VaultSysTemplate(this);
}
@Override
public VaultTokenOperations opsForToken() {
return new VaultTokenTemplate(this);
}
@Override
public VaultSysOperations opsForSys() {
return new VaultSysTemplate(this);
public VaultTransitOperations opsForTransit() {
return opsForTransit("transit");
}
@Override
public VaultTransitOperations opsForTransit(String path) {
return new VaultTransitTemplate(this, path);
}
@Override

View File

@@ -0,0 +1,140 @@
/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.vault.core;
import org.springframework.vault.support.VaultTransitKeyConfiguration;
import org.springframework.vault.support.VaultTransitKey;
import org.springframework.vault.support.VaultTransitKeyCreationRequest;
import org.springframework.vault.support.VaultTransitRequest;
/**
* Interface that specifies operations using the {@code transit} backend.
*
* @author Mark Paluch
* @see <a href="https://www.vaultproject.io/docs/secrets/transit/index.html">Transit Secret Backend</a>
*/
public interface VaultTransitOperations {
/**
* Creates a new named encryption key given a {@code name}.
*
* @param keyName must not be empty or {@literal null}.
*/
void createKey(String keyName);
/**
* Creates a new named encryption key given a {@code name} and {@link VaultTransitKeyCreationRequest}. The key options
* set here cannot be changed after key creation.
*
* @param keyName must not be empty or {@literal null}.
* @param createKeyRequest must not be {@literal null}.
*/
void createKey(String keyName, VaultTransitKeyCreationRequest createKeyRequest);
/**
* Creates a new named encryption key given a {@code name}.
*
* @param keyName must not be empty or {@literal null}.
* @param keyConfiguration must not be {@literal null}.
*/
void configureKey(String keyName, VaultTransitKeyConfiguration keyConfiguration);
/**
* Returns information about a named encryption key.
*
* @param keyName must not be empty or {@literal null}.
* @return the {@link VaultTransitKey}.
*/
VaultTransitKey getKey(String keyName);
/**
* Deletes a named encryption key. It will no longer be possible to decrypt any data encrypted with the named key.
*
* @param keyName must not be empty or {@literal null}.
*/
void deleteKey(String keyName);
/**
* Rotates the version of the named key. After rotation, new plaintext requests will be encrypted with the new version
* of the key. To upgrade ciphertext to be encrypted with the latest version of the key, use
* {@link #rewrap(String, String)}.
*
* @param keyName
* @see #rewrap(String, String)
*/
void rotate(String keyName);
/**
* Encrypts the provided plaintext using the named key.
*
* @param keyName must not be empty or {@literal null}.
* @param plaintext must not be empty or {@literal null}.
* @return cipher text.
*/
String encrypt(String keyName, String plaintext);
/**
* Encrypts the provided plaintext using the named key.
*
* @param keyName must not be empty or {@literal null}.
* @param plaintext must not be empty or {@literal null}.
* @param transitRequest may be {@literal null} if no request options provided.
* @return cipher text.
*/
String encrypt(String keyName, byte[] plaintext, VaultTransitRequest transitRequest);
/**
* Decrypts the provided plaintext using the named key.
*
* @param keyName must not be empty or {@literal null}.
* @param ciphertext must not be empty or {@literal null}.
* @return plain text.
*/
String decrypt(String keyName, String ciphertext);
/**
* Decrypts the provided plaintext using the named key.
*
* @param keyName must not be empty or {@literal null}.
* @param ciphertext must not be empty or {@literal null}.
* @param transitRequest may be {@literal null} if no request options provided.
* @return plain text.
*/
byte[] decrypt(String keyName, String ciphertext, VaultTransitRequest transitRequest);
/**
* 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 untrusted users or scripts.
*
* @param keyName must not be empty or {@literal null}.
* @param ciphertext must not be empty or {@literal null}.
* @return cipher text.
* @see #rotate(String)
*/
String rewrap(String keyName, String ciphertext);
/**
* 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 untrusted users or scripts.
*
* @param keyName must not be empty or {@literal null}.
* @param ciphertext must not be empty or {@literal null}.
* @param transitRequest may be {@literal null} if no request options provided.
* @return cipher text.
* @see #rotate(String)
*/
String rewrap(String keyName, String ciphertext, VaultTransitRequest transitRequest);
}

View File

@@ -0,0 +1,215 @@
/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.vault.core;
import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.util.Assert;
import org.springframework.util.Base64Utils;
import org.springframework.vault.support.VaultTransitKeyConfiguration;
import org.springframework.vault.support.VaultResponseSupport;
import org.springframework.vault.support.VaultTransitKey;
import org.springframework.vault.support.VaultTransitKeyCreationRequest;
import org.springframework.vault.support.VaultTransitRequest;
/**
* Default implementation of {@link VaultTransitOperations}.
*
* @author Mark Paluch
*/
public class VaultTransitTemplate implements VaultTransitOperations {
private final VaultOperations vaultOperations;
private final String path;
public VaultTransitTemplate(VaultOperations vaultOperations, String path) {
Assert.notNull(vaultOperations, "VaultOperations must not be null");
Assert.hasText(path, "Path must not be empty");
this.vaultOperations = vaultOperations;
this.path = path;
}
@Override
public void createKey(final String keyName) {
Assert.hasText(keyName, "KeyName must not be empty");
vaultOperations.write(String.format("%s/keys/%s", path, keyName), null);
}
@Override
public void createKey(final String keyName, final VaultTransitKeyCreationRequest createKeyRequest) {
Assert.hasText(keyName, "KeyName must not be empty");
Assert.notNull(createKeyRequest, "VaultTransitKeyCreationRequest must not be empty");
vaultOperations.write(String.format("%s/keys/%s", path, keyName), createKeyRequest);
}
@Override
public void configureKey(final String keyName, final VaultTransitKeyConfiguration keyConfiguration) {
Assert.hasText(keyName, "KeyName must not be empty");
Assert.notNull(keyConfiguration, "VaultKeyConfiguration must not be empty");
vaultOperations.write(String.format("%s/keys/%s/config", path, keyName), keyConfiguration);
}
@Override
public VaultTransitKey getKey(final String keyName) {
Assert.hasText(keyName, "KeyName must not be empty");
VaultResponseSupport<VaultTransitKey> result = vaultOperations.read(String.format("%s/keys/%s", path, keyName),
VaultTransitKey.class);
if (result != null) {
return result.getData();
}
return null;
}
@Override
public void deleteKey(String keyName) {
Assert.hasText(keyName, "KeyName must not be empty");
vaultOperations.delete(String.format("%s/keys/%s", path, keyName));
}
@Override
public void rotate(String keyName) {
Assert.hasText(keyName, "KeyName must not be empty");
vaultOperations.write(String.format("%s/keys/%s/rotate", path, keyName), null);
}
@Override
public String encrypt(String keyName, String plaintext) {
Assert.hasText(keyName, "KeyName must not be empty");
Assert.notNull(plaintext, "Plain text must not be null");
Map<String, String> request = new LinkedHashMap<String, String>();
request.put("plaintext", Base64Utils.encodeToString(plaintext.getBytes()));
return (String) vaultOperations.write(String.format("%s/encrypt/%s", path, keyName), request).getData()
.get("ciphertext");
}
@Override
public String encrypt(String keyName, byte[] plaintext, VaultTransitRequest transitRequest) {
Assert.hasText(keyName, "KeyName must not be empty");
Assert.notNull(plaintext, "Plain text must not be null");
Map<String, String> request = new LinkedHashMap<String, String>();
request.put("plaintext", Base64Utils.encodeToString(plaintext));
if (transitRequest != null) {
applyTransitOptions(transitRequest, request);
}
return (String) vaultOperations.write(String.format("%s/encrypt/%s", path, keyName), request).getData()
.get("ciphertext");
}
@Override
public String decrypt(String keyName, String ciphertext) {
Assert.hasText(keyName, "KeyName must not be empty");
Assert.hasText(keyName, "Cipher text must not be empty");
Map<String, String> request = new LinkedHashMap<String, String>();
request.put("ciphertext", ciphertext);
String plaintext = (String) vaultOperations.write(String.format("%s/decrypt/%s", path, keyName), request).getData()
.get("plaintext");
return new String(Base64Utils.decodeFromString(plaintext));
}
@Override
public byte[] decrypt(String keyName, String ciphertext, VaultTransitRequest transitRequest) {
Assert.hasText(keyName, "KeyName must not be empty");
Assert.hasText(keyName, "Cipher text must not be empty");
Map<String, String> request = new LinkedHashMap<String, String>();
request.put("ciphertext", ciphertext);
if (transitRequest != null) {
applyTransitOptions(transitRequest, request);
}
String plaintext = (String) vaultOperations.write(String.format("%s/decrypt/%s", path, keyName), request).getData()
.get("plaintext");
return Base64Utils.decodeFromString(plaintext);
}
@Override
public String rewrap(String keyName, String ciphertext) {
Assert.hasText(keyName, "KeyName must not be empty");
Assert.hasText(ciphertext, "Cipher text must not be empty");
Map<String, String> request = new LinkedHashMap<String, String>();
request.put("ciphertext", ciphertext);
return (String) vaultOperations.write(String.format("%s/rewrap/%s", path, keyName), request).getData()
.get("ciphertext");
}
@Override
public String rewrap(String keyName, String ciphertext, VaultTransitRequest transitRequest) {
Assert.hasText(keyName, "KeyName must not be empty");
Assert.hasText(ciphertext, "Cipher text must not be empty");
Map<String, String> request = new LinkedHashMap<String, String>();
request.put("ciphertext", ciphertext);
if (transitRequest != null) {
applyTransitOptions(transitRequest, request);
}
return (String) vaultOperations.write(String.format("%s/rewrap/%s", path, keyName), request).getData()
.get("ciphertext");
}
private void applyTransitOptions(VaultTransitRequest transitRequest, Map<String, String> request) {
if (transitRequest.getContext() != null) {
request.put("context", Base64Utils.encodeToString(transitRequest.getContext()));
}
if (transitRequest.getNonce() != null) {
request.put("nonce", Base64Utils.encodeToString(transitRequest.getNonce()));
}
}
}

View File

@@ -17,6 +17,8 @@ package org.springframework.vault.support;
import java.util.Map;
import org.springframework.util.Assert;
/**
* Value object to bind Vault HTTP Mount API requests/responses.
*
@@ -30,9 +32,20 @@ public class VaultMount {
private Map<String, Object> config;
/**
* Creates a new {@link VaultMount}.
*/
public VaultMount() {}
/**
* Creates a new {@link VaultMount} given a {@code type}.
*
* @param type must not be empty or {@literal null}.
*/
public VaultMount(String type) {
Assert.hasText(type, "Type must not be empty");
this.type = type;
}

View File

@@ -0,0 +1,98 @@
/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.vault.support;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* Value object to bind Vault HTTP Transit Key API responses.
*
* @author Mark Paluch
*/
public class VaultTransitKey {
@JsonProperty("cipher_mode") private String cipherMode;
@JsonProperty("deletion_allowed") private boolean deletionAllowed;
private boolean derived;
private Map<String, Long> keys;
@JsonProperty("latest_version") private boolean latestVersion;
@JsonProperty("min_decryption_version") private int minDecryptionVersion;
private String name;
public String getCipherMode() {
return cipherMode;
}
public void setCipherMode(String cipherMode) {
this.cipherMode = cipherMode;
}
public boolean isDeletionAllowed() {
return deletionAllowed;
}
public void setDeletionAllowed(boolean deletionAllowed) {
this.deletionAllowed = deletionAllowed;
}
public boolean isDerived() {
return derived;
}
public void setDerived(boolean derived) {
this.derived = derived;
}
public Map<String, Long> getKeys() {
return keys;
}
public void setKeys(Map<String, Long> keys) {
this.keys = keys;
}
public boolean isLatestVersion() {
return latestVersion;
}
public void setLatestVersion(boolean latestVersion) {
this.latestVersion = latestVersion;
}
public int getMinDecryptionVersion() {
return minDecryptionVersion;
}
public void setMinDecryptionVersion(int minDecryptionVersion) {
this.minDecryptionVersion = minDecryptionVersion;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.vault.support;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* Value object to bind Vault HTTP Transit Key Config API requests.
*
* @author Mark Paluch
*/
public class VaultTransitKeyConfiguration {
@JsonProperty("deletion_allowed") private Boolean deletionAllowed;
@JsonProperty("latest_version") private Integer latestVersion;
public VaultTransitKeyConfiguration() {
}
public VaultTransitKeyConfiguration(Boolean deletionAllowed, Integer latestVersion) {
this.deletionAllowed = deletionAllowed;
this.latestVersion = latestVersion;
}
public Boolean getDeletionAllowed() {
return deletionAllowed;
}
public void setDeletionAllowed(Boolean deletionAllowed) {
this.deletionAllowed = deletionAllowed;
}
public Integer getLatestVersion() {
return latestVersion;
}
public void setLatestVersion(Integer latestVersion) {
this.latestVersion = latestVersion;
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.vault.support;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* Transit backend key creation request options.
*
* @author Mark Paluch
*/
public class VaultTransitKeyCreationRequest {
private Boolean derived;
@JsonProperty("convergent_encryption") private Boolean convergentEncryption;
/**
* Creates a new {@link VaultTransitKeyCreationRequest}.
*/
public VaultTransitKeyCreationRequest() {}
/**
* Creates a new {@link VaultTransitKeyCreationRequest} and sets {@code derived} and {@code convergentEncryption}
* properties.
*
* @param derived
* @param convergentEncryption
*/
public VaultTransitKeyCreationRequest(boolean derived, boolean convergentEncryption) {
this.derived = derived;
this.convergentEncryption = convergentEncryption;
}
public Boolean getDerived() {
return derived;
}
public void setDerived(Boolean derived) {
this.derived = derived;
}
public Boolean getConvergentEncryption() {
return convergentEncryption;
}
public void setConvergentEncryption(Boolean convergentEncryption) {
this.convergentEncryption = convergentEncryption;
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.vault.support;
/**
* Transit backend encryption/decryption/rewrapping request options.
*
* @author Mark Paluch
*/
public class VaultTransitRequest {
private byte[] context;
private byte[] nonce;
public byte[] getContext() {
return context;
}
public void setContext(byte[] context) {
this.context = context;
}
public byte[] getNonce() {
return nonce;
}
public void setNonce(byte[] nonce) {
this.nonce = nonce;
}
}

View File

@@ -15,10 +15,8 @@
*/
package org.springframework.vault.core;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.vault.authentication.ClientAuthentication;
import org.springframework.vault.authentication.DefaultSessionManager;
import org.springframework.vault.authentication.TokenAuthentication;
import org.springframework.vault.client.VaultEndpoint;
import org.springframework.vault.config.AbstractVaultConfiguration;
@@ -48,26 +46,3 @@ class VaultIntegrationTestConfiguration extends AbstractVaultConfiguration {
return Settings.createSslConfiguration();
}
}
class test {
@Bean
public VaultTemplate vaultTemplate() {
VaultTemplate vaultTemplate = new VaultTemplate();
vaultTemplate.setSessionManager(sessionManager());
vaultTemplate.setVaultClientFactory(clientFactory());
return vaultTemplate;
}
@Bean
public DefaultVaultClientFactory clientFactory() {
return new DefaultVaultClientFactory();
}
@Bean
public DefaultSessionManager sessionManager() {
return new DefaultSessionManager(new TokenAuthentication(""));
}
}

View File

@@ -0,0 +1,201 @@
/*
* Copyright 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.vault.core;
import static org.assertj.core.api.Assertions.*;
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.client.VaultException;
import org.springframework.vault.support.VaultTransitKeyConfiguration;
import org.springframework.vault.support.VaultMount;
import org.springframework.vault.support.VaultTransitKey;
import org.springframework.vault.support.VaultTransitKeyCreationRequest;
import org.springframework.vault.support.VaultTransitRequest;
import org.springframework.vault.util.IntegrationTestSupport;
/**
* Integration tests for {@link VaultTransitTemplate} through {@link VaultTransitOperations}.
*
* @author Mark Paluch
*/
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = VaultIntegrationTestConfiguration.class)
public class VaultTransitTemplateIntegrationTests extends IntegrationTestSupport {
@Autowired private VaultOperations vaultOperations;
private VaultTransitOperations transitOperations;
@Before
public void before() throws Exception {
transitOperations = vaultOperations.opsForTransit();
if (!vaultOperations.opsForSys().getMounts().containsKey("transit/")) {
vaultOperations.opsForSys().mount("transit", new VaultMount("transit"));
}
try {
transitOperations.configureKey("mykey", new VaultTransitKeyConfiguration(true, null));
} catch (Exception e) {}
try {
transitOperations.deleteKey("mykey");
} catch (Exception e) {}
}
@Test
public void createKeyShouldCreateKey() throws Exception {
transitOperations.createKey("mykey");
VaultTransitKey mykey = transitOperations.getKey("mykey");
assertThat(mykey.getCipherMode()).isEqualTo("aes-gcm");
assertThat(mykey.getName()).isEqualTo("mykey");
assertThat(mykey.isDeletionAllowed()).isFalse();
assertThat(mykey.isDerived()).isFalse();
assertThat(mykey.getMinDecryptionVersion()).isEqualTo(1);
assertThat(mykey.isLatestVersion()).isTrue();
}
@Test
public void createKeyShouldCreateKeyWithOptions() throws Exception {
VaultTransitKeyCreationRequest request = new VaultTransitKeyCreationRequest();
request.setConvergentEncryption(true);
request.setDerived(true);
transitOperations.createKey("mykey", request);
VaultTransitKey mykey = transitOperations.getKey("mykey");
assertThat(mykey.getCipherMode()).isEqualTo("aes-gcm");
assertThat(mykey.getName()).isEqualTo("mykey");
assertThat(mykey.isDeletionAllowed()).isFalse();
assertThat(mykey.isDerived()).isTrue();
assertThat(mykey.getMinDecryptionVersion()).isEqualTo(1);
assertThat(mykey.isLatestVersion()).isTrue();
}
@Test
public void getKeyShouldReturnNullIfKeyNotExists() throws Exception {
VaultTransitKey key = transitOperations.getKey("hello-world");
assertThat(key).isNull();
}
@Test
public void deleteKeyShouldFailIfKeyNotExists() throws Exception {
try {
transitOperations.deleteKey("hello-world");
fail("Missing VaultException");
} catch (VaultException e) {
assertThat(e).hasMessageContaining("could not delete");
}
}
@Test
public void deleteKeyShouldDeleteKey() throws Exception {
transitOperations.createKey("mykey");
transitOperations.configureKey("mykey", new VaultTransitKeyConfiguration(true, null));
transitOperations.deleteKey("mykey");
assertThat(transitOperations.getKey("mykey")).isNull();
}
@Test
public void encryptShouldCreateCiphertext() throws Exception {
transitOperations.createKey("mykey");
String ciphertext = transitOperations.encrypt("mykey", "hello-world");
assertThat(ciphertext).startsWith("vault:v");
}
@Test
public void encryptShouldCreateCiphertextWithNonceAndContext() throws Exception {
transitOperations.createKey("mykey", new VaultTransitKeyCreationRequest(true, true));
VaultTransitRequest transitRequest = new VaultTransitRequest();
transitRequest.setContext("blubb".getBytes());
transitRequest.setNonce("123456789012".getBytes());
String ciphertext = transitOperations.encrypt("mykey", "hello-world".getBytes(), transitRequest);
assertThat(ciphertext).startsWith("vault:v1:");
}
@Test
public void decryptShouldCreatePlaintext() throws Exception {
transitOperations.createKey("mykey");
String ciphertext = transitOperations.encrypt("mykey", "hello-world");
String plaintext = transitOperations.decrypt("mykey", ciphertext);
assertThat(plaintext).isEqualTo("hello-world");
}
@Test
public void decryptShouldCreatePlaintextWithNonceAndContext() throws Exception {
transitOperations.createKey("mykey", new VaultTransitKeyCreationRequest(true, true));
VaultTransitRequest transitRequest = new VaultTransitRequest();
transitRequest.setContext("blubb".getBytes());
transitRequest.setNonce("123456789012".getBytes());
String ciphertext = transitOperations.encrypt("mykey", "hello-world".getBytes(), transitRequest);
byte[] plaintext = transitOperations.decrypt("mykey", ciphertext, transitRequest);
assertThat(new String(plaintext)).isEqualTo("hello-world");
}
@Test
public void encryptAndRewrapShouldCreateCiphertext() throws Exception {
transitOperations.createKey("mykey");
String ciphertext = transitOperations.encrypt("mykey", "hello-world");
transitOperations.rotate("mykey");
String rewrapped = transitOperations.rewrap("mykey", ciphertext);
assertThat(rewrapped).startsWith("vault:v2:");
}
@Test
public void encryptAndRewrapShouldCreateCiphertextWithNonceAndContext() throws Exception {
transitOperations.createKey("mykey", new VaultTransitKeyCreationRequest(true, true));
VaultTransitRequest transitRequest = new VaultTransitRequest();
transitRequest.setContext("blubb".getBytes());
transitRequest.setNonce("123456789012".getBytes());
String ciphertext = transitOperations.encrypt("mykey", "hello-world".getBytes(), transitRequest);
transitOperations.rotate("mykey");
String rewrapped = transitOperations.rewrap("mykey", ciphertext, transitRequest);
assertThat(rewrapped).startsWith("vault:v2");
}
}