Skip to content

Commit

Permalink
feat(HTTPS): implement HTTPS keystore (#257)
Browse files Browse the repository at this point in the history
Signed-off-by: Ming Yu Wang <90855268+mwangggg@users.noreply.github.com>
Co-authored-by: Andrew Azores <aazores@redhat.com>
  • Loading branch information
mwangggg and andrewazores authored Jul 9, 2024
1 parent a7456d8 commit 8f95260
Show file tree
Hide file tree
Showing 5 changed files with 266 additions and 58 deletions.
17 changes: 13 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,19 +166,28 @@ and how it advertises itself to a Cryostat server instance. Properties that requ
- [x] `cryostat.agent.baseuri` [`java.net.URI`]: the URL location of the Cryostat server backend that this agent advertises itself to.
- [ ] `cryostat.agent.baseuri-range` [`String`]: a `String` representing the `io.cryostat.agent.ConfigModule.UriRange` enum level that restricts the acceptable hosts specified in the `cryostat.agent.baseuri` property. This is used to control the server locations that this Cryostat Agent instance is willing to register itself with. Default `dns_local`, which means any IP or hostname that is or resolves to `localhost`, a link-local IP address, an IP address from a private range block, or a hostname ending in `.local` will be accepted. If a `cryostat.agent.baseuri` is specified with a host outside of this range then the Agent will refuse to start. Acceptable values are: `loopback`, `link_local`, `site_local`, `dns_local`, and `public`. Each higher/more relaxed level implies that each lower level is also acceptable.
- [x] `cryostat.agent.callback` [`java.net.URI`]: a URL pointing back to this agent, ex. `"https://12.34.56.78:1234/"`. Cryostat will use this URL to perform health checks and request updates from the agent. This reflects the externally-visible IP address/hostname and port where this application and agent can be found.
- [ ] `cryostat.agent.api.writes-enabled` [`boolean`]: Control whether the agent accepts "write" or mutating operations on its HTTP API. Requests for remote operations such as dynamically starting Flight Recordings will be rejected unless this is set. Default `false`.
- [ ] `cryostat.agent.api.writes-enabled` [`boolean`]: control whether the agent accepts "write" or mutating operations on its HTTP API. Requests for remote operations such as dynamically starting Flight Recordings will be rejected unless this is set. Default `false`.
- [ ] `cryostat.agent.instance-id` [`String`]: a unique ID for this agent instance. This will be used to uniquely identify the agent in the Cryostat discovery database, as well as to unambiguously match its encrypted stored credentials. The default is a random UUID string. It is not recommended to override this value.
- [ ] `cryostat.agent.hostname` [`String`]: the hostname for this application instance. This will be used for the published JMX connection URL. If not provided then the default is to attempt to resolve the localhost hostname.
- [ ] `cryostat.agent.realm` [`String`]: the Cryostat Discovery API "realm" that this agent belongs to. This should be unique per agent instance. The default is the value of `cryostat.agent.app.name`.
- [ ] `cryostat.agent.authorization` [`String`]: `Authorization` header value to include with API requests to the Cryostat server, ex. `Bearer abcd1234`. Takes precedence over `cryostat.agent.authorization.type` and `cryostat.agent.authorization.value`. Defaults to the empty string, so `cryostat.agent.authorization.type` and `cryostat.agent.authorization.value` are used instead.
- [ ] `cryostat.agent.authorization` [`String`]: `authorization` header value to include with API requests to the Cryostat server, ex. `Bearer abcd1234`. Takes precedence over `cryostat.agent.authorization.type` and `cryostat.agent.authorization.value`. Defaults to the empty string, so `cryostat.agent.authorization.type` and `cryostat.agent.authorization.value` are used instead.
- [ ] `cryostat.agent.authorization.type` [`String`]: may be `basic`, `bearer`, `kubernetes`, `none`, or `auto`. Each performs a mapping of the `cryostat.agent.authorization.value` to produce an `Authorization` header (see above). `basic` encodes the value using base64 to produce a `Basic base64(value)` header, `bearer` directly embeds the value into a `Bearer value` header, `kubernetes` reads the value as a file location to produce a `Bearer fileAsString(value)` header, `none` produces no header. Default `auto`, which tries to do `kubernetes` first and falls back on `none`.
- [ ] `cryostat.agent.authorization.value` [`String`]: the value to map into an `Authorization` header. If the `cryostat.agent.authorization.type` is `basic` then this should be the unencoded basic credentials, ex. `user:pass`. If `bearer` then it should be the token to be presented. If `kubernetes` it should be the filesystem path to the service account token secret file. If `none` it is ignored. Default `/var/run/secrets/kubernetes.io/serviceaccount/token`, the standard location for Kubernetes serviceaccount token secret files.
- [ ] `cryostat.agent.webclient.ssl.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.ssl.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.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.connect.timeout-ms` [`long`]: the duration in milliseconds to wait for HTTP requests to the Cryostat server to connect. Default `1000`.
- [ ] `cryostat.agent.webclient.response.timeout-ms` [`long`]: the duration in milliseconds to wait for HTTP requests to the Cryostat server to respond. Default `1000`.
- [ ] `cryostat.agent.webserver.host` [`String`]: the internal hostname or IP address for the embedded webserver to bind to. Default `0.0.0.0`.
- [ ] `cryostat.agent.webserver.port` [`int`]: the internal port number for the embedded webserver to bind to. Default `9977`.
- [ ] `cryostat.agent.webserver.tls.version` [`String`]: the version of TLS used for the Agent's server SSL context. Default `TLSv1.2`.
- [ ] `cryostat.agent.webserver.tls.keystore.pass` [`String`]: the filepath to the HTTPS server keystore's password
- [ ] `cryostat.agent.webserver.tls.keystore.pass.charset` [`String`]: the character set used by the HTTPS server keystore's password. Default `utf-8`.
- [ ] `cryostat.agent.webserver.tls.keystore.file` [`String`]: the file path to the HTTPS server keystore
- [ ] `cryostat.agent.webserver.tls.keystore.type` [`String`]: the type of keystore used for the Agent's HTTPS server. Default `PKCS12`.
- [ ] `cryostat.agent.webserver.tls.cert.alias` [`String`]: the alias for the certificate stored in the HTTPS server keystore. Default `serverCert`.
- [ ] `cryostat.agent.webserver.tls.cert.file` [`String`]: the filepath to the certificate to be stored by the HTTPS server keystore
- [ ] `cryostat.agent.webserver.tls.cert.type` [`String`]: the type of certificate that the HTTPS server keystore will present. Default `X.509`.
- [ ] `cryostat.agent.webserver.credentials.user` [`String`]: the username used for `Basic` authorization on the embedded webserver. Default `user`.
- [ ] `cryostat.agent.webserver.credentials.pass.length` [`int`]: the length of the generated password used for `Basic` authorization on the embedded webserver. Default `24`.
- [ ] `cryostat.agent.webserver.credentials.pass.hash-function` [`String`]: the name of the hash function to use when generating passwords. Default `SHA-256`.
Expand Down
97 changes: 89 additions & 8 deletions src/main/java/io/cryostat/agent/ConfigModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,35 @@ public abstract class ConfigModule {
public static final String CRYOSTAT_AGENT_AUTHORIZATION_VALUE =
"cryostat.agent.authorization.value";

public static final String CRYOSTAT_AGENT_WEBCLIENT_SSL_TRUST_ALL =
"cryostat.agent.webclient.ssl.trust-all";
public static final String CRYOSTAT_AGENT_WEBCLIENT_SSL_VERIFY_HOSTNAME =
"cryostat.agent.webclient.ssl.verify-hostname";
public static final String CRYOSTAT_AGENT_WEBCLIENT_TLS_VERSION =
"cryostat.agent.webclient.tls.version";
public static final String CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUST_ALL =
"cryostat.agent.webclient.tls.trust-all";
public static final String CRYOSTAT_AGENT_WEBCLIENT_TLS_VERIFY_HOSTNAME =
"cryostat.agent.webclient.tls.verify-hostname";
public static final String CRYOSTAT_AGENT_WEBCLIENT_CONNECT_TIMEOUT_MS =
"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_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 =
"cryostat.agent.webserver.tls.version";
public static final String CRYOSTAT_AGENT_WEBSERVER_TLS_KEYSTORE_PASS =
"cryostat.agent.webserver.tls.keystore.pass";
public static final String CRYOSTAT_AGENT_WEBSERVER_TLS_KEYSTORE_PASS_CHARSET =
"cryostat.agent.webserver.tls.keystore.pass-charset";
public static final String CRYOSTAT_AGENT_WEBSERVER_TLS_KEYSTORE_FILE =
"cryostat.agent.webserver.tls.keystore.file";
public static final String CRYOSTAT_AGENT_WEBSERVER_TLS_KEYSTORE_TYPE =
"cryostat.agent.webserver.tls.keystore.type";
public static final String CRYOSTAT_AGENT_WEBSERVER_TLS_CERT_ALIAS =
"cryostat.agent.webserver.tls.cert.alias";
public static final String CRYOSTAT_AGENT_WEBSERVER_TLS_CERT_FILE =
"cryostat.agent.webserver.tls.cert.file";
public static final String CRYOSTAT_AGENT_WEBSERVER_TLS_CERT_TYPE =
"cryostat.agent.webserver.tls.cert.type";
public static final String CRYOSTAT_AGENT_WEBSERVER_CREDENTIALS_USER =
"cryostat.agent.webserver.credentials.user";
public static final String CRYOSTAT_AGENT_WEBSERVER_CREDENTIALS_PASS_HASH_FUNCTION =
Expand Down Expand Up @@ -196,16 +214,16 @@ public static Optional<String> provideCryostatAgentAuthorizationValue(Config con

@Provides
@Singleton
@Named(CRYOSTAT_AGENT_WEBCLIENT_SSL_TRUST_ALL)
@Named(CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUST_ALL)
public static boolean provideCryostatAgentWebclientTrustAll(Config config) {
return config.getValue(CRYOSTAT_AGENT_WEBCLIENT_SSL_TRUST_ALL, boolean.class);
return config.getValue(CRYOSTAT_AGENT_WEBCLIENT_TLS_TRUST_ALL, boolean.class);
}

@Provides
@Singleton
@Named(CRYOSTAT_AGENT_WEBCLIENT_SSL_VERIFY_HOSTNAME)
@Named(CRYOSTAT_AGENT_WEBCLIENT_TLS_VERIFY_HOSTNAME)
public static boolean provideCryostatAgentWebclientVerifyHostname(Config config) {
return config.getValue(CRYOSTAT_AGENT_WEBCLIENT_SSL_VERIFY_HOSTNAME, boolean.class);
return config.getValue(CRYOSTAT_AGENT_WEBCLIENT_TLS_VERIFY_HOSTNAME, boolean.class);
}

@Provides
Expand Down Expand Up @@ -236,6 +254,69 @@ public static int provideCryostatAgentWebserverPort(Config config) {
return config.getValue(CRYOSTAT_AGENT_WEBSERVER_PORT, int.class);
}

@Provides
@Singleton
@Named(CRYOSTAT_AGENT_WEBCLIENT_TLS_VERSION)
public static String provideCryostatAgentWebclientTlsVersion(Config config) {
return config.getValue(CRYOSTAT_AGENT_WEBCLIENT_TLS_VERSION, String.class);
}

@Provides
@Singleton
@Named(CRYOSTAT_AGENT_WEBSERVER_TLS_VERSION)
public static String provideCryostatAgentWebserverTlsVersion(Config config) {
return config.getValue(CRYOSTAT_AGENT_WEBSERVER_TLS_VERSION, String.class);
}

@Provides
@Singleton
@Named(CRYOSTAT_AGENT_WEBSERVER_TLS_KEYSTORE_PASS)
public static Optional<String> provideCryostatAgentWebserverTlsKeyStorePass(Config config) {
return config.getOptionalValue(CRYOSTAT_AGENT_WEBSERVER_TLS_KEYSTORE_PASS, String.class);
}

@Provides
@Singleton
@Named(CRYOSTAT_AGENT_WEBSERVER_TLS_KEYSTORE_PASS_CHARSET)
public static String provideCryostatAgentWebserverTlsKeyStorePassCharset(Config config) {
return config.getValue(CRYOSTAT_AGENT_WEBSERVER_TLS_KEYSTORE_PASS_CHARSET, String.class);
}

@Provides
@Singleton
@Named(CRYOSTAT_AGENT_WEBSERVER_TLS_KEYSTORE_FILE)
public static Optional<String> provideCryostatAgentWebserverTlsKeyStoreFile(Config config) {
return config.getOptionalValue(CRYOSTAT_AGENT_WEBSERVER_TLS_KEYSTORE_FILE, String.class);
}

@Provides
@Singleton
@Named(CRYOSTAT_AGENT_WEBSERVER_TLS_KEYSTORE_TYPE)
public static String provideCryostatAgentWebserverTlsKeyStoreType(Config config) {
return config.getValue(CRYOSTAT_AGENT_WEBSERVER_TLS_KEYSTORE_TYPE, String.class);
}

@Provides
@Singleton
@Named(CRYOSTAT_AGENT_WEBSERVER_TLS_CERT_ALIAS)
public static String provideCryostatAgentWebserverTlsCertAlias(Config config) {
return config.getValue(CRYOSTAT_AGENT_WEBSERVER_TLS_CERT_ALIAS, String.class);
}

@Provides
@Singleton
@Named(CRYOSTAT_AGENT_WEBSERVER_TLS_CERT_FILE)
public static Optional<String> provideCryostatAgentWebserverTlsCertFile(Config config) {
return config.getOptionalValue(CRYOSTAT_AGENT_WEBSERVER_TLS_CERT_FILE, String.class);
}

@Provides
@Singleton
@Named(CRYOSTAT_AGENT_WEBSERVER_TLS_CERT_TYPE)
public static String provideCryostatAgentWebserverTlsCertType(Config config) {
return config.getValue(CRYOSTAT_AGENT_WEBSERVER_TLS_CERT_TYPE, String.class);
}

@Provides
@Singleton
@Named(CRYOSTAT_AGENT_WEBSERVER_CREDENTIALS_USER)
Expand Down
Loading

0 comments on commit 8f95260

Please sign in to comment.