|
29 | 29 | */ |
30 | 30 | public class Logical extends OperationsBase { |
31 | 31 |
|
| 32 | + private static final WriteOptions DEFAULT_WRITE_OPTIONS = new WriteOptions().build(); |
| 33 | + |
32 | 34 | private String nameSpace; |
33 | 35 |
|
34 | 36 | public enum logicalOperations {authentication, deleteV1, deleteV2, destroy, listV1, listV2, readV1, readV2, writeV1, writeV2, unDelete, mount} |
@@ -201,9 +203,11 @@ public LogicalResponse read(final String path, Boolean shouldRetry, final Intege |
201 | 203 | public LogicalResponse write(final String path, final Map<String, Object> nameValuePairs) |
202 | 204 | throws VaultException { |
203 | 205 | if (engineVersionForSecretPath(path).equals(2)) { |
204 | | - return write(path, nameValuePairs, logicalOperations.writeV2, null); |
| 206 | + return write(path, nameValuePairs, logicalOperations.writeV2, null, |
| 207 | + DEFAULT_WRITE_OPTIONS); |
205 | 208 | } else { |
206 | | - return write(path, nameValuePairs, logicalOperations.writeV1, null); |
| 209 | + return write(path, nameValuePairs, logicalOperations.writeV1, null, |
| 210 | + DEFAULT_WRITE_OPTIONS); |
207 | 211 | } |
208 | 212 | } |
209 | 213 |
|
@@ -238,47 +242,50 @@ public LogicalResponse write(final String path, final Map<String, Object> nameVa |
238 | 242 | final Integer wrapTTL) |
239 | 243 | throws VaultException { |
240 | 244 | if (engineVersionForSecretPath(path).equals(2)) { |
241 | | - return write(path, nameValuePairs, logicalOperations.writeV2, wrapTTL); |
| 245 | + return write(path, nameValuePairs, logicalOperations.writeV2, wrapTTL, |
| 246 | + DEFAULT_WRITE_OPTIONS); |
242 | 247 | } else { |
243 | | - return write(path, nameValuePairs, logicalOperations.writeV1, wrapTTL); |
| 248 | + return write(path, nameValuePairs, logicalOperations.writeV1, wrapTTL, |
| 249 | + DEFAULT_WRITE_OPTIONS); |
| 250 | + } |
| 251 | + } |
| 252 | + |
| 253 | + /** |
| 254 | + * <p>Operation to store secrets with the ability to specify additional write options |
| 255 | + * See {@link #write(String, Map, Integer) write} for common behavior |
| 256 | + * </p> |
| 257 | + * |
| 258 | + * @param path The Vault key value to which to write (e.g. <code>secret/hello</code>) |
| 259 | + * @param nameValuePairs Secret name and value pairs to store under this Vault key (can be |
| 260 | + * @param wrapTTL Time (in seconds) which secret is wrapped |
| 261 | + * @param writeOptions Additional options to be used for the write operation |
| 262 | + * @return The response information received from Vault |
| 263 | + * @throws VaultException If invalid engine version or if errors occurs with the REST request, |
| 264 | + * and the maximum number of retries is exceeded. |
| 265 | + */ |
| 266 | + public LogicalResponse write(final String path, final Map<String, Object> nameValuePairs, |
| 267 | + final Integer wrapTTL, final WriteOptions writeOptions) |
| 268 | + throws VaultException { |
| 269 | + if (!this.engineVersionForSecretPath(path).equals(2)) { |
| 270 | + throw new VaultException("Write options are only supported in KV Engine version 2."); |
244 | 271 | } |
| 272 | + return write(path, nameValuePairs, logicalOperations.writeV2, wrapTTL, writeOptions); |
245 | 273 | } |
246 | 274 |
|
247 | 275 | private LogicalResponse write(final String path, final Map<String, Object> nameValuePairs, |
248 | | - final logicalOperations operation, final Integer wrapTTL) throws VaultException { |
| 276 | + final logicalOperations operation, final Integer wrapTTL, |
| 277 | + final WriteOptions writeOptions) |
| 278 | + throws VaultException { |
249 | 279 |
|
250 | 280 | return retry(attempt -> { |
251 | | - JsonObject requestJson = Json.object(); |
252 | | - if (nameValuePairs != null) { |
253 | | - for (final Map.Entry<String, Object> pair : nameValuePairs.entrySet()) { |
254 | | - final Object value = pair.getValue(); |
255 | | - if (value == null) { |
256 | | - requestJson = requestJson.add(pair.getKey(), (String) null); |
257 | | - } else if (value instanceof Boolean) { |
258 | | - requestJson = requestJson.add(pair.getKey(), (Boolean) pair.getValue()); |
259 | | - } else if (value instanceof Integer) { |
260 | | - requestJson = requestJson.add(pair.getKey(), (Integer) pair.getValue()); |
261 | | - } else if (value instanceof Long) { |
262 | | - requestJson = requestJson.add(pair.getKey(), (Long) pair.getValue()); |
263 | | - } else if (value instanceof Float) { |
264 | | - requestJson = requestJson.add(pair.getKey(), (Float) pair.getValue()); |
265 | | - } else if (value instanceof Double) { |
266 | | - requestJson = requestJson.add(pair.getKey(), (Double) pair.getValue()); |
267 | | - } else if (value instanceof JsonValue) { |
268 | | - requestJson = requestJson.add(pair.getKey(), |
269 | | - (JsonValue) pair.getValue()); |
270 | | - } else { |
271 | | - requestJson = requestJson.add(pair.getKey(), |
272 | | - pair.getValue().toString()); |
273 | | - } |
274 | | - } |
275 | | - } |
276 | | - // Make an HTTP request to Vault |
| 281 | + JsonObject dataJson = buildJsonFromMap(nameValuePairs); |
| 282 | + JsonObject optionsJson = buildJsonFromMap(writeOptions.getOptionsMap()); |
| 283 | + // Make an HTTP request to Vault |
277 | 284 | final RestResponse restResponse = getRest()//NOPMD |
278 | 285 | .url(config.getAddress() + "/v1/" + adjustPathForReadOrWrite(path, |
279 | 286 | config.getPrefixPathDepth(), operation)) |
280 | | - .body(jsonObjectToWriteFromEngineVersion(operation, requestJson).toString() |
281 | | - .getBytes(StandardCharsets.UTF_8)) |
| 287 | + .body(jsonObjectToWriteFromEngineVersion(operation, dataJson, optionsJson) |
| 288 | + .toString().getBytes(StandardCharsets.UTF_8)) |
282 | 289 | .header("X-Vault-Token", config.getToken()) |
283 | 290 | .header("X-Vault-Namespace", this.nameSpace) |
284 | 291 | .header("X-Vault-Request", "true") |
@@ -607,4 +614,34 @@ private Integer engineVersionForSecretPath(final String secretPath) { |
607 | 614 | public Integer getEngineVersionForSecretPath(final String path) { |
608 | 615 | return this.engineVersionForSecretPath(path); |
609 | 616 | } |
| 617 | + |
| 618 | + private JsonObject buildJsonFromMap(Map<String, Object> nameValuePairs) { |
| 619 | + JsonObject jsonObject = Json.object(); |
| 620 | + if (nameValuePairs != null) { |
| 621 | + for (final Map.Entry<String, Object> pair : nameValuePairs.entrySet()) { |
| 622 | + final Object value = pair.getValue(); |
| 623 | + if (value == null) { |
| 624 | + jsonObject = jsonObject.add(pair.getKey(), (String) null); |
| 625 | + } else if (value instanceof Boolean) { |
| 626 | + jsonObject = jsonObject.add(pair.getKey(), (Boolean) pair.getValue()); |
| 627 | + } else if (value instanceof Integer) { |
| 628 | + jsonObject = jsonObject.add(pair.getKey(), (Integer) pair.getValue()); |
| 629 | + } else if (value instanceof Long) { |
| 630 | + jsonObject = jsonObject.add(pair.getKey(), (Long) pair.getValue()); |
| 631 | + } else if (value instanceof Float) { |
| 632 | + jsonObject = jsonObject.add(pair.getKey(), (Float) pair.getValue()); |
| 633 | + } else if (value instanceof Double) { |
| 634 | + jsonObject = jsonObject.add(pair.getKey(), (Double) pair.getValue()); |
| 635 | + } else if (value instanceof JsonValue) { |
| 636 | + jsonObject = jsonObject.add(pair.getKey(), |
| 637 | + (JsonValue) pair.getValue()); |
| 638 | + } else { |
| 639 | + jsonObject = jsonObject.add(pair.getKey(), |
| 640 | + pair.getValue().toString()); |
| 641 | + } |
| 642 | + } |
| 643 | + } |
| 644 | + return jsonObject; |
| 645 | + } |
| 646 | + |
610 | 647 | } |
0 commit comments