GithubHelp home page GithubHelp logo

bettercloud / vault-java-driver Goto Github PK

View Code? Open in Web Editor NEW
333.0 333.0 224.0 1.45 MB

Zero-dependency Java client for HashiCorp's Vault

Home Page: https://bettercloud.github.io/vault-java-driver/

Java 99.77% Shell 0.14% HCL 0.09%

vault-java-driver's People

Contributors

adkhare avatar aiwaniuk avatar bitbrain avatar danharris-asurion avatar dubreuia avatar eirslett avatar elupu avatar expeddrewery avatar eyal-lupu avatar gm2211 avatar goodrum avatar happybob007 avatar innossh avatar issacg avatar jarrodcodes avatar jeinwag avatar jetersen avatar markussammallahti avatar mikegrass avatar mrunesson avatar naktibalda avatar nathanc avatar paulburlumi avatar robm-openjdk avatar schulzh avatar sinneduy avatar steve-perkins avatar steve-perkins-bc avatar vladrassokhin avatar zglozman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vault-java-driver's Issues

[Documentation] Constructor of VaultConfig no longer accepts parameters

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");

Improve resilience when client can not connect?

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.

License clarification

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?

Add root/intermediate CA to vault

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?

Support overriding`VaultConfig#environmentLoader` with NoOp loader

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;
        }
    });
}}

Allow password protected truststores

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't use PKI backends mounted at paths other than /pki

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?

DISABLED_SSL_CONTEXT does not send server name for SNI

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;
	}

}

SslConfig does not support TLSv1.2

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

LogicalResponse doesn't include lease information

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.

Adding body to Pki Respone exceptions:

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()?

Keys with null values cause UnsupportedOperationException

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.

New feature: encrypt / decrypt in batch mode

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?

error running integration test on MacOS

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?

Tagging releases in git

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.

Use 'java-test-containers' for Integration Tests

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.

Unexpected end of file from server

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?

Support Response Wrapping

There's great feature introduced recently named 'Resource Wrapping'.
It would be useful to support in in Java client library.

Use case:

  1. Service A authenticates with /auth/approle/login endpoint providing App Role role_id, secret_id and X-Vault-Wrap-TTL header.
  2. Response contains AccessorID and WrappedTokenID, first one left on Service A, second passed to Service B.
  3. Service B connects to Vault server and performs GET on /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.

need aws-ec2 auth support

In order to work with ec2 roles, it needs a new auth method as it require different parameters, pkcs7 and nonce

Support for App-ID

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.

arbitrary object value serialization for write()

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.

NullPointerException if Vault token is specified during initialization

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

Unable to run the new integrationTest suite on MacOS

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!

Cannot compile code with gradle

Steps to reproduce:

  • Clone the project
  • Execute gradle compile
  • Expected: the code compiles, Actual: exception
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

createToken missing explicit_max_ttl and renewable options

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 (

public static class TokenRequest implements Serializable {
) to take these parameters.

Tag 1.1.0

Could you please tag the v1.1.0 version? Keep up the good work!

Add support for AWS auth backend

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.

Please make less classes 'final'

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.

Any plans to support token renew?

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?

Add support for /auth/token/create/[role_name] in Auth

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

Permission denied error could be handled better

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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.