From 23fbc7a6d3c9d4401044af29d51e504fb94f7ebe Mon Sep 17 00:00:00 2001 From: Stefan Kalscheuer <stefan@stklcode.de> Date: Sat, 24 Mar 2018 13:59:22 +0100 Subject: [PATCH] Replaced VaultConnectorFactory with VaultConnectorBuilder The class is more a builder than a factory, so is has been renamed. The factory delegates to the builder for now to ease migration, but will be removed with the next major release. --- CHANGELOG.md | 1 + .../builder/HTTPVaultConnectorBuilder.java | 284 ++++++++++++++++++ .../builder/VaultConnectorBuilder.java | 54 ++++ .../factory/HTTPVaultConnectorFactory.java | 113 ++----- .../factory/VaultConnectorFactory.java | 7 +- .../HTTPVaultConnectorBuilderTest.java | 130 ++++++++ .../HTTPVaultConnectorFactoryTest.java | 2 +- 7 files changed, 493 insertions(+), 98 deletions(-) create mode 100644 src/main/java/de/stklcode/jvault/connector/builder/HTTPVaultConnectorBuilder.java create mode 100644 src/main/java/de/stklcode/jvault/connector/builder/VaultConnectorBuilder.java create mode 100644 src/test/java/de/stklcode/jvault/connector/builder/HTTPVaultConnectorBuilderTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index febc0a4..6e28590 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ * **[breaking]** Removed support for `HTTPVaultConnectorFactory#withSslContext()` in favor of `#withTrustedCA()` due to refactoring of the internal SSL handling. * [improvement] `VaultConnector` extends `java.io.Serializable` +* [deprecation] `VaultConnectorFactory` is deprecated in favor of `VaultConnectorBuilder` with identical API. ## 0.7.1 [2018-03-17] * [improvement] Added automatic module name for JPMS compatibility diff --git a/src/main/java/de/stklcode/jvault/connector/builder/HTTPVaultConnectorBuilder.java b/src/main/java/de/stklcode/jvault/connector/builder/HTTPVaultConnectorBuilder.java new file mode 100644 index 0000000..f79212b --- /dev/null +++ b/src/main/java/de/stklcode/jvault/connector/builder/HTTPVaultConnectorBuilder.java @@ -0,0 +1,284 @@ +/* + * Copyright 2016-2018 Stefan Kalscheuer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package de.stklcode.jvault.connector.builder; + +import de.stklcode.jvault.connector.HTTPVaultConnector; +import de.stklcode.jvault.connector.exception.ConnectionException; +import de.stklcode.jvault.connector.exception.TlsException; +import de.stklcode.jvault.connector.exception.VaultConnectorException; +import de.stklcode.jvault.connector.factory.VaultConnectorFactory; + +import javax.net.ssl.SSLContext; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; + +/** + * Vault Connector Factory implementation for HTTP Vault connectors. + * + * @author Stefan Kalscheuer + * @since 0.1 + */ +public final class HTTPVaultConnectorBuilder extends VaultConnectorFactory { + private static final String ENV_VAULT_ADDR = "VAULT_ADDR"; + private static final String ENV_VAULT_CACERT = "VAULT_CACERT"; + private static final String ENV_VAULT_TOKEN = "VAULT_TOKEN"; + private static final String ENV_VAULT_MAX_RETRIES = "VAULT_MAX_RETRIES"; + + public static final String DEFAULT_HOST = "127.0.0.1"; + public static final Integer DEFAULT_PORT = 8200; + public static final boolean DEFAULT_TLS = true; + public static final String DEFAULT_PREFIX = "/v1/"; + public static final int DEFAULT_NUMBER_OF_RETRIES = 0; + + private String host; + private Integer port; + private boolean tls; + private String prefix; + private X509Certificate trustedCA; + private int numberOfRetries; + private Integer timeout; + private String token; + + /** + * Default empty constructor. + * Initializes factory with default values. + */ + public HTTPVaultConnectorBuilder() { + host = DEFAULT_HOST; + port = DEFAULT_PORT; + tls = DEFAULT_TLS; + prefix = DEFAULT_PREFIX; + numberOfRetries = DEFAULT_NUMBER_OF_RETRIES; + } + + /** + * Set hostname (default: 127.0.0.1). + * + * @param host Hostname or IP address + * @return self + */ + public HTTPVaultConnectorBuilder withHost(final String host) { + this.host = host; + return this; + } + + /** + * Set port (default: 8200). + * + * @param port Vault TCP port + * @return self + */ + public HTTPVaultConnectorBuilder withPort(final Integer port) { + this.port = port; + return this; + } + + /** + * Set TLS usage (default: TRUE). + * + * @param useTLS use TLS or not + * @return self + */ + public HTTPVaultConnectorBuilder withTLS(final boolean useTLS) { + this.tls = useTLS; + return this; + } + + /** + * Convenience Method for TLS usage (enabled by default). + * + * @return self + */ + public HTTPVaultConnectorBuilder withTLS() { + return withTLS(true); + } + + /** + * Convenience Method for NOT using TLS. + * + * @return self + */ + public HTTPVaultConnectorBuilder withoutTLS() { + return withTLS(false); + } + + /** + * Set API prefix. Default is "/v1/" and changes should not be necessary for current state of development. + * + * @param prefix Vault API prefix (default: "/v1/" + * @return self + */ + public HTTPVaultConnectorBuilder withPrefix(final String prefix) { + this.prefix = prefix; + return this; + } + + /** + * Add a trusted CA certifiate for HTTPS connections. + * + * @param cert path to certificate file + * @return self + * @throws VaultConnectorException on error + * @since 0.4.0 + */ + public HTTPVaultConnectorBuilder withTrustedCA(final Path cert) throws VaultConnectorException { + if (cert != null) { + return withTrustedCA(certificateFromFile(cert)); + } else { + this.trustedCA = null; + } + return this; + } + + /** + * Add a trusted CA certifiate for HTTPS connections. + * + * @param cert path to certificate file + * @return self + * @since 0.8.0 + */ + public HTTPVaultConnectorBuilder withTrustedCA(final X509Certificate cert) { + this.trustedCA = cert; + return this; + } + + /** + * Add a custom SSL context. + * Overwrites certificates set by {@link #withTrustedCA}. + * + * @param sslContext the SSL context + * @return self + * @since 0.4.0 + * @deprecated As of 0.8.0 this is no longer supported, please use {@link #withTrustedCA(Path)} or {@link #withTrustedCA(X509Certificate)}. + */ + public HTTPVaultConnectorBuilder withSslContext(final SSLContext sslContext) { + throw new UnsupportedOperationException("Use of deprecated method, please switch to withTrustedCA()"); + } + + /** + * Set token for automatic authentication, using {@link #buildAndAuth()}. + * + * @param token Vault token + * @return self + * @since 0.6.0 + */ + public HTTPVaultConnectorBuilder withToken(final String token) { + this.token = token; + return this; + } + + /** + * Build connector based on the {@code }VAULT_ADDR} and {@code VAULT_CACERT} (optional) environment variables. + * + * @return self + * @throws VaultConnectorException if Vault address from environment variables is malformed + * @since 0.6.0 + */ + public HTTPVaultConnectorBuilder fromEnv() throws VaultConnectorException { + /* Parse URL from environment variable */ + if (System.getenv(ENV_VAULT_ADDR) != null && !System.getenv(ENV_VAULT_ADDR).trim().isEmpty()) { + try { + URL url = new URL(System.getenv(ENV_VAULT_ADDR)); + this.host = url.getHost(); + this.port = url.getPort(); + this.tls = url.getProtocol().equals("https"); + } catch (MalformedURLException e) { + throw new ConnectionException("URL provided in environment variable malformed", e); + } + } + + /* Read number of retries */ + if (System.getenv(ENV_VAULT_MAX_RETRIES) != null) { + try { + numberOfRetries = Integer.parseInt(System.getenv(ENV_VAULT_MAX_RETRIES)); + } catch (NumberFormatException ignored) { + /* Ignore malformed values. */ + } + } + + /* Read token */ + token = System.getenv(ENV_VAULT_TOKEN); + + /* Parse certificate, if set */ + if (System.getenv(ENV_VAULT_CACERT) != null && !System.getenv(ENV_VAULT_CACERT).trim().isEmpty()) { + return withTrustedCA(Paths.get(System.getenv(ENV_VAULT_CACERT))); + } + return this; + } + + /** + * Define the number of retries to attempt on 5xx errors. + * + * @param numberOfRetries The number of retries to attempt on 5xx errors (default: 0) + * @return self + * @since 0.6.0 + */ + public HTTPVaultConnectorBuilder withNumberOfRetries(final int numberOfRetries) { + this.numberOfRetries = numberOfRetries; + return this; + } + + /** + * Define a custom timeout for the HTTP connection. + * + * @param milliseconds Timeout value in milliseconds. + * @return self + * @since 0.6.0 + */ + public HTTPVaultConnectorBuilder withTimeout(final int milliseconds) { + this.timeout = milliseconds; + return this; + } + + @Override + public HTTPVaultConnector build() { + return new HTTPVaultConnector(host, tls, port, prefix, trustedCA, numberOfRetries, timeout); + } + + @Override + public HTTPVaultConnector buildAndAuth() throws VaultConnectorException { + if (token == null) + throw new ConnectionException("No vault token provided, unable to authenticate."); + HTTPVaultConnector con = new HTTPVaultConnector(host, tls, port, prefix, trustedCA, numberOfRetries, timeout); + con.authToken(token); + return con; + } + + /** + * Read given certificate file to X.509 certificate. + * + * @param certFile Path to certificate file + * @return X.509 Certificate object + * @throws TlsException on error + * @since 0.4.0 + */ + private X509Certificate certificateFromFile(final Path certFile) throws TlsException { + try (InputStream is = Files.newInputStream(certFile)) { + return (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(is); + } catch (IOException | CertificateException e) { + throw new TlsException("Unable to read certificate.", e); + } + } +} diff --git a/src/main/java/de/stklcode/jvault/connector/builder/VaultConnectorBuilder.java b/src/main/java/de/stklcode/jvault/connector/builder/VaultConnectorBuilder.java new file mode 100644 index 0000000..2697089 --- /dev/null +++ b/src/main/java/de/stklcode/jvault/connector/builder/VaultConnectorBuilder.java @@ -0,0 +1,54 @@ +/* + * Copyright 2016-2018 Stefan Kalscheuer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package de.stklcode.jvault.connector.builder; + +import de.stklcode.jvault.connector.VaultConnector; +import de.stklcode.jvault.connector.exception.VaultConnectorException; + +/** + * Abstract Vault Connector Builder interface. + * Provides builder style for Vault connectors. + * + * @author Stefan Kalscheuer + * @since 0.8.0 + */ +public interface VaultConnectorBuilder { + /** + * Get Factory implementation for HTTP Vault Connector. + * + * @return HTTP Connector Factory + */ + static HTTPVaultConnectorBuilder http() { + return new HTTPVaultConnectorBuilder(); + } + + /** + * Build command, produces connector after initialization. + * + * @return Vault Connector instance. + */ + VaultConnector build(); + + /** + * Build connector and authenticate with token set in factory or from environment. + * + * @return Authenticated Vault connector instance. + * @throws VaultConnectorException if authentication failed + * @since 0.6.0 + */ + VaultConnector buildAndAuth() throws VaultConnectorException; +} diff --git a/src/main/java/de/stklcode/jvault/connector/factory/HTTPVaultConnectorFactory.java b/src/main/java/de/stklcode/jvault/connector/factory/HTTPVaultConnectorFactory.java index 7d80c83..98e57f8 100644 --- a/src/main/java/de/stklcode/jvault/connector/factory/HTTPVaultConnectorFactory.java +++ b/src/main/java/de/stklcode/jvault/connector/factory/HTTPVaultConnectorFactory.java @@ -17,20 +17,11 @@ package de.stklcode.jvault.connector.factory; import de.stklcode.jvault.connector.HTTPVaultConnector; -import de.stklcode.jvault.connector.exception.ConnectionException; -import de.stklcode.jvault.connector.exception.TlsException; +import de.stklcode.jvault.connector.builder.HTTPVaultConnectorBuilder; import de.stklcode.jvault.connector.exception.VaultConnectorException; import javax.net.ssl.SSLContext; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; /** @@ -38,38 +29,19 @@ import java.security.cert.X509Certificate; * * @author Stefan Kalscheuer * @since 0.1 + * @deprecated As of 0.8.0 please refer to {@link de.stklcode.jvault.connector.builder.HTTPVaultConnectorBuilder} with identical API. */ +@Deprecated public final class HTTPVaultConnectorFactory extends VaultConnectorFactory { - private static final String ENV_VAULT_ADDR = "VAULT_ADDR"; - private static final String ENV_VAULT_CACERT = "VAULT_CACERT"; - private static final String ENV_VAULT_TOKEN = "VAULT_TOKEN"; - private static final String ENV_VAULT_MAX_RETRIES = "VAULT_MAX_RETRIES"; - public static final String DEFAULT_HOST = "127.0.0.1"; - public static final Integer DEFAULT_PORT = 8200; - public static final boolean DEFAULT_TLS = true; - public static final String DEFAULT_PREFIX = "/v1/"; - public static final int DEFAULT_NUMBER_OF_RETRIES = 0; - - private String host; - private Integer port; - private boolean tls; - private String prefix; - private X509Certificate trustedCA; - private int numberOfRetries; - private Integer timeout; - private String token; + private final HTTPVaultConnectorBuilder delegate; /** * Default empty constructor. * Initializes factory with default values. */ public HTTPVaultConnectorFactory() { - host = DEFAULT_HOST; - port = DEFAULT_PORT; - tls = DEFAULT_TLS; - prefix = DEFAULT_PREFIX; - numberOfRetries = DEFAULT_NUMBER_OF_RETRIES; + delegate = new HTTPVaultConnectorBuilder(); } /** @@ -79,7 +51,7 @@ public final class HTTPVaultConnectorFactory extends VaultConnectorFactory { * @return self */ public HTTPVaultConnectorFactory withHost(final String host) { - this.host = host; + delegate.withHost(host); return this; } @@ -90,7 +62,7 @@ public final class HTTPVaultConnectorFactory extends VaultConnectorFactory { * @return self */ public HTTPVaultConnectorFactory withPort(final Integer port) { - this.port = port; + delegate.withPort(port); return this; } @@ -101,7 +73,7 @@ public final class HTTPVaultConnectorFactory extends VaultConnectorFactory { * @return self */ public HTTPVaultConnectorFactory withTLS(final boolean useTLS) { - this.tls = useTLS; + delegate.withTLS(useTLS); return this; } @@ -130,7 +102,7 @@ public final class HTTPVaultConnectorFactory extends VaultConnectorFactory { * @return self */ public HTTPVaultConnectorFactory withPrefix(final String prefix) { - this.prefix = prefix; + delegate.withPrefix(prefix); return this; } @@ -143,11 +115,7 @@ public final class HTTPVaultConnectorFactory extends VaultConnectorFactory { * @since 0.4.0 */ public HTTPVaultConnectorFactory withTrustedCA(final Path cert) throws VaultConnectorException { - if (cert != null) { - return withTrustedCA(certificateFromFile(cert)); - } else { - this.trustedCA = null; - } + delegate.withTrustedCA(cert); return this; } @@ -159,7 +127,7 @@ public final class HTTPVaultConnectorFactory extends VaultConnectorFactory { * @since 0.8.0 */ public HTTPVaultConnectorFactory withTrustedCA(final X509Certificate cert) { - this.trustedCA = cert; + delegate.withTrustedCA(cert); return this; } @@ -184,7 +152,7 @@ public final class HTTPVaultConnectorFactory extends VaultConnectorFactory { * @since 0.6.0 */ public HTTPVaultConnectorFactory withToken(final String token) { - this.token = token; + delegate.withToken(token); return this; } @@ -196,34 +164,7 @@ public final class HTTPVaultConnectorFactory extends VaultConnectorFactory { * @since 0.6.0 */ public HTTPVaultConnectorFactory fromEnv() throws VaultConnectorException { - /* Parse URL from environment variable */ - if (System.getenv(ENV_VAULT_ADDR) != null && !System.getenv(ENV_VAULT_ADDR).trim().isEmpty()) { - try { - URL url = new URL(System.getenv(ENV_VAULT_ADDR)); - this.host = url.getHost(); - this.port = url.getPort(); - this.tls = url.getProtocol().equals("https"); - } catch (MalformedURLException e) { - throw new ConnectionException("URL provided in environment variable malformed", e); - } - } - - /* Read number of retries */ - if (System.getenv(ENV_VAULT_MAX_RETRIES) != null) { - try { - numberOfRetries = Integer.parseInt(System.getenv(ENV_VAULT_MAX_RETRIES)); - } catch (NumberFormatException ignored) { - /* Ignore malformed values. */ - } - } - - /* Read token */ - token = System.getenv(ENV_VAULT_TOKEN); - - /* Parse certificate, if set */ - if (System.getenv(ENV_VAULT_CACERT) != null && !System.getenv(ENV_VAULT_CACERT).trim().isEmpty()) { - return withTrustedCA(Paths.get(System.getenv(ENV_VAULT_CACERT))); - } + delegate.fromEnv(); return this; } @@ -235,7 +176,7 @@ public final class HTTPVaultConnectorFactory extends VaultConnectorFactory { * @since 0.6.0 */ public HTTPVaultConnectorFactory withNumberOfRetries(final int numberOfRetries) { - this.numberOfRetries = numberOfRetries; + delegate.withNumberOfRetries(numberOfRetries); return this; } @@ -247,37 +188,17 @@ public final class HTTPVaultConnectorFactory extends VaultConnectorFactory { * @since 0.6.0 */ public HTTPVaultConnectorFactory withTimeout(final int milliseconds) { - this.timeout = milliseconds; + delegate.withTimeout(milliseconds); return this; } @Override public HTTPVaultConnector build() { - return new HTTPVaultConnector(host, tls, port, prefix, trustedCA, numberOfRetries, timeout); + return delegate.build(); } @Override public HTTPVaultConnector buildAndAuth() throws VaultConnectorException { - if (token == null) - throw new ConnectionException("No vault token provided, unable to authenticate."); - HTTPVaultConnector con = new HTTPVaultConnector(host, tls, port, prefix, trustedCA, numberOfRetries, timeout); - con.authToken(token); - return con; - } - - /** - * Read given certificate file to X.509 certificate. - * - * @param certFile Path to certificate file - * @return X.509 Certificate object - * @throws TlsException on error - * @since 0.4.0 - */ - private X509Certificate certificateFromFile(final Path certFile) throws TlsException { - try (InputStream is = Files.newInputStream(certFile)) { - return (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(is); - } catch (IOException | CertificateException e) { - throw new TlsException("Unable to read certificate.", e); - } + return delegate.buildAndAuth(); } } diff --git a/src/main/java/de/stklcode/jvault/connector/factory/VaultConnectorFactory.java b/src/main/java/de/stklcode/jvault/connector/factory/VaultConnectorFactory.java index 5c43f43..caf6385 100644 --- a/src/main/java/de/stklcode/jvault/connector/factory/VaultConnectorFactory.java +++ b/src/main/java/de/stklcode/jvault/connector/factory/VaultConnectorFactory.java @@ -17,6 +17,7 @@ package de.stklcode.jvault.connector.factory; import de.stklcode.jvault.connector.VaultConnector; +import de.stklcode.jvault.connector.builder.VaultConnectorBuilder; import de.stklcode.jvault.connector.exception.VaultConnectorException; /** @@ -25,13 +26,17 @@ import de.stklcode.jvault.connector.exception.VaultConnectorException; * * @author Stefan Kalscheuer * @since 0.1 + * @deprecated As of 0.8.0 please refer to {@link VaultConnectorBuilder} with identical API. */ -public abstract class VaultConnectorFactory { +@Deprecated +public abstract class VaultConnectorFactory implements VaultConnectorBuilder { /** * Get Factory implementation for HTTP Vault Connector. * * @return HTTP Connector Factory + * @deprecated As of 0.8.0 please refer to {@link VaultConnectorBuilder#http()}. */ + @Deprecated public static HTTPVaultConnectorFactory httpFactory() { return new HTTPVaultConnectorFactory(); } diff --git a/src/test/java/de/stklcode/jvault/connector/builder/HTTPVaultConnectorBuilderTest.java b/src/test/java/de/stklcode/jvault/connector/builder/HTTPVaultConnectorBuilderTest.java new file mode 100644 index 0000000..d43492b --- /dev/null +++ b/src/test/java/de/stklcode/jvault/connector/builder/HTTPVaultConnectorBuilderTest.java @@ -0,0 +1,130 @@ +/* + * Copyright 2016-2018 Stefan Kalscheuer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package de.stklcode.jvault.connector.builder; + +import de.stklcode.jvault.connector.HTTPVaultConnector; +import de.stklcode.jvault.connector.exception.TlsException; +import de.stklcode.jvault.connector.exception.VaultConnectorException; +import de.stklcode.jvault.connector.factory.VaultConnectorFactory; +import org.junit.Rule; +import org.junit.contrib.java.lang.system.EnvironmentVariables; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.migrationsupport.rules.EnableRuleMigrationSupport; +import org.junit.rules.TemporaryFolder; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.nio.file.NoSuchFileException; + +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.fail; + +/** + * JUnit test for HTTP Vault connector factory + * + * @author Stefan Kalscheuer + * @since 0.8.0 + */ +@EnableRuleMigrationSupport +public class HTTPVaultConnectorBuilderTest { + private static String VAULT_ADDR = "https://localhost:8201"; + private static Integer VAULT_MAX_RETRIES = 13; + private static String VAULT_TOKEN = "00001111-2222-3333-4444-555566667777"; + + @Rule + public TemporaryFolder tmpDir = new TemporaryFolder(); + + @Rule + public final EnvironmentVariables environment = new EnvironmentVariables(); + + /** + * Test building from environment variables + */ + @Test + public void testFromEnv() throws NoSuchFieldException, IllegalAccessException, IOException { + /* Provide address only should be enough */ + setenv(VAULT_ADDR, null, null, null); + + HTTPVaultConnectorBuilder factory = null; + HTTPVaultConnector connector; + try { + factory = VaultConnectorBuilder.http().fromEnv(); + } catch (VaultConnectorException e) { + fail("Factory creation from minimal environment failed"); + } + connector = factory.build(); + + assertThat("URL nor set correctly", getPrivate(connector, "baseURL"), is(equalTo(VAULT_ADDR + "/v1/"))); + assertThat("Trusted CA cert set when no cert provided", getPrivate(connector, "trustedCaCert"), is(nullValue())); + assertThat("Non-default number of retries, when none set", getPrivate(connector, "retries"), is(0)); + + /* Provide address and number of retries */ + setenv(VAULT_ADDR, null, VAULT_MAX_RETRIES.toString(), null); + + try { + factory = VaultConnectorBuilder.http().fromEnv(); + } catch (VaultConnectorException e) { + fail("Factory creation from environment failed"); + } + connector = factory.build(); + + assertThat("URL nor set correctly", getPrivate(connector, "baseURL"), is(equalTo(VAULT_ADDR + "/v1/"))); + assertThat("Trusted CA cert set when no cert provided", getPrivate(connector, "trustedCaCert"), is(nullValue())); + assertThat("Number of retries not set correctly", getPrivate(connector, "retries"), is(VAULT_MAX_RETRIES)); + + /* Provide CA certificate */ + String VAULT_CACERT = tmpDir.newFolder().toString() + "/doesnotexist"; + setenv(VAULT_ADDR, VAULT_CACERT, VAULT_MAX_RETRIES.toString(), null); + + try { + VaultConnectorFactory.httpFactory().fromEnv(); + fail("Creation with unknown cert path failed."); + } catch (VaultConnectorException e) { + assertThat(e, is(instanceOf(TlsException.class))); + assertThat(e.getCause(), is(instanceOf(NoSuchFileException.class))); + assertThat(((NoSuchFileException) e.getCause()).getFile(), is(VAULT_CACERT)); + } + + /* Automatic authentication */ + setenv(VAULT_ADDR, null, VAULT_MAX_RETRIES.toString(), VAULT_TOKEN); + + try { + factory = VaultConnectorBuilder.http().fromEnv(); + } catch (VaultConnectorException e) { + fail("Factory creation from minimal environment failed"); + } + assertThat("Token nor set correctly", getPrivate(factory, "token"), is(equalTo(VAULT_TOKEN))); + } + + private void setenv(String vault_addr, String vault_cacert, String vault_max_retries, String vault_token) { + environment.set("VAULT_ADDR", vault_addr); + environment.set("VAULT_CACERT", vault_cacert); + environment.set("VAULT_MAX_RETRIES", vault_max_retries); + environment.set("VAULT_TOKEN", vault_token); + } + + private Object getPrivate(Object target, String fieldName) throws NoSuchFieldException, IllegalAccessException { + Field field = target.getClass().getDeclaredField(fieldName); + if (field.isAccessible()) + return field.get(target); + field.setAccessible(true); + Object value = field.get(target); + field.setAccessible(false); + return value; + } +} diff --git a/src/test/java/de/stklcode/jvault/connector/factory/HTTPVaultConnectorFactoryTest.java b/src/test/java/de/stklcode/jvault/connector/factory/HTTPVaultConnectorFactoryTest.java index 8e4901b..7673b34 100644 --- a/src/test/java/de/stklcode/jvault/connector/factory/HTTPVaultConnectorFactoryTest.java +++ b/src/test/java/de/stklcode/jvault/connector/factory/HTTPVaultConnectorFactoryTest.java @@ -107,7 +107,7 @@ public class HTTPVaultConnectorFactoryTest { } catch (VaultConnectorException e) { fail("Factory creation from minimal environment failed"); } - assertThat("Token nor set correctly", getPrivate(factory, "token"), is(equalTo(VAULT_TOKEN))); + assertThat("Token nor set correctly", getPrivate(getPrivate(factory, "delegate"), "token"), is(equalTo(VAULT_TOKEN))); } private void setenv(String vault_addr, String vault_cacert, String vault_max_retries, String vault_token) {