From 16edc30c69b00ec82bb85d7e6596410fca861a16 Mon Sep 17 00:00:00 2001 From: Manish Kumar Date: Mon, 24 Sep 2018 20:50:17 +0530 Subject: [PATCH 1/3] added method to read versioned secret --- .../com/bettercloud/vault/api/Logical.java | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/bettercloud/vault/api/Logical.java b/src/main/java/com/bettercloud/vault/api/Logical.java index 0fed2937..6f1b9275 100644 --- a/src/main/java/com/bettercloud/vault/api/Logical.java +++ b/src/main/java/com/bettercloud/vault/api/Logical.java @@ -51,6 +51,18 @@ public Logical(final VaultConfig config) { * @throws VaultException If any errors occurs with the REST request (e.g. non-200 status code, invalid JSON payload, etc), and the maximum number of retries is exceeded. */ public LogicalResponse read(final String path) throws VaultException { + return read(path, 0); + } + + /** + *

Basic read operation to retrieve a secret of specific version

+ * + * @param path The Vault key value from which to read + * @param secretVersion version number of key-value secret + * @return The response information returned from Vault + * @throws VaultException If any errors occurs with the REST request (e.g. non-200 status code, invalid JSON payload, etc), and the maximum number of retries is exceeded. + */ + public LogicalResponse read(final String path, final int secretVersion) throws VaultException { final String version = getSecretEngineVersion(getPathSegments(path).get(0)); final String adjustedPath = adjustPathForReadOrWrite(path); int retryCount = 0; @@ -58,13 +70,13 @@ public LogicalResponse read(final String path) throws VaultException { try { // Make an HTTP request to Vault final RestResponse restResponse = new Rest()//NOPMD - .url(config.getAddress() + "/v1/" + adjustedPath) - .header("X-Vault-Token", config.getToken()) - .connectTimeoutSeconds(config.getOpenTimeout()) - .readTimeoutSeconds(config.getReadTimeout()) - .sslPemUTF8(config.getSslPemUTF8()) - .sslVerification(config.isSslVerify() != null ? config.isSslVerify() : null) - .get(); + .url(config.getAddress() + "/v1/" + adjustedPath + "?version=" + String.valueOf(secretVersion)) + .header("X-Vault-Token", config.getToken()) + .connectTimeoutSeconds(config.getOpenTimeout()) + .readTimeoutSeconds(config.getReadTimeout()) + .sslPemUTF8(config.getSslPemUTF8()) + .sslVerification(config.isSslVerify() != null ? config.isSslVerify() : null) + .get(); // Validate response if (restResponse.getStatus() != 200) { From 716a14b68386ff21a48f55ed1224383ff22bdadd Mon Sep 17 00:00:00 2001 From: Manish Kumar Date: Mon, 24 Sep 2018 20:55:47 +0530 Subject: [PATCH 2/3] added integration test for v2 changes --- .../bettercloud/vault/api/LogicalV2Tests.java | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 src/test-integration/java/com/bettercloud/vault/api/LogicalV2Tests.java diff --git a/src/test-integration/java/com/bettercloud/vault/api/LogicalV2Tests.java b/src/test-integration/java/com/bettercloud/vault/api/LogicalV2Tests.java new file mode 100644 index 00000000..3e0c6022 --- /dev/null +++ b/src/test-integration/java/com/bettercloud/vault/api/LogicalV2Tests.java @@ -0,0 +1,44 @@ +package com.bettercloud.vault.api; + +import com.bettercloud.vault.Vault; +import com.bettercloud.vault.VaultConfig; +import com.bettercloud.vault.VaultException; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.HashMap; + +public class LogicalV2Tests { + private static final String address = "http://localhost:8200"; + private static final String token = "00000000-0000-0000-0000-000000000000"; + private static final boolean isVerifySsl = false; + private static Vault vault; + + @BeforeClass + public static void setUp() throws VaultException { + VaultConfig vaultConfig = new VaultConfig().address(address) + .token(token).sslVerify(isVerifySsl).build(); + vault = new Vault(vaultConfig); + } + + @Test + public void testReadAndWrite() throws VaultException { + final String path = "secret/place"; + final String key = "city"; + final String value_1 = "Bangalore"; + final String value_2 = "Denver"; + vault.logical().write(path, new HashMap() {{ + put(key, value_1); + }}); + Assert.assertEquals(value_1, vault.logical().read(path).getData().get(key)); + Assert.assertEquals(value_1, vault.logical().read(path, 1).getData().get(key)); + vault.logical().write(path, new HashMap() {{ + put(key, value_2); + }}); + Assert.assertEquals(value_2, vault.logical().read(path, 2).getData().get(key)); + Assert.assertEquals(value_1, vault.logical().read(path, 1).getData().get(key)); + + vault.logical().delete(path); + } +} From 01ab522feff6281b07a8dc1c343ec07cb0676b71 Mon Sep 17 00:00:00 2001 From: Manish Kumar Date: Tue, 25 Sep 2018 15:32:00 +0530 Subject: [PATCH 3/3] incorporated the review comments --- .../java/com/bettercloud/vault/api/Logical.java | 16 +++++++++++++--- .../bettercloud/vault/api/LogicalV2Tests.java | 8 ++++++-- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/bettercloud/vault/api/Logical.java b/src/main/java/com/bettercloud/vault/api/Logical.java index 6f1b9275..75a29063 100644 --- a/src/main/java/com/bettercloud/vault/api/Logical.java +++ b/src/main/java/com/bettercloud/vault/api/Logical.java @@ -28,6 +28,7 @@ public class Logical { private final VaultConfig config; + private static final int defaultSecretVersion = 0; //set as logical flag to read latest secrets of kv v1 and v2 without a given version number public Logical(final VaultConfig config) { this.config = config; @@ -51,26 +52,30 @@ public Logical(final VaultConfig config) { * @throws VaultException If any errors occurs with the REST request (e.g. non-200 status code, invalid JSON payload, etc), and the maximum number of retries is exceeded. */ public LogicalResponse read(final String path) throws VaultException { - return read(path, 0); + return read(path, defaultSecretVersion); } /** *

Basic read operation to retrieve a secret of specific version

* * @param path The Vault key value from which to read - * @param secretVersion version number of key-value secret + * @param secretVersion version number of key-value secret, set to 0 for kv version-1, set greater than 0 for kv version-2 * @return The response information returned from Vault * @throws VaultException If any errors occurs with the REST request (e.g. non-200 status code, invalid JSON payload, etc), and the maximum number of retries is exceeded. */ public LogicalResponse read(final String path, final int secretVersion) throws VaultException { final String version = getSecretEngineVersion(getPathSegments(path).get(0)); + if (secretVersion > 0 && "1".equals(version)) { + throw new VaultException("Detected vault v1 which doesn't support kv v2 secret versioning, please enable KV Secrets Engine - Version 2 \n"); + } final String adjustedPath = adjustPathForReadOrWrite(path); + final String url = getVersionedUrl(secretVersion, adjustedPath); int retryCount = 0; while (true) { try { // Make an HTTP request to Vault final RestResponse restResponse = new Rest()//NOPMD - .url(config.getAddress() + "/v1/" + adjustedPath + "?version=" + String.valueOf(secretVersion)) + .url(url) .header("X-Vault-Token", config.getToken()) .connectTimeoutSeconds(config.getOpenTimeout()) .readTimeoutSeconds(config.getReadTimeout()) @@ -105,6 +110,11 @@ public LogicalResponse read(final String path, final int secretVersion) throws V } } + private String getVersionedUrl(int secretVersion, String adjustedPath) { + return secretVersion > 0 ? String.format("%s/v1/%s?version=%d", config.getAddress(), adjustedPath, secretVersion) : + String.format("%s/v1/%s", config.getAddress(), adjustedPath); + } + /** *

Basic operation to store secrets. Multiple name value pairs can be stored under the same secret key. * E.g.:

diff --git a/src/test-integration/java/com/bettercloud/vault/api/LogicalV2Tests.java b/src/test-integration/java/com/bettercloud/vault/api/LogicalV2Tests.java index 3e0c6022..6b47685f 100644 --- a/src/test-integration/java/com/bettercloud/vault/api/LogicalV2Tests.java +++ b/src/test-integration/java/com/bettercloud/vault/api/LogicalV2Tests.java @@ -9,6 +9,10 @@ import java.util.HashMap; +/** + * Integration test to run on KV Secrets Engine - Version 2 + * This test expects the vault is running with url http://localhost:8200 and enabled a token as "00000000-0000-0000-0000-000000000000" with read and write privilege. + */ public class LogicalV2Tests { private static final String address = "http://localhost:8200"; private static final String token = "00000000-0000-0000-0000-000000000000"; @@ -38,7 +42,7 @@ public void testReadAndWrite() throws VaultException { }}); Assert.assertEquals(value_2, vault.logical().read(path, 2).getData().get(key)); Assert.assertEquals(value_1, vault.logical().read(path, 1).getData().get(key)); - + Assert.assertEquals(value_2, vault.logical().read(path).getData().get(key)); vault.logical().delete(path); } -} +} \ No newline at end of file