Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 29 additions & 7 deletions src/main/java/com/bettercloud/vault/api/Logical.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -51,20 +52,36 @@ 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, defaultSecretVersion);
}

/**
* <p>Basic read operation to retrieve a secret of specific version</p>
*
* @param path The Vault key value from which to read
* @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)
.header("X-Vault-Token", config.getToken())
.connectTimeoutSeconds(config.getOpenTimeout())
.readTimeoutSeconds(config.getReadTimeout())
.sslPemUTF8(config.getSslPemUTF8())
.sslVerification(config.isSslVerify() != null ? config.isSslVerify() : null)
.get();
.url(url)
.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) {
Expand Down Expand Up @@ -93,6 +110,11 @@ public LogicalResponse read(final String path) throws VaultException {
}
}

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);
}

/**
* <p>Basic operation to store secrets. Multiple name value pairs can be stored under the same secret key.
* E.g.:</p>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
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;

/**
* 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";
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<String, String>() {{
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<String, String>() {{
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));
Comment thread
emailtomanishkr marked this conversation as resolved.
Assert.assertEquals(value_2, vault.logical().read(path).getData().get(key));
vault.logical().delete(path);
}
}