diff --git a/README.md b/README.md index 88894a2f..ce2d548e 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,7 @@ Once you have initialized a `VaultConfig` object, you can use it to construct an the `Vault` primary driver class: ``` -final Vault vault = new Vault(config); +final Vault vault = Vault.create(config); ``` Key Value Secret Engine Config diff --git a/src/main/java/io/github/jopenlibs/vault/SslConfig.java b/src/main/java/io/github/jopenlibs/vault/SslConfig.java index 24845658..78dc75a5 100644 --- a/src/main/java/io/github/jopenlibs/vault/SslConfig.java +++ b/src/main/java/io/github/jopenlibs/vault/SslConfig.java @@ -699,7 +699,7 @@ private static String inputStreamToUTF8(final InputStream input) throws IOExcept } /** - *

There was a community request to make {@link Vault} and its config class serializable + *

There was a community request to make {@link VaultImpl} and its config class serializable * (https://github.com/BetterCloud/vault-java-driver/pull/51). * However, this SslConfig class now contains a member field of type {@link SSLContext}, which diff --git a/src/main/java/io/github/jopenlibs/vault/Vault.java b/src/main/java/io/github/jopenlibs/vault/Vault.java index 51efdfdd..f026e75b 100644 --- a/src/main/java/io/github/jopenlibs/vault/Vault.java +++ b/src/main/java/io/github/jopenlibs/vault/Vault.java @@ -2,12 +2,13 @@ import io.github.jopenlibs.vault.api.Auth; import io.github.jopenlibs.vault.api.Debug; -import io.github.jopenlibs.vault.api.Leases; import io.github.jopenlibs.vault.api.Logical; -import io.github.jopenlibs.vault.api.Seal; import io.github.jopenlibs.vault.api.database.Database; -import io.github.jopenlibs.vault.api.mounts.Mounts; import io.github.jopenlibs.vault.api.pki.Pki; +import io.github.jopenlibs.vault.api.sys.Leases; +import io.github.jopenlibs.vault.api.sys.Seal; +import io.github.jopenlibs.vault.api.sys.Sys; +import io.github.jopenlibs.vault.api.sys.mounts.Mounts; import io.github.jopenlibs.vault.json.Json; import io.github.jopenlibs.vault.json.JsonObject; import io.github.jopenlibs.vault.json.JsonValue; @@ -17,70 +18,11 @@ import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; -import java.util.logging.Logger; -/** - *

The Vault driver class, the primary interface through which dependent applications will - * access Vault.

- * - *

This driver exposes a DSL, compartmentalizing the various endpoints of the HTTP API (e.g. - * "/", "sys/init", "sys/seal") into separate implementation classes (e.g. Logical, - * Init, etc).

- * - *

Example usage:

- * - *
- *
{@code
- * final VaultConfig config = new VaultConfig
- *                                    .address("http://127.0.0.1:8200")
- *                                    .token("eace6676-4d78-c687-4e54-03cad00e3abf")
- *                                    .build();
- * final Vault vault = new Vault(config);
- *
- * ...
- *
- * final Map secrets = new HashMap();
- * secrets.put("value", "world");
- * secrets.put("other_value", "You can store multiple name/value pairs under a given key");
- *
- * final LogicalResponse writeResponse = vault
- *                                         .withRetries(5, 1000)  // optional
- *                                         .logical()
- *                                         .write("secret/hello", secrets);
- *
- * ...
- *
- * final String value = vault.logical()
- *                        .read("secret/hello")
- *                        .getData().get("value");
- * }
- *
- */ -public class Vault { +public interface Vault { - private final VaultConfig vaultConfig; - private Logger logger = Logger.getLogger(Vault.class.getCanonicalName()); - - /** - * Construct a Vault driver instance with the provided config settings. - * - * @param vaultConfig Configuration settings for Vault interaction (e.g. server address, token, - * etc) If the VaultConfig Engine version path map is not supplied in the config, default to - * global KV engine version 2. - */ - public Vault(final VaultConfig vaultConfig) { - this.vaultConfig = vaultConfig; - if (this.vaultConfig.getNameSpace() != null && !this.vaultConfig.getNameSpace().isEmpty()) { - logger.info(String.format( - "The NameSpace %s has been bound to this Vault instance. Please keep this in mind when running operations.", - this.vaultConfig.getNameSpace())); - } - if (this.vaultConfig.getSecretsEnginePathMap().isEmpty() - && this.vaultConfig.getGlobalEngineVersion() == null) { - logger.info( - "Constructing a Vault instance with no provided Engine version, defaulting to version 2."); - this.vaultConfig.setEngineVersion(2); - } + static Vault create(VaultConfig vaultConfig){ + return new VaultImpl(vaultConfig); } /** @@ -92,19 +34,8 @@ public Vault(final VaultConfig vaultConfig) { * @param engineVersion Which version of the Key/Value Secret Engine to use globally (i.e. 1 or * 2) */ - public Vault(final VaultConfig vaultConfig, final Integer engineVersion) { - if (engineVersion < 1 || engineVersion > 2) { - throw new IllegalArgumentException( - "The Engine version must be '1' or '2', the version supplied was: '" - + engineVersion + "'."); - } - vaultConfig.setEngineVersion(engineVersion); - this.vaultConfig = vaultConfig; - if (this.vaultConfig.getNameSpace() != null && !this.vaultConfig.getNameSpace().isEmpty()) { - logger.info(String.format( - "The Namespace %s has been bound to this Vault instance. Please keep this in mind when running operations.", - this.vaultConfig.getNameSpace())); - } + static Vault create(final VaultConfig vaultConfig, final Integer engineVersion) { + return new VaultImpl(vaultConfig, engineVersion); } /** @@ -120,31 +51,10 @@ public Vault(final VaultConfig vaultConfig, final Integer engineVersion) { * fallback. * @throws VaultException If any error occurs */ - public Vault(final VaultConfig vaultConfig, final Boolean useSecretsEnginePathMap, + static Vault create(final VaultConfig vaultConfig, final Boolean useSecretsEnginePathMap, final Integer globalFallbackVersion) throws VaultException { - this.vaultConfig = vaultConfig; - if (this.vaultConfig.getNameSpace() != null && !this.vaultConfig.getNameSpace().isEmpty()) { - logger.info(String.format( - "The Namespace %s has been bound to this Vault instance. Please keep this in mind when running operations.", - this.vaultConfig.getNameSpace())); - } - this.vaultConfig.setEngineVersion(globalFallbackVersion); - if (useSecretsEnginePathMap && this.vaultConfig.getSecretsEnginePathMap().isEmpty()) { - try { - logger.info( - "No secrets Engine version map was supplied, attempting to generate one."); - final Map secretsEnginePathMap = collectSecretEngineVersions(); - assert secretsEnginePathMap != null; - this.vaultConfig.getSecretsEnginePathMap().putAll(secretsEnginePathMap); - } catch (Exception e) { - throw new VaultException(String.format( - "An Engine KV version map was not supplied, and unable to determine " + - "KV Engine " + - "version, " + "due to exception: %s", - e.getMessage() + ". Do you have admin rights?")); - } - } + return new VaultImpl(vaultConfig, useSecretsEnginePathMap, globalFallbackVersion); } /** @@ -157,20 +67,14 @@ public Vault(final VaultConfig vaultConfig, final Boolean useSecretsEnginePathMa * between retries * @return This object, with maxRetries and retryIntervalMilliseconds populated */ - public Vault withRetries(final int maxRetries, final int retryIntervalMilliseconds) { - this.vaultConfig.setMaxRetries(maxRetries); - this.vaultConfig.setRetryIntervalMilliseconds(retryIntervalMilliseconds); - return this; - } + Vault withRetries(final int maxRetries, final int retryIntervalMilliseconds); /** * Returns the implementing class for Vault's core/logical operations (e.g. read, write). * * @return The implementing class for Vault's core/logical operations (e.g. read, write) */ - public Logical logical() { - return new Logical(vaultConfig); - } + Logical logical(); /** * Returns the implementing class for operations on Vault's /v1/auth/* REST @@ -178,9 +82,15 @@ public Logical logical() { * * @return The implementing class for Vault's auth operations. */ - public Auth auth() { - return new Auth(vaultConfig); - } + Auth auth(); + + /** + * Returns the implementing class for operations on Vault's /v1/sys/* REST + * endpoints + * + * @return The implementing class for Vault's auth operations. + */ + Sys sys(); /** * Returns the implementing class for Vault's PKI secret backend (i.e. /v1/pki/* @@ -188,9 +98,7 @@ public Auth auth() { * * @return The implementing class for Vault's PKI secret backend. */ - public Pki pki() { - return new Pki(vaultConfig); - } + Pki pki(); /** *

Returns the implementing class for Vault's PKI secret backend, using a custom path when @@ -203,7 +111,7 @@ public Pki pki() { *

*
{@code
      * final VaultConfig config = new VaultConfig().address(...).token(...).build();
-     * final Vault vault = new Vault(config);
+     * final Vault vault = Vault.create(config);
      * final PkiResponse response = vault.pki("root-ca").createOrUpdateRole("testRole");
      *
      * assertEquals(204, response.getRestResponse().getStatus());
@@ -214,116 +122,37 @@ public Pki pki() {
      * /v1/ prefix
      * @return The implementing class for Vault's PKI secret backend.
      */
-    public Pki pki(final String mountPath) {
-        return new Pki(vaultConfig, mountPath);
-    }
+    Pki pki(final String mountPath);
 
-    public Database database() {
-        return new Database(vaultConfig);
-    }
+    Database database();
 
-    public Database database(final String mountPath) {
-        return new Database(vaultConfig, mountPath);
-    }
+    Database database(final String mountPath);
 
     /**
-     * Returns the implementing class for Vault's lease operations (e.g. revoke, revoke-prefix).
-     *
-     * @return The implementing class for Vault's lease operations (e.g. revoke, revoke-prefix).
+     * @see Sys#leases()
+     * @deprecated This method is deprecated and in future it will be removed
      */
-    public Leases leases() {
-        return new Leases(vaultConfig);
-    }
+    Leases leases();
 
     /**
      * Returns the implementing class for Vault's debug operations (e.g. raw, health).
      *
      * @return The implementing class for Vault's debug operations (e.g. raw, health)
      */
-    public Debug debug() {
-        return new Debug(vaultConfig);
-    }
+    Debug debug();
 
     /**
-     * Returns the implementing class for Vault's sys mounts operations (i.e.
-     * /v1/sys/mounts/* REST endpoints).
-     *
-     * @return the implementing class for Vault's sys mounts operations
+     * @see Sys#mounts()
+     * @deprecated This method is deprecated and in future it will be removed
      */
-    public Mounts mounts() {
-        return new Mounts(vaultConfig);
-    }
+    Mounts mounts();
 
     /**
-     * Returns the implementing class for Vault's seal operations (e.g. seal, unseal, sealStatus).
-     *
-     * @return The implementing class for Vault's seal operations (e.g. seal, unseal, sealStatus).
+     * @see Sys#seal()
+     * @deprecated This method is deprecated and in future it will be removed
      */
-    public Seal seal() {
-        return new Seal(vaultConfig);
-    }
+    Seal seal();
 
-    /**
-     * Makes a REST call to Vault, to collect information on which secret engine version (if any) is
-     * used by each available mount point.  Possibilities are:
-     *
-     * 
    - *
  • "2" - A mount point running on Vault 0.10 or higher, configured to use the engine 2 - * API
  • - *
  • "1" - A mount point running on Vault 0.10 or higher, configured to use the engine 1 - * API
  • - *
  • "unknown" - A mount point running on an older version of Vault. Can more or less be - * treated as "1".
  • - *
- *

- * IMPORTANT: Whichever authentication mechanism is being used with the - * VaultConfig object, that principal needs permission to access the - * /v1/sys/mounts REST endpoint. - * - * @return A map of mount points (e.g. "/secret") to secret engine version numbers (e.g. "2") - */ - private Map collectSecretEngineVersions() { - try { - final RestResponse restResponse = new Rest()//NOPMD - .url(vaultConfig.getAddress() + "/v1/sys/mounts") - .header("X-Vault-Token", vaultConfig.getToken()) - .header("X-Vault-Namespace", this.vaultConfig.getNameSpace()) - .header("X-Vault-Request", "true") - .connectTimeoutSeconds(vaultConfig.getOpenTimeout()) - .readTimeoutSeconds(vaultConfig.getReadTimeout()) - .sslVerification(vaultConfig.getSslConfig().isVerify()) - .sslContext(vaultConfig.getSslConfig().getSslContext()) - .get(); - if (restResponse.getStatus() != 200) { - return null; - } + Map getSecretEngineVersions(); - final String jsonString = new String(restResponse.getBody(), StandardCharsets.UTF_8); - final Map data = new HashMap<>(); - final JsonObject jsonData = Json.parse(jsonString).asObject().get("data").asObject(); - for (JsonObject.Member member : jsonData) { - final String name = member.getName(); - String version = "unknown"; - - final JsonValue options = member.getValue().asObject().get("options"); - if (options != null && options.isObject()) { - final JsonValue ver = options.asObject().get("version"); - if (ver != null && ver.isString()) { - version = ver.asString(); - } - } - data.put(name, version); - } - return data; - } catch (RestException e) { - System.err.print( - String.format("Unable to retrieve the KV Engine secrets, due to exception: %s", - e.getMessage())); - return null; - } - } - - public Map getSecretEngineVersions() { - return this.collectSecretEngineVersions(); - } } diff --git a/src/main/java/io/github/jopenlibs/vault/VaultImpl.java b/src/main/java/io/github/jopenlibs/vault/VaultImpl.java new file mode 100644 index 00000000..4e57e50d --- /dev/null +++ b/src/main/java/io/github/jopenlibs/vault/VaultImpl.java @@ -0,0 +1,353 @@ +package io.github.jopenlibs.vault; + +import io.github.jopenlibs.vault.api.Auth; +import io.github.jopenlibs.vault.api.Debug; +import io.github.jopenlibs.vault.api.Logical; +import io.github.jopenlibs.vault.api.database.Database; +import io.github.jopenlibs.vault.api.pki.Pki; +import io.github.jopenlibs.vault.api.sys.Leases; +import io.github.jopenlibs.vault.api.sys.Seal; +import io.github.jopenlibs.vault.api.sys.Sys; +import io.github.jopenlibs.vault.api.sys.mounts.Mounts; +import io.github.jopenlibs.vault.json.Json; +import io.github.jopenlibs.vault.json.JsonObject; +import io.github.jopenlibs.vault.json.JsonValue; +import io.github.jopenlibs.vault.rest.Rest; +import io.github.jopenlibs.vault.rest.RestException; +import io.github.jopenlibs.vault.rest.RestResponse; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Logger; + +/** + *

The Vault driver class, the primary interface through which dependent applications will + * access Vault.

+ * + *

This driver exposes a DSL, compartmentalizing the various endpoints of the HTTP API (e.g. + * "/", "sys/init", "sys/seal") into separate implementation classes (e.g. Logical, + * Init, etc).

+ * + *

Example usage:

+ * + *
+ *
{@code
+ * final VaultConfig config = new VaultConfig
+ *                                    .address("http://127.0.0.1:8200")
+ *                                    .token("eace6676-4d78-c687-4e54-03cad00e3abf")
+ *                                    .build();
+ * final Vault vault = Vault.create(config);
+ *
+ * ...
+ *
+ * final Map secrets = new HashMap();
+ * secrets.put("value", "world");
+ * secrets.put("other_value", "You can store multiple name/value pairs under a given key");
+ *
+ * final LogicalResponse writeResponse = vault
+ *                                         .withRetries(5, 1000)  // optional
+ *                                         .logical()
+ *                                         .write("secret/hello", secrets);
+ *
+ * ...
+ *
+ * final String value = vault.logical()
+ *                        .read("secret/hello")
+ *                        .getData().get("value");
+ * }
+ *
+ */ +public class VaultImpl implements Vault { + + private final VaultConfig vaultConfig; + private final Logger logger = Logger.getLogger(VaultImpl.class.getCanonicalName()); + + /** + * Construct a Vault driver instance with the provided config settings. + * + * @param vaultConfig Configuration settings for Vault interaction (e.g. server address, token, + * etc) If the VaultConfig Engine version path map is not supplied in the config, default to + * global KV engine version 2. + */ + public VaultImpl(final VaultConfig vaultConfig) { + this.vaultConfig = vaultConfig; + if (this.vaultConfig.getNameSpace() != null && !this.vaultConfig.getNameSpace().isEmpty()) { + logger.info(String.format( + "The NameSpace %s has been bound to this Vault instance. Please keep this in mind when running operations.", + this.vaultConfig.getNameSpace())); + } + if (this.vaultConfig.getSecretsEnginePathMap().isEmpty() + && this.vaultConfig.getGlobalEngineVersion() == null) { + logger.info( + "Constructing a Vault instance with no provided Engine version, defaulting to version 2."); + this.vaultConfig.setEngineVersion(2); + } + } + + /** + * Construct a Vault driver instance with the provided config settings, and use the provided + * global KV Engine version for all secrets. + * + * @param vaultConfig Configuration settings for Vault interaction (e.g. server address, token, + * etc) + * @param engineVersion Which version of the Key/Value Secret Engine to use globally (i.e. 1 or + * 2) + */ + public VaultImpl(final VaultConfig vaultConfig, final Integer engineVersion) { + if (engineVersion < 1 || engineVersion > 2) { + throw new IllegalArgumentException( + "The Engine version must be '1' or '2', the version supplied was: '" + + engineVersion + "'."); + } + vaultConfig.setEngineVersion(engineVersion); + this.vaultConfig = vaultConfig; + if (this.vaultConfig.getNameSpace() != null && !this.vaultConfig.getNameSpace().isEmpty()) { + logger.info(String.format( + "The Namespace %s has been bound to this Vault instance. Please keep this in mind when running operations.", + this.vaultConfig.getNameSpace())); + } + } + + /** + * Construct a Vault driver instance with the provided config settings. + * + * @param vaultConfig Configuration settings for Vault interaction (e.g. server address, token, + * etc) If the Secrets engine version path map is not provided, or does not contain the + * requested secret, fall back to the global version supplied. + * @param useSecretsEnginePathMap Whether to use a provided KV Engine version map from the Vault + * config, or generate one. If a secrets KV Engine version map is not supplied, use Vault APIs + * to determine the KV Engine version for each secret. This call requires admin rights. + * @param globalFallbackVersion The Integer version of the KV Engine to use as a global + * fallback. + * @throws VaultException If any error occurs + */ + public VaultImpl(final VaultConfig vaultConfig, final Boolean useSecretsEnginePathMap, + final Integer globalFallbackVersion) + throws VaultException { + this.vaultConfig = vaultConfig; + if (this.vaultConfig.getNameSpace() != null && !this.vaultConfig.getNameSpace().isEmpty()) { + logger.info(String.format( + "The Namespace %s has been bound to this Vault instance. Please keep this in mind when running operations.", + this.vaultConfig.getNameSpace())); + } + this.vaultConfig.setEngineVersion(globalFallbackVersion); + if (useSecretsEnginePathMap && this.vaultConfig.getSecretsEnginePathMap().isEmpty()) { + try { + logger.info( + "No secrets Engine version map was supplied, attempting to generate one."); + final Map secretsEnginePathMap = collectSecretEngineVersions(); + assert secretsEnginePathMap != null; + this.vaultConfig.getSecretsEnginePathMap().putAll(secretsEnginePathMap); + } catch (Exception e) { + throw new VaultException(String.format( + "An Engine KV version map was not supplied, and unable to determine " + + "KV Engine " + + "version, " + "due to exception: %s", + e.getMessage() + ". Do you have admin rights?")); + } + } + } + + /** + * This method is chained ahead of endpoints (e.g. logical(), auth(), + * etc... to specify retry rules for any API operations invoked on that endpoint. + * + * @param maxRetries The number of times that API operations will be retried when a failure + * occurs + * @param retryIntervalMilliseconds The number of milliseconds that the driver will wait in + * between retries + * @return This object, with maxRetries and retryIntervalMilliseconds populated + */ + @Override + public VaultImpl withRetries(final int maxRetries, final int retryIntervalMilliseconds) { + this.vaultConfig.setMaxRetries(maxRetries); + this.vaultConfig.setRetryIntervalMilliseconds(retryIntervalMilliseconds); + return this; + } + + /** + * Returns the implementing class for Vault's core/logical operations (e.g. read, write). + * + * @return The implementing class for Vault's core/logical operations (e.g. read, write) + */ + @Override + public Logical logical() { + return new Logical(vaultConfig); + } + + /** + * Returns the implementing class for operations on Vault's /v1/auth/* REST + * endpoints + * + * @return The implementing class for Vault's auth operations. + */ + @Override + public Auth auth() { + return new Auth(vaultConfig); + } + + /** + * Returns the implementing class for operations on Vault's /v1/sys/* REST + * endpoints + * + * @return The implementing class for Vault's auth operations. + */ + @Override + public Sys sys() { + return new Sys(vaultConfig); + } + + /** + * Returns the implementing class for Vault's PKI secret backend (i.e. /v1/pki/* + * REST endpoints). + * + * @return The implementing class for Vault's PKI secret backend. + */ + @Override + public Pki pki() { + return new Pki(vaultConfig); + } + + /** + *

Returns the implementing class for Vault's PKI secret backend, using a custom path when + * that backend is mounted on something other than the default (i.e. /v1/pki).

+ * + *

For instance, if your PKI backend is instead mounted on /v1/root-ca, then + * "root-ca" + * would be passed via the mountPath parameter. Example usage:

+ * + *
+ *
{@code
+     * final VaultConfig config = new VaultConfig().address(...).token(...).build();
+     * final Vault vault = Vault.create(config);
+     * final PkiResponse response = vault.pki("root-ca").createOrUpdateRole("testRole");
+     *
+     * assertEquals(204, response.getRestResponse().getStatus());
+     * }
+ *
+ * + * @param mountPath The path on which your Vault PKI backend is mounted, without the + * /v1/ prefix + * @return The implementing class for Vault's PKI secret backend. + */ + @Override + public Pki pki(final String mountPath) { + return new Pki(vaultConfig, mountPath); + } + + @Override + public Database database() { + return new Database(vaultConfig); + } + + @Override + public Database database(final String mountPath) { + return new Database(vaultConfig, mountPath); + } + + /** + * Returns the implementing class for Vault's lease operations (e.g. revoke, revoke-prefix). + * + * @return The implementing class for Vault's lease operations (e.g. revoke, revoke-prefix). + */ + @Override + public Leases leases() { + return new Leases(vaultConfig); + } + + /** + * Returns the implementing class for Vault's debug operations (e.g. raw, health). + * + * @return The implementing class for Vault's debug operations (e.g. raw, health) + */ + @Override + public Debug debug() { + return new Debug(vaultConfig); + } + + /** + * Returns the implementing class for Vault's sys mounts operations (i.e. + * /v1/sys/mounts/* REST endpoints). + * + * @return the implementing class for Vault's sys mounts operations + */ + @Override + public Mounts mounts() { + return new Mounts(vaultConfig); + } + + /** + * Returns the implementing class for Vault's seal operations (e.g. seal, unseal, sealStatus). + * + * @return The implementing class for Vault's seal operations (e.g. seal, unseal, sealStatus). + */ + @Override + public Seal seal() { + return new Seal(vaultConfig); + } + + /** + * Makes a REST call to Vault, to collect information on which secret engine version (if any) is + * used by each available mount point. Possibilities are: + * + *
    + *
  • "2" - A mount point running on Vault 0.10 or higher, configured to use the engine 2 + * API
  • + *
  • "1" - A mount point running on Vault 0.10 or higher, configured to use the engine 1 + * API
  • + *
  • "unknown" - A mount point running on an older version of Vault. Can more or less be + * treated as "1".
  • + *
+ *

+ * IMPORTANT: Whichever authentication mechanism is being used with the + * VaultConfig object, that principal needs permission to access the + * /v1/sys/mounts REST endpoint. + * + * @return A map of mount points (e.g. "/secret") to secret engine version numbers (e.g. "2") + */ + private Map collectSecretEngineVersions() { + try { + final RestResponse restResponse = new Rest()//NOPMD + .url(vaultConfig.getAddress() + "/v1/sys/mounts") + .header("X-Vault-Token", vaultConfig.getToken()) + .header("X-Vault-Namespace", this.vaultConfig.getNameSpace()) + .header("X-Vault-Request", "true") + .connectTimeoutSeconds(vaultConfig.getOpenTimeout()) + .readTimeoutSeconds(vaultConfig.getReadTimeout()) + .sslVerification(vaultConfig.getSslConfig().isVerify()) + .sslContext(vaultConfig.getSslConfig().getSslContext()) + .get(); + if (restResponse.getStatus() != 200) { + return null; + } + + final String jsonString = new String(restResponse.getBody(), StandardCharsets.UTF_8); + final Map data = new HashMap<>(); + final JsonObject jsonData = Json.parse(jsonString).asObject().get("data").asObject(); + for (JsonObject.Member member : jsonData) { + final String name = member.getName(); + String version = "unknown"; + + final JsonValue options = member.getValue().asObject().get("options"); + if (options != null && options.isObject()) { + final JsonValue ver = options.asObject().get("version"); + if (ver != null && ver.isString()) { + version = ver.asString(); + } + } + data.put(name, version); + } + return data; + } catch (RestException e) { + System.err.print( + String.format("Unable to retrieve the KV Engine secrets, due to exception: %s", + e.getMessage())); + return null; + } + } + + @Override + public Map getSecretEngineVersions() { + return this.collectSecretEngineVersions(); + } +} diff --git a/src/main/java/io/github/jopenlibs/vault/api/Auth.java b/src/main/java/io/github/jopenlibs/vault/api/Auth.java index d9800f38..36452e73 100644 --- a/src/main/java/io/github/jopenlibs/vault/api/Auth.java +++ b/src/main/java/io/github/jopenlibs/vault/api/Auth.java @@ -1,8 +1,9 @@ package io.github.jopenlibs.vault.api; -import io.github.jopenlibs.vault.Vault; +import io.github.jopenlibs.vault.VaultImpl; import io.github.jopenlibs.vault.VaultConfig; import io.github.jopenlibs.vault.VaultException; +import io.github.jopenlibs.vault.api.sys.Sys; import io.github.jopenlibs.vault.json.Json; import io.github.jopenlibs.vault.json.JsonObject; import io.github.jopenlibs.vault.response.AuthResponse; @@ -16,7 +17,6 @@ import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.UUID; @@ -27,7 +27,7 @@ * Vault in a DSL-style builder pattern. See the Javadoc comments of each * public method for usage examples.

* - * @see Vault#auth() + * @see VaultImpl#auth() */ public class Auth extends OperationsBase { @@ -273,7 +273,7 @@ public Auth withNameSpace(final String nameSpace) { *
*
{@code
      * final VaultConfig config = new VaultConfig().address(...).token(...).build();
-     * final Vault vault = new Vault(config);
+     * final Vault vault = Vault.create(config);
      * final AuthResponse response = vault.auth().createToken(new TokenRequest().withTtl("1h"));
      *
      * final String token = response.getAuthClientToken();
@@ -295,7 +295,7 @@ public AuthResponse createToken(final TokenRequest tokenRequest) throws VaultExc
      * 
*
{@code
      * final VaultConfig config = new VaultConfig().address(...).token(...).build();
-     * final Vault vault = new Vault(config);
+     * final Vault vault = Vault.create(config);
      * final AuthResponse response = vault.auth().createToken(new TokenRequest().withTtl("1h"));
      *
      * final String token = response.getAuthClientToken();
@@ -840,8 +840,9 @@ public AuthResponse loginByAwsEc2(final String role, final String pkcs7, final S
      * login fails.
      * @param iamRequestUrl PKCS7 signature of the identity document with all \n characters
      * removed.Base64-encoded HTTP URL used in the signed request. Most likely just
-     * aHR0cHM6Ly9zdHMuYW1hem9uYXdzLmNvbS8= (base64-encoding of https://sts.amazonaws.com/) as most
-     * requests will probably use POST with an empty URI.
+     * aHR0cHM6Ly9zdHMuYW1hem9uYXdzLmNvbS8= (base64-encoding of https://sts.amazonaws.com/) as most requests will
+     * probably use POST with an empty URI.
      * @param iamRequestBody Base64-encoded body of the signed request. Most likely
      * QWN0aW9uPUdldENhbGxlcklkZW50aXR5JlZlcnNpb249MjAxMS0wNi0xNQ== which is the base64 encoding of
      * Action=GetCallerIdentity&Version=2011-06-15.
@@ -987,12 +988,39 @@ public AuthResponse loginByGithub(final String githubToken, final String githubA
     // TODO: Needs integration test coverage if possible
     public AuthResponse loginByJwt(final String provider, final String role, final String jwt)
             throws VaultException {
+
+        return loginByJwt(provider, role, jwt, "auth/" + provider);
+    }
+
+    /**
+     * 

Basic login operation to authenticate to an JWT backend with custom authentication path. Example usage:

+ * + *
+ *
{@code
+     * final AuthResponse response = vault.auth().loginByJwt("kubernetes", "dev", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "custom/path");
+     *
+     * final String token = response.getAuthClientToken();
+     * }
+ *
+ * + * @param provider Provider of JWT token. + * @param role The gcp role used for authentication + * @param jwt The JWT token for the role + * @param authPath The Authentication Path for Vault + * @return The auth token, with additional response metadata + * @throws VaultException If any error occurs, or unexpected response received from Vault + */ + // TODO: Needs integration test coverage if possible + public AuthResponse loginByJwt(final String provider, final String role, final String jwt, + String authPath) + throws VaultException { + return retry(attempt -> { // HTTP request to Vault final String requestJson = Json.object().add("role", role).add("jwt", jwt) .toString(); final RestResponse restResponse = new Rest() - .url(config.getAddress() + "/v1/auth/" + provider + "/login") + .url(config.getAddress() + "/v1/" + authPath + "/login") .header("X-Vault-Namespace", this.nameSpace) .header("X-Vault-Request", "true") .body(requestJson.getBytes(StandardCharsets.UTF_8)) @@ -1042,7 +1070,7 @@ public AuthResponse loginByGCP(final String role, final String jwt) throws Vault /** - * Basic login operation to authenticate to an kubernetes backend. Example usage: + * Basic login operation to authenticate to a kubernetes backend. Example usage: * *
* @@ -1065,6 +1093,31 @@ public AuthResponse loginByKubernetes(final String role, final String jwt) return loginByJwt("kubernetes", role, jwt); } + /** + * Basic login operation to authenticate to a kubernetes backend with custom path. Example usage: + * + *
+ * + *
{@code
+     * final AuthResponse response =
+     *     vault.auth().loginByKubernetes("dev", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "customAuthPath");
+     *
+     * final String token = response.getAuthClientToken();
+     * }
+ *
+ * + * @param role The kubernetes role used for authentication + * @param jwt The JWT token for the role, typically read from + * /var/run/secrets/kubernetes.io/serviceaccount/token + * @param authPath The Authentication Path for Vault + * @return The auth token, with additional response metadata + * @throws VaultException If any error occurs, or unexpected response received from Vault + */ + public AuthResponse loginByKubernetes(final String role, final String jwt, final String authPath) + throws VaultException { + return loginByJwt("kubernetes", role, jwt, authPath); + } + /** *

Basic login operation to authenticate using Vault's TLS Certificate auth backend. * Example usage:

@@ -1079,7 +1132,7 @@ public AuthResponse loginByKubernetes(final String role, final String jwt) * .address("https://127.0.0.1:8200") * .sslConfig(sslConfig) * .build(); - * final Vault vault = new Vault(vaultConfig); + * final Vault vault = Vault.create(vaultConfig); * * final AuthResponse response = vault.auth().loginByCert(); * final String token = response.getAuthClientToken(); @@ -1107,7 +1160,7 @@ public AuthResponse loginByCert() throws VaultException { * .address("https://127.0.0.1:8200") * .sslConfig(sslConfig) * .build(); - * final Vault vault = new Vault(vaultConfig); + * final Vault vault = Vault.create(vaultConfig); * * final AuthResponse response = vault.auth().loginByCert(); * final String token = response.getAuthClientToken(); @@ -1280,118 +1333,31 @@ public LookupResponse lookupSelf(final String tokenAuthMount) throws VaultExcept } /** - *

Returns information about the current client token for a wrapped token, for which the - * lookup endpoint is at "sys/wrapping/lookup". Example usage:

- * - *
- *
{@code
-     * final String wrappingToken = "...";
-     * final VaultConfig config = new VaultConfig().address(...).token(wrappingToken).build();
-     * final Vault vault = new Vault(config);
-     * final LogicalResponse response = vault.auth().lookupWarp();
-     * // Then you can validate "path" for example ...
-     * final String path = response.getData().get("path");
-     * }
- *
- * - * @return The response information returned from Vault - * @throws VaultException If any error occurs, or unexpected response received from Vault + * @see io.github.jopenlibs.vault.api.sys.Wrapping#lookupWrap() + * @deprecated This method is deprecated and in future it will be removed */ public LogicalResponse lookupWrap() throws VaultException { - return lookupWrap(config.getToken(), false); + Sys sys = new Sys(this.config); + return sys.wrapping().lookupWrap(config.getToken(), false); } /** - *

Returns information about the a wrapped token when authorization is needed for lookup, - * for which the lookup endpoint is at "sys/wrapping/lookup". Example usage:

- * - *
- *
{@code
-     * final VaultConfig config = new VaultConfig().address(...).token(authToken).build();
-     * final Vault vault = new Vault(config);
-     * ...
-     * final String wrappingToken = "...";
-     * final LogicalResponse response = vault.auth().lookupWarp(wrappingToken);
-     * // Then you can validate "path" for example ...
-     * final String path = response.getData().get("path");
-     * }
- *
- * - * @param wrappedToken Wrapped token. - * @return The response information returned from Vault - * @throws VaultException If any error occurs, or unexpected response received from Vault + * @see io.github.jopenlibs.vault.api.sys.Wrapping#lookupWrap(String) + * @deprecated This method is deprecated and in future it will be removed */ public LogicalResponse lookupWrap(final String wrappedToken) throws VaultException { - return lookupWrap(wrappedToken, true); + Sys sys = new Sys(this.config); + return sys.wrapping().lookupWrap(wrappedToken, true); } /** - *

Returns information about the a wrapped token, - * for which the lookup endpoint is at "sys/wrapping/lookup". Example usage:

- * - *
- *
{@code
-     * final VaultConfig config = new VaultConfig().address(...).token(authToken).build();
-     * final Vault vault = new Vault(config);
-     * ...
-     * final String wrappingToken = "...";
-     * final LogicalResponse response = vault.auth().lookupWarp(wrappingToken);
-     * // Then you can validate "path" for example ...
-     * final String path = response.getData().get("path");
-     * }
- *
- * - * @param wrappedToken Wrapped token. - * @param inBody When {@code true} the token value placed in the body request: - * {@code {"token": "$wrappedToken"}}, otherwise, set the token into header: - * {@code "X-Vault-Token: $wrappedToken"}. - * @return The response information returned from Vault - * @throws VaultException If any error occurs, or unexpected response received from Vault + * @see io.github.jopenlibs.vault.api.sys.Wrapping#lookupWrap(String, boolean) + * @deprecated This method is deprecated and in future it will be removed */ public LogicalResponse lookupWrap(final String wrappedToken, boolean inBody) throws VaultException { - final String requestJson = - inBody ? Json.object().add("token", wrappedToken).toString() : null; - - return retry(attempt -> { - // HTTP request to Vault - Rest rest = new Rest()//NOPMD - .url(config.getAddress() + "/v1/sys/wrapping/lookup") - .header("X-Vault-Namespace", this.nameSpace) - .header("X-Vault-Request", "true") - .connectTimeoutSeconds(config.getOpenTimeout()) - .readTimeoutSeconds(config.getReadTimeout()) - .sslVerification(config.getSslConfig().isVerify()) - .sslContext(config.getSslConfig().getSslContext()); - - if (inBody) { - rest = rest - .header("X-Vault-Token", config.getToken()) - .body(requestJson.getBytes(StandardCharsets.UTF_8)); - } else { - rest = rest.header("X-Vault-Token", wrappedToken); - } - - final RestResponse restResponse = rest.post(); - - // Validate restResponse - if (restResponse.getStatus() != 200) { - throw new VaultException( - "Vault responded with HTTP status code: " + restResponse.getStatus() + - "\nResponse body: " + new String(restResponse.getBody(), - StandardCharsets.UTF_8), - restResponse.getStatus()); - } - - final String mimeType = restResponse.getMimeType(); - if (!"application/json".equals(mimeType)) { - throw new VaultException("Vault responded with MIME type: " + mimeType, - restResponse.getStatus()); - } - - return new LogicalResponse(restResponse, attempt, - Logical.logicalOperations.authentication); - }); + Sys sys = new Sys(this.config); + return sys.wrapping().lookupWrap(wrappedToken, inBody); } /** @@ -1440,356 +1406,47 @@ public void revokeSelf(final String tokenAuthMount) throws VaultException { } /** - *

Returns the original response inside the wrapped auth token. This method is useful if you - * need to unwrap a token without being authenticated. See {@link #unwrap(String)} if you need - * to do that authenticated.

- * - *

In the example below, you cannot use twice the {@code VaultConfig}, since - * after the first usage of the {@code wrappingToken}, it is not usable anymore. You need to use - * the {@code unwrappedToken} in a new vault configuration to continue. Example usage:

- * - *
- *
{@code
-     * final String wrappingToken = "...";
-     * final VaultConfig config = new VaultConfig().address(...).token(wrappingToken).build();
-     * final Vault vault = new Vault(config);
-     * final AuthResponse response = vault.auth().unwrap();
-     * final String unwrappedToken = response.getAuthClientToken();
-     * }
- *
- * - * @return The response information returned from Vault - * @throws VaultException If any error occurs, or unexpected response received from Vault - * @see #unwrap(String) + * @see io.github.jopenlibs.vault.api.sys.Wrapping#unwrap() + * @deprecated This method is deprecated and in future it will be removed */ public UnwrapResponse unwrap() throws VaultException { - return unwrap(config.getToken(), false); + Sys sys = new Sys(this.config); + return sys.wrapping().unwrap(config.getToken(), false); } /** - *

Provide access to the {@code /sys/wrapping/unwrap} endpoint.

- * - *

Returns the original response inside the given wrapping token. Unlike simply reading - * {@code cubbyhole/response} (which is deprecated), this endpoint provides additional - * validation checks on the token, returns the original value on the wire rather than a JSON - * string representation of it, and ensures that the response is properly audit-logged.

- * - *

This endpoint can be used by using a wrapping token as the client token in the API call, - * in which case the token parameter is not required; or, a different token with permissions to - * access this endpoint can make the call and pass in the wrapping token in the token parameter. - * Do not use the wrapping token in both locations; this will cause the wrapping token to be - * revoked but the value to be unable to be looked up, as it will basically be a double-use of - * the token!

- * - *

In the example below, {@code authToken} is NOT your wrapped token, and should have - * unwrapping permissions. The unwrapped data in {@link UnwrapResponse#getData()}. Example - * usage:

- * - *
- *
{@code
-     * final String authToken = "...";
-     * final String wrappingToken = "...";
-     * final VaultConfig config = new VaultConfig().address(...).token(authToken).build();
-     * final Vault vault = new Vault(config);
-     *
-     * final WrapResponse wrapResponse = vault.auth().wrap(
-     *                 // Data to wrap
-     *                 new JsonObject()
-     *                         .add("foo", "bar")
-     *                         .add("zoo", "zar"),
-     *
-     *                 // TTL of the response-wrapping token
-     *                 60
-     *         );
-     *
-     * final UnwrapResponse unwrapResponse = vault.auth().unwrap(wrapResponse.getToken());
-     * final JsonObject unwrappedData = response.getData(); // original data
-     * }
- *
- * - * @param wrappedToken Specifies the wrapping token ID, do NOT also put this in your - * {@link VaultConfig#getToken()}, if token is {@code null}, this method will unwrap the auth - * token in {@link VaultConfig#getToken()} - * @return The response information returned from Vault - * @throws VaultException If any error occurs, or unexpected response received from Vault - * @see #wrap(JsonObject, int) - * @see #unwrap() + * @see io.github.jopenlibs.vault.api.sys.Wrapping#unwrap(String) + * @deprecated This method is deprecated and in future it will be removed */ public UnwrapResponse unwrap(final String wrappedToken) throws VaultException { - return unwrap(wrappedToken, true); + Sys sys = new Sys(this.config); + return sys.wrapping().unwrap(wrappedToken, true); } /** - *

Provide access to the {@code /sys/wrapping/unwrap} endpoint.

- * - *

Returns the original response inside the given wrapping token. Unlike simply reading - * {@code cubbyhole/response} (which is deprecated), this endpoint provides additional - * validation checks on the token, returns the original value on the wire rather than a JSON - * string representation of it, and ensures that the response is properly audit-logged.

- * - *

This endpoint can be used by using a wrapping token as the client token in the API call, - * in which case the token parameter is not required; or, a different token with permissions to - * access this endpoint can make the call and pass in the wrapping token in the token parameter. - * Do not use the wrapping token in both locations; this will cause the wrapping token to be - * revoked but the value to be unable to be looked up, as it will basically be a double-use of - * the token!

- * - *

In the example below, {@code authToken} is NOT your wrapped token, and should have - * unwrapping permissions. The unwrapped data in {@link UnwrapResponse#getData()}. Example - * usage:

- * - *
- *
{@code
-     * final String authToken = "...";
-     * final String wrappingToken = "...";
-     * final VaultConfig config = new VaultConfig().address(...).token(authToken).build();
-     * final Vault vault = new Vault(config);
-     *
-     * final WrapResponse wrapResponse = vault.auth().wrap(
-     *                 // Data to wrap
-     *                 new JsonObject()
-     *                         .add("foo", "bar")
-     *                         .add("zoo", "zar"),
-     *
-     *                 // TTL of the response-wrapping token
-     *                 60
-     *         );
-     *
-     * final UnwrapResponse unwrapResponse = vault.auth().unwrap(wrapResponse.getToken(), true);
-     * final JsonObject unwrappedData = response.getData(); // original data
-     * }
- *
- * - * @param wrappedToken Specifies the wrapping token ID, do NOT also put this in your - * {@link VaultConfig#getToken()}, if token is {@code null}, this method will unwrap the auth - * token in {@link VaultConfig#getToken()} - * @param inBody When {@code true} the token value placed in the body request: - * {@code {"token": "$wrappedToken"}}, otherwise, set the token into header: - * {@code "X-Vault-Token: $wrappedToken"}. - * @return The response information returned from Vault - * @throws VaultException If any error occurs, or unexpected response received from Vault - * @see #wrap(JsonObject, int) - * @see #unwrap() + * @see io.github.jopenlibs.vault.api.sys.Wrapping#unwrap(String, boolean) + * @deprecated This method is deprecated and in future it will be removed */ public UnwrapResponse unwrap(final String wrappedToken, boolean inBody) throws VaultException { - Objects.requireNonNull(wrappedToken, "Wrapped token is null"); - - return retry(attempt -> { - final String url = config.getAddress() + "/v1/sys/wrapping/unwrap"; - - // HTTP request to Vault - Rest rest = new Rest() - .url(url) - .header("X-Vault-Namespace", this.nameSpace) - .header("X-Vault-Request", "true") - .connectTimeoutSeconds(config.getOpenTimeout()) - .readTimeoutSeconds(config.getReadTimeout()) - .sslVerification(config.getSslConfig().isVerify()) - .sslContext(config.getSslConfig().getSslContext()); - - if (inBody) { - final String requestJson = Json.object().add("token", wrappedToken).toString(); - rest = rest - .header("X-Vault-Token", config.getToken()) - .body(requestJson.getBytes(StandardCharsets.UTF_8)); - } else { - rest = rest - .header("X-Vault-Token", wrappedToken); - } - - RestResponse restResponse = rest.post(); - - // Validate restResponse - if (restResponse.getStatus() != 200) { - throw new VaultException( - "Vault responded with HTTP status code: " + restResponse.getStatus() - + "\nResponse body: " + new String(restResponse.getBody(), - StandardCharsets.UTF_8), - restResponse.getStatus()); - } - - final String mimeType = - restResponse.getMimeType() == null ? "null" : restResponse.getMimeType(); - - if (!mimeType.equals("application/json")) { - throw new VaultException("Vault responded with MIME type: " + mimeType, - restResponse.getStatus()); - } - - return new UnwrapResponse(restResponse, attempt); - }); + Sys sys = new Sys(this.config); + return sys.wrapping().unwrap(wrappedToken, inBody); } /** - *

Provide access to the {@code /sys/wrapping/wrap} endpoint.

- * - *

This provides a powerful mechanism for information sharing in many environments. - * In the types of scenarios, often the best practical option is to provide cover for the secret - * information, be able to detect malfeasance (interception, tampering), and limit lifetime of - * the secret's exposure. Response wrapping performs all three of these duties:

- * - *
    - *
  • It provides cover by ensuring that the value being transmitted across the wire is - * not the actual secret but a reference to such a secret, namely the response-wrapping token. - * Information stored in logs or captured along the way do not directly see the sensitive information. - *
  • - *
  • It provides malfeasance detection by ensuring that only a single party can ever - * unwrap the token and see what's inside. A client receiving a token that cannot be unwrapped - * can trigger an immediate security incident. In addition, a client can inspect - * a given token before unwrapping to ensure that its origin is from the expected - * location in Vault. - *
  • - *
  • It limits the lifetime of secret exposure because the response-wrapping token has - * a lifetime that is separate from the wrapped secret (and often can be much shorter), - * so if a client fails to come up and unwrap the token, the token can expire very quickly. - *
  • - *
- * - *
- *
{@code
-     * final String authToken = "...";
-     * final String wrappingToken = "...";
-     * final VaultConfig config = new VaultConfig().address(...).token(authToken).build();
-     * final Vault vault = new Vault(config);
-     *
-     * final WrapResponse wrapResponse = vault.auth().wrap(
-     *                 // Data to wrap
-     *                 new JsonObject()
-     *                         .add("foo", "bar")
-     *                         .add("zoo", "zar"),
-     *
-     *                 // TTL of the response-wrapping token
-     *                 60
-     *         );
-     *
-     * final UnwrapResponse unwrapResponse = vault.auth().unwrap(wrapResponse.getToken());
-     * final JsonObject unwrappedData = response.getData(); // original data
-     * }
- *
- * - * @param jsonObject User data to wrap. - * @param ttlInSec Wrap TTL in seconds - * @return The response information returned from Vault - * @throws VaultException If any error occurs, or unexpected response received from Vault - * @see #unwrap(String) + * @see io.github.jopenlibs.vault.api.sys.Wrapping#wrap(JsonObject, int) + * @deprecated This method is deprecated and in future it will be removed */ public WrapResponse wrap(final JsonObject jsonObject, int ttlInSec) throws VaultException { - Objects.requireNonNull(jsonObject); - - return retry(attempt -> { - // Parse parameters to JSON - final String requestJson = jsonObject.toString(); - final String url = config.getAddress() + "/v1/sys/wrapping/wrap"; - - // HTTP request to Vault - final RestResponse restResponse = new Rest() - .url(url) - .header("X-Vault-Token", config.getToken()) - .header("X-Vault-Wrap-TTL", Integer.toString(ttlInSec)) - .header("X-Vault-Namespace", this.nameSpace) - .header("X-Vault-Request", "true") - .body(requestJson.getBytes(StandardCharsets.UTF_8)) - .connectTimeoutSeconds(config.getOpenTimeout()) - .readTimeoutSeconds(config.getReadTimeout()) - .sslVerification(config.getSslConfig().isVerify()) - .sslContext(config.getSslConfig().getSslContext()) - .post(); - - // Validate restResponse - if (restResponse.getStatus() != 200) { - throw new VaultException( - "Vault responded with HTTP status code: " + restResponse.getStatus() - + "\nResponse body: " + new String(restResponse.getBody(), - StandardCharsets.UTF_8), - restResponse.getStatus()); - } - - final String mimeType = - restResponse.getMimeType() == null ? "null" : restResponse.getMimeType(); - if (!mimeType.equals("application/json")) { - throw new VaultException("Vault responded with MIME type: " + mimeType, - restResponse.getStatus()); - } - - return new WrapResponse(restResponse, attempt); - }); + Sys sys = new Sys(this.config); + return sys.wrapping().wrap(jsonObject, ttlInSec); } /** - *

Provide access to the {@code /sys/wrapping/rewrap} endpoint. This endpoint rewraps a - * response-wrapped token. The new token will use the same creation TTL as the original token - * and contain the same response. The old token will be invalidated. This can be used for - * long-term storage of a secret in a response-wrapped token when rotation is a - * requirement.

- * - *
- *
{@code
-     * final String authToken = "...";
-     * final String wrappingToken = "...";
-     * final VaultConfig config = new VaultConfig().address(...).token(authToken).build();
-     * final Vault vault = new Vault(config);
-     *
-     * final WrapResponse wrapResponse = vault.auth().wrap(
-     *                 // Data to wrap
-     *                 new JsonObject()
-     *                         .add("foo", "bar")
-     *                         .add("zoo", "zar"),
-     *
-     *                 // TTL of the response-wrapping token
-     *                 60
-     *         );
-     * ...
-     * final WrapResponse wrapResponse2 = vault.auth().rewrap(wrapResponse.getToken());
-     *
-     * final UnwrapResponse unwrapResponse = vault.auth().unwrap(wrapResponse2.getToken());
-     * final JsonObject unwrappedData = response.getData(); // original data
-     * }
- *
- * - * @param wrappedToken Wrapped token ID to re-wrap. - * @return The response information returned from Vault - * @throws VaultException If any error occurs, or unexpected response received from Vault - * @see #wrap(JsonObject, int) + * @see io.github.jopenlibs.vault.api.sys.Wrapping#rewrap(String) + * @deprecated This method is deprecated and in future it will be removed */ public WrapResponse rewrap(final String wrappedToken) throws VaultException { - Objects.requireNonNull(wrappedToken); - - return retry(attempt -> { - // Parse parameters to JSON - final String requestJson = Json.object().add("token", wrappedToken).toString(); - final String url = config.getAddress() + "/v1/sys/wrapping/rewrap"; - - // HTTP request to Vault - final RestResponse restResponse = new Rest() - .url(url) -// .header("X-Vault-Token", wrappedToken) - .header("X-Vault-Token", config.getToken()) - .header("X-Vault-Namespace", this.nameSpace) - .header("X-Vault-Request", "true") - .body(requestJson.getBytes(StandardCharsets.UTF_8)) - .connectTimeoutSeconds(config.getOpenTimeout()) - .readTimeoutSeconds(config.getReadTimeout()) - .sslVerification(config.getSslConfig().isVerify()) - .sslContext(config.getSslConfig().getSslContext()) - .post(); - - // Validate restResponse - if (restResponse.getStatus() != 200) { - throw new VaultException( - "Vault responded with HTTP status code: " + restResponse.getStatus() - + "\nResponse body: " + new String(restResponse.getBody(), - StandardCharsets.UTF_8), - restResponse.getStatus()); - } - - final String mimeType = - restResponse.getMimeType() == null ? "null" : restResponse.getMimeType(); - if (!mimeType.equals("application/json")) { - throw new VaultException("Vault responded with MIME type: " + mimeType, - restResponse.getStatus()); - } - - return new WrapResponse(restResponse, attempt); - }); + Sys sys = new Sys(this.config); + return sys.wrapping().rewrap(wrappedToken); } } diff --git a/src/main/java/io/github/jopenlibs/vault/api/Debug.java b/src/main/java/io/github/jopenlibs/vault/api/Debug.java index 49135db9..ffa8f5a6 100644 --- a/src/main/java/io/github/jopenlibs/vault/api/Debug.java +++ b/src/main/java/io/github/jopenlibs/vault/api/Debug.java @@ -49,7 +49,7 @@ public Debug withNameSpace(final String nameSpace) { *
*
{@code
      * final VaultConfig config = new VaultConfig.address(...).token(...).build();
-     * final Vault vault = new Vault(config);
+     * final Vault vault = Vault.create(config);
      *
      * final HealthResponse response = vault.sys().debug().health();
      *
diff --git a/src/main/java/io/github/jopenlibs/vault/api/database/Database.java b/src/main/java/io/github/jopenlibs/vault/api/database/Database.java
index 074b5302..4c182f68 100644
--- a/src/main/java/io/github/jopenlibs/vault/api/database/Database.java
+++ b/src/main/java/io/github/jopenlibs/vault/api/database/Database.java
@@ -69,7 +69,7 @@ public Database(final VaultConfig config, final String mountPath) {
      * 
*
{@code
      * final VaultConfig config = new VaultConfig.address(...).token(...).build();
-     * final Vault vault = new Vault(config);
+     * final Vault vault = Vault.create(config);
      *
      * final DatabaseRoleOptions options = new DatabaseRoleOptions()
      *                              .dbName("test")
@@ -124,7 +124,7 @@ public DatabaseResponse createOrUpdateRole(final String roleName,
      * 
*
{@code
      * final VaultConfig config = new VaultConfig.address(...).token(...).build();
-     * final Vault vault = new Vault(config);
+     * final Vault vault = Vault.create(config);
      * final DatabaseResponse response = vault.database().getRole("testRole");
      *
      * final RoleOptions details = response.getRoleOptions();
@@ -170,7 +170,7 @@ public DatabaseResponse getRole(final String roleName) throws VaultException {
      * 
*
{@code
      * final VaultConfig config = new VaultConfig.address(...).token(...).build();
-     * final Vault vault = new Vault(config);
+     * final Vault vault = Vault.create(config);
      *
      * final DatabaseResponse response = vault.database().revoke("serialnumber");
      * assertEquals(204, response.getRestResponse().getStatus();
@@ -222,7 +222,7 @@ public DatabaseResponse revoke(final String serialNumber) throws VaultException
      * 
*
{@code
      * final VaultConfig config = new VaultConfig.address(...).token(...).build();
-     * final Vault vault = new Vault(config);
+     * final Vault vault = Vault.create(config);
      *
      * final DatabaseResponse response = vault.database().deleteRole("testRole");
      * assertEquals(204, response.getRestResponse().getStatus();
@@ -269,7 +269,7 @@ public DatabaseResponse deleteRole(final String roleName) throws VaultException
      * 
*
{@code
      * final VaultConfig config = new VaultConfig.address(...).token(...).build();
-     * final Vault vault = new Vault(config);
+     * final Vault vault = Vault.create(config);
      *
      * final DatabaseResponse response = vault.database().creds("testRole");
      * assertEquals(204, response.getRestResponse().getStatus();
diff --git a/src/main/java/io/github/jopenlibs/vault/api/mounts/Mounts.java b/src/main/java/io/github/jopenlibs/vault/api/mounts/Mounts.java
index b9ea0c03..cbc153bf 100644
--- a/src/main/java/io/github/jopenlibs/vault/api/mounts/Mounts.java
+++ b/src/main/java/io/github/jopenlibs/vault/api/mounts/Mounts.java
@@ -1,4 +1,4 @@
-package io.github.jopenlibs.vault.api.mounts;
+package io.github.jopenlibs.vault.api.sys.mounts;
 
 import io.github.jopenlibs.vault.VaultConfig;
 import io.github.jopenlibs.vault.VaultException;
@@ -34,7 +34,7 @@ public Mounts(final VaultConfig config) {
      * 
*
{@code
      * final VaultConfig config = new VaultConfig.address(...).token(...).build();
-     * final Vault vault = new Vault(config);
+     * final Vault vault = Vault.create(config);
      *
      * final MountResponse response = vault.mounts().list();
      * final Map mounts = response.getMounts();
@@ -83,7 +83,7 @@ public MountResponse list() throws VaultException {
      * 
*
{@code
      * final VaultConfig config = new VaultConfig.address(...).token(...).build();
-     * final Vault vault = new Vault(config);
+     * final Vault vault = Vault.create(config);
      *
      * final MountPayload payload = new MountPayload()
      *                                       .defaultLeaseTtl(TimeToLive.of(86400, TimeUnit.SECONDS))
@@ -150,7 +150,7 @@ public MountResponse enable(final String path, final MountType type, final Mount
      * 
*
{@code
      * final VaultConfig config = new VaultConfig.address(...).token(...).build();
-     * final Vault vault = new Vault(config);
+     * final Vault vault = Vault.create(config);
      *
      * final MountResponse response = vault.mounts().disable("pki/mount/point/path");
      *
@@ -198,7 +198,7 @@ public MountResponse disable(final String path) throws VaultException {
      * 
*
{@code
      * final VaultConfig config = new VaultConfig.address(...).token(...).build();
-     * final Vault vault = new Vault(config);
+     * final Vault vault = Vault.create(config);
      *
      * final MountResponse response = vault.mounts().read("pki/mount/point/path");
      * final Mount mount = response.getMount();
@@ -249,7 +249,7 @@ public MountResponse read(final String path) throws VaultException {
      * 
*
{@code
      * final VaultConfig config = new VaultConfig.address(...).token(...).build();
-     * final Vault vault = new Vault(config);
+     * final Vault vault = Vault.create(config);
      *
      * final MountPayload payload = new MountPayload()
      *                                   .defaultLeaseTtl(TimeToLive.of(12, TimeUnit.HOURS))
diff --git a/src/main/java/io/github/jopenlibs/vault/api/pki/Pki.java b/src/main/java/io/github/jopenlibs/vault/api/pki/Pki.java
index a8e8dc43..24b288ed 100644
--- a/src/main/java/io/github/jopenlibs/vault/api/pki/Pki.java
+++ b/src/main/java/io/github/jopenlibs/vault/api/pki/Pki.java
@@ -69,7 +69,7 @@ public Pki(final VaultConfig config, final String mountPath) {
      * 
*
{@code
      * final VaultConfig config = new VaultConfig.address(...).token(...).build();
-     * final Vault vault = new Vault(config);
+     * final Vault vault = Vault.create(config);
      * final PkiResponse response = vault.pki().createOrUpdateRole("testRole");
      *
      * assertEquals(204, response.getRestResponse().getStatus());
@@ -94,7 +94,7 @@ public PkiResponse createOrUpdateRole(final String roleName) throws VaultExcepti
      * 
*
{@code
      * final VaultConfig config = new VaultConfig.address(...).token(...).build();
-     * final Vault vault = new Vault(config);
+     * final Vault vault = Vault.create(config);
      *
      * final RoleOptions options = new RoleOptions()
      *                              .allowedDomains(new ArrayList(){{ add("myvault.com"); }})
@@ -152,7 +152,7 @@ public PkiResponse createOrUpdateRole(final String roleName, final RoleOptions o
      * 
*
{@code
      * final VaultConfig config = new VaultConfig.address(...).token(...).build();
-     * final Vault vault = new Vault(config);
+     * final Vault vault = Vault.create(config);
      * final PkiResponse response = vault.pki().getRole("testRole");
      *
      * final RoleOptions details = response.getRoleOptions();
@@ -198,7 +198,7 @@ public PkiResponse getRole(final String roleName) throws VaultException {
      * 
*
{@code
      * final VaultConfig config = new VaultConfig.address(...).token(...).build();
-     * final Vault vault = new Vault(config);
+     * final Vault vault = Vault.create(config);
      *
      * final PkiResponse response = vault.pki().revoke("serialnumber");
      * assertEquals(204, response.getRestResponse().getStatus();
@@ -249,7 +249,7 @@ public PkiResponse revoke(final String serialNumber) throws VaultException {
      * 
*
{@code
      * final VaultConfig config = new VaultConfig.address(...).token(...).build();
-     * final Vault vault = new Vault(config);
+     * final Vault vault = Vault.create(config);
      *
      * final PkiResponse response = vault.pki().deleteRole("testRole");
      * assertEquals(204, response.getRestResponse().getStatus();
@@ -297,7 +297,7 @@ public PkiResponse deleteRole(final String roleName) throws VaultException {
      * 
*
{@code
      * final VaultConfig config = new VaultConfig.address(...).token(...).build();
-     * final Vault vault = new Vault(config);
+     * final Vault vault = Vault.create(config);
      *
      * final PkiResponse response = vault.pki().deleteRole("testRole");
      * assertEquals(204, response.getRestResponse().getStatus();
@@ -347,7 +347,7 @@ public PkiResponse issue(
      * 
*
{@code
      * final VaultConfig config = new VaultConfig.address(...).token(...).build();
-     * final Vault vault = new Vault(config);
+     * final Vault vault = Vault.create(config);
      *
      * final PkiResponse response = vault.pki().deleteRole("testRole");
      * assertEquals(204, response.getRestResponse().getStatus();
diff --git a/src/test-integration/java/io/github/jopenlibs/vault/util/VaultAgentContainer.java b/src/test-integration/java/io/github/jopenlibs/vault/util/VaultAgentContainer.java
index 8935f795..fc6486a3 100644
--- a/src/test-integration/java/io/github/jopenlibs/vault/util/VaultAgentContainer.java
+++ b/src/test-integration/java/io/github/jopenlibs/vault/util/VaultAgentContainer.java
@@ -56,7 +56,7 @@ public Vault getVault() throws VaultException {
                         .openTimeout(5)
                         .readTimeout(30)
                         .build();
-        return new Vault(config);
+        return Vault.create(config);
     }
 
     /**
diff --git a/src/test-integration/java/io/github/jopenlibs/vault/util/VaultContainer.java b/src/test-integration/java/io/github/jopenlibs/vault/util/VaultContainer.java
index b67fe147..de63fcec 100644
--- a/src/test-integration/java/io/github/jopenlibs/vault/util/VaultContainer.java
+++ b/src/test-integration/java/io/github/jopenlibs/vault/util/VaultContainer.java
@@ -302,7 +302,7 @@ public void setEngineVersions() throws IOException, InterruptedException {
      */
     public Vault getVault(final VaultConfig config, final Integer maxRetries,
             final Integer retryMillis) {
-        Vault vault = new Vault(config);
+        Vault vault = Vault.create(config);
         if (maxRetries != null && retryMillis != null) {
             vault = vault.withRetries(maxRetries, retryMillis);
         } else if (maxRetries != null) {
@@ -353,7 +353,7 @@ public Vault getVault(final String token) throws VaultException {
                         .readTimeout(30)
                         .sslConfig(new SslConfig().pemFile(new File(CERT_PEMFILE)).build())
                         .build();
-        return new Vault(config).withRetries(MAX_RETRIES, RETRY_MILLIS);
+        return Vault.create(config).withRetries(MAX_RETRIES, RETRY_MILLIS);
     }
 
     /**
@@ -368,7 +368,7 @@ public Vault getRootVaultWithCustomVaultConfig(VaultConfig vaultConfig) throws V
                         .readTimeout(30)
                         .sslConfig(new SslConfig().pemFile(new File(CERT_PEMFILE)).build())
                         .build();
-        return new Vault(config).withRetries(MAX_RETRIES, RETRY_MILLIS);
+        return Vault.create(config).withRetries(MAX_RETRIES, RETRY_MILLIS);
     }
 
     /**
diff --git a/src/test/java/io/github/jopenlibs/vault/RetryTests.java b/src/test/java/io/github/jopenlibs/vault/RetryTests.java
index 968a5555..d1f88d40 100644
--- a/src/test/java/io/github/jopenlibs/vault/RetryTests.java
+++ b/src/test/java/io/github/jopenlibs/vault/RetryTests.java
@@ -24,7 +24,7 @@ public void testRetries_Read() throws Exception {
 
         final VaultConfig vaultConfig = new VaultConfig().address("http://127.0.0.1:8999")
                 .token("mock_token").engineVersion(1).build();
-        final Vault vault = new Vault(vaultConfig);
+        final Vault vault = Vault.create(vaultConfig);
         final LogicalResponse response = vault.withRetries(5, 100).logical().read("secret/hello");
         assertEquals(5, response.getRetries());
         assertEquals("mock", response.getData().get("value"));
@@ -43,7 +43,7 @@ public void testRetries_Write() throws Exception {
 
         final VaultConfig vaultConfig = new VaultConfig().address("http://127.0.0.1:8999")
                 .token("mock_token").build();
-        final Vault vault = new Vault(vaultConfig);
+        final Vault vault = Vault.create(vaultConfig);
         final LogicalResponse response = vault.withRetries(5, 100).logical()
                 .write("secret/hello", new HashMap() {{
                     put("value", "world");
diff --git a/src/test/java/io/github/jopenlibs/vault/SSLTests.java b/src/test/java/io/github/jopenlibs/vault/SSLTests.java
index 9190b227..e87fba52 100644
--- a/src/test/java/io/github/jopenlibs/vault/SSLTests.java
+++ b/src/test/java/io/github/jopenlibs/vault/SSLTests.java
@@ -33,7 +33,7 @@ public void testSslVerify_Enabled_Get() throws Exception {
                 .sslConfig(new SslConfig().verify(false))
                 .engineVersion(1)
                 .build();
-        final Vault vault = new Vault(vaultConfig);
+        final Vault vault = Vault.create(vaultConfig);
         final LogicalResponse response = vault.logical().read("secret/hello");
 
         assertEquals(200, response.getRestResponse().getStatus());
@@ -52,7 +52,7 @@ public void testSslVerify_Disabled_Get() throws Exception {
                 .address("https://127.0.0.1:9998")
                 .token("mock_token")
                 .build();
-        final Vault vault = new Vault(vaultConfig);
+        final Vault vault = Vault.create(vaultConfig);
 
         try {
             final LogicalResponse response = vault.logical().read("secret/hello");
@@ -73,7 +73,7 @@ public void testSslVerify_Enabled_Post() throws Exception {
                 .sslConfig(new SslConfig().pemResource("/cert.pem").build())
                 .token("mock_token")
                 .build();
-        final Vault vault = new Vault(vaultConfig);
+        final Vault vault = Vault.create(vaultConfig);
         HashMap testMap = new HashMap<>();
         testMap.put("value", "world");
         final LogicalResponse response = vault.logical().write("secret/hello", testMap);
@@ -90,7 +90,7 @@ public void testSslVerify_Disabled_Post() throws Exception {
 
         final VaultConfig vaultConfig = new VaultConfig().address("https://127.0.0.1:9998")
                 .token("mock_token").build();
-        final Vault vault = new Vault(vaultConfig);
+        final Vault vault = Vault.create(vaultConfig);
 
         try {
             final LogicalResponse response = vault.logical().read("secret/hello");
@@ -122,7 +122,7 @@ public void testSslPem_File() throws Exception {
                 .token("mock_token")
                 .sslConfig(new SslConfig().pemFile(pem).build())
                 .build();
-        final Vault vault = new Vault(vaultConfig);
+        final Vault vault = Vault.create(vaultConfig);
         final LogicalResponse response = vault.logical().read("secret/hello");
 
         VaultTestUtils.shutdownMockVault(server);
@@ -139,7 +139,7 @@ public void testSslPem_Resource_Get() throws Exception {
                 .token("mock_token")
                 .sslConfig(new SslConfig().pemResource("/cert.pem").build())
                 .build();
-        final Vault vault = new Vault(vaultConfig);
+        final Vault vault = Vault.create(vaultConfig);
         final LogicalResponse response = vault.logical().read("secret/hello");
 
         VaultTestUtils.shutdownMockVault(server);
@@ -156,7 +156,7 @@ public void testSslPem_Resource_Post() throws Exception {
                 .token("mock_token")
                 .sslConfig(new SslConfig().pemResource("/cert.pem").build())
                 .build();
-        final Vault vault = new Vault(vaultConfig);
+        final Vault vault = Vault.create(vaultConfig);
         HashMap testMap = new HashMap<>();
         testMap.put("value", "world");
         final LogicalResponse response = vault.logical()
@@ -187,7 +187,7 @@ public void testSslPem_UTF8() throws Exception {
                 .token("mock_token")
                 .sslConfig(new SslConfig().pemUTF8(pemUTF8).build())
                 .build();
-        final Vault vault = new Vault(vaultConfig);
+        final Vault vault = Vault.create(vaultConfig);
         final LogicalResponse response = vault.logical().read("secret/hello");
 
         VaultTestUtils.shutdownMockVault(server);
@@ -204,7 +204,7 @@ public void testSslJks_loadTrustStoreFromClasspath() throws Exception {
                 .token("mock_token")
                 .sslConfig(new SslConfig().trustStoreResource("/keystore.jks").build())
                 .build();
-        final Vault vault = new Vault(vaultConfig);
+        final Vault vault = Vault.create(vaultConfig);
         final LogicalResponse response = vault.logical().read("secret/hello");
 
         VaultTestUtils.shutdownMockVault(server);
@@ -235,7 +235,7 @@ public void testSslJks_loadTrustStoreFromFile() throws Exception {
                 .token("mock_token")
                 .sslConfig(new SslConfig().trustStoreFile(jks).build())
                 .build();
-        final Vault vault = new Vault(vaultConfig);
+        final Vault vault = Vault.create(vaultConfig);
         final LogicalResponse response = vault.logical().read("secret/hello");
 
         VaultTestUtils.shutdownMockVault(server);
@@ -256,7 +256,7 @@ public void testSslJks_loadTrustStoreFromMemory() throws Exception {
                 .token("mock_token")
                 .sslConfig(new SslConfig().trustStore(trustStore).build())
                 .build();
-        final Vault vault = new Vault(vaultConfig);
+        final Vault vault = Vault.create(vaultConfig);
         final LogicalResponse response = vault.logical().read("secret/hello");
 
         VaultTestUtils.shutdownMockVault(server);
@@ -274,7 +274,7 @@ public void testSslJks_loadKeyStoreAndTrustStore() throws Exception {
                 .sslConfig(new SslConfig().trustStoreResource("/keystore.jks").keyStoreResource(
                         "/keystore.jks", "password").build())
                 .build();
-        final Vault vault = new Vault(vaultConfig);
+        final Vault vault = Vault.create(vaultConfig);
         final LogicalResponse response = vault.logical().read("secret/hello");
 
         VaultTestUtils.shutdownMockVault(server);
diff --git a/src/test/java/io/github/jopenlibs/vault/TimeoutTests.java b/src/test/java/io/github/jopenlibs/vault/TimeoutTests.java
index e3a46af1..e001ea24 100644
--- a/src/test/java/io/github/jopenlibs/vault/TimeoutTests.java
+++ b/src/test/java/io/github/jopenlibs/vault/TimeoutTests.java
@@ -27,7 +27,7 @@ public void testOpenTimeout_WithinThreshold() throws Exception {
                 .token("mock_token")
                 .openTimeout(3)
                 .build();
-        final Vault vault = new Vault(vaultConfig);
+        final Vault vault = Vault.create(vaultConfig);
 
         // The Vault call should succeed
         final LogicalResponse response = vault.logical().read("secret/hello");
@@ -49,7 +49,7 @@ public void testOpenTimeout_BeyondThreshold() throws Exception {
                 .token("mock_token")
                 .openTimeout(1)
                 .build();
-        final Vault vault = new Vault(vaultConfig);
+        final Vault vault = Vault.create(vaultConfig);
 
         // The Vault call should time out
         try {
@@ -74,7 +74,7 @@ public void testReadTimeout_WithinThreshold() throws Exception {
                 .token("mock_token")
                 .readTimeout(3)
                 .build();
-        final Vault vault = new Vault(vaultConfig);
+        final Vault vault = Vault.create(vaultConfig);
 
         // The Vault call should succeed
         final LogicalResponse response = vault.logical().read("secret/hello");
@@ -96,7 +96,7 @@ public void testReadTimeout_BeyondThreshold() throws Exception {
                 .token("mock_token")
                 .readTimeout(1)
                 .build();
-        final Vault vault = new Vault(vaultConfig);
+        final Vault vault = Vault.create(vaultConfig);
 
         // The Vault call should time out
         try {
diff --git a/src/test/java/io/github/jopenlibs/vault/VaultTests.java b/src/test/java/io/github/jopenlibs/vault/VaultTests.java
index 622539f0..65163da6 100644
--- a/src/test/java/io/github/jopenlibs/vault/VaultTests.java
+++ b/src/test/java/io/github/jopenlibs/vault/VaultTests.java
@@ -18,7 +18,7 @@ public class VaultTests {
     @Test
     public void testDefaultVaultConstructor() {
         VaultConfig vaultConfig = new VaultConfig();
-        Vault vault = new Vault(vaultConfig);
+        Vault vault = Vault.create(vaultConfig);
         Assert.assertNotNull(vault);
         Assert.assertEquals(String.valueOf(2),
                 vault.logical().getEngineVersionForSecretPath("*").toString());
@@ -27,7 +27,7 @@ public void testDefaultVaultConstructor() {
     @Test
     public void testGlobalEngineVersionVaultConstructor() {
         VaultConfig vaultConfig = new VaultConfig();
-        Vault vault = new Vault(vaultConfig, 1);
+        Vault vault = Vault.create(vaultConfig, 1);
         Assert.assertNotNull(vault);
         Assert.assertEquals(String.valueOf(1),
                 vault.logical().getEngineVersionForSecretPath("*").toString());
@@ -36,7 +36,7 @@ public void testGlobalEngineVersionVaultConstructor() {
     @Test
     public void testNameSpaceProvidedVaultConstructor() throws VaultException {
         VaultConfig vaultConfig = new VaultConfig().nameSpace("testNameSpace");
-        Vault vault = new Vault(vaultConfig, 1);
+        Vault vault = Vault.create(vaultConfig, 1);
         Assert.assertNotNull(vault);
     }
 
@@ -52,14 +52,14 @@ public void testNameSpaceProvidedVaultConstructorCannotBeEmpty() {
     @Test(expected = IllegalArgumentException.class)
     public void testInvalidGlobalEngineVersionVaultConstructor() {
         VaultConfig vaultConfig = new VaultConfig();
-        Vault vault = new Vault(vaultConfig, 3);
+        Vault vault = Vault.create(vaultConfig, 3);
         Assert.assertNull(vault);
     }
 
     @Test(expected = VaultException.class)
     public void testVaultWithNoKVEnginePathMap() throws VaultException {
         VaultConfig vaultConfig = new VaultConfig();
-        Vault vault = new Vault(vaultConfig, true, 1);
+        Vault vault = Vault.create(vaultConfig, true, 1);
         Assert.assertNull(vault);
     }
 
@@ -67,7 +67,7 @@ public void testVaultWithNoKVEnginePathMap() throws VaultException {
     public void testVaultWithEmptyKVEnginePathMap() throws VaultException {
         Map emptyEngineKVMap = new HashMap<>();
         VaultConfig vaultConfig = new VaultConfig().secretsEnginePathMap(emptyEngineKVMap);
-        Vault vault = new Vault(vaultConfig, true, 1);
+        Vault vault = Vault.create(vaultConfig, true, 1);
         Assert.assertNull(vault);
     }
 
@@ -76,7 +76,7 @@ public void testVaultWithoutKVEnginePathMap() throws VaultException {
         Map engineKVMap = new HashMap<>();
         engineKVMap.put("/hello", "2");
         VaultConfig vaultConfig = new VaultConfig().secretsEnginePathMap(engineKVMap);
-        Vault vault = new Vault(vaultConfig, false, 1);
+        Vault vault = Vault.create(vaultConfig, false, 1);
         Assert.assertNotNull(vault);
         Assert.assertEquals(String.valueOf(1),
                 vault.logical().getEngineVersionForSecretPath("/hello").toString());
@@ -90,7 +90,7 @@ public void kvEngineMapIsHonored() throws VaultException {
         testMap.put("kv-v1/", "1");
         VaultConfig vaultConfig = new VaultConfig().secretsEnginePathMap(testMap);
         Assert.assertNotNull(vaultConfig);
-        Vault vault = new Vault(vaultConfig, true, 2);
+        Vault vault = Vault.create(vaultConfig, true, 2);
         Assert.assertNotNull(vault);
         Assert.assertEquals(String.valueOf(1),
                 vault.logical().getEngineVersionForSecretPath("kv-v1").toString());
@@ -109,7 +109,7 @@ public void testConfigBuiler_WithInvalidRequestAsNonError() throws Exception {
                 .address("http://127.0.0.1:8999")
                 .token("mock_token")
                 .build();
-        final Vault vault = new Vault(vaultConfig);
+        final Vault vault = Vault.create(vaultConfig);
 
         LogicalResponse response = vault.logical().read("path/that/does/not/exist/");
         VaultTestUtils.shutdownMockVault(server);
diff --git a/src/test/java/io/github/jopenlibs/vault/vault/api/AuthBackendAwsTests.java b/src/test/java/io/github/jopenlibs/vault/vault/api/AuthBackendAwsTests.java
index 419cc54a..583e1f6a 100644
--- a/src/test/java/io/github/jopenlibs/vault/vault/api/AuthBackendAwsTests.java
+++ b/src/test/java/io/github/jopenlibs/vault/vault/api/AuthBackendAwsTests.java
@@ -3,6 +3,7 @@
 import io.github.jopenlibs.vault.Vault;
 import io.github.jopenlibs.vault.VaultConfig;
 import io.github.jopenlibs.vault.VaultException;
+import io.github.jopenlibs.vault.VaultImpl;
 import io.github.jopenlibs.vault.json.JsonObject;
 import io.github.jopenlibs.vault.response.AuthResponse;
 import io.github.jopenlibs.vault.vault.VaultTestUtils;
@@ -38,7 +39,7 @@ public void testLoginByAwsEc2Id() throws Exception {
         final VaultConfig vaultConfig = new VaultConfig()
                 .address("http://127.0.0.1:8999")
                 .build();
-        final Vault vault = new Vault(vaultConfig);
+        final Vault vault = Vault.create(vaultConfig);
 
         String token = null;
         String nonce = null;
@@ -80,7 +81,7 @@ public void testLoginByAwsEc2Pkcs7() throws Exception {
         final VaultConfig vaultConfig = new VaultConfig()
                 .address("http://127.0.0.1:8999")
                 .build();
-        final Vault vault = new Vault(vaultConfig);
+        final Vault vault = Vault.create(vaultConfig);
 
         System.out.println("Running Aws EC2 test");
 
@@ -121,7 +122,7 @@ public void testLoginByAwsIam() throws Exception {
         final VaultConfig vaultConfig = new VaultConfig()
                 .address("http://127.0.0.1:8999")
                 .build();
-        final Vault vault = new Vault(vaultConfig);
+        final Vault vault = Vault.create(vaultConfig);
 
         AuthResponse response = vault.auth()
                 .loginByAwsIam("role", "url", "body", "headers",
diff --git a/src/test/java/io/github/jopenlibs/vault/vault/api/AuthLookupTest.java b/src/test/java/io/github/jopenlibs/vault/vault/api/AuthLookupTest.java
index db84f92b..edfe08c0 100644
--- a/src/test/java/io/github/jopenlibs/vault/vault/api/AuthLookupTest.java
+++ b/src/test/java/io/github/jopenlibs/vault/vault/api/AuthLookupTest.java
@@ -2,6 +2,7 @@
 
 import io.github.jopenlibs.vault.Vault;
 import io.github.jopenlibs.vault.VaultConfig;
+import io.github.jopenlibs.vault.VaultImpl;
 import io.github.jopenlibs.vault.json.JsonArray;
 import io.github.jopenlibs.vault.json.JsonObject;
 import io.github.jopenlibs.vault.response.LookupResponse;
@@ -41,7 +42,7 @@ public void after() throws Exception {
     public void should_lookup_self_use_url_auth_token_lookup_self() throws Exception {
         VaultConfig vaultConfig = new VaultConfig().address("http://127.0.0.1:8999").token("token")
                 .build();
-        Vault vault = new Vault(vaultConfig);
+        Vault vault = Vault.create(vaultConfig);
         LookupResponse response = vault.auth().lookupSelf();
 
         assertEquals(200, response.getRestResponse().getStatus());
@@ -60,7 +61,7 @@ public void should_lookup_self_use_url_auth_token_lookup_self() throws Exception
     public void should_lookup_self_with_param_use_url_auth_mount_lookup_self() throws Exception {
         VaultConfig vaultConfig = new VaultConfig().address("http://127.0.0.1:8999").token("token")
                 .build();
-        Vault vault = new Vault(vaultConfig);
+        Vault vault = Vault.create(vaultConfig);
         LookupResponse response = vault.auth().lookupSelf("mount");
 
         assertEquals(200, response.getRestResponse().getStatus());
diff --git a/src/test/java/io/github/jopenlibs/vault/vault/api/AuthLookupWrapTest.java b/src/test/java/io/github/jopenlibs/vault/vault/api/AuthLookupWrapTest.java
index a8aca43d..e450372d 100644
--- a/src/test/java/io/github/jopenlibs/vault/vault/api/AuthLookupWrapTest.java
+++ b/src/test/java/io/github/jopenlibs/vault/vault/api/AuthLookupWrapTest.java
@@ -2,6 +2,7 @@
 
 import io.github.jopenlibs.vault.Vault;
 import io.github.jopenlibs.vault.VaultConfig;
+import io.github.jopenlibs.vault.VaultImpl;
 import io.github.jopenlibs.vault.json.JsonObject;
 import io.github.jopenlibs.vault.response.LogicalResponse;
 import io.github.jopenlibs.vault.vault.VaultTestUtils;
@@ -39,7 +40,7 @@ public void after() throws Exception {
     public void should_lookup_wrap_use_url_sys_wrapping_lookup() throws Exception {
         VaultConfig vaultConfig = new VaultConfig().address("http://127.0.0.1:8999")
                 .token("wrapped").build();
-        Vault vault = new Vault(vaultConfig);
+        Vault vault = Vault.create(vaultConfig);
         LogicalResponse response = vault.auth().lookupWrap();
 
         assertEquals(200, response.getRestResponse().getStatus());
diff --git a/src/test/java/io/github/jopenlibs/vault/vault/api/AuthUnwrapTest.java b/src/test/java/io/github/jopenlibs/vault/vault/api/AuthUnwrapTest.java
index 326192f9..62cd1a18 100644
--- a/src/test/java/io/github/jopenlibs/vault/vault/api/AuthUnwrapTest.java
+++ b/src/test/java/io/github/jopenlibs/vault/vault/api/AuthUnwrapTest.java
@@ -2,6 +2,7 @@
 
 import io.github.jopenlibs.vault.Vault;
 import io.github.jopenlibs.vault.VaultConfig;
+import io.github.jopenlibs.vault.VaultImpl;
 import io.github.jopenlibs.vault.json.JsonArray;
 import io.github.jopenlibs.vault.json.JsonObject;
 import io.github.jopenlibs.vault.response.AuthResponse;
@@ -43,7 +44,7 @@ public void should_unwrap_without_param_sends_no_token_and_return_unwrapped_toke
             throws Exception {
         VaultConfig vaultConfig = new VaultConfig().address("http://127.0.0.1:8999")
                 .token("wrappedToken").build();
-        Vault vault = new Vault(vaultConfig);
+        Vault vault = Vault.create(vaultConfig);
         AuthResponse response = vault.auth().unwrap();
 
         assertEquals(200, response.getRestResponse().getStatus());
@@ -60,7 +61,7 @@ public void should_unwrap_without_param_sends_no_token_and_return_unwrapped_toke
     public void should_unwrap_param_sends_token_and_return_unwrapped_token() throws Exception {
         VaultConfig vaultConfig = new VaultConfig().address("http://127.0.0.1:8999")
                 .token("authToken").build();
-        Vault vault = new Vault(vaultConfig);
+        Vault vault = Vault.create(vaultConfig);
         AuthResponse response = vault.auth().unwrap("wrappedToken");
 
         assertEquals(200, response.getRestResponse().getStatus());
diff --git a/src/test/java/io/github/jopenlibs/vault/vault/api/AuthUnwrapWithoutAuthResponseTest.java b/src/test/java/io/github/jopenlibs/vault/vault/api/AuthUnwrapWithoutAuthResponseTest.java
index f6eeec19..f87a03b8 100644
--- a/src/test/java/io/github/jopenlibs/vault/vault/api/AuthUnwrapWithoutAuthResponseTest.java
+++ b/src/test/java/io/github/jopenlibs/vault/vault/api/AuthUnwrapWithoutAuthResponseTest.java
@@ -2,6 +2,7 @@
 
 import io.github.jopenlibs.vault.Vault;
 import io.github.jopenlibs.vault.VaultConfig;
+import io.github.jopenlibs.vault.VaultImpl;
 import io.github.jopenlibs.vault.json.Json;
 import io.github.jopenlibs.vault.json.JsonObject;
 import io.github.jopenlibs.vault.response.UnwrapResponse;
@@ -37,7 +38,7 @@ public void unwrap_response_without_auth() throws Exception {
 
         VaultConfig vaultConfig = new VaultConfig().address("http://127.0.0.1:8999")
                 .token("wrappedToken").build();
-        Vault vault = new Vault(vaultConfig);
+        Vault vault = Vault.create(vaultConfig);
         UnwrapResponse response = vault.auth().unwrap("wrappedToken");
 
         assertEquals(200, response.getRestResponse().getStatus());
@@ -63,7 +64,7 @@ public void unwrap_response_without_implicit_null_auth() throws Exception {
 
         VaultConfig vaultConfig = new VaultConfig().address("http://127.0.0.1:8999")
                 .token("wrappedToken").build();
-        Vault vault = new Vault(vaultConfig);
+        Vault vault = Vault.create(vaultConfig);
         UnwrapResponse response = vault.auth().unwrap("wrappedToken");
 
         assertEquals(200, response.getRestResponse().getStatus());
diff --git a/src/test/java/io/github/jopenlibs/vault/vault/api/AuthWrapTest.java b/src/test/java/io/github/jopenlibs/vault/vault/api/AuthWrapTest.java
index 0163c23a..821e7836 100644
--- a/src/test/java/io/github/jopenlibs/vault/vault/api/AuthWrapTest.java
+++ b/src/test/java/io/github/jopenlibs/vault/vault/api/AuthWrapTest.java
@@ -2,6 +2,7 @@
 
 import io.github.jopenlibs.vault.Vault;
 import io.github.jopenlibs.vault.VaultConfig;
+import io.github.jopenlibs.vault.VaultImpl;
 import io.github.jopenlibs.vault.json.JsonObject;
 import io.github.jopenlibs.vault.response.WrapResponse;
 import io.github.jopenlibs.vault.vault.VaultTestUtils;
@@ -43,7 +44,7 @@ public void after() throws Exception {
     public void check_wrap_request_response() throws Exception {
         VaultConfig vaultConfig = new VaultConfig().address("http://127.0.0.1:8999")
                 .token("wrappedToken").build();
-        Vault vault = new Vault(vaultConfig);
+        Vault vault = Vault.create(vaultConfig);
 
         WrapResponse response = vault.auth().wrap(
                 new JsonObject()
diff --git a/src/test/java/io/github/jopenlibs/vault/vault/api/TransitApiTest.java b/src/test/java/io/github/jopenlibs/vault/vault/api/TransitApiTest.java
index 502421f7..03eaedba 100644
--- a/src/test/java/io/github/jopenlibs/vault/vault/api/TransitApiTest.java
+++ b/src/test/java/io/github/jopenlibs/vault/vault/api/TransitApiTest.java
@@ -2,6 +2,7 @@
 
 import io.github.jopenlibs.vault.Vault;
 import io.github.jopenlibs.vault.VaultConfig;
+import io.github.jopenlibs.vault.VaultImpl;
 import io.github.jopenlibs.vault.json.JsonArray;
 import io.github.jopenlibs.vault.json.JsonObject;
 import io.github.jopenlibs.vault.response.LogicalResponse;
@@ -52,7 +53,7 @@ public void testTransitEncrypt() throws Exception {
         final VaultConfig vaultConfig = new VaultConfig()
                 .address("http://127.0.0.1:8999")
                 .build();
-        final Vault vault = new Vault(vaultConfig, 1);
+        final Vault vault = Vault.create(vaultConfig, 1);
 
         LogicalResponse response = vault.logical().write("transit/encrypt/test",
                 Collections.singletonMap("plaintext", PLAIN_DATA[0]));
@@ -75,7 +76,7 @@ public void testTransitDecrypt() throws Exception {
         final VaultConfig vaultConfig = new VaultConfig()
                 .address("http://127.0.0.1:8999")
                 .build();
-        final Vault vault = new Vault(vaultConfig, 1);
+        final Vault vault = Vault.create(vaultConfig, 1);
 
         LogicalResponse response = vault.logical().write("transit/decrypt/test",
                 Collections.singletonMap("ciphertext", CIPHER_DATA[0]));
@@ -106,7 +107,7 @@ public void testBulkTransitEncrypt() throws Exception {
         final VaultConfig vaultConfig = new VaultConfig()
                 .address("http://127.0.0.1:8999")
                 .build();
-        final Vault vault = new Vault(vaultConfig, 1);
+        final Vault vault = Vault.create(vaultConfig, 1);
 
         JsonArray batch = new JsonArray();
         for (String text : PLAIN_DATA) {
@@ -141,7 +142,7 @@ public void testBulkTransitDecrypt() throws Exception {
         final VaultConfig vaultConfig = new VaultConfig()
                 .address("http://127.0.0.1:8999")
                 .build();
-        final Vault vault = new Vault(vaultConfig, 1);
+        final Vault vault = Vault.create(vaultConfig, 1);
 
         JsonArray batch = new JsonArray();
         for (String text : CIPHER_DATA) {
diff --git a/src/test/java/io/github/jopenlibs/vault/vault/mock/MockVault.java b/src/test/java/io/github/jopenlibs/vault/vault/mock/MockVault.java
index fd69ac9c..f7766cd7 100644
--- a/src/test/java/io/github/jopenlibs/vault/vault/mock/MockVault.java
+++ b/src/test/java/io/github/jopenlibs/vault/vault/mock/MockVault.java
@@ -29,7 +29,7 @@
  * server.start();
  *
  * final VaultConfig vaultConfig = new VaultConfig().address("http://127.0.0.1:8999").token("mock_token").build();
- * final Vault vault = new Vault(vaultConfig);
+ * final Vault vault = Vault.create(vaultConfig);
  * final LogicalResponse response = vault.logical().read("secret/hello");
  *
  * assertEquals(200, response.getRestResponse().getStatus());
diff --git a/src/test/java/io/github/jopenlibs/vault/vault/mock/RetriesMockVault.java b/src/test/java/io/github/jopenlibs/vault/vault/mock/RetriesMockVault.java
index 1555d887..e33fa72f 100644
--- a/src/test/java/io/github/jopenlibs/vault/vault/mock/RetriesMockVault.java
+++ b/src/test/java/io/github/jopenlibs/vault/vault/mock/RetriesMockVault.java
@@ -33,7 +33,7 @@
  * server.start();
  *
  * final VaultConfig vaultConfig = new VaultConfig("http://127.0.0.1:8999", "mock_token");
- * final Vault vault = new Vault(vaultConfig);
+ * final Vault vault = Vault.create(vaultConfig);
  * final LogicalResponse response = vault.withRetries(5, 100).logical().read("secret/hello");
  * assertEquals(5, response.getRetries());
  * assertEquals("mock", response.getData().get("value"));