bettercloud / vault-java-driver Goto Github PK
View Code? Open in Web Editor NEWZero-dependency Java client for HashiCorp's Vault
Home Page: https://bettercloud.github.io/vault-java-driver/
Zero-dependency Java client for HashiCorp's Vault
Home Page: https://bettercloud.github.io/vault-java-driver/
In v3.0.0 constructor of VaultConfig no longer accepts parameters.
Result: groovy.lang.GroovyRuntimeException: Could not find matching constructor for: com.bettercloud.vault.VaultConfig(java.lang.String, java.lang.String)
However the first 2 examples in documentation still use constructor parameters
https://github.com/BetterCloud/vault-java-driver/blob/v3.0.0/README.md#initializing-a-driver-instance
final VaultConfig config = new VaultConfig("http://127.0.0.1:8200", "3c9fd6be-7bc2-9d1f-6fb3-cd746c0fc4e8");
// 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("http://127.0.0.1:8200");
Right now (v. 1.2.0) there will be thrown a VaultException
when calling vault.logical().write(...)
when the client can not connect. The problem is that, for instance, a token (passed by the VaultConfig) may not be valid anymore (because it is expired or configuration on the server has changed), or the Vault server might be offline for a few seconds which leads to the same outcome (depending on the timeouts).
My question is: should this driver take the responsibility (e.g. by using Hystrix) to ensure reconnecting properly/recovering? Or should I write a "wrapper" around this driver to ensure connectivity and retrying? I don't know if this would be out-of-scope for this project.
๐ฌ Discussion appreciated.
Hello there! Thanks for building this! Would it be possible to clarify the license? Maybe by adding a LICENSE file to the root of the repository?
I couldn't find the APIs to do this. Is there a way for me to create and add a new root CA/intermediate CA to vault and then get certs issued from them?
I'd suggest to make VaultConfig#environmentLoader
public and add NoOpEnvironmentLoader
class that actually wouldn't load anything or maybe some another approach.
Use case: I'd like to be sure that environment cannot affect code.
As workaround next code works:
final VaultConfig config = new VaultConfig() {{
environmentLoader(new EnvironmentLoader(){
@Override
public String loadVariable(String name) {
return null;
}
});
}}
Vault API for user/pass, defines much more methods that supported by this project (user creation, update, etc).
https://www.vaultproject.io/docs/auth/userpass.html
Any plans implementing those?
I know it's already a TODO, but it'd be great to add support for the AppRole authentication backend. I'm selfishly opening this ticket to track progress on the implementation ;)
Presently you can provide a keystore and a keystore password for client certificates, but you cannot supply a keystore password for a supplied truststore for CA certs. This is somewhat surprising since keytool will only make keystores that have a password on them. It seems somewhat trivial to add this, but since it technically changes the SslConfig API I figured it's worth opening here for discussion before submitting a PR.
Can you please release 0.7.0 to Maven Central? Thank you!
Let me begin by saying that this may just be a colossal misunderstanding on my part, but as near as I can tell, vault-java-driver
's PKI support only works in cases where we're talking to a PKI backend mounted literally at /pki
.
We've found ourselves in a situation where we have two pki
backends (a root CA and an intermediate CA), and we'd like to issue certificates from the intermediate CA. The trouble is that we've given both of our backends descriptive paths (/root-ca
and /intermediate-ca
, for example), but the URLs constructed in Pki.java
hard-code a path of pki
.
I think it might make sense to take an optional path
argument for the various PKI operations (that could reasonably default to pki
for backward compatibility!) and construct URLs with that in mind. Seem legit?
Hi,
The used SSL context does not send the SNIServerNames SSLProperty when SSL verification is disabled.
So when Vault is running e.g. in OpenShift it does not work because it does not know where to route the requests.
Basically the SSLSocketFactory needs to set the right server name to the created SSLSocket.
There is also the way to do this on our own by setting a custom SSLContext in the SSLConfig, but then the HostnameVerifier is not set to the one which just allows everything and it still fails.
I had to do a dirty hack to get it working and it will also only work for one vault connection in the whole JVM:
final SSLContext sslContext = SSLContext.getInstance("TLS");
SSLContextSpi spi = new SSLContextSpi() {
@Override
protected void engineInit(final KeyManager[] km, final TrustManager[] tm, final SecureRandom sr) throws KeyManagementException {
sslContext.init(km, tm, sr);
}
@Override
protected SSLSocketFactory engineGetSocketFactory() {
SSLParameters params = new SSLParameters();
params.setServerNames(Arrays.asList(new SNIHostName("my-vault-connector.foobar.com")));
return new SSLSocketFactoryWrapper(sslContext.getSocketFactory(), params);
}
@Override
protected SSLServerSocketFactory engineGetServerSocketFactory() {
return sslContext.getServerSocketFactory();
}
@Override
protected SSLSessionContext engineGetServerSessionContext() {
return sslContext.getServerSessionContext();
}
@Override
protected SSLSessionContext engineGetClientSessionContext() {
return sslContext.getClientSessionContext();
}
@Override
protected SSLEngine engineCreateSSLEngine(final String host, final int port) {
return sslContext.createSSLEngine(host, port);
}
@Override
protected SSLEngine engineCreateSSLEngine() {
return sslContext.createSSLEngine();
}
};
sslContext.init(null, new TrustManager[] { new X509TrustManager() {
@Override
public void checkClientTrusted(final X509Certificate[] x509Certificates, final String s)
throws CertificateException {
}
@Override
public void checkServerTrusted(final X509Certificate[] x509Certificates, final String s)
throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
} }, new java.security.SecureRandom());
class SSLContextWrapper extends SSLContext {
public SSLContextWrapper(final SSLContextSpi spi, final java.security.Provider provider, final String protocol) {
super(spi, provider, protocol);
}
}
Field field = Rest.class.getDeclaredField("DISABLED_SSL_CONTEXT");
field.setAccessible(true);
field.set(null, new SSLContextWrapper(spi, sslContext.getProvider(), sslContext.getProtocol()));
vault = new Vault(new VaultConfig()
.address(address)
.token(token)
.sslConfig(new SslConfig().verify(false).build())
.build());
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
public class SSLSocketFactoryWrapper extends SSLSocketFactory {
private final SSLSocketFactory wrappedFactory;
private final SSLParameters sslParameters;
public SSLSocketFactoryWrapper(final SSLSocketFactory factory, final SSLParameters sslParameters) {
this.wrappedFactory = factory;
this.sslParameters = sslParameters;
}
@Override
public Socket createSocket(final String host, final int port) throws IOException, UnknownHostException {
SSLSocket socket = (SSLSocket) wrappedFactory.createSocket(host, port);
socket.setSSLParameters(sslParameters);
return socket;
}
@Override
public Socket createSocket(final String host, final int port, final InetAddress localHost, final int localPort)
throws IOException, UnknownHostException {
SSLSocket socket = (SSLSocket) wrappedFactory.createSocket(host, port, localHost, localPort);
socket.setSSLParameters(sslParameters);
return socket;
}
@Override
public Socket createSocket(final InetAddress host, final int port) throws IOException {
SSLSocket socket = (SSLSocket) wrappedFactory.createSocket(host, port);
socket.setSSLParameters(sslParameters);
return socket;
}
@Override
public Socket createSocket(final InetAddress address, final int port, final InetAddress localAddress,
final int localPort) throws IOException {
SSLSocket socket = (SSLSocket) wrappedFactory.createSocket(address, port, localAddress, localPort);
socket.setSSLParameters(sslParameters);
return socket;
}
@Override
public Socket createSocket() throws IOException {
SSLSocket socket = (SSLSocket) wrappedFactory.createSocket();
socket.setSSLParameters(sslParameters);
return socket;
}
@Override
public String[] getDefaultCipherSuites() {
return wrappedFactory.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return wrappedFactory.getSupportedCipherSuites();
}
@Override
public Socket createSocket(final Socket s, final String host, final int port, final boolean autoClose)
throws IOException {
SSLSocket socket = (SSLSocket) wrappedFactory.createSocket(s, host, port, autoClose);
socket.setSSLParameters(sslParameters);
return socket;
}
}
Line 518 hard-codes "TLS". This breaks my ability to use TLSv1.2. Overriding it to TLSv1.2 in a debugger allows me to get past errors like:
http: TLS handshake error from XXXXXXX: tls: client offered an unsupported, maximum protocol version of 301
It seems that LogicalResponse only includes the data portion of the REST reply.
It does not include important metadata such as:
"lease_id": "<secret backend>/creds/<role>/<uuid>",
"renewable": true,
"lease_duration": 3600,
This metadata is necessary in order for an application to honor the TTL for credentials.
I'm happy to submit a pull request if that seems reasonable. These would be provided as new properties of LogicalResponse.
currently, most exceptions are returned like this:
throw new VaultException("Vault responded with HTTP status code: " + restResponse.getStatus(), restResponse.getStatus());
as such it is impossible to debug from calling code, as the body is not included in the exception, how do you guys feel about changing to restResponse.getBody()?
When a logical().read()
result includes a null value, the following error is thrown: java.lang.UnsupportedOperationException: Not a string: null
This is because the .asString() call fails.
One example where this is common is the aws backend as it returns 3 keys:
access_key
secret_key
security_token
security_token is always null if STS is not being used.
member.getValue()
should include a .isNull()
check before calling .asString()
to ensure safety.
In Vault transit/encrypt or transit/decrypt rest APIs, the batch mode is supported by specifying {"batch_input":[{"ciphertext": ""}, {"ciphertext": ""}]} in the request body. However, the write function in Logical.java does not support batch mode. Could we provide a write function that takes as input a path and a body bytes, for example write(String path, byte[] body) that will support any kind of rest API call?
Vault allows authentication using SSL/TLS client certificates:
https://www.vaultproject.io/docs/auth/cert.html
Are there any plans to add support for this auth backend in this client/driver?
Nice, simple API. Thanks! Any plan to support delete?
Do you have plans to support listing all secrets for URL? I will be willing to help.
Hi, I'm trying to run the integration test on my mac, but all the test that involve the Vault TestContainer returns the following errors
13:45:28.612 [DEBUG] [TestEventLogger] com.bettercloud.vault.api.LeasesTests STARTED
13:45:34.440 [DEBUG] [TestEventLogger]
13:45:34.440 [DEBUG] [TestEventLogger] com.bettercloud.vault.api.LeasesTests STANDARD_ERROR
13:45:34.440 [DEBUG] [TestEventLogger] [Test worker] INFO ๐ณ [vault:0.7.3] - Creating container for image: vault:0.7.3
13:45:34.571 [DEBUG] [TestEventLogger] [Test worker] INFO ๐ณ [vault:0.7.3] - Starting container with ID: 9dfa9693d83f196eaede324c33cc96f5695d6cc3740d8ba186fb3839329bdfef
13:45:34.820 [DEBUG] [TestEventLogger] [Test worker] INFO ๐ณ [vault:0.7.3] - Container vault:0.7.3 is starting: 9dfa9693d83f196eaede324c33cc96f5695d6cc3740d8ba186fb3839329bdfef
13:45:34.827 [DEBUG] [TestEventLogger] [Test worker] INFO ๐ณ [vault:0.7.3] - Container vault:0.7.3 started
13:45:34.827 [DEBUG] [TestEventLogger] [Test worker] INFO com.bettercloud.vault.api.VaultContainer - Command: vault init -ca-cert=/vault/config/ssl/cert.pem -key-shares=1 -key-threshold=1
13:45:34.900 [DEBUG] [TestEventLogger] [Test worker] INFO com.bettercloud.vault.api.VaultContainer - Command stdout:
13:45:34.900 [DEBUG] [TestEventLogger] [Test worker] INFO com.bettercloud.vault.api.VaultContainer - Command stderr: Error initializing Vault: Put https://127.0.0.1:8200/v1/sys/init: dial tcp 127.0.0.1:8200: getsockopt: connection refused
13:45:34.900 [DEBUG] [TestEventLogger]
13:45:35.292 [DEBUG] [TestEventLogger]
13:45:35.292 [DEBUG] [TestEventLogger] com.bettercloud.vault.api.LeasesTests > classMethod STARTED
13:45:35.292 [null] [org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor]
13:45:35.292 [DEBUG] [org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor] Executing test class com.bettercloud.vault.api.LogicalTests
13:45:36.096 [DEBUG] [org.gradle.process.internal.health.memory.MemoryManager] Emitting OS memory status event {Total: 17179869184, Free: 8128143360}
13:45:36.096 [DEBUG] [org.gradle.launcher.daemon.server.health.LowMemoryDaemonExpirationStrategy] Received memory status update: {Total: 17179869184, Free: 8128143360}
13:45:36.096 [DEBUG] [org.gradle.process.internal.health.memory.MemoryManager] Emitting JVM memory status event {Maximum: 954728448, Committed: 574095360}
13:45:38.756 [DEBUG] [org.gradle.launcher.daemon.server.Daemon] DaemonExpirationPeriodicCheck running
13:45:38.756 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Waiting to acquire shared lock on daemon addresses registry.
13:45:38.756 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Lock acquired on daemon addresses registry.
13:45:38.756 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Releasing lock on daemon addresses registry.
13:45:38.756 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Waiting to acquire shared lock on daemon addresses registry.
13:45:38.756 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Lock acquired on daemon addresses registry.
13:45:38.756 [DEBUG] [org.gradle.cache.internal.DefaultFileLockManager] Releasing lock on daemon addresses registry.
13:45:35.386 [null] [org.gradle.internal.progress.DefaultBuildOperationExecutor]
> Task :integrationTest
13:45:35.294 [DEBUG] [TestEventLogger]
13:45:35.294 [DEBUG] [TestEventLogger] com.bettercloud.vault.api.LeasesTests > classMethod FAILED
13:45:35.294 [DEBUG] [TestEventLogger] java.lang.ArrayIndexOutOfBoundsException: 1
13:45:35.294 [DEBUG] [TestEventLogger] at com.bettercloud.vault.api.VaultContainer.initAndUnsealVault(VaultContainer.java:154)
13:45:35.294 [DEBUG] [TestEventLogger] at com.bettercloud.vault.api.LeasesTests.setupClass(LeasesTests.java:43)
13:45:35.294 [DEBUG] [TestEventLogger] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
13:45:35.294 [DEBUG] [TestEventLogger] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
13:45:35.294 [DEBUG] [TestEventLogger] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
13:45:35.294 [DEBUG] [TestEventLogger] at java.lang.reflect.Method.invoke(Method.java:498)
13:45:35.294 [DEBUG] [TestEventLogger] at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
13:45:35.294 [DEBUG] [TestEventLogger] at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
13:45:35.294 [DEBUG] [TestEventLogger] at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
13:45:35.294 [DEBUG] [TestEventLogger] at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
13:45:35.294 [DEBUG] [TestEventLogger] at org.testcontainers.containers.FailureDetectingExternalResource$1.evaluate(FailureDetectingExternalResource.java:30)
13:45:35.294 [DEBUG] [TestEventLogger] at org.junit.rules.RunRules.evaluate(RunRules.java:20)
13:45:35.294 [DEBUG] [TestEventLogger] at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
13:45:35.294 [DEBUG] [TestEventLogger] at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:114)
13:45:35.294 [DEBUG] [TestEventLogger] at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:57)
13:45:35.294 [DEBUG] [TestEventLogger] at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:66)
13:45:35.294 [DEBUG] [TestEventLogger] at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
13:45:35.295 [DEBUG] [TestEventLogger] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
13:45:35.295 [DEBUG] [TestEventLogger] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
13:45:35.295 [DEBUG] [TestEventLogger] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
13:45:35.295 [DEBUG] [TestEventLogger] at java.lang.reflect.Method.invoke(Method.java:498)
13:45:35.295 [DEBUG] [TestEventLogger] at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
13:45:35.295 [DEBUG] [TestEventLogger] at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
13:45:35.295 [DEBUG] [TestEventLogger] at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
13:45:35.295 [DEBUG] [TestEventLogger] at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
13:45:35.295 [DEBUG] [TestEventLogger] at com.sun.proxy.$Proxy3.processTestClass(Unknown Source)
13:45:35.295 [DEBUG] [TestEventLogger] at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:108)
13:45:35.295 [DEBUG] [TestEventLogger] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
13:45:35.295 [DEBUG] [TestEventLogger] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
13:45:35.295 [DEBUG] [TestEventLogger] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
13:45:35.295 [DEBUG] [TestEventLogger] at java.lang.reflect.Method.invoke(Method.java:498)
13:45:35.295 [DEBUG] [TestEventLogger] at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
13:45:35.295 [DEBUG] [TestEventLogger] at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
13:45:35.295 [DEBUG] [TestEventLogger] at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:146)
13:45:35.295 [DEBUG] [TestEventLogger] at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:128)
13:45:35.295 [DEBUG] [TestEventLogger] at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
13:45:35.295 [DEBUG] [TestEventLogger] at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
13:45:35.295 [DEBUG] [TestEventLogger] at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
13:45:35.295 [DEBUG] [TestEventLogger] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
13:45:35.295 [DEBUG] [TestEventLogger] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
13:45:35.295 [DEBUG] [TestEventLogger] at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
13:45:35.295 [DEBUG] [TestEventLogger] at java.lang.Thread.run(Thread.java:748)
13:45:35.296 [DEBUG] [TestEventLogger]
13:45:35.296 [DEBUG] [TestEventLogger] com.bettercloud.vault.api.LeasesTests FAILED
I tried to connect to the Vault container while it's running from outside the test, and I always get a connection refused error, with and without the mac firewall disabled.
My docker versions are:
docker-machine version 0.12.2, build 9371605
Docker version 17.09.0-ce, build afdb6d4
am I doing something wrong or missing something?
Just curious about releasing this to maven central w/o a corresponding tag in git? We are looking to use your lib in production and we like to review version deltas. W/o tags in git it makes a bit more difficult to confirm what's actually on maven central.
It seems that /sys/renew functionality was left out from the Leases class. Was there a particular reason or just an oversight?
Right now the integration tests expect a locally running Vault server and particular environment variables set. By using java-test-containers a Docker container is created when running the tests, all integration tests are running against a Vault dev server running in Docker. After all tests have run the container will be destroyed automatically.
Hi,
I starting to play around with vault and used these examples to connect to a vault instance running out of a docker container on my local system.
I am using this command to start the docker container - docker run -p 8200:8200 --cap-add IPC_LOCK -e 'VAULT_LOCAL_CONFIG={"backend": {"file": {"path": "/vault/file"}}, "default_lease_ttl": "168h", "max_lease_ttl": "720h", "listener": {"tcp":{"address":"127.0.0.1:8200", "tls_disable": "true"}}}' --hostname vault --name vault docker.artifactory.abc/shared/vault:0.9.5 server
Post which, I am logging into the container, and executing the following commands to initialise the vault -
/ # export VAULT_ADDR=http://127.0.0.1:8200
/ # vault operator init
From the output of this command, I note the root token and am using it for the test case outlined below.
Now, I have the following test case and intend to write to the vault and read from it.
package abc.co.nz;
import org.junit.Test;
import org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import java.util.Map;
import java.util.HashMap;
import com.bettercloud.vault.response.*;
import com.bettercloud.vault.*;
public class VaultTest {
@Test
public void testVault() throws Exception {
final VaultConfig config = new VaultConfig()
.address("http://127.0.0.1:8200")
.token("6d14c36e-c975-ee50-62fc-fd3afefad4e0")
.openTimeout(5)
.readTimeout(3)
.sslConfig(new SslConfig().verify(false).build())
.build();
final Vault vault = new Vault(config);
final Map<String, Object> secrets = new HashMap<String, Object>();
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
//return vault.logical().read("secret/hello").getData().get("value");
assertEquals("world", vault.logical().read("secret/hello").getData().get("value"));
}
}
I get an error - com.bettercloud.vault.VaultException: com.bettercloud.vault.rest.RestException: java.net.SocketException: Unexpected end of file from server
What am I missing?
There's great feature introduced recently named 'Resource Wrapping'.
It would be useful to support in in Java client library.
Use case:
/auth/approle/login
endpoint providing App Role role_id, secret_id and X-Vault-Wrap-TTL
header./sys/wrapping/unwrap?token=${WrappedTokenId}
and receives proper token, then reconfigures itself and proceeds with operations.Example was shown during Securing Applications Using Nomad
presentation.
For example, the Auth.loginByCert() API calls to /v1/auth/cert/login. However, the "cert" portion of this path is actually configurable within Vault. For example, I configure this to be environment specific (e.g. /v1/auth/env-1/login)
See https://www.vaultproject.io/api/system/auth.html regarding configurable auth mounts.
It'd be great if the Mount-point list API could be supported (https://www.vaultproject.io/api/system/mounts.html)
There are cases where writing returns data. See https://www.vaultproject.io/docs/secrets/pki/index.html. For example, executing "vault write pki/issue/example-dot-com common_name=blah.example.com" returns certificates.
In order to work with ec2 roles, it needs a new auth method as it require different parameters, pkcs7
and nonce
I took a quick look around the code and it looks like it's focussed around using tokens as the only auth method. I was wondering if there was any plan to support app-id?
We're running on Docker where passing the token via ENV doesn't seem to be the best of ideas. App-id seems like a reasonable compromise sitting in between cubbyhole and tokens.
Add support of App ID authentication which is recommended choice to use by servers/applications.
https://www.vaultproject.io/docs/secrets/transit/
https://www.vaultproject.io/api/secret/transit/index.html
Perhaps the existing Logical.{read,write} can be used with the callers responsibility to specify their key with transit/ prefix?
The read,write api of transit is the highest priority for me over create,list,delete
Currently, logical().write() supports writing only string/string key-value pairs. However, Vault's API supports writing arbitrary JSON or YAML records into the database. In particular, this is important for arrays.
This API should reflect that, by changing the API as write(String path, Map<String, Object> keyValuePairs)
. This would be a source compatible change, and the objects could be internally converted to JSON.
According to https://www.vaultproject.io/docs/commands/environment.html vault will read the vault token from $HOME/.vault-token if it's not in the environtment
It would be nice to have that supported
Setup Vault as explained at:
https://github.com/arun-gupta/kubernetes-aws-workshop/tree/master/config-secrets#vault
Java application deployed as Pod in Kubernetes that reads secrets from Vault is:
https://github.com/arun-gupta/java-app-secrets/blob/master/src/main/java/org/examples/java/App.java
Pod spec is:
apiVersion: v1
kind: Pod
metadata:
name: java-app-secrets
spec:
containers:
- name: java-app-secrets
image: arungupta/java-app-secrets:latest
env:
- name: VAULT_ADDR
value: http://ec2-54-237-223-40.compute-1.amazonaws.com:8200
- name: VAULT_TOKEN
value: 4e93b3c6-c459-f166-e7e9-6c48044cfdb6
restartPolicy: Never
VaultConfig
initialized as shown below works and is able to retrieve the secrets:
final VaultConfig config = new VaultConfig()
.address(System.getenv("VAULT_ADDR"))
.token(System.getenv("VAULT_TOKEN"))
.sslConfig(new SslConfig().verify(false).build())
.build();
VaultConfig
initialized as shown below returns a NPE:
final VaultConfig config = new VaultConfig()
.address(System.getenv("VAULT_ADDR"))
.sslConfig(new SslConfig().verify(false).build())
.build();
Here is the NPE:
Exception in thread "main" com.bettercloud.vault.VaultException: java.lang.NullPointerException
at com.bettercloud.vault.api.Logical.read(Logical.java:84)
at org.examples.java.App.main(App.java:26)
Caused by: java.lang.NullPointerException
at java.net.URLEncoder.encode(URLEncoder.java:204)
at com.bettercloud.vault.rest.Rest.header(Rest.java:173)
at com.bettercloud.vault.api.Logical.read(Logical.java:56)
... 1 more
Hey I was wondering if i should contribute support of the sign method the pki api ?
Hi there!
I've forked this repo to extend the API endpoint coverage to sys/policy
for getting/creating policies, but I'm having trouble running 3.0.0's integration test suite. I have a strong feeling that the problem may be PEBKAC but I wanted to bring it to your attention in the event that I'm wrong.
Here's an example stack trace that I'm seeing:
17:26:19.664 [DEBUG] [org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor] Executing test class com.bettercloud.vault.api.AuthBackendAppRoleTests
17:26:14.533 [null] [org.gradle.internal.progress.DefaultBuildOperationExecutor]
> Task :integrationTest
17:26:19.660 [DEBUG] [TestEventLogger] [Test worker] ERROR org.testcontainers.dockerclient.DockerClientProviderStrategy - Could not find a valid Docker environment. Please check configuration. Attempted configurations were:
17:26:19.660 [DEBUG] [TestEventLogger] [Test worker] ERROR org.testcontainers.dockerclient.DockerClientProviderStrategy - EnvironmentAndSystemPropertyClientProviderStrategy: failed with exception ExceptionInInitializerError (null). Root cause IllegalStateException (Only supported on Linux)
17:26:19.660 [DEBUG] [TestEventLogger] [Test worker] ERROR org.testcontainers.dockerclient.DockerClientProviderStrategy - UnixSocketClientProviderStrategy: failed with exception InvalidConfigurationException (this strategy is only applicable to Linux)
17:26:19.661 [DEBUG] [TestEventLogger] [Test worker] ERROR org.testcontainers.dockerclient.DockerClientProviderStrategy - ProxiedUnixSocketClientProviderStrategy: failed with exception IllegalArgumentException (Socket file does not exist: /var/run/docker.sock)
17:26:19.661 [DEBUG] [TestEventLogger] [Test worker] ERROR org.testcontainers.dockerclient.DockerClientProviderStrategy - DockerMachineClientProviderStrategy: failed with exception InvalidConfigurationException (Exception when executing docker-machine status )
17:26:19.662 [DEBUG] [TestEventLogger] [Test worker] ERROR org.testcontainers.dockerclient.DockerClientProviderStrategy - WindowsClientProviderStrategy: failed with exception TimeoutException (Timeout waiting for result with exception). Root cause ConnectException (Connection refused: localhost/127.0.0.1:2375)
17:26:19.662 [DEBUG] [TestEventLogger] [Test worker] ERROR org.testcontainers.dockerclient.DockerClientProviderStrategy - As no valid configuration was found, execution cannot continue
17:26:19.664 [DEBUG] [TestEventLogger]
17:26:19.664 [DEBUG] [TestEventLogger] com.bettercloud.vault.api.AuthBackendAppIdTests > classMethod STARTED
17:26:19.692 [DEBUG] [TestEventLogger]
17:26:19.692 [DEBUG] [TestEventLogger] com.bettercloud.vault.api.AuthBackendAppIdTests > classMethod FAILED
17:26:19.692 [DEBUG] [TestEventLogger] java.lang.ExceptionInInitializerError
17:26:19.692 [DEBUG] [TestEventLogger] at sun.misc.Unsafe.ensureClassInitialized(Native Method)
17:26:19.692 [DEBUG] [TestEventLogger] at sun.reflect.UnsafeFieldAccessorFactory.newFieldAccessor(UnsafeFieldAccessorFactory.java:43)
17:26:19.692 [DEBUG] [TestEventLogger] at sun.reflect.ReflectionFactory.newFieldAccessor(ReflectionFactory.java:156)
17:26:19.692 [DEBUG] [TestEventLogger] at java.lang.reflect.Field.acquireFieldAccessor(Field.java:1088)
17:26:19.692 [DEBUG] [TestEventLogger] at java.lang.reflect.Field.getFieldAccessor(Field.java:1069)
17:26:19.692 [DEBUG] [TestEventLogger] at java.lang.reflect.Field.get(Field.java:393)
17:26:19.692 [DEBUG] [TestEventLogger] at org.junit.runners.model.FrameworkField.get(FrameworkField.java:73)
17:26:19.692 [DEBUG] [TestEventLogger] at org.junit.runners.model.TestClass.getAnnotatedFieldValues(TestClass.java:230)
17:26:19.692 [DEBUG] [TestEventLogger] at org.junit.runners.ParentRunner.classRules(ParentRunner.java:255)
17:26:19.692 [DEBUG] [TestEventLogger] at org.junit.runners.ParentRunner.withClassRules(ParentRunner.java:244)
17:26:19.692 [DEBUG] [TestEventLogger] at org.junit.runners.ParentRunner.classBlock(ParentRunner.java:194)
17:26:19.692 [DEBUG] [TestEventLogger] at org.junit.runners.ParentRunner.run(ParentRunner.java:362)
17:26:19.692 [DEBUG] [TestEventLogger] at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:114)
17:26:19.692 [DEBUG] [TestEventLogger] at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:57)
17:26:19.692 [DEBUG] [TestEventLogger] at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:66)
17:26:19.692 [DEBUG] [TestEventLogger] at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
17:26:19.692 [DEBUG] [TestEventLogger] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
17:26:19.692 [DEBUG] [TestEventLogger] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
17:26:19.692 [DEBUG] [TestEventLogger] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
17:26:19.692 [DEBUG] [TestEventLogger] at java.lang.reflect.Method.invoke(Method.java:498)
17:26:19.692 [DEBUG] [TestEventLogger] at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
17:26:19.693 [DEBUG] [TestEventLogger] at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
17:26:19.693 [DEBUG] [TestEventLogger] at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
17:26:19.693 [DEBUG] [TestEventLogger] at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
17:26:19.693 [DEBUG] [TestEventLogger] at com.sun.proxy.$Proxy3.processTestClass(Unknown Source)
17:26:19.693 [DEBUG] [TestEventLogger] at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:109)
17:26:19.693 [DEBUG] [TestEventLogger] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
17:26:19.693 [DEBUG] [TestEventLogger] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
17:26:19.693 [DEBUG] [TestEventLogger] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
17:26:19.693 [DEBUG] [TestEventLogger] at java.lang.reflect.Method.invoke(Method.java:498)
17:26:19.693 [DEBUG] [TestEventLogger] at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
17:26:19.693 [DEBUG] [TestEventLogger] at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
17:26:19.693 [DEBUG] [TestEventLogger] at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:146)
17:26:19.693 [DEBUG] [TestEventLogger] at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:128)
17:26:19.693 [DEBUG] [TestEventLogger] at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
17:26:19.693 [DEBUG] [TestEventLogger] at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
17:26:19.693 [DEBUG] [TestEventLogger] at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:46)
17:26:19.693 [DEBUG] [TestEventLogger] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
17:26:19.693 [DEBUG] [TestEventLogger] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
17:26:19.693 [DEBUG] [TestEventLogger] at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
17:26:19.693 [DEBUG] [TestEventLogger] at java.lang.Thread.run(Thread.java:748)
17:26:19.693 [DEBUG] [TestEventLogger]
17:26:19.693 [DEBUG] [TestEventLogger] Caused by:
17:26:19.693 [DEBUG] [TestEventLogger] java.lang.IllegalStateException: Could not find a valid Docker environment. Please see logs and check configuration
17:26:19.693 [DEBUG] [TestEventLogger] at org.testcontainers.dockerclient.DockerClientProviderStrategy.getFirstValidStrategy(DockerClientProviderStrategy.java:90)
17:26:19.693 [DEBUG] [TestEventLogger] at org.testcontainers.DockerClientFactory.client(DockerClientFactory.java:83)
17:26:19.693 [DEBUG] [TestEventLogger] at org.testcontainers.containers.GenericContainer.<init>(GenericContainer.java:111)
17:26:19.693 [DEBUG] [TestEventLogger] at com.bettercloud.vault.api.VaultContainer.<init>(VaultContainer.java:105)
17:26:19.693 [DEBUG] [TestEventLogger] at com.bettercloud.vault.api.AuthBackendAppIdTests.<clinit>(AuthBackendAppIdTests.java:18)
17:26:19.693 [DEBUG] [TestEventLogger] ... 41 more
17:26:19.694 [DEBUG] [TestEventLogger]
17:26:19.694 [DEBUG] [TestEventLogger] com.bettercloud.vault.api.AuthBackendAppIdTests FAILED
I did some browsing of TestContainer issues for similar stuff, and it looked like a similar problem was resolved for those who made sure docker-machine
was available on their path. I confirmed both docker
and docker-machine
are available:
bmcfeeley-rMBP:vault-java-driver bmcfeeley$ which docker
/usr/local/bin/docker
bmcfeeley-rMBP:vault-java-driver bmcfeeley$ which docker-machine
/usr/local/bin/docker-machine
I couldn't find any more docs to see if I'm missing some setup or configuration piece of the puzzle so I thought I'd give you a shout.
Hope you have a nice weekend!
Steps to reproduce:
gradle compile
gradle compileOnly
FAILURE: Build failed with an exception.
* Where:
Build file '/home/alexandre/Documents/project/vault-java-driver/build.gradle' line: 79
* What went wrong:
A problem occurred evaluating root project 'vault-java-driver'.
> Could not get unknown property 'classesDirs' for unit tests classes of type org.gradle.api.internal.tasks.DefaultSourceSetOutput.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
BUILD FAILED
Total time: 0.577 secs
https://www.vaultproject.io/docs/auth/token.html#post includes options for an explicit_max_ttl and whether or not the token should be renewable. v3.0.0 of the vault-java-driver does not support these options. It would be great if these could be added.
Acceptance Criteria:
java-vault-driver should support all options for createToken
Suggested Tech Steps:
Update Auth.TokenRequest (
Can I share a single Vault instance between multiple threads ?
Could you please tag the v1.1.0 version? Keep up the good work!
Can you add support for the AWS Auth backend? My thought was another method on com.bettercloud.vault.api.Auth:
public AuthResponse loginByAwsIam(final String role, final String iamHttpRequestMethod, final String iamRquestUrl, final String iamRequestBody, final String iamRequestHeaders)
and
public AuthResponse loginByAwsEc2(final String role, final String pkcs7, final String nonce)
I'd be happy to submit a pull request if you'd consider it.
Is it possible that a resource gets leaked when the code fails to open a new connection?
e.g. in this code:
https://github.com/BetterCloud/vault-java-driver/blob/master/src/main/java/com/bettercloud/vault/rest/Rest.java#L403
I'm thinking it would be good form to have a finally{} block that releases the connection resource if it is not null?
i.e. calls disconnect()
Thanks,
Nate
It would be nice to have the ability to login to ldap
Hello,
Can I have an example of how to use AWS auth backend.
Regards,
Gorka.
This makes it very difficult to unit test. It can be impossible to mock out the library, instead requiring the user to wrap every type in their own types so that they can be mocked out.
A feature that would be very useful to us would be /auth/token/renew-self
. Is there any interest or plans to include this?
I would be willing to help with a PR if necessary, but it looked like a new type of API request (and so I am not sure how exactly you would want it to fit into the library). Would it make sense to make this accessible from Logical
?
Hi there,
Vault introduced the concept of roles in 0.6.0, with a new auth API endpoint in /auth/token/create/[role_name]
. It'll be good if the Auth class would support a method that hits that endpoint directly.
I am internally writing something to provide this, and I'll look to submit a PR at a later date if others haven't gotten to it yet later.
Thanks,
Alex
Vault returns status 400 with body {"errors":["permission denied"]}
if access token is incorrect or has insufficient permissions.
On receiving such status, vault-java-driver throws com.bettercloud.vault.VaultException: Expecting HTTP status 204 or 200, but instead receiving 400
.
Which is very confusing, because Vault documentation says that it means 400 - Invalid request, missing or invalid data. See the "validation" section for more details on the error response.
And it doesn't provide any more details.
vault-java-driver makes it hard to debug by not exposing response body.
I think that vault-java-driver should incorporate contents of errors
field in exception message.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.