diff --git a/src/main/java/io/cryostat/agent/ConfigModule.java b/src/main/java/io/cryostat/agent/ConfigModule.java index bacbd6d1..d039586e 100644 --- a/src/main/java/io/cryostat/agent/ConfigModule.java +++ b/src/main/java/io/cryostat/agent/ConfigModule.java @@ -15,11 +15,15 @@ */ package io.cryostat.agent; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; import java.net.InetAddress; import java.net.URI; import java.net.URL; import java.net.URLClassLoader; import java.net.UnknownHostException; +import java.nio.charset.Charset; import java.security.AccessController; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -45,6 +49,8 @@ import dagger.Module; import dagger.Provides; + +import org.apache.commons.io.IOUtils; import org.eclipse.microprofile.config.Config; import org.eclipse.microprofile.config.ConfigProvider; import org.slf4j.Logger; @@ -76,6 +82,16 @@ public abstract class ConfigModule { "cryostat.agent.webclient.connect.timeout-ms"; public static final String CRYOSTAT_AGENT_WEBCLIENT_RESPONSE_TIMEOUT_MS = "cryostat.agent.webclient.response.timeout-ms"; + public static final String CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_PATH = + "cryostat.agent.webclient.tls.truststore.path"; + public static final String CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_PASS_FILE = + "cryostat.agent.webclient.tls.truststore.pass.file"; + public static final String CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_PASS_CHARSET = + "cryostat.agent.webclient.tls.truststore.pass-charset"; + public static final String CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_PASS = + "cryostat.agent.webclient.tls.truststore.pass"; + public static final String CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_TYPE = + "cryostat.agent.webclient.tls.truststore.type"; public static final String CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_CERTS = "cryostat.agent.webclient.tls.truststore.cert"; public static final Pattern CRYOSTAT_AGENT_TRUSTSTORE_PATTERN = @@ -251,6 +267,51 @@ public static int provideCryostatAgentWebclientResponseTimeoutMs(Config config) return config.getValue(CRYOSTAT_AGENT_WEBCLIENT_RESPONSE_TIMEOUT_MS, int.class); } + @Provides + @Singleton + @Named(CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_PATH) + public static Optional provideCryostatAgentWebclientTlsTruststorePath(Config config) { + return config.getOptionalValue(CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_PATH, String.class); + } + + @Provides + @Singleton + @Named(CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_PASS_FILE) + public static Optional provideCryostatAgentWebclientTlsTruststorePassFromFile(Config config, @Named(CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_PASS_CHARSET) String passCharset) { + Optional truststorePassFile = config.getOptionalValue(CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_PASS_FILE, String.class); + Optional password = Optional.empty(); + try (FileInputStream passFile = new FileInputStream(truststorePassFile.get())) { + String pass = IOUtils.toString(passFile, Charset.forName(passCharset)); + pass = pass.substring(0, pass.length() - 1); + password = Optional.ofNullable(pass); + } catch (IOException e) { + throw new RuntimeException(e); + } + return password; + } + + @Provides + @Singleton + @Named(CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_PASS_CHARSET) + public static String provideCryostatAgentWebclientTlsTruststorePassCharset(Config config) { + return config.getValue(CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_PASS_CHARSET, String.class); + } + + @Provides + @Singleton + @Named(CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_PASS) + public static Optional provideCryostatAgentWebclientTlsTruststorePass(Config config, @Named(CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_PASS_FILE) Optional truststorePass) { + Optional opt = config.getOptionalValue(CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_PASS, String.class); + return opt.or(() -> truststorePass); + } + + @Provides + @Singleton + @Named(CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_TYPE) + public static String provideCryostatAgentWebclientTlsTruststoreType(Config config) { + return config.getValue(CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_TYPE, String.class); + } + @Provides @Singleton @Named(CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_CERTS) diff --git a/src/main/java/io/cryostat/agent/MainModule.java b/src/main/java/io/cryostat/agent/MainModule.java index f7e28cfd..0e8334a6 100644 --- a/src/main/java/io/cryostat/agent/MainModule.java +++ b/src/main/java/io/cryostat/agent/MainModule.java @@ -132,8 +132,11 @@ public static WebServer provideWebServer( public static SSLContext provideClientSslContext( @Named(ConfigModule.CRYOSTAT_AGENT_WEBCLIENT_TLS_VERSION) String clientTlsVersion, @Named(ConfigModule.CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUST_ALL) boolean trustAll, + @Named(ConfigModule.CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_PATH) Optional truststorePath, + @Named(ConfigModule.CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_PASS) Optional truststorePass, + @Named(ConfigModule.CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_TYPE) String truststoreType, @Named(ConfigModule.CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUSTSTORE_CERTS) - List truststores) { + List truststoreCerts) { try { if (trustAll) { SSLContext sslCtx = SSLContext.getInstance(clientTlsVersion); @@ -176,11 +179,19 @@ public X509Certificate[] getAcceptedIssuers() { } } - // initialize truststore - KeyStore ts = KeyStore.getInstance(KeyStore.getDefaultType()); - ts.load(null, null); + KeyStore ts = KeyStore.getInstance(truststoreType); - for (TruststoreConfig truststore : truststores) { + // initialize truststore with user provided path and pass + if (truststorePath.isEmpty() && truststorePass.isEmpty()) { + try (InputStream truststore = new FileInputStream(truststorePath.get())) { + ts.load(truststore, truststorePass.get().toCharArray()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + //initialize truststore with user provided certs + for (TruststoreConfig truststore : truststoreCerts) { // load truststore with certificatesCertificate InputStream certFile = new FileInputStream(truststore.getPath()); CertificateFactory cf = CertificateFactory.getInstance(truststore.getType()); diff --git a/src/main/resources/META-INF/microprofile-config.properties b/src/main/resources/META-INF/microprofile-config.properties index fdde3978..3bebd816 100644 --- a/src/main/resources/META-INF/microprofile-config.properties +++ b/src/main/resources/META-INF/microprofile-config.properties @@ -7,6 +7,8 @@ cryostat.agent.api.writes-enabled=false cryostat.agent.webclient.tls.version=TLSv1.2 cryostat.agent.webclient.tls.trust-all=false cryostat.agent.webclient.tls.verify-hostname=true +cryostat.agent.webclient.tls.truststore.type=JKS +cryostat.agent.webclient.tls.truststore.pass-charset=utf-8 cryostat.agent.webclient.connect.timeout-ms=1000 cryostat.agent.webclient.response.timeout-ms=1000 cryostat.agent.webserver.host=0.0.0.0