#2 Option to provide trusted CA certificate

This commit is contained in:
2016-11-04 21:58:19 +01:00
parent 4adefc2cda
commit d2b31122b6
12 changed files with 435 additions and 59 deletions

View File

@@ -17,12 +17,26 @@
package de.stklcode.jvault.connector.factory;
import de.stklcode.jvault.connector.HTTPVaultConnector;
import de.stklcode.jvault.connector.exception.TlsException;
import de.stklcode.jvault.connector.exception.VaultConnectorException;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.*;
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
* @author Stefan Kalscheuer
* @since 0.1
*/
public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
public static final String DEFAULT_HOST = "127.0.0.1";
@@ -34,6 +48,7 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
private Integer port;
private boolean tls;
private String prefix;
private SSLContext sslContext;
/**
* Default empty constructor.
@@ -48,8 +63,9 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
/**
* Set hostname (default: 127.0.0.1)
* @param host Hostname or IP address
* @return self
*
* @param host Hostname or IP address
* @return self
*/
public HTTPVaultConnectorFactory withHost(String host) {
this.host = host;
@@ -58,8 +74,9 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
/**
* Set port (default: 8200)
* @param port Vault TCP port
* @return self
*
* @param port Vault TCP port
* @return self
*/
public HTTPVaultConnectorFactory withPort(Integer port) {
this.port = port;
@@ -68,8 +85,9 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
/**
* Set TLS usage (default: TRUE)
* @param useTLS use TLS or not
* @return self
*
* @param useTLS use TLS or not
* @return self
*/
public HTTPVaultConnectorFactory withTLS(boolean useTLS) {
this.tls = useTLS;
@@ -78,7 +96,8 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
/**
* Convenience Method for TLS usage (enabled by default)
* @return self
*
* @return self
*/
public HTTPVaultConnectorFactory withTLS() {
return withTLS(true);
@@ -86,7 +105,8 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
/**
* Convenience Method for NOT using TLS
* @return self
*
* @return self
*/
public HTTPVaultConnectorFactory withoutTLS() {
return withTLS(false);
@@ -94,16 +114,98 @@ public class HTTPVaultConnectorFactory extends VaultConnectorFactory {
/**
* 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
*
* @param prefix Vault API prefix (default: "/v1/"
* @return self
*/
public HTTPVaultConnectorFactory withPrefix(String prefix) {
this.prefix = prefix;
return this;
}
/**
* Add a trusted CA certifiate for HTTPS connections.
*
* @param cert path to certificate file
* @return self
* @since 0.4.0
*/
public HTTPVaultConnectorFactory withTrustedCA(Path cert) throws VaultConnectorException {
return withSslContext(createSslContext(cert));
}
/**
* Add a custom SSL context.
* Overwrites certificates set by {@link #withTrustedCA}.
*
* @param sslContext the SSL context
* @return self
* @since 0.4.0
*/
public HTTPVaultConnectorFactory withSslContext(SSLContext sslContext) {
this.sslContext = sslContext;
return this;
}
@Override
public HTTPVaultConnector build() {
return new HTTPVaultConnector(host, tls, port, prefix);
return new HTTPVaultConnector(host, tls, port, prefix, sslContext);
}
/**
* 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(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(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.
*
* @param certFile Path to certificate file
* @return X.509 Certificate object
* @throws TlsException on error
* @since 0.4.0
*/
private X509Certificate certificateFromFile(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);
}
}
}

View File

@@ -17,6 +17,7 @@
package de.stklcode.jvault.connector.factory;
import de.stklcode.jvault.connector.VaultConnector;
import de.stklcode.jvault.connector.exception.VaultConnectorException;
/**
* Abstract Vault Connector Factory interface.