From e41a61f33b017620dda1ab5b8222950cc0a805ec Mon Sep 17 00:00:00 2001 From: Stefan Kalscheuer Date: Tue, 20 Nov 2018 11:49:01 +0100 Subject: [PATCH] Add methods to delete, undelete and destroy KV v2 secret versions --- .../jvault/connector/HTTPVaultConnector.java | 59 ++++++++++++++++++- .../jvault/connector/VaultConnector.java | 53 +++++++++++++++++ 2 files changed, 110 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/stklcode/jvault/connector/HTTPVaultConnector.java b/src/main/java/de/stklcode/jvault/connector/HTTPVaultConnector.java index 8e16e6e..c3e77e3 100644 --- a/src/main/java/de/stklcode/jvault/connector/HTTPVaultConnector.java +++ b/src/main/java/de/stklcode/jvault/connector/HTTPVaultConnector.java @@ -74,6 +74,11 @@ public class HTTPVaultConnector implements VaultConnector { private static final String PATH_AUTH_APPROLE_ROLE = "auth/approle/role/%s%s"; private static final String PATH_REVOKE = "sys/leases/revoke/"; private static final String PATH_HEALTH = "sys/health"; + private static final String PATH_DATA = "/data/"; + private static final String PATH_METADATA = "/metadata/"; + private static final String PATH_DELETE = "/delete/"; + private static final String PATH_UNDELETE = "/undelete/"; + private static final String PATH_DESTROY = "/destroy/"; private static final String HEADER_VAULT_TOKEN = "X-Vault-Token"; @@ -605,7 +610,7 @@ public class HTTPVaultConnector implements VaultConnector { } /* Request HTTP response and parse secret metadata */ try { - String response = requestGet(PATH_SECRET + "data/" + key, new HashMap<>()); + String response = requestGet(PATH_SECRET + PATH_DATA + key, new HashMap<>()); return jsonMapper.readValue(response, SecretResponse.class); } catch (IOException e) { throw new InvalidResponseException(Error.PARSE_RESPONSE, e); @@ -622,7 +627,7 @@ public class HTTPVaultConnector implements VaultConnector { } /* Request HTTP response and parse secret metadata */ try { - String response = requestGet(PATH_SECRET + "metadata/" + key, new HashMap<>()); + String response = requestGet(PATH_SECRET + PATH_METADATA + key, new HashMap<>()); return jsonMapper.readValue(response, MetadataResponse.class); } catch (IOException e) { throw new InvalidResponseException(Error.PARSE_RESPONSE, e); @@ -688,6 +693,56 @@ public class HTTPVaultConnector implements VaultConnector { throw new InvalidResponseException(Error.UNEXPECTED_RESPONSE); } + @Override + public final void deleteLatestSecretVersion(final String key) throws VaultConnectorException { + delete(PATH_SECRET + PATH_DATA + key); + } + + @Override + public final void deleteAllSecretVersions(final String key) throws VaultConnectorException { + delete(PATH_SECRET + PATH_METADATA + key); + } + + @Override + public final void deleteSecretVersions(final String key, final int... versions) throws VaultConnectorException { + handleSecretVersions(PATH_DELETE, key, versions); + } + + @Override + public final void undeleteSecretVersions(final String key, final int... versions) throws VaultConnectorException { + handleSecretVersions(PATH_UNDELETE, key, versions); + } + + @Override + public final void destroySecretVersions(final String key, final int... versions) throws VaultConnectorException { + handleSecretVersions(PATH_DESTROY, key, versions); + } + + /** + * Common method to bundle secret version operations. + * + * @param pathPart Path part to query. + * @param key Secret key. + * @param versions Versions to handle. + * @throws VaultConnectorException on error + * @since 0.8 + */ + private void handleSecretVersions(final String pathPart, final String key, final int... versions) throws VaultConnectorException { + if (!isAuthorized()) { + throw new AuthorizationRequiredException(); + } + + /* Request HTTP response and expect empty result */ + Map payload = new HashMap<>(); + payload.put("versions", versions); + String response = requestPost(PATH_SECRET + pathPart + key, payload); + + /* Response should be code 204 without content */ + if (!response.isEmpty()) { + throw new InvalidResponseException(Error.UNEXPECTED_RESPONSE); + } + } + @Override public final void revoke(final String leaseID) throws VaultConnectorException { if (!isAuthorized()) diff --git a/src/main/java/de/stklcode/jvault/connector/VaultConnector.java b/src/main/java/de/stklcode/jvault/connector/VaultConnector.java index 5f61e2a..50a23bf 100644 --- a/src/main/java/de/stklcode/jvault/connector/VaultConnector.java +++ b/src/main/java/de/stklcode/jvault/connector/VaultConnector.java @@ -539,6 +539,59 @@ public interface VaultConnector extends AutoCloseable, Serializable { delete(PATH_SECRET + "/" + key); } + /** + * Delete latest version of a secret from Vault. + * Only available for KV v2 stores. + * + * @param key Secret path. + * @throws VaultConnectorException on error + * @since 0.8 + */ + void deleteLatestSecretVersion(final String key) throws VaultConnectorException; + + /** + * Delete latest version of a secret from Vault. + * Only available for KV v2 stores. + * + * @param key Secret path. + * @throws VaultConnectorException on error + * @since 0.8 + */ + void deleteAllSecretVersions(final String key) throws VaultConnectorException; + + /** + * Delete secret versions from Vault. + * Only available for KV v2 stores. + * + * @param key Secret path. + * @param versions Versions of the secret to delete. + * @throws VaultConnectorException on error + * @since 0.8 + */ + void deleteSecretVersions(final String key, final int... versions) throws VaultConnectorException; + + /** + * Undelete (restore) secret versions from Vault. + * Only available for KV v2 stores. + * + * @param key Secret path. + * @param versions Versions of the secret to undelete. + * @throws VaultConnectorException on error + * @since 0.8 + */ + void undeleteSecretVersions(final String key, final int... versions) throws VaultConnectorException; + + /** + * Destroy secret versions from Vault. + * Only available for KV v2 stores. + * + * @param key Secret path. + * @param versions Versions of the secret to destroy. + * @throws VaultConnectorException on error + * @since 0.8 + */ + void destroySecretVersions(final String key, final int... versions) throws VaultConnectorException; + /** * Revoke given lease immediately. *