diff --git a/spring-vault-core/pom.xml b/spring-vault-core/pom.xml
index dfa38614..8c7ee83f 100644
--- a/spring-vault-core/pom.xml
+++ b/spring-vault-core/pom.xml
@@ -13,8 +13,6 @@
Spring Vault Core Components
jar
- http://projects.spring.io/spring-vault/
-
com.fasterxml.jackson.core
diff --git a/spring-vault-core/src/main/java/org/springframework/vault/core/VaultOperations.java b/spring-vault-core/src/main/java/org/springframework/vault/core/VaultOperations.java
index 6fd9af84..20cd1953 100644
--- a/spring-vault-core/src/main/java/org/springframework/vault/core/VaultOperations.java
+++ b/spring-vault-core/src/main/java/org/springframework/vault/core/VaultOperations.java
@@ -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.
diff --git a/spring-vault-core/src/main/java/org/springframework/vault/core/VaultTemplate.java b/spring-vault-core/src/main/java/org/springframework/vault/core/VaultTemplate.java
index 9158f2d3..49402cd1 100644
--- a/spring-vault-core/src/main/java/org/springframework/vault/core/VaultTemplate.java
+++ b/spring-vault-core/src/main/java/org/springframework/vault/core/VaultTemplate.java
@@ -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
diff --git a/spring-vault-core/src/main/java/org/springframework/vault/core/VaultTransitOperations.java b/spring-vault-core/src/main/java/org/springframework/vault/core/VaultTransitOperations.java
new file mode 100644
index 00000000..3169dfb0
--- /dev/null
+++ b/spring-vault-core/src/main/java/org/springframework/vault/core/VaultTransitOperations.java
@@ -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 Transit Secret Backend
+ */
+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);
+}
diff --git a/spring-vault-core/src/main/java/org/springframework/vault/core/VaultTransitTemplate.java b/spring-vault-core/src/main/java/org/springframework/vault/core/VaultTransitTemplate.java
new file mode 100644
index 00000000..dbcdc3ef
--- /dev/null
+++ b/spring-vault-core/src/main/java/org/springframework/vault/core/VaultTransitTemplate.java
@@ -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 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 request = new LinkedHashMap();
+
+ 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 request = new LinkedHashMap();
+
+ 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 request = new LinkedHashMap();
+
+ 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 request = new LinkedHashMap();
+
+ 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 request = new LinkedHashMap();
+ 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 request = new LinkedHashMap();
+
+ 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 request) {
+
+ if (transitRequest.getContext() != null) {
+ request.put("context", Base64Utils.encodeToString(transitRequest.getContext()));
+ }
+
+ if (transitRequest.getNonce() != null) {
+ request.put("nonce", Base64Utils.encodeToString(transitRequest.getNonce()));
+ }
+ }
+}
diff --git a/spring-vault-core/src/main/java/org/springframework/vault/support/VaultMount.java b/spring-vault-core/src/main/java/org/springframework/vault/support/VaultMount.java
index 890436b1..0570a551 100644
--- a/spring-vault-core/src/main/java/org/springframework/vault/support/VaultMount.java
+++ b/spring-vault-core/src/main/java/org/springframework/vault/support/VaultMount.java
@@ -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 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;
}
diff --git a/spring-vault-core/src/main/java/org/springframework/vault/support/VaultTransitKey.java b/spring-vault-core/src/main/java/org/springframework/vault/support/VaultTransitKey.java
new file mode 100644
index 00000000..44231206
--- /dev/null
+++ b/spring-vault-core/src/main/java/org/springframework/vault/support/VaultTransitKey.java
@@ -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 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 getKeys() {
+ return keys;
+ }
+
+ public void setKeys(Map 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;
+ }
+}
diff --git a/spring-vault-core/src/main/java/org/springframework/vault/support/VaultTransitKeyConfiguration.java b/spring-vault-core/src/main/java/org/springframework/vault/support/VaultTransitKeyConfiguration.java
new file mode 100644
index 00000000..fb01cd72
--- /dev/null
+++ b/spring-vault-core/src/main/java/org/springframework/vault/support/VaultTransitKeyConfiguration.java
@@ -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;
+ }
+}
diff --git a/spring-vault-core/src/main/java/org/springframework/vault/support/VaultTransitKeyCreationRequest.java b/spring-vault-core/src/main/java/org/springframework/vault/support/VaultTransitKeyCreationRequest.java
new file mode 100644
index 00000000..2e8953a4
--- /dev/null
+++ b/spring-vault-core/src/main/java/org/springframework/vault/support/VaultTransitKeyCreationRequest.java
@@ -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;
+ }
+}
diff --git a/spring-vault-core/src/main/java/org/springframework/vault/support/VaultTransitRequest.java b/spring-vault-core/src/main/java/org/springframework/vault/support/VaultTransitRequest.java
new file mode 100644
index 00000000..8427ecf4
--- /dev/null
+++ b/spring-vault-core/src/main/java/org/springframework/vault/support/VaultTransitRequest.java
@@ -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;
+ }
+}
diff --git a/spring-vault-core/src/test/java/org/springframework/vault/core/VaultIntegrationTestConfiguration.java b/spring-vault-core/src/test/java/org/springframework/vault/core/VaultIntegrationTestConfiguration.java
index ebd28354..cedebf85 100644
--- a/spring-vault-core/src/test/java/org/springframework/vault/core/VaultIntegrationTestConfiguration.java
+++ b/spring-vault-core/src/test/java/org/springframework/vault/core/VaultIntegrationTestConfiguration.java
@@ -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("…"));
- }
-}
diff --git a/spring-vault-core/src/test/java/org/springframework/vault/core/VaultTransitTemplateIntegrationTests.java b/spring-vault-core/src/test/java/org/springframework/vault/core/VaultTransitTemplateIntegrationTests.java
new file mode 100644
index 00000000..31a99729
--- /dev/null
+++ b/spring-vault-core/src/test/java/org/springframework/vault/core/VaultTransitTemplateIntegrationTests.java
@@ -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");
+ }
+}