diff --git a/src/main/java/de/stklcode/jvault/connector/HTTPVaultConnector.java b/src/main/java/de/stklcode/jvault/connector/HTTPVaultConnector.java index 1f35cc1..6fce9ce 100644 --- a/src/main/java/de/stklcode/jvault/connector/HTTPVaultConnector.java +++ b/src/main/java/de/stklcode/jvault/connector/HTTPVaultConnector.java @@ -60,6 +60,7 @@ public class HTTPVaultConnector implements VaultConnector { private static final String PATH_AUTH_USERPASS = "auth/userpass/login/"; private static final String PATH_AUTH_APPID = "auth/app-id/"; private static final String PATH_SECRET = "secret"; + private static final String PATH_REVOKE = "sys/revoke/"; private final ObjectMapper jsonMapper; @@ -71,6 +72,7 @@ public class HTTPVaultConnector implements VaultConnector { /** * Create connector using hostname and schema. + * * @param hostname The hostname * @param useTLS If TRUE, use HTTPS, otherwise HTTP */ @@ -80,6 +82,7 @@ public class HTTPVaultConnector implements VaultConnector { /** * Create connector using hostname, schema and port. + * * @param hostname The hostname * @param useTLS If TRUE, use HTTPS, otherwise HTTP * @param port The port @@ -89,7 +92,8 @@ public class HTTPVaultConnector implements VaultConnector { } /** - * Create connector using hostname, schame, port and path + * Create connector using hostname, schame, port and path. + * * @param hostname The hostname * @param useTLS If TRUE, use HTTPS, otherwise HTTP * @param port The port @@ -103,7 +107,8 @@ public class HTTPVaultConnector implements VaultConnector { } /** - * Create connector using full URL + * Create connector using full URL. + * * @param baseURL The URL */ public HTTPVaultConnector(String baseURL) { @@ -310,10 +315,26 @@ public class HTTPVaultConnector implements VaultConnector { return requestPost(PATH_SECRET + "/" + key, param).equals(""); } + @Override + public boolean revoke(String leaseID) throws VaultConnectorException { + if (!isAuthorized()) + throw new AuthorizationRequiredException(); + + /* Request HTTP response and expect empty result */ + String response = requestPut(PATH_REVOKE + leaseID, new HashMap<>()); + return response.equals(""); + } + + @Override + public VaultResponse renew(String leaseID, Integer seconds) { + /* TODO */ + return null; + } /** * Execute HTTP request using POST method. + * * @param path URL path (relative to base) * @param payload Map of payload values (will be converted to JSON) * @return HTTP response @@ -341,6 +362,7 @@ public class HTTPVaultConnector implements VaultConnector { /** * Execute HTTP request using PUT method. + * * @param path URL path (relative to base) * @param payload Map of payload values (will be converted to JSON) * @return HTTP response @@ -367,9 +389,10 @@ public class HTTPVaultConnector implements VaultConnector { /** * Execute HTTP request using GET method. + * * @param path URL path (relative to base) * @param payload Map of payload values (will be converted to JSON) - * @return HTTP response + * @return HTTP response * @throws VaultConnectorException on connection error */ private String requestGet(final String path, final Map payload) throws VaultConnectorException, URISyntaxException { @@ -388,9 +411,10 @@ public class HTTPVaultConnector implements VaultConnector { } /** - * Execute prepared HTTP request and return result - * @param base Prepares Request - * @return HTTP response + * Execute prepared HTTP request and return result. + * + * @param base Prepares Request + * @return HTTP response * @throws VaultConnectorException on connection error */ private String request(HttpRequestBase base) throws VaultConnectorException { diff --git a/src/main/java/de/stklcode/jvault/connector/VaultConnector.java b/src/main/java/de/stklcode/jvault/connector/VaultConnector.java index f3c58ae..f82e2fa 100644 --- a/src/main/java/de/stklcode/jvault/connector/VaultConnector.java +++ b/src/main/java/de/stklcode/jvault/connector/VaultConnector.java @@ -26,13 +26,14 @@ import java.util.List; * Vault Connector interface. * Provides methods to connect with Vault backend and handle secrets. * - * @author Stefan Kalscheuer - * @since 0.1 + * @author Stefan Kalscheuer + * @since 0.1 */ public interface VaultConnector { /** * Verify that vault connection is initialized. - * @return TRUE if correctly initialized + * + * @return TRUE if correctly initialized */ boolean init(); @@ -43,28 +44,32 @@ public interface VaultConnector { /** * Retrieve status of vault seal. - * @return Seal status + * + * @return Seal status */ SealResponse sealStatus(); /** * Seal vault. - * @return TRUE on success + * + * @return TRUE on success */ boolean seal(); /** * Unseal vault. - * @param key A single master share key - * @param reset Discard previously provided keys (optional) - * @return TRUE on success + * + * @param key A single master share key + * @param reset Discard previously provided keys (optional) + * @return TRUE on success */ SealResponse unseal(final String key, final Boolean reset); /** * Unseal vault. - * @param key A single master share key - * @return TRUE on success + * + * @param key A single master share key + * @return TRUE on success */ default SealResponse unseal(final String key) { return unseal(key, null); @@ -72,64 +77,71 @@ public interface VaultConnector { /** * Get all availale authentication backends. - * @return List of backends - * @throws VaultConnectorException on error + * + * @return List of backends + * @throws VaultConnectorException on error */ List getAuthBackends() throws VaultConnectorException; /** * Authorize to Vault using token. - * @param token The token - * @return Token response - * @throws VaultConnectorException on error + * + * @param token The token + * @return Token response + * @throws VaultConnectorException on error */ TokenResponse authToken(final String token) throws VaultConnectorException; /** * Authorize to Vault using username and password. - * @param username The username - * @param password The password - * @return Authorization result - * @throws VaultConnectorException on error + * + * @param username The username + * @param password The password + * @return Authorization result + * @throws VaultConnectorException on error */ AuthResponse authUserPass(final String username, final String password) throws VaultConnectorException; /** * Authorize to Vault using AppID method. - * @param appID The App ID - * @param userID The User ID - * @return TRUE on success - * @throws VaultConnectorException on error + * + * @param appID The App ID + * @param userID The User ID + * @return TRUE on success + * @throws VaultConnectorException on error */ AuthResponse authAppId(final String appID, final String userID) throws VaultConnectorException; /** * Register new App-ID with policy. - * @param appID The unique App-ID - * @param policy The policy to associate with - * @param displayName Arbitrary name to display - * @return TRUE on success - * @throws VaultConnectorException on error + * + * @param appID The unique App-ID + * @param policy The policy to associate with + * @param displayName Arbitrary name to display + * @return TRUE on success + * @throws VaultConnectorException on error */ boolean registerAppId(final String appID, final String policy, final String displayName) throws VaultConnectorException; /** * Register User-ID with App-ID - * @param appID The App-ID - * @param userID The User-ID - * @return TRUE on success - * @throws VaultConnectorException on error + * + * @param appID The App-ID + * @param userID The User-ID + * @return TRUE on success + * @throws VaultConnectorException on error */ boolean registerUserId(final String appID, final String userID) throws VaultConnectorException; /** * Register new App-ID and User-ID at once. - * @param appID The App-ID - * @param policy The policy to associate with - * @param displayName Arbitrary name to display - * @param userID The User-ID - * @return TRUE on success - * @throws VaultConnectorException on error + * + * @param appID The App-ID + * @param policy The policy to associate with + * @param displayName Arbitrary name to display + * @param userID The User-ID + * @return TRUE on success + * @throws VaultConnectorException on error */ default boolean registerAppUserId(final String appID, final String policy, final String displayName, final String userID) throws VaultConnectorException { return registerAppId(appID, policy, userID) && registerUserId(appID, userID); @@ -137,32 +149,54 @@ public interface VaultConnector { /** * Get authorization status - * @return TRUE, if successfully authorized + * + * @return TRUE, if successfully authorized */ boolean isAuthorized(); /** * Retrieve secret form Vault. - * @param key Secret identifier - * @return Secret response - * @throws VaultConnectorException on error + * + * @param key Secret identifier + * @return Secret response + * @throws VaultConnectorException on error */ SecretResponse readSecret(final String key) throws VaultConnectorException; /** * List available secrets from Vault. - * @param path Root path to search - * @return List of secret keys - * @throws VaultConnectorException on error + * + * @param path Root path to search + * @return List of secret keys + * @throws VaultConnectorException on error */ List listSecrets(final String path) throws VaultConnectorException; /** * Write secret to Vault. + * * @param key Secret path * @param value Secret value - * @return TRUE on success - * @throws VaultConnectorException on error + * @return TRUE on success + * @throws VaultConnectorException on error */ boolean writeSecret(final String key, final String value) throws VaultConnectorException; + + /** + * Revoke given lease immediately. + * + * @param leaseID the lease ID + * @return TRUE on success + * @throws VaultConnectorException on error + */ + boolean revoke(final String leaseID) throws VaultConnectorException; + + /** + * Renew lease with given ID. + * + * @param leaseID the lase ID + * @param seconds number of seconds to extend lease time + * @return Renewed lease + */ + VaultResponse renew(final String leaseID, final Integer seconds); } diff --git a/src/test/java/de/stklcode/jvault/connector/HTTPVaultConnectorTest.java b/src/test/java/de/stklcode/jvault/connector/HTTPVaultConnectorTest.java index dfe673d..16b5807 100644 --- a/src/test/java/de/stklcode/jvault/connector/HTTPVaultConnectorTest.java +++ b/src/test/java/de/stklcode/jvault/connector/HTTPVaultConnectorTest.java @@ -35,13 +35,10 @@ import java.io.IOException; import java.net.ServerSocket; import java.util.List; -import static org.hamcrest.CoreMatchers.*; -import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.*; import static org.hamcrest.core.Is.is; import static org.junit.Assert.*; -import static org.junit.Assume.assumeFalse; -import static org.junit.Assume.assumeNotNull; -import static org.junit.Assume.assumeTrue; +import static org.junit.Assume.*; /** * JUnit Test for HTTP Vault connector. @@ -303,6 +300,45 @@ public class HTTPVaultConnectorTest { } } + /** + * Test revocation of secrets. + */ + @Test + public void revokeTest() { + authRoot(); + assumeTrue(connector.isAuthorized()); + + /* Write a test secret to vault */ + try { + boolean res = connector.writeSecret(SECRET_PATH + "/toRevoke", "secret content"); + assumeThat("Secret could not be written path.", res, is(true)); + } catch (VaultConnectorException e) { + fail("Secret written to inaccessible path."); + } + SecretResponse res = null; + try { + res = connector.readSecret(SECRET_PATH + "/toRevoke"); + } catch (VaultConnectorException e) { + fail("Written secret could not be read."); + } + assumeThat(res, is(notNullValue())); + + /* Revoke secret by lease id */ + try { + boolean revoked = connector.revoke(SECRET_PATH + "/toRevoke"); + assertThat("Revocation of secret faiked.", revoked, is(true)); + } catch (VaultConnectorException e) { + fail("Revocation threw unexpected exception."); + } + + try { + connector.readSecret(SECRET_PATH + "/toRevoke"); + fail("Revoked secret could still be read"); + } catch (VaultConnectorException e) { + assertThat(e, is(notNullValue())); + } + } + /** * Initialize Vault with resource datastore and generated configuration. * @return Vault Configuration