Refactored custom trusted CA strategy
The connector no longer stores the final SSLContext, but the trusted X509Certificate object and creates a SSLSocketFactory as required.
This commit is contained in:
parent
0c23f47bd5
commit
1a18f9f6b7
@ -1,3 +1,8 @@
|
|||||||
|
## 0.8.0 [unreleased]
|
||||||
|
* **[breaking]** Removed support for `HTTPVaultConnectorFactory#withSslContext()` in favor of `#withTrustedCA()` due to
|
||||||
|
refactoring of the internal SSL handling.
|
||||||
|
* [improvement] `VaultConnector` extends `java.io.Serializable`
|
||||||
|
|
||||||
## 0.7.1 [2018-03-17]
|
## 0.7.1 [2018-03-17]
|
||||||
* [improvement] Added automatic module name for JPMS compatibility
|
* [improvement] Added automatic module name for JPMS compatibility
|
||||||
* [dependencies] Minor dependency updates
|
* [dependencies] Minor dependency updates
|
||||||
|
2
pom.xml
2
pom.xml
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
<groupId>de.stklcode.jvault</groupId>
|
<groupId>de.stklcode.jvault</groupId>
|
||||||
<artifactId>connector</artifactId>
|
<artifactId>connector</artifactId>
|
||||||
<version>0.7.1</version>
|
<version>0.8.0-SNAPSHOT</version>
|
||||||
|
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
@ -29,18 +29,23 @@ import org.apache.http.HttpResponse;
|
|||||||
import org.apache.http.client.config.RequestConfig;
|
import org.apache.http.client.config.RequestConfig;
|
||||||
import org.apache.http.client.methods.*;
|
import org.apache.http.client.methods.*;
|
||||||
import org.apache.http.client.utils.URIBuilder;
|
import org.apache.http.client.utils.URIBuilder;
|
||||||
|
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||||
import org.apache.http.entity.StringEntity;
|
import org.apache.http.entity.StringEntity;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
import org.apache.http.impl.client.HttpClientBuilder;
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
import org.apache.http.util.EntityUtils;
|
import org.apache.http.util.EntityUtils;
|
||||||
|
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -74,14 +79,14 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
|
|
||||||
private final ObjectMapper jsonMapper;
|
private final ObjectMapper jsonMapper;
|
||||||
|
|
||||||
private final String baseURL; /* Base URL of Vault */
|
private final String baseURL; // Base URL of Vault.
|
||||||
private final SSLContext sslContext; /* Custom SSLSocketFactory */
|
private final X509Certificate trustedCaCert; // Trusted CA certificate.
|
||||||
private final int retries; /* Number of retries on 5xx errors */
|
private final int retries; // Number of retries on 5xx errors.
|
||||||
private final Integer timeout; /* Timeout in milliseconds */
|
private final Integer timeout; // Timeout in milliseconds.
|
||||||
|
|
||||||
private boolean authorized = false; /* authorization status */
|
private boolean authorized = false; // Authorization status.
|
||||||
private String token; /* current token */
|
private String token; // Current token.
|
||||||
private long tokenTTL = 0; /* expiration time for current token */
|
private long tokenTTL = 0; // Expiration time for current token.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create connector using hostname and schema.
|
* Create connector using hostname and schema.
|
||||||
@ -122,18 +127,18 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
/**
|
/**
|
||||||
* Create connector using hostname, schema, port, path and trusted certificate.
|
* Create connector using hostname, schema, port, path and trusted certificate.
|
||||||
*
|
*
|
||||||
* @param hostname The hostname
|
* @param hostname The hostname
|
||||||
* @param useTLS If TRUE, use HTTPS, otherwise HTTP
|
* @param useTLS If TRUE, use HTTPS, otherwise HTTP
|
||||||
* @param port The port
|
* @param port The port
|
||||||
* @param prefix HTTP API prefix (default: /v1/)
|
* @param prefix HTTP API prefix (default: /v1/)
|
||||||
* @param sslContext Custom SSL Context
|
* @param trustedCaCert Trusted CA certificate
|
||||||
*/
|
*/
|
||||||
public HTTPVaultConnector(final String hostname,
|
public HTTPVaultConnector(final String hostname,
|
||||||
final boolean useTLS,
|
final boolean useTLS,
|
||||||
final Integer port,
|
final Integer port,
|
||||||
final String prefix,
|
final String prefix,
|
||||||
final SSLContext sslContext) {
|
final X509Certificate trustedCaCert) {
|
||||||
this(hostname, useTLS, port, prefix, sslContext, 0, null);
|
this(hostname, useTLS, port, prefix, trustedCaCert, 0, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -143,7 +148,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
* @param useTLS If TRUE, use HTTPS, otherwise HTTP
|
* @param useTLS If TRUE, use HTTPS, otherwise HTTP
|
||||||
* @param port The port
|
* @param port The port
|
||||||
* @param prefix HTTP API prefix (default: /v1/)
|
* @param prefix HTTP API prefix (default: /v1/)
|
||||||
* @param sslContext Custom SSL Context
|
* @param trustedCaCert Trusted CA certificate
|
||||||
* @param numberOfRetries Number of retries on 5xx errors
|
* @param numberOfRetries Number of retries on 5xx errors
|
||||||
* @param timeout Timeout for HTTP requests (milliseconds)
|
* @param timeout Timeout for HTTP requests (milliseconds)
|
||||||
*/
|
*/
|
||||||
@ -151,14 +156,14 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
final boolean useTLS,
|
final boolean useTLS,
|
||||||
final Integer port,
|
final Integer port,
|
||||||
final String prefix,
|
final String prefix,
|
||||||
final SSLContext sslContext,
|
final X509Certificate trustedCaCert,
|
||||||
final int numberOfRetries,
|
final int numberOfRetries,
|
||||||
final Integer timeout) {
|
final Integer timeout) {
|
||||||
this(((useTLS) ? "https" : "http")
|
this(((useTLS) ? "https" : "http")
|
||||||
+ "://" + hostname
|
+ "://" + hostname
|
||||||
+ ((port != null) ? ":" + port : "")
|
+ ((port != null) ? ":" + port : "")
|
||||||
+ prefix,
|
+ prefix,
|
||||||
sslContext,
|
trustedCaCert,
|
||||||
numberOfRetries,
|
numberOfRetries,
|
||||||
timeout);
|
timeout);
|
||||||
}
|
}
|
||||||
@ -175,38 +180,38 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
/**
|
/**
|
||||||
* Create connector using full URL and trusted certificate.
|
* Create connector using full URL and trusted certificate.
|
||||||
*
|
*
|
||||||
* @param baseURL The URL
|
* @param baseURL The URL
|
||||||
* @param sslContext Custom SSL Context
|
* @param trustedCaCert Trusted CA certificate
|
||||||
*/
|
*/
|
||||||
public HTTPVaultConnector(final String baseURL, final SSLContext sslContext) {
|
public HTTPVaultConnector(final String baseURL, final X509Certificate trustedCaCert) {
|
||||||
this(baseURL, sslContext, 0, null);
|
this(baseURL, trustedCaCert, 0, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create connector using full URL and trusted certificate.
|
* Create connector using full URL and trusted certificate.
|
||||||
*
|
*
|
||||||
* @param baseURL The URL
|
* @param baseURL The URL
|
||||||
* @param sslContext Custom SSL Context
|
* @param trustedCaCert Trusted CA certificate
|
||||||
* @param numberOfRetries Number of retries on 5xx errors
|
* @param numberOfRetries Number of retries on 5xx errors
|
||||||
*/
|
*/
|
||||||
public HTTPVaultConnector(final String baseURL, final SSLContext sslContext, final int numberOfRetries) {
|
public HTTPVaultConnector(final String baseURL, final X509Certificate trustedCaCert, final int numberOfRetries) {
|
||||||
this(baseURL, sslContext, numberOfRetries, null);
|
this(baseURL, trustedCaCert, numberOfRetries, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create connector using full URL and trusted certificate.
|
* Create connector using full URL and trusted certificate.
|
||||||
*
|
*
|
||||||
* @param baseURL The URL
|
* @param baseURL The URL
|
||||||
* @param sslContext Custom SSL Context
|
* @param trustedCaCert Trusted CA certificate
|
||||||
* @param numberOfRetries Number of retries on 5xx errors
|
* @param numberOfRetries Number of retries on 5xx errors
|
||||||
* @param timeout Timeout for HTTP requests (milliseconds)
|
* @param timeout Timeout for HTTP requests (milliseconds)
|
||||||
*/
|
*/
|
||||||
public HTTPVaultConnector(final String baseURL,
|
public HTTPVaultConnector(final String baseURL,
|
||||||
final SSLContext sslContext,
|
final X509Certificate trustedCaCert,
|
||||||
final int numberOfRetries,
|
final int numberOfRetries,
|
||||||
final Integer timeout) {
|
final Integer timeout) {
|
||||||
this.baseURL = baseURL;
|
this.baseURL = baseURL;
|
||||||
this.sslContext = sslContext;
|
this.trustedCaCert = trustedCaCert;
|
||||||
this.retries = numberOfRetries;
|
this.retries = numberOfRetries;
|
||||||
this.timeout = timeout;
|
this.timeout = timeout;
|
||||||
this.jsonMapper = new ObjectMapper();
|
this.jsonMapper = new ObjectMapper();
|
||||||
@ -818,8 +823,11 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
/* Set JSON Header */
|
/* Set JSON Header */
|
||||||
base.addHeader("accept", "application/json");
|
base.addHeader("accept", "application/json");
|
||||||
|
|
||||||
HttpResponse response = null;
|
CloseableHttpResponse response = null;
|
||||||
try (CloseableHttpClient httpClient = HttpClientBuilder.create().setSSLContext(sslContext).build()) {
|
|
||||||
|
try (CloseableHttpClient httpClient = HttpClientBuilder.create()
|
||||||
|
.setSSLSocketFactory(createSSLSocketFactory())
|
||||||
|
.build()) {
|
||||||
/* Set custom timeout, if defined */
|
/* Set custom timeout, if defined */
|
||||||
if (this.timeout != null)
|
if (this.timeout != null)
|
||||||
base.setConfig(RequestConfig.copy(RequestConfig.DEFAULT).setConnectTimeout(timeout).build());
|
base.setConfig(RequestConfig.copy(RequestConfig.DEFAULT).setConnectTimeout(timeout).build());
|
||||||
@ -890,7 +898,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
new InputStreamReader(response.getEntity().getContent()))) {
|
new InputStreamReader(response.getEntity().getContent()))) {
|
||||||
String responseString = br.lines().collect(Collectors.joining("\n"));
|
String responseString = br.lines().collect(Collectors.joining("\n"));
|
||||||
ErrorResponse er = jsonMapper.readValue(responseString, ErrorResponse.class);
|
ErrorResponse er = jsonMapper.readValue(responseString, ErrorResponse.class);
|
||||||
/* Check for "permission denied" response */
|
/* Check for "permission denied" response */
|
||||||
if (!er.getErrors().isEmpty() && er.getErrors().get(0).equals("permission denied"))
|
if (!er.getErrors().isEmpty() && er.getErrors().get(0).equals("permission denied"))
|
||||||
throw new PermissionDeniedException();
|
throw new PermissionDeniedException();
|
||||||
throw new InvalidResponseException(Error.RESPONSE_CODE,
|
throw new InvalidResponseException(Error.RESPONSE_CODE,
|
||||||
@ -901,6 +909,39 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a custom socket factory from trusted CA certificate.
|
||||||
|
*
|
||||||
|
* @return The factory.
|
||||||
|
* @throws TlsException An error occured during initialization of the SSL context.
|
||||||
|
* @since 0.8.0
|
||||||
|
*/
|
||||||
|
private SSLConnectionSocketFactory createSSLSocketFactory() throws TlsException {
|
||||||
|
try {
|
||||||
|
// Create Keystore with trusted certificate.
|
||||||
|
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||||
|
keyStore.load(null, null);
|
||||||
|
keyStore.setCertificateEntry("trustedCert", trustedCaCert);
|
||||||
|
|
||||||
|
// Initialize TrustManager.
|
||||||
|
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||||
|
tmf.init(keyStore);
|
||||||
|
|
||||||
|
// Create context usint this TrustManager.
|
||||||
|
SSLContext context = SSLContext.getInstance("TLS");
|
||||||
|
context.init(null, tmf.getTrustManagers(), new SecureRandom());
|
||||||
|
|
||||||
|
return new SSLConnectionSocketFactory(
|
||||||
|
context,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
SSLConnectionSocketFactory.getDefaultHostnameVerifier()
|
||||||
|
);
|
||||||
|
} catch (CertificateException | NoSuchAlgorithmException | KeyStoreException | IOException | KeyManagementException e) {
|
||||||
|
throw new TlsException(Error.INIT_SSL_CONTEXT, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inner class to bundle common error messages.
|
* Inner class to bundle common error messages.
|
||||||
*/
|
*/
|
||||||
@ -910,6 +951,7 @@ public class HTTPVaultConnector implements VaultConnector {
|
|||||||
private static final String UNEXPECTED_RESPONSE = "Received response where none was expected";
|
private static final String UNEXPECTED_RESPONSE = "Received response where none was expected";
|
||||||
private static final String URI_FORMAT = "Invalid URI format";
|
private static final String URI_FORMAT = "Invalid URI format";
|
||||||
private static final String RESPONSE_CODE = "Invalid response code";
|
private static final String RESPONSE_CODE = "Invalid response code";
|
||||||
|
private static final String INIT_SSL_CONTEXT = "Unable to intialize SSLContext";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor hidden, this class should not be instantiated.
|
* Constructor hidden, this class should not be instantiated.
|
||||||
|
@ -21,6 +21,7 @@ import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
|||||||
import de.stklcode.jvault.connector.model.*;
|
import de.stklcode.jvault.connector.model.*;
|
||||||
import de.stklcode.jvault.connector.model.response.*;
|
import de.stklcode.jvault.connector.model.response.*;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -33,7 +34,7 @@ import java.util.Map;
|
|||||||
* @author Stefan Kalscheuer
|
* @author Stefan Kalscheuer
|
||||||
* @since 0.1
|
* @since 0.1
|
||||||
*/
|
*/
|
||||||
public interface VaultConnector extends AutoCloseable {
|
public interface VaultConnector extends AutoCloseable, Serializable {
|
||||||
/**
|
/**
|
||||||
* Default sub-path for Vault secrets.
|
* Default sub-path for Vault secrets.
|
||||||
*/
|
*/
|
||||||
|
@ -22,8 +22,6 @@ import de.stklcode.jvault.connector.exception.TlsException;
|
|||||||
import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
import de.stklcode.jvault.connector.exception.VaultConnectorException;
|
||||||
|
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
import javax.net.ssl.TrustManager;
|
|
||||||
import javax.net.ssl.TrustManagerFactory;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
@ -31,7 +29,6 @@ import java.net.URL;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.security.*;
|
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
import java.security.cert.CertificateFactory;
|
import java.security.cert.CertificateFactory;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
@ -58,7 +55,7 @@ public final class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
|||||||
private Integer port;
|
private Integer port;
|
||||||
private boolean tls;
|
private boolean tls;
|
||||||
private String prefix;
|
private String prefix;
|
||||||
private SSLContext sslContext;
|
private X509Certificate trustedCA;
|
||||||
private int numberOfRetries;
|
private int numberOfRetries;
|
||||||
private Integer timeout;
|
private Integer timeout;
|
||||||
private String token;
|
private String token;
|
||||||
@ -146,8 +143,23 @@ public final class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
|||||||
* @since 0.4.0
|
* @since 0.4.0
|
||||||
*/
|
*/
|
||||||
public HTTPVaultConnectorFactory withTrustedCA(final Path cert) throws VaultConnectorException {
|
public HTTPVaultConnectorFactory withTrustedCA(final Path cert) throws VaultConnectorException {
|
||||||
if (cert != null)
|
if (cert != null) {
|
||||||
return withSslContext(createSslContext(cert));
|
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 HTTPVaultConnectorFactory withTrustedCA(final X509Certificate cert) {
|
||||||
|
this.trustedCA = cert;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,10 +170,10 @@ public final class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
|||||||
* @param sslContext the SSL context
|
* @param sslContext the SSL context
|
||||||
* @return self
|
* @return self
|
||||||
* @since 0.4.0
|
* @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 HTTPVaultConnectorFactory withSslContext(final SSLContext sslContext) {
|
public HTTPVaultConnectorFactory withSslContext(final SSLContext sslContext) {
|
||||||
this.sslContext = sslContext;
|
throw new UnsupportedOperationException("Use of deprecated method, please switch to withTrustedCA()");
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -241,59 +253,18 @@ public final class HTTPVaultConnectorFactory extends VaultConnectorFactory {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HTTPVaultConnector build() {
|
public HTTPVaultConnector build() {
|
||||||
return new HTTPVaultConnector(host, tls, port, prefix, sslContext, numberOfRetries, timeout);
|
return new HTTPVaultConnector(host, tls, port, prefix, trustedCA, numberOfRetries, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HTTPVaultConnector buildAndAuth() throws VaultConnectorException {
|
public HTTPVaultConnector buildAndAuth() throws VaultConnectorException {
|
||||||
if (token == null)
|
if (token == null)
|
||||||
throw new ConnectionException("No vault token provided, unable to authenticate.");
|
throw new ConnectionException("No vault token provided, unable to authenticate.");
|
||||||
HTTPVaultConnector con = new HTTPVaultConnector(host, tls, port, prefix, sslContext, numberOfRetries, timeout);
|
HTTPVaultConnector con = new HTTPVaultConnector(host, tls, port, prefix, trustedCA, numberOfRetries, timeout);
|
||||||
con.authToken(token);
|
con.authToken(token);
|
||||||
return con;
|
return con;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create SSL Context trusting only provided certificate.
|
|
||||||
*
|
|
||||||
* @param trustedCert Path to trusted CA certificate
|
|
||||||
* @return SSL context
|
|
||||||
* @throws TlsException on errors
|
|
||||||
* @since 0.4.0
|
|
||||||
*/
|
|
||||||
private SSLContext createSslContext(final Path trustedCert) throws TlsException {
|
|
||||||
try {
|
|
||||||
SSLContext context = SSLContext.getInstance("TLS");
|
|
||||||
context.init(null, createTrustManager(trustedCert), new SecureRandom());
|
|
||||||
return context;
|
|
||||||
} catch (NoSuchAlgorithmException | KeyManagementException e) {
|
|
||||||
throw new TlsException("Unable to intialize SSLContext", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a custom TrustManager for given CA certificate file.
|
|
||||||
*
|
|
||||||
* @param trustedCert Path to trusted CA certificate
|
|
||||||
* @return TrustManger
|
|
||||||
* @throws TlsException on error
|
|
||||||
* @since 0.4.0
|
|
||||||
*/
|
|
||||||
private TrustManager[] createTrustManager(final Path trustedCert) throws TlsException {
|
|
||||||
try {
|
|
||||||
/* Create Keystore with trusted certificate */
|
|
||||||
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
|
||||||
keyStore.load(null, null);
|
|
||||||
keyStore.setCertificateEntry("trustedCert", certificateFromFile(trustedCert));
|
|
||||||
/* Initialize TrustManager */
|
|
||||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
|
||||||
tmf.init(keyStore);
|
|
||||||
return tmf.getTrustManagers();
|
|
||||||
} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e) {
|
|
||||||
throw new TlsException("Unable to initialize TrustManager", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read given certificate file to X.509 certificate.
|
* Read given certificate file to X.509 certificate.
|
||||||
*
|
*
|
||||||
|
@ -34,10 +34,12 @@ import org.junit.jupiter.api.BeforeAll;
|
|||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import javax.net.ssl.SSLContext;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.cert.CertificateException;
|
||||||
|
import java.security.cert.CertificateFactory;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
import static net.bytebuddy.implementation.MethodDelegation.to;
|
import static net.bytebuddy.implementation.MethodDelegation.to;
|
||||||
@ -89,7 +91,7 @@ public class HTTPVaultConnectorOfflineTest {
|
|||||||
.load(HttpClientBuilder.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());
|
.load(HttpClientBuilder.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent());
|
||||||
|
|
||||||
// Ignore SSL context settings.
|
// Ignore SSL context settings.
|
||||||
when(httpMockBuilder.setSSLContext(null)).thenReturn(httpMockBuilder);
|
when(httpMockBuilder.setSSLSocketFactory(any())).thenReturn(httpMockBuilder);
|
||||||
|
|
||||||
// Re-initialize HTTP mock to ensure fresh (empty) results.
|
// Re-initialize HTTP mock to ensure fresh (empty) results.
|
||||||
httpMock = mock(CloseableHttpClient.class);
|
httpMock = mock(CloseableHttpClient.class);
|
||||||
@ -159,7 +161,7 @@ public class HTTPVaultConnectorOfflineTest {
|
|||||||
* Test constductors of the {@link HTTPVaultConnector} class.
|
* Test constductors of the {@link HTTPVaultConnector} class.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void constructorTest() throws NoSuchAlgorithmException {
|
public void constructorTest() throws IOException, CertificateException {
|
||||||
final String url = "https://vault.example.net/test/";
|
final String url = "https://vault.example.net/test/";
|
||||||
final String hostname = "vault.example.com";
|
final String hostname = "vault.example.com";
|
||||||
final Integer port = 1337;
|
final Integer port = 1337;
|
||||||
@ -168,7 +170,11 @@ public class HTTPVaultConnectorOfflineTest {
|
|||||||
final String expectedNoTls = "http://" + hostname + "/v1/";
|
final String expectedNoTls = "http://" + hostname + "/v1/";
|
||||||
final String expectedCustomPort = "https://" + hostname + ":" + port + "/v1/";
|
final String expectedCustomPort = "https://" + hostname + ":" + port + "/v1/";
|
||||||
final String expectedCustomPrefix = "https://" + hostname + ":" + port + prefix;
|
final String expectedCustomPrefix = "https://" + hostname + ":" + port + prefix;
|
||||||
final SSLContext sslContext = SSLContext.getInstance("TLS");
|
X509Certificate trustedCaCert = null;
|
||||||
|
|
||||||
|
try (InputStream is = getClass().getResourceAsStream("/tls/ca.pem")) {
|
||||||
|
trustedCaCert = (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(is);
|
||||||
|
}
|
||||||
|
|
||||||
// Most basic constructor expects complete URL.
|
// Most basic constructor expects complete URL.
|
||||||
HTTPVaultConnector connector = new HTTPVaultConnector(url);
|
HTTPVaultConnector connector = new HTTPVaultConnector(url);
|
||||||
@ -185,15 +191,15 @@ public class HTTPVaultConnectorOfflineTest {
|
|||||||
// Specify custom prefix.
|
// Specify custom prefix.
|
||||||
connector = new HTTPVaultConnector(hostname, true, port, prefix);
|
connector = new HTTPVaultConnector(hostname, true, port, prefix);
|
||||||
assertThat("Unexpected base URL with custom prefix", getPrivate(connector, "baseURL"), is(expectedCustomPrefix));
|
assertThat("Unexpected base URL with custom prefix", getPrivate(connector, "baseURL"), is(expectedCustomPrefix));
|
||||||
assertThat("SSL context set, but not specified", getPrivate(connector, "sslContext"), is(nullValue()));
|
assertThat("Trusted CA cert set, but not specified", getPrivate(connector, "trustedCaCert"), is(nullValue()));
|
||||||
|
|
||||||
// Provide custom SSL context.
|
// Provide custom SSL context.
|
||||||
connector = new HTTPVaultConnector(hostname, true, port, prefix, sslContext);
|
connector = new HTTPVaultConnector(hostname, true, port, prefix, trustedCaCert);
|
||||||
assertThat("Unexpected base URL with custom prefix", getPrivate(connector, "baseURL"), is(expectedCustomPrefix));
|
assertThat("Unexpected base URL with custom prefix", getPrivate(connector, "baseURL"), is(expectedCustomPrefix));
|
||||||
assertThat("SSL context not filled correctly", getPrivate(connector, "sslContext"), is(sslContext));
|
assertThat("Trusted CA cert not filled correctly", getPrivate(connector, "trustedCaCert"), is(trustedCaCert));
|
||||||
|
|
||||||
// Specify number of retries.
|
// Specify number of retries.
|
||||||
connector = new HTTPVaultConnector(url, sslContext, retries);
|
connector = new HTTPVaultConnector(url, trustedCaCert, retries);
|
||||||
assertThat("Number of retries not set correctly", getPrivate(connector, "retries"), is(retries));
|
assertThat("Number of retries not set correctly", getPrivate(connector, "retries"), is(retries));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -466,7 +472,7 @@ public class HTTPVaultConnectorOfflineTest {
|
|||||||
private void setPrivate(Object target, String fieldName, Object value) {
|
private void setPrivate(Object target, String fieldName, Object value) {
|
||||||
try {
|
try {
|
||||||
Field field = target.getClass().getDeclaredField(fieldName);
|
Field field = target.getClass().getDeclaredField(fieldName);
|
||||||
boolean accessible =field.isAccessible();
|
boolean accessible = field.isAccessible();
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
field.set(target, value);
|
field.set(target, value);
|
||||||
field.setAccessible(accessible);
|
field.setAccessible(accessible);
|
||||||
|
@ -69,7 +69,7 @@ public class HTTPVaultConnectorFactoryTest {
|
|||||||
connector = factory.build();
|
connector = factory.build();
|
||||||
|
|
||||||
assertThat("URL nor set correctly", getPrivate(connector, "baseURL"), is(equalTo(VAULT_ADDR + "/v1/")));
|
assertThat("URL nor set correctly", getPrivate(connector, "baseURL"), is(equalTo(VAULT_ADDR + "/v1/")));
|
||||||
assertThat("SSL context set when no cert provided", getPrivate(connector, "sslContext"), is(nullValue()));
|
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));
|
assertThat("Non-default number of retries, when none set", getPrivate(connector, "retries"), is(0));
|
||||||
|
|
||||||
/* Provide address and number of retries */
|
/* Provide address and number of retries */
|
||||||
@ -83,7 +83,7 @@ public class HTTPVaultConnectorFactoryTest {
|
|||||||
connector = factory.build();
|
connector = factory.build();
|
||||||
|
|
||||||
assertThat("URL nor set correctly", getPrivate(connector, "baseURL"), is(equalTo(VAULT_ADDR + "/v1/")));
|
assertThat("URL nor set correctly", getPrivate(connector, "baseURL"), is(equalTo(VAULT_ADDR + "/v1/")));
|
||||||
assertThat("SSL context set when no cert provided", getPrivate(connector, "sslContext"), is(nullValue()));
|
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));
|
assertThat("Number of retries not set correctly", getPrivate(connector, "retries"), is(VAULT_MAX_RETRIES));
|
||||||
|
|
||||||
/* Provide CA certificate */
|
/* Provide CA certificate */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user