Skip to content

Commit

Permalink
feat(tls): Use TLS by default in the agent (#554)
Browse files Browse the repository at this point in the history
Co-authored-by: Andrew Azores <[email protected]>
  • Loading branch information
Josh-Matsuoka and andrewazores authored Dec 20, 2024
1 parent c27e08e commit 292b2bd
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 8 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ and how it advertises itself to a Cryostat server instance. Properties that requ
- [ ] `cryostat.agent.webclient.tls.version` [`String`]: the version of TLS used for the Agent's client SSL context. Default `TLSv1.2`.
- [ ] `cryostat.agent.webclient.tls.trust-all` [`boolean`]: control whether the agent trusts all certificates presented by the Cryostat server. Default `false`. This should only be overridden for development and testing purposes, never in production.
- [ ] `cryostat.agent.webclient.tls.verify-hostname` [`boolean`]: control whether the agent verifies hostnames on certificates presented by the Cryostat server. Default `true`. This should only be overridden for development and testing purposes, never in production.
- [ ] `cryostat.agent.webclient.tls.required` [`boolean`]: Specify whether the agent should require TLS on Cryostat server connections, expecting the base URI to be an https connection with a certificate it trusts. Defaults to `true`. Should only be disabled for testing/prototyping purposes.
- [ ] `cryostat.agent.webclient.tls.trustore.cert` [`list`]: the list of truststoreConfig objects with alias, path, and type properties for certificates to be stored in the agent's truststore. For example, 'cryostat.agent.webclient.tls.truststore.cert[0].type' would be the type of the first certificate in this list. A truststoreConfig object must contain all three properties to be a valid certificate entry.
- [ ] `cryostat.agent.webclient.tls.truststore.type` [`String`]: the type of truststore used for the agent's client truststore. Default `JKS`.
- [ ] `cryostat.agent.webclient.tls.truststore.path` [`String`]: the filepath to the agent's webclient truststore. This takes precedence over `cryostat.agent.webclient.tls.truststore.cert` and must be configured with the truststore's pass with `cryostat.agent.webclient.tls.truststore.pass.file` or `cryostat.agent.webclient.tls.truststore.pass`.
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/io/cryostat/agent/ConfigModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ public abstract class ConfigModule {
public static final String CRYOSTAT_AGENT_WEBCLIENT_RESPONSE_RETRY_COUNT =
"cryostat.agent.webclient.response.retry-count";

public static final String CRYOSTAT_AGENT_WEBCLIENT_TLS_REQUIRED =
"cryostat.agent.webclient.tls.required";

public static final String CRYOSTAT_AGENT_WEBSERVER_HOST = "cryostat.agent.webserver.host";
public static final String CRYOSTAT_AGENT_WEBSERVER_PORT = "cryostat.agent.webserver.port";
public static final String CRYOSTAT_AGENT_WEBSERVER_TLS_VERSION =
Expand Down Expand Up @@ -959,6 +962,13 @@ public static long provideCryostatSmartTriggerEvaluationPeriodMs(Config config)
return config.getValue(CRYOSTAT_AGENT_SMART_TRIGGER_EVALUATION_PERIOD_MS, long.class);
}

@Provides
@Singleton
@Named(CRYOSTAT_AGENT_WEBCLIENT_TLS_REQUIRED)
public static boolean provideCryostatAgentTlsEnabled(Config config) {
return config.getValue(CRYOSTAT_AGENT_WEBCLIENT_TLS_REQUIRED, boolean.class);
}

public enum URIRange {
LOOPBACK(u -> check(u, u2 -> true, InetAddress::isLoopbackAddress)),
LINK_LOCAL(
Expand Down
28 changes: 20 additions & 8 deletions src/main/java/io/cryostat/agent/MainModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.conn.socket.ConnectionSocketFactory;
Expand Down Expand Up @@ -236,9 +235,19 @@ public static SSLContext provideClientSslContext(
@Named(ConfigModule.CRYOSTAT_AGENT_WEBCLIENT_TLS_CLIENT_AUTH_KEY_PASS_CHARSET)
String clientAuthKeyPassFileCharset,
@Named(ConfigModule.CRYOSTAT_AGENT_WEBCLIENT_TLS_CLIENT_AUTH_KEY_MANAGER_TYPE)
String clientAuthKeyManagerType) {
String clientAuthKeyManagerType,
@Named(ConfigModule.CRYOSTAT_AGENT_BASEURI) URI baseUri,
@Named(ConfigModule.CRYOSTAT_AGENT_WEBCLIENT_TLS_REQUIRED) boolean tlsRequired) {
try {
KeyManager[] keyManagers = null;
if (tlsRequired && !baseUri.getScheme().equals("https")) {
throw new IllegalArgumentException(
String.format(
"If TLS is enabled via the (%s) property, the base URI (%s)"
+ " must be an https connection.",
ConfigModule.CRYOSTAT_AGENT_WEBCLIENT_TLS_REQUIRED,
ConfigModule.CRYOSTAT_AGENT_BASEURI));
}
if (clientAuthCertPath.isPresent() && clientAuthKeyPath.isPresent()) {
KeyStore ks = KeyStore.getInstance(clientAuthKeystoreType);
Optional<CharBuffer> keystorePass =
Expand Down Expand Up @@ -610,20 +619,23 @@ public static HttpClient provideHttpClient(
boolean verifyHostname,
@Named(ConfigModule.CRYOSTAT_AGENT_WEBCLIENT_CONNECT_TIMEOUT_MS) int connectTimeout,
@Named(ConfigModule.CRYOSTAT_AGENT_WEBCLIENT_RESPONSE_TIMEOUT_MS) int responseTimeout,
@Named(ConfigModule.CRYOSTAT_AGENT_WEBCLIENT_RESPONSE_RETRY_COUNT) int retryCount) {
@Named(ConfigModule.CRYOSTAT_AGENT_WEBCLIENT_RESPONSE_RETRY_COUNT) int retryCount,
@Named(ConfigModule.CRYOSTAT_AGENT_WEBCLIENT_TLS_REQUIRED) boolean tlsRequired) {
SSLConnectionSocketFactory sslSocketFactory =
new SSLConnectionSocketFactory(
sslContext,
verifyHostname
? SSLConnectionSocketFactory.getDefaultHostnameVerifier()
: NoopHostnameVerifier.INSTANCE);
Registry<ConnectionSocketFactory> socketFactoryRegistry =

RegistryBuilder<ConnectionSocketFactory> socketFactoryRegistryBuilder =
RegistryBuilder.<ConnectionSocketFactory>create()
.register("https", sslSocketFactory)
.register("http", new PlainConnectionSocketFactory())
.build();
.register("https", sslSocketFactory);
if (!tlsRequired) {
socketFactoryRegistryBuilder.register("http", new PlainConnectionSocketFactory());
}
HttpClientConnectionManager connMan =
new BasicHttpClientConnectionManager(socketFactoryRegistry);
new BasicHttpClientConnectionManager(socketFactoryRegistryBuilder.build());
return HttpClients.custom()
.setSSLContext(sslContext)
.setSSLSocketFactory(sslSocketFactory)
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/META-INF/microprofile-config.properties
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ cryostat.agent.webclient.response.retry-count=3
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.required=true
cryostat.agent.webclient.tls.truststore.type=JKS
cryostat.agent.webclient.tls.truststore.pass-charset=utf-8

Expand Down Expand Up @@ -82,3 +83,4 @@ cryostat.agent.harvester.max-size-b=0

cryostat.agent.smart-trigger.definitions=
cryostat.agent.smart-trigger.evaluation.period-ms=1000

0 comments on commit 292b2bd

Please sign in to comment.