Skip to content

Commit 61a4a57

Browse files
authored
Added wrapped TTL parameter when write a logical secret (#33)
1 parent cd25b49 commit 61a4a57

File tree

3 files changed

+79
-3
lines changed

3 files changed

+79
-3
lines changed

src/main/java/io/github/jopenlibs/vault/api/Logical.java

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,14 +202,51 @@ public LogicalResponse read(final String path, Boolean shouldRetry, final Intege
202202
public LogicalResponse write(final String path, final Map<String, Object> nameValuePairs)
203203
throws VaultException {
204204
if (engineVersionForSecretPath(path).equals(2)) {
205-
return write(path, nameValuePairs, logicalOperations.writeV2);
205+
return write(path, nameValuePairs, logicalOperations.writeV2, null);
206206
} else {
207-
return write(path, nameValuePairs, logicalOperations.writeV1);
207+
return write(path, nameValuePairs, logicalOperations.writeV1, null);
208+
}
209+
}
210+
211+
/**
212+
* <p>Basic operation to store secrets. Multiple name value pairs can be stored under the same
213+
* secret key. E.g.:</p>
214+
*
215+
* <blockquote>
216+
* <pre>{@code
217+
* final Map<String, String> nameValuePairs = new HashMap<String, Object>();
218+
* nameValuePairs.put("value", "foo");
219+
* nameValuePairs.put("other_value", "bar");
220+
*
221+
* final LogicalResponse response = vault.logical().write("secret/hello", nameValuePairs);
222+
* }</pre>
223+
* </blockquote>
224+
*
225+
* <p>The values in these name-value pairs may be booleans, numerics, strings, or nested JSON
226+
* objects. However, be aware that this method does not recursively parse any nested
227+
* structures. If you wish to write arbitrary JSON objects to Vault... then you should parse
228+
* them to JSON outside of this method, and pass them here as JSON strings.</p>
229+
*
230+
* @param path The Vault key value to which to write (e.g. <code>secret/hello</code>)
231+
* @param nameValuePairs Secret name and value pairs to store under this Vault key (can be
232+
* @param wrapTTL Time (in seconds) which secret is wrapped
233+
* <code>null</code> for writing to keys that do not need or expect any fields to be specified)
234+
* @return The response information received from Vault
235+
* @throws VaultException If any errors occurs with the REST request, and the maximum number of
236+
* retries is exceeded.
237+
*/
238+
public LogicalResponse write(final String path, final Map<String, Object> nameValuePairs,
239+
final Integer wrapTTL)
240+
throws VaultException {
241+
if (engineVersionForSecretPath(path).equals(2)) {
242+
return write(path, nameValuePairs, logicalOperations.writeV2, wrapTTL);
243+
} else {
244+
return write(path, nameValuePairs, logicalOperations.writeV1, wrapTTL);
208245
}
209246
}
210247

211248
private LogicalResponse write(final String path, final Map<String, Object> nameValuePairs,
212-
final logicalOperations operation) throws VaultException {
249+
final logicalOperations operation, final Integer wrapTTL) throws VaultException {
213250

214251
return retry(attempt -> {
215252
JsonObject requestJson = Json.object();
@@ -246,6 +283,7 @@ private LogicalResponse write(final String path, final Map<String, Object> nameV
246283
.header("X-Vault-Token", config.getToken())
247284
.header("X-Vault-Namespace", this.nameSpace)
248285
.header("X-Vault-Request", "true")
286+
.header("X-Vault-Wrap-TTL", wrapTTL != null ? wrapTTL.toString() : null)
249287
.connectTimeoutSeconds(config.getOpenTimeout())
250288
.readTimeoutSeconds(config.getReadTimeout())
251289
.sslVerification(config.getSslConfig().isVerify())

src/main/java/io/github/jopenlibs/vault/response/LogicalResponse.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ public class LogicalResponse extends VaultResponse {
2222
private List<String> listData = new ArrayList<>();
2323
private JsonObject dataObject = null;
2424
private String leaseId;
25+
private WrapResponse wrapResponse;
2526
private Boolean renewable;
2627
private Long leaseDuration;
2728

@@ -61,6 +62,10 @@ public Long getLeaseDuration() {
6162
return leaseDuration;
6263
}
6364

65+
public WrapResponse getWrapResponse() {
66+
return wrapResponse;
67+
}
68+
6469
private void parseMetadataFields() {
6570
try {
6671
final String jsonString = new String(getRestResponse().getBody(),
@@ -70,6 +75,8 @@ private void parseMetadataFields() {
7075
this.leaseId = jsonObject.get("lease_id").asString();
7176
this.renewable = jsonObject.get("renewable").asBoolean();
7277
this.leaseDuration = jsonObject.get("lease_duration").asLong();
78+
79+
this.wrapResponse = new WrapResponse(getRestResponse(), getRetries());
7380
} catch (Exception ignored) {
7481
}
7582
}

src/test-integration/java/io/github/jopenlibs/vault/api/LogicalTests.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import io.github.jopenlibs.vault.VaultException;
66
import io.github.jopenlibs.vault.response.AuthResponse;
77
import io.github.jopenlibs.vault.response.LogicalResponse;
8+
import io.github.jopenlibs.vault.response.WrapResponse;
89
import io.github.jopenlibs.vault.util.VaultContainer;
910
import java.io.IOException;
1011
import java.util.HashMap;
@@ -21,6 +22,8 @@
2122

2223
import static junit.framework.TestCase.assertEquals;
2324
import static junit.framework.TestCase.assertFalse;
25+
import static junit.framework.TestCase.assertNotNull;
26+
import static junit.framework.TestCase.assertNotSame;
2427
import static junit.framework.TestCase.assertTrue;
2528

2629
/**
@@ -66,6 +69,34 @@ public void testWriteAndRead() throws VaultException {
6669
assertEquals(value, valueRead);
6770
}
6871

72+
/**
73+
* Write a wrapped secret and verify that it can be read, using KV Secrets engine version 2.
74+
*
75+
* @throws VaultException On error.
76+
*/
77+
@Test
78+
public void testWriteAndReadWrapped() throws VaultException {
79+
final String pathToWrite = "secret/hellowrapped";
80+
final String pathToRead = "secret/hellowrapped";
81+
final int wrapTTL = 60;
82+
83+
final String value = "world";
84+
final Vault vault = container.getRootVault();
85+
86+
final Map<String, Object> testMap = new HashMap<>();
87+
testMap.put("value", value);
88+
89+
LogicalResponse response = vault.logical().write(pathToWrite, testMap, wrapTTL);
90+
91+
final String valueRead = vault.logical().read(pathToRead).getData().get("value");
92+
WrapResponse wrapResponse = response.getWrapResponse();
93+
assertNotNull(response.getWrapResponse());
94+
95+
assertNotSame("", wrapResponse.getToken());
96+
assertEquals(wrapTTL, wrapResponse.getTtl());
97+
assertEquals(value, valueRead);
98+
}
99+
69100
/**
70101
* Write a secret and verify that it can be read, using KV Secrets engine version 1.
71102
*

0 commit comments

Comments
 (0)