From c111a6aff080356dcdc14d1c668f9576a75f5323 Mon Sep 17 00:00:00 2001 From: Stefan Kalscheuer Date: Sat, 6 Oct 2018 14:24:06 +0200 Subject: [PATCH] Enforce TLS 1.2 by default with option to override (#22) The TLS version can be explicitly set in builder or constructor. If not given, the connector will only use 1.2 as Vault does by default, too. --- CHANGELOG.md | 1 + .../jvault/connector/HTTPVaultConnector.java | 30 ++++++++++++++-- .../builder/HTTPVaultConnectorBuilder.java | 35 +++++++++++++++++-- .../HTTPVaultConnectorOfflineTest.java | 8 ++++- 4 files changed, 67 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d3bdb85..6ff3a3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ refactoring of the internal SSL handling (#17) * [improvement] `VaultConnector` extends `java.io.Serializable` (#19) * [improvement] Added missing flags to `SealResponse` (#20) * [improvement] Added replication flags to `HealthResponse` (#21) +* [improvement] Enforce TLS 1.2 by default with option to override (#22) * [improvement] Build environment and tests now compatible with Java 10 * [dependencies] Updated dependencies to fix vulnerabilities (i.e. CVE-2018-7489) * [deprecation] `VaultConnectorFactory` is deprecated in favor of `VaultConnectorBuilder` with identical API (#18) diff --git a/src/main/java/de/stklcode/jvault/connector/HTTPVaultConnector.java b/src/main/java/de/stklcode/jvault/connector/HTTPVaultConnector.java index d00b1fd..668d1e3 100644 --- a/src/main/java/de/stklcode/jvault/connector/HTTPVaultConnector.java +++ b/src/main/java/de/stklcode/jvault/connector/HTTPVaultConnector.java @@ -77,9 +77,12 @@ public class HTTPVaultConnector implements VaultConnector { private static final String HEADER_VAULT_TOKEN = "X-Vault-Token"; + public static final String DEFAULT_TLS_VERSION = "TLSv1.2"; + private final ObjectMapper jsonMapper; private final String baseURL; // Base URL of Vault. + private final String tlsVersion; // TLS version (#22). private final X509Certificate trustedCaCert; // Trusted CA certificate. private final int retries; // Number of retries on 5xx errors. private final Integer timeout; // Timeout in milliseconds. @@ -138,7 +141,7 @@ public class HTTPVaultConnector implements VaultConnector { final Integer port, final String prefix, final X509Certificate trustedCaCert) { - this(hostname, useTLS, port, prefix, trustedCaCert, 0, null); + this(hostname, useTLS, DEFAULT_TLS_VERSION, port, prefix, trustedCaCert, 0, null); } /** @@ -146,6 +149,7 @@ public class HTTPVaultConnector implements VaultConnector { * * @param hostname The hostname * @param useTLS If TRUE, use HTTPS, otherwise HTTP + * @param tlsVersion TLS version * @param port The port * @param prefix HTTP API prefix (default: /v1/) * @param trustedCaCert Trusted CA certificate @@ -154,6 +158,7 @@ public class HTTPVaultConnector implements VaultConnector { */ public HTTPVaultConnector(final String hostname, final boolean useTLS, + final String tlsVersion, final Integer port, final String prefix, final X509Certificate trustedCaCert, @@ -165,7 +170,8 @@ public class HTTPVaultConnector implements VaultConnector { + prefix, trustedCaCert, numberOfRetries, - timeout); + timeout, + tlsVersion); } /** @@ -210,10 +216,28 @@ public class HTTPVaultConnector implements VaultConnector { final X509Certificate trustedCaCert, final int numberOfRetries, final Integer timeout) { + this(baseURL, trustedCaCert, numberOfRetries, timeout, DEFAULT_TLS_VERSION); + } + + /** + * Create connector using full URL and trusted certificate. + * + * @param baseURL The URL + * @param trustedCaCert Trusted CA certificate + * @param numberOfRetries Number of retries on 5xx errors + * @param timeout Timeout for HTTP requests (milliseconds) + * @param tlsVersion TLS Version. + */ + public HTTPVaultConnector(final String baseURL, + final X509Certificate trustedCaCert, + final int numberOfRetries, + final Integer timeout, + final String tlsVersion) { this.baseURL = baseURL; this.trustedCaCert = trustedCaCert; this.retries = numberOfRetries; this.timeout = timeout; + this.tlsVersion = tlsVersion; this.jsonMapper = new ObjectMapper(); } @@ -928,7 +952,7 @@ public class HTTPVaultConnector implements VaultConnector { tmf.init(keyStore); // Create context usint this TrustManager. - SSLContext context = SSLContext.getInstance("TLS"); + SSLContext context = SSLContext.getInstance(tlsVersion); context.init(null, tmf.getTrustManagers(), new SecureRandom()); return new SSLConnectionSocketFactory( diff --git a/src/main/java/de/stklcode/jvault/connector/builder/HTTPVaultConnectorBuilder.java b/src/main/java/de/stklcode/jvault/connector/builder/HTTPVaultConnectorBuilder.java index 70896fd..3906388 100644 --- a/src/main/java/de/stklcode/jvault/connector/builder/HTTPVaultConnectorBuilder.java +++ b/src/main/java/de/stklcode/jvault/connector/builder/HTTPVaultConnectorBuilder.java @@ -47,12 +47,14 @@ public final class HTTPVaultConnectorBuilder implements VaultConnectorBuilder { 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_TLS_VERSION = "TLSv1.2"; 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 tlsVersion; private String prefix; private X509Certificate trustedCA; private int numberOfRetries; @@ -67,6 +69,7 @@ public final class HTTPVaultConnectorBuilder implements VaultConnectorBuilder { host = DEFAULT_HOST; port = DEFAULT_PORT; tls = DEFAULT_TLS; + tlsVersion = DEFAULT_TLS_VERSION; prefix = DEFAULT_PREFIX; numberOfRetries = DEFAULT_NUMBER_OF_RETRIES; } @@ -104,6 +107,31 @@ public final class HTTPVaultConnectorBuilder implements VaultConnectorBuilder { return this; } + /** + * Set TLS usage (default: TRUE). + * + * @param useTLS Use TLS or not. + * @param version Supported TLS version ({@code TLSv1.2}, {@code TLSv1.1}, {@code TLSv1.0}, {@code TLS}). + * @return self + * @since 0.8 Added version parameter (#22). + */ + public HTTPVaultConnectorBuilder withTLS(final boolean useTLS, final String version) { + this.tls = useTLS; + this.tlsVersion = version; + return this; + } + + /** + * Convenience Method for TLS usage (enabled by default). + * + * @param version Supported TLS version ({@code TLSv1.2}, {@code TLSv1.1}, {@code TLSv1.0}, {@code TLS}). + * @return self + * @since 0.8 Added version parameter (#22). + */ + public HTTPVaultConnectorBuilder withTLS(final String version) { + return withTLS(true, version); + } + /** * Convenience Method for TLS usage (enabled by default). * @@ -239,14 +267,15 @@ public final class HTTPVaultConnectorBuilder implements VaultConnectorBuilder { @Override public HTTPVaultConnector build() { - return new HTTPVaultConnector(host, tls, port, prefix, trustedCA, numberOfRetries, timeout); + return new HTTPVaultConnector(host, tls, tlsVersion, port, prefix, trustedCA, numberOfRetries, timeout); } @Override public HTTPVaultConnector buildAndAuth() throws VaultConnectorException { - if (token == null) + if (token == null) { throw new ConnectionException("No vault token provided, unable to authenticate."); - HTTPVaultConnector con = new HTTPVaultConnector(host, tls, port, prefix, trustedCA, numberOfRetries, timeout); + } + HTTPVaultConnector con = build(); con.authToken(token); return con; } diff --git a/src/test/java/de/stklcode/jvault/connector/HTTPVaultConnectorOfflineTest.java b/src/test/java/de/stklcode/jvault/connector/HTTPVaultConnectorOfflineTest.java index 046be8b..44b2f76 100644 --- a/src/test/java/de/stklcode/jvault/connector/HTTPVaultConnectorOfflineTest.java +++ b/src/test/java/de/stklcode/jvault/connector/HTTPVaultConnectorOfflineTest.java @@ -163,7 +163,7 @@ public class HTTPVaultConnectorOfflineTest { final String expectedNoTls = "http://" + hostname + "/v1/"; final String expectedCustomPort = "https://" + hostname + ":" + port + "/v1/"; final String expectedCustomPrefix = "https://" + hostname + ":" + port + prefix; - X509Certificate trustedCaCert = null; + X509Certificate trustedCaCert; try (InputStream is = getClass().getResourceAsStream("/tls/ca.pem")) { trustedCaCert = (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(is); @@ -194,6 +194,12 @@ public class HTTPVaultConnectorOfflineTest { // Specify number of retries. connector = new HTTPVaultConnector(url, trustedCaCert, retries); assertThat("Number of retries not set correctly", getPrivate(connector, "retries"), is(retries)); + + // Test TLS version (#22). + assertThat("TLS version should be 1.2 if not specified", getPrivate(connector, "tlsVersion"), is("TLSv1.2")); + // Now override. + connector = new HTTPVaultConnector(url, trustedCaCert, retries, null, "TLSv1.1"); + assertThat("Overridden TLS version 1.1 not correct", getPrivate(connector, "tlsVersion"), is("TLSv1.1")); } /**