A zero-dependency Java client for the Vault secrets management solution from HashiCorp.
This driver strives to implement Vault's full HTTP API, along with supporting functionality such as automatic retry handling. It does so without relying on any other external libraries beyond the Java standard library, and is compatible with Java 8 and up. So it will play nice with all of your projects, greenfield and legacy alike, without causing conflicts with any other dependency.
NOTE: Although the binary artifact produced by the project is backwards-compatible with Java 8, you do need JDK 9 or higher to modify or build the source code of this library itself.
The driver is available from Maven Central, for all modern Java build systems.
Gradle:
dependencies {
implementation 'com.bettercloud:vault-java-driver:5.0.0'
}
Maven:
<dependency>
<groupId>com.bettercloud</groupId>
<artifactId>vault-java-driver</artifactId>
<version>5.0.0</version>
</dependency>
The com.bettercloud.vault.VaultConfig class is used to initialize a driver instance with desired settings.
In the most basic use cases, where you are only supplying a Vault server address and perhaps a root token, there
are convenience constructor methods available:
final VaultConfig config = new VaultConfig()
.address("http://127.0.0.1:8200")
.token("3c9fd6be-7bc2-9d1f-6fb3-cd746c0fc4e8")
.build();
// You may choose not to provide a root token initially, if you plan to use
// the Vault driver to retrieve one programmatically from an auth backend.
final VaultConfig config = new VaultConfig().address("http://127.0.0.1:8200").build();
To explicitly set additional config parameters (*), you can use a builder pattern style to construct the VaultConfig
instance. Either way, the initialization process will try to populate any unset values by looking to
environment variables.
final VaultConfig config =
new VaultConfig()
.address("http://127.0.0.1:8200") // Defaults to "VAULT_ADDR" environment variable
.token("3c9fd6be-7bc2-9d1f-6fb3-cd746c0fc4e8") // Defaults to "VAULT_TOKEN" environment variable
.openTimeout(5) // Defaults to "VAULT_OPEN_TIMEOUT" environment variable
.readTimeout(30) // Defaults to "VAULT_READ_TIMEOUT" environment variable
.sslConfig(new SslConfig().build()) // See "SSL Config" section below
.build();
Once you have initialized a VaultConfig object, you can use it to construct an instance of the Vault primary
driver class:
final Vault vault = new Vault(config);
Shortly before its 1.0 release, Vault added a Version 2 of its Key/Value Secrets Engine. This
supports some addition features beyond the Version 1 that was the default in earlier Vault builds (e.g. secret rotation, soft deletes, etc).
Unfortunately, K/V V2 introduces some breaking changes, in terms of both request/response payloads as well as how URL's are constructed
for Vault's REST API. Therefore, version 4.0.0 of this Vault Driver likewise had to introduce some breaking changes, to allow support
for both K/V versions.
If you are using the new K/V V2 across the board, then no action is needed. The Vault Driver now assumes this by default.
If you are still using the old K/V V1 across the board, then you can use the Vault class constructor:
public Vault(final VaultConfig vaultConfig, final Integer engineVersion), supplying a 1 as the engine version parameter.
constructor, then you can declare whether to use Version 1 or 2 across the board.
If you are using a mix, of some secret paths mounted with V1 and others mounted with V2, then you have two options:
You can explicitly specify your Vault secret paths, and which K/V version each one is using. Construct your Vault objects
with the constructor public Vault(final VaultConfig vaultConfig, final Boolean useSecretsEnginePathMap, final Integer globalFallbackVersion).
Within the VaultConfig object, supply a map of Vault secret paths to their associated K/V version (1 or 2).
You can rely on the Vault Driver to auto-detect your mounts and K/V versions upon instantiation. Use the same constructor as above,
but leave the map null. Note that this option requires your authentication credentials to have access to read Vault's /v1/sys/mounts
path.
If your Vault server uses a SSL certificate, then you must supply that certificate to establish connections. Also, if you are using certificate-based client authentication, then you must supply a client certificate and private key that have been previously registered with your Vault server.
SSL configuration has been broken off from the VaultConfig class, and placed in its own SslConfig class. This
class likewise using a builder pattern.
.verify(false) // Defaults to "VAULT_SSL_VERIFY" environment variable (or else "true")
To disable SSL certificate verification altogether, set sslVerify(false). YOU SHOULD NOT DO THIS IS A REAL
PRODUCTION SETTING! However, it can be useful in a development or testing server context. If this value is
explicitly set to false, then all other SSL config is basically unused.
You can provide the driver with a JKS truststore, containing Vault's server-side certificate for basic SSL, using one of the following three options:
.trustStore(object) - Supply an in-memory java.security.KeyStore file, containing Vault server cert(s) that
can be trusted.
.trustStoreFile(path) - Same as the above, but the path references a JKS file on the filesystem.
.trustStoreResource(path) - Same as the above, but the path references a classpath resource rather than a filesystem
path (e.g. if you've bundled the JKS file into your application's JAR, WAR, or EAR file).
If you are only using basic SSL, then no keystore need be provided. However, if you would like to use Vault's TLS Certificate auth backend for client side auth, then you need to provide a JKS keystore containing your client-side certificate and private key:
.keyStore(object, password) - Supply an in-memory java.security.KeyStore file containing a client
certificate and private key, and the password needed to access it (can be null).
can be trusted.
.keyStoreFile(path, password) - Same as the above, but the path references a JKS file on the filesystem.
.keyStoreResource(path, password) - Same as the above, but the path references a classpath resource rather than a
filesystem path (e.g. if you've bundled the JKS file into your application's JAR,
WAR, or EAR file).
NOTE: JKS-based config trumps PEM-based config (see below). If for some reason you build an SslConfig object
with both JKS and PEM data present, then only the JKS data will be used. You cannot "mix-and-match", providing
a JKS-based truststore and PEM-based client auth data.
To supply Vault's server-side certificate for basic SSL, you can use one of the following three options:
.pemFile(path) - Supply the path to an X.509 certificate in unencrypted PEM format, using UTF-8 encoding (defaults
to "VAULT_SSL_CERT" environment variable).
.pemResource(path) - Same as above, but the path references a classpath resource rather than a filesystem path (e.g. if
you've bundled the PEM file into your applications's JAR, WAR, or EAR file).
.pemUTF8(contents) - The string contents extracted from the PEM file. For Java to parse the certificate properly,
there must be a line-break in between the certificate header and body (see the SslConfig
Javadocs for more detail).
If SSL verification is enabled, no JKS-based config is provided, AND none of these three methods are called,
then SslConfig will by default check for a VAULT_SSL_CERT environment variable. If that's setw then it will be
treated as a filesystem path.
To use Vault's TLS Certificate auth backend for SSL client auth, you must provide your client certificate and private key, using some pair from the following options:
.clientPemUTF8(path) - Supply the path to an X.509 certificate in unencrypted PEM format, using UTF-8 encoding.
.clientPemResource(path) - Same as above, but the path references a classpath resource rather than a filesystem path (e.g. if
you've bundled the PEM file into your applications's JAR, WAR, or EAR file).
.clientPemUTF8(contents) - The string contents extracted from the PEM file. For Java to parse the certificate properly,
there must be a line-break in between the certificate header and body (see the SslConfig
Javadocs for more detail).
.clientKeyPemUTF8(path) - Supply the path to an RSA private key in unencrypted PEM format, using UTF-8 encoding.
.clientKeyPemResource(path) - Same as above, but the path references a classpath resource rather than a filesystem path (e.g. if
you've bundled the PEM file into your applications's JAR, WAR, or EAR file).
.clientKeyPemUTF8(contents) - The string contents extracted from the PEM file. For Java to parse the certificate properly,
there must be a line-break in between the certificate header and body (see the SslConfig
Javadocs for more detail).
Like the VaultConfig class, Vault too supports a builder pattern DSL style:
final Map<String, String> secrets = new HashMap<String, String>();
secrets.put("value", "world");
secrets.put("other_value", "You can store multiple name/value pairs under a single key");
// Write operation
final LogicalResponse writeResponse = vault.logical()
.write("secret/hello", secrets);
...
// Read operation
final String value = vault.logical()
.read("secret/hello")
.getData().get("value");
Vault has a number of methods for accessing the classes that implement the various endpoints of Vault's HTTP API:
logical(): Contains core operations such as reading and writing secrets.auth(): Exposes methods for working with Vault's various auth backends (e.g. to programmatically retrieve a token
by authenticating with a username and password).pki(): Operations on the PKI backend (e.g. create and delete roles, issue certificate credentials).debug(): Health check endpoints.The driver DSL also allows you to specify retry logic, by chaining the withRetries() ahead of accessing the endpoint
implementation:
// Retry up to 5 times if failures occur, waiting 1000 milliseconds in between each retry attempt.
final LogicalResponse response = vault.withRetries(5, 1000)
.logical()
.read("secret/hello");
Full Javadoc documentation.
Note that changes to the major version (i.e. the first number) represent possible breaking changes, and may require modifications in your code to migrate. Changes to the minor version (i.e. the second number) should represent non-breaking changes. The third number represents any very minor bugfix patches.
System.out.println in favor of java.util.logging. (PR #178)Adds the enum constant MountType.KEY_VALUE_V2. (PR #182)
4.1.0: This release contains the following updates:
$ claude mcp add vault-java-driver \
-- python -m otcore.mcp_server <graph>