From 836462ad895f675f707205dd354f2952fc32788b Mon Sep 17 00:00:00 2001 From: Ming Wang Date: Thu, 23 Nov 2023 11:05:24 -0500 Subject: [PATCH] set up server cert --- pom.xml | 12 ++ .../java/io/cryostat/agent/MainModule.java | 7 ++ .../java/io/cryostat/agent/WebServer.java | 118 +++++++++++------- .../agent/certs/cryostat-keystore.p12 | Bin 0 -> 2666 bytes .../agent/certs}/generate-dev-certs.sh | 0 .../io/cryostat/agent/certs/keystore.pass | 1 + .../java/io/cryostat/agent/certs/server.cer | Bin 0 -> 781 bytes .../resources/certs}/cryostat-keystore.p12 | Bin .../resources/certs/generate-dev-certs.sh | 58 +++++++++ .../main/resources/certs}/keystore.pass | 0 .../main/resources/certs}/server.cer | Bin 11 files changed, 149 insertions(+), 47 deletions(-) create mode 100644 src/main/java/io/cryostat/agent/certs/cryostat-keystore.p12 rename {certs => src/main/java/io/cryostat/agent/certs}/generate-dev-certs.sh (100%) create mode 100644 src/main/java/io/cryostat/agent/certs/keystore.pass create mode 100644 src/main/java/io/cryostat/agent/certs/server.cer rename {certs => src/main/resources/certs}/cryostat-keystore.p12 (100%) create mode 100644 src/main/resources/certs/generate-dev-certs.sh rename {certs => src/main/resources/certs}/keystore.pass (100%) rename {certs => src/main/resources/certs}/server.cer (100%) diff --git a/pom.xml b/pom.xml index cad02c86..be447eaa 100644 --- a/pom.xml +++ b/pom.xml @@ -238,6 +238,18 @@ src/main/resources true + + **/*.p12 + **/*.cer + + + + src/main/resources + false + + **/*.p12 + **/*.cer + diff --git a/src/main/java/io/cryostat/agent/MainModule.java b/src/main/java/io/cryostat/agent/MainModule.java index 9f3d7e2a..76ab78c2 100644 --- a/src/main/java/io/cryostat/agent/MainModule.java +++ b/src/main/java/io/cryostat/agent/MainModule.java @@ -38,6 +38,7 @@ import io.cryostat.agent.triggers.TriggerModule; import io.cryostat.core.JvmIdentifier; import io.cryostat.core.net.IDException; +import io.cryostat.core.sys.FileSystem; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; @@ -236,6 +237,12 @@ public static FlightRecorderHelper provideFlightRecorderHelper() { return new FlightRecorderHelper(); } + @Provides + @Singleton + public static FileSystem provideFileSystem() { + return new FileSystem(); + } + @Provides @Singleton @Named(JVM_ID) diff --git a/src/main/java/io/cryostat/agent/WebServer.java b/src/main/java/io/cryostat/agent/WebServer.java index c8407b9c..f0a03d98 100644 --- a/src/main/java/io/cryostat/agent/WebServer.java +++ b/src/main/java/io/cryostat/agent/WebServer.java @@ -15,8 +15,8 @@ */ package io.cryostat.agent; -import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStream; import java.net.InetSocketAddress; import java.net.URI; import java.nio.charset.StandardCharsets; @@ -28,7 +28,9 @@ import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.UnrecoverableKeyException; +import java.security.cert.Certificate; import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; import java.time.Duration; import java.util.Arrays; import java.util.HashSet; @@ -44,7 +46,6 @@ import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; -import javax.net.ssl.SSLParameters; import javax.net.ssl.TrustManagerFactory; import io.cryostat.agent.remote.RemoteContext; @@ -59,6 +60,7 @@ import com.sun.net.httpserver.HttpsParameters; import com.sun.net.httpserver.HttpsServer; import dagger.Lazy; +import org.apache.commons.io.IOUtils; import org.apache.http.HttpStatus; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -107,7 +109,7 @@ class WebServer { this.compressionFilter = new CompressionFilter(); } - void start() throws IOException, NoSuchAlgorithmException { + void start() { if (this.https != null) { stop(); } @@ -118,57 +120,79 @@ void start() throws IOException, NoSuchAlgorithmException { SSLContext sslContext = SSLContext.getInstance("TLS"); // initialize keystore - FileInputStream passwordFile = new FileInputStream("keystore.pass"); - char[] password = new String(passwordFile.readAllBytes()).toCharArray(); - passwordFile.close(); - KeyStore ks = KeyStore.getInstance("JKS"); - FileInputStream fis = new FileInputStream("cryostat-keystore.p12"); - ks.load(fis, password); - + InputStream pass = this.getClass().getResourceAsStream("/certs/keystore.pass"); + String password = IOUtils.toString(pass, StandardCharsets.US_ASCII); + password = password.substring(0, password.length() - 1); + pass.close(); + KeyStore ks = KeyStore.getInstance("PKCS12"); + InputStream keystore = + this.getClass().getResourceAsStream("/certs/cryostat-keystore.p12"); + ks.load(keystore, password.toCharArray()); + if (keystore != null) { + keystore.close(); + } + + // set up certificate factory + InputStream certFile = this.getClass().getResourceAsStream("/certs/server.cer"); + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + Certificate cert = cf.generateCertificate(certFile); + ks.setCertificateEntry("serverCert", cert); + certFile.close(); + // set up key manager factory - KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - kmf.init(ks, password); + KeyManagerFactory kmf = + KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(ks, password.toCharArray()); // set up trust manager factory - // TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - // tmf.init(ks); + TrustManagerFactory tmf = + TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(ks); // set up HTTPS context - sslContext.init(kmf.getKeyManagers(), null, null); - this.https.setHttpsConfigurator(new HttpsConfigurator(sslContext) { - public void configure(HttpsParameters params) { - try { - SSLContext context = getSSLContext(); - SSLEngine engine = context.createSSLEngine(); - params.setNeedClientAuth(false); - params.setCipherSuites(engine.getEnabledCipherSuites()); - params.setProtocols((engine.getEnabledProtocols())); - params.setSSLParameters(context.getDefaultSSLParameters()); - } catch (Exception e) { - log.error("Failed to configure the HTTPS parameters", e); - } - } - }); - } catch (KeyStoreException - | CertificateException - | UnrecoverableKeyException - | KeyManagementException e) { + sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + this.https.setHttpsConfigurator( + new HttpsConfigurator(sslContext) { + public void configure(HttpsParameters params) { + try { + SSLContext context = getSSLContext(); + SSLEngine engine = context.createSSLEngine(); + params.setNeedClientAuth(false); + params.setCipherSuites(engine.getEnabledCipherSuites()); + params.setProtocols((engine.getEnabledProtocols())); + params.setSSLParameters(context.getDefaultSSLParameters()); + } catch (Exception e) { + log.error( + "Failed to configure the HTTPS context and parameters", e); + } + } + }); + + Set mergedContexts = new HashSet<>(remoteContexts.get()); + mergedContexts.add(new PingContext(registration)); + mergedContexts.stream() + .filter(RemoteContext::available) + .forEach( + rc -> { + HttpContext ctx = + this.https.createContext(rc.path(), wrap(rc::handle)); + ctx.setAuthenticator(agentAuthenticator); + ctx.getFilters().add(requestLoggingFilter); + ctx.getFilters().add(compressionFilter); + }); + this.https.setExecutor(executor); + this.https.start(); + + log.info("HERE WE ARE"); + + } catch (KeyStoreException + | CertificateException + | UnrecoverableKeyException + | KeyManagementException + | IOException + | NoSuchAlgorithmException e) { log.error("Failed to set up HTTPS server", e); } - - Set mergedContexts = new HashSet<>(remoteContexts.get()); - mergedContexts.add(new PingContext(registration)); - mergedContexts.stream() - .filter(RemoteContext::available) - .forEach( - rc -> { - HttpContext ctx = this.https.createContext(rc.path(), wrap(rc::handle)); - ctx.setAuthenticator(agentAuthenticator); - ctx.getFilters().add(requestLoggingFilter); - ctx.getFilters().add(compressionFilter); - }); - this.https.setExecutor(executor); - this.https.start(); } Path discoverCertPath() { diff --git a/src/main/java/io/cryostat/agent/certs/cryostat-keystore.p12 b/src/main/java/io/cryostat/agent/certs/cryostat-keystore.p12 new file mode 100644 index 0000000000000000000000000000000000000000..727295039592db1af3e6785ca99213425b7e630a GIT binary patch literal 2666 zcma)8c{tRI8lF`%!^m1nSxQ9WH@1c(#?s)}GnDMv#+K|^&%`*CtcuVq{9R|rIk2LcuYxHu61z6e3WLBL54qyrfbc7ejc zGB6$&PwF%0ZTR5n>?b#2Kcfs`Bv^m9*1YcflETB%tMgnu}-CM|`ituj5A{Y$xol!3~tC)<>}Hq0$- zaC%i3$s=VyFfJ<0(bgr4@YPutY_*vLsuNw4ykD*$`g~7oHk4>B$Q!;dM$|fL$-wZ> zcZ|MvmTbnVz5MgNpXnSZlnv(K&jg?b}0Rc%mz z%bnp=3QMmZrnOMxS9?e9vqDhZd3*tmrZ$QO%mjGmq+VzcDq29Xmb&5vbz81{(S^w1 z1cQ(4F3KK7nn@qpq77(YbmZxkP^jG~NrQarjz(#imC9VL?YHjvuu+R?2{l(z&Ja^G6 zDN9W#HDqMPvFgv?sZ!T2N`H@Q{%g%a#<7@CL$L(v-Uo<&*z>3>;g*cV4|X>55^ z*m3ZS~`3X;{qh~+Ku+HmCXO(cOLnP{tKHFExO&86bQc~6xTZ z+$hbNjz?ZX%wuzF!2vTGDIP2IBjQztMheJA>yUdTFQFZxwSLc8-ecU> zsLka>Gk)&t^YbG16W+p)bwo@A`GUXT!!#;hojxL)FIyTNlI&Z$1&=?@lBwFp_HutM<3&2^oXqQ|@}yARHZmu@(8;jTt5M%(9j04tXmFut>JpQbt8Wy*BPDZihH zz|Y&y*18s01f4a&G}gqp$1^a(!Cx`SRS!A7TkZ&R=&ci?-p_IR{JE9qZ8d9+wOAyj zuJ(tYFvc7>|0^z$0vIt75s)(|5abUE0QrKvLFW(9ZBXdJ{5RtW3IN3aSr^0z!1%6u zc)N&UE&vM3s!9N$ctJ%KAi*%dmJV@HNw8A~ln4Y2I%r4#QNaHzxV=5)tYsG-m-o}o zSVA?KxATL0r~aSdUVqOGNt*K;y~9sarGe6tqDfF{F|v$!2b0)r_-LtZlUY}k`?x`o zP6+7!DqFXmqL!h#q2n$!*0VRZVk16VHs;}tS{LrSg-JfXQRcX#BHC`rH8NYVGfy2U z75!9M<-Z3Zxp{oRGn&cl5qE1=Uls&U;ulWgRiLc@!O@?xLYSZtw@qSSI5TeTX}@KB z-?v{U79o`G-8H;Wu%VSMB!$+@*=;0?YK4cYg({-h!k6h#G|yHUDdfhQ`HZ3@lz>^8w?j@`~o<{XXx&?HoT z0s7`*SOVLjU(oq*B(t~lin3hE__9w9TGHa63vb*|J0W<&!PQOLEp)qhi6yjq$Z6vz0WA+F7dA`@j(6S)7%PWW;V65R z>p5gIi4{MjGc_gvyv#MHL$wOA5gzHc^ps0JDNPFqZ=J05fCXxmVD|^A1 z&JA&c82F%YPSa|Pv#Df2rp(X3c3DKEn!e=e0Ndsh+^b<-2^z#3@^Cm4~6`#TA{8XA>V@Bj>TAi)6X?xwWKVmUsuA zST29pH!e|Mzw3;r@}OIqMeBF?W@y(W8SybBvlb5`8mof9Yv(|^N>-A^P0o*{N4 zica}wo|D5{n>>A#y1KQdZ_&3V*wWGCuiuFDx4n<3He<|I*fn)Mo7ID0f-KtvB3P8| z#9YspXMK%U&d+JjTcQ14UKkyk&I61941oUie?h=-5KOG>l{?XWznJZjot)I4m)>Z# si@Ejk3LVt)mM3ksg+CT1pyNXf89p`{f=JhQ((o(3`i|J>^mj!33)36X%m4rY literal 0 HcmV?d00001 diff --git a/certs/generate-dev-certs.sh b/src/main/java/io/cryostat/agent/certs/generate-dev-certs.sh similarity index 100% rename from certs/generate-dev-certs.sh rename to src/main/java/io/cryostat/agent/certs/generate-dev-certs.sh diff --git a/src/main/java/io/cryostat/agent/certs/keystore.pass b/src/main/java/io/cryostat/agent/certs/keystore.pass new file mode 100644 index 00000000..df1b52fc --- /dev/null +++ b/src/main/java/io/cryostat/agent/certs/keystore.pass @@ -0,0 +1 @@ +7XIvZiCyrx6akly_dDvOtpe7QM6ksYoH diff --git a/src/main/java/io/cryostat/agent/certs/server.cer b/src/main/java/io/cryostat/agent/certs/server.cer new file mode 100644 index 0000000000000000000000000000000000000000..35cfdd57df4c74d271f7c0c045e1a5e57d02c364 GIT binary patch literal 781 zcmXqLV&*hxV*I#(nTe5!i9>zQ$xZtw2c{bEvT0s^NULoOJG9G!W_v^Ap<#aUL#{eBSRA-BNH+BaiBSpJag3}C%uS5^3_w3{F*PwVGR&APEO31}&phr)KYh&$S5H|KmM0kHVEfDV z-#W=dFN$m}CsoG$YG*3U{dDW`8-b=*J!d70ma)ks&RJUb`l!}lmj82ao>Wo4p?xfW zT8R0l%8r(q0u3%3Ib~OIE%Rv#DLuq^Pxrs_z82%{lDn_{U&cGnmxs|*J-2)==bv9% zr}=jz1WnVH-%uX6t1$9VRmU=M?W9}Ri;De&Zplcx6;_=sTl%@cakA#cSDz1j|MC9k z?#;KZ?)#a!W&e@?xzbk;&i>5$Rw{IV-ZR4`3;tHjId-Me`_r<^GBQfqzK5psy__&5 zUsB`e{^{&1&dIzc8>+hgDKclW;9SAZOdz!(MwA|r#`-$zdu_qG39R{YxPFstSX zJ=yP@E6m;B|9X31M*p^q_I4|epQ&b10Y+LgWHzm154_tH+A4eB`G0Es@q>%EPpz<5 zxXQiSU_I}efJc!rOU`fUJaA@X;mmM`kDbyTrAfsTcD%D>~3ME`=t9b%wr~Y%Am$!S53IN%Wmte`Tr&S&anaj-aJQZ literal 0 HcmV?d00001 diff --git a/certs/cryostat-keystore.p12 b/src/main/resources/certs/cryostat-keystore.p12 similarity index 100% rename from certs/cryostat-keystore.p12 rename to src/main/resources/certs/cryostat-keystore.p12 diff --git a/src/main/resources/certs/generate-dev-certs.sh b/src/main/resources/certs/generate-dev-certs.sh new file mode 100644 index 00000000..51ae381b --- /dev/null +++ b/src/main/resources/certs/generate-dev-certs.sh @@ -0,0 +1,58 @@ +#!/bin/sh + +set -x + +CERTS_DIR=$(realpath "$(dirname "$0")") + +SSL_KEYSTORE=cryostat-keystore.p12 + +SSL_KEYSTORE_PASS_FILE=keystore.pass + +cleanup() { + cd "$CERTS_DIR" + rm $SSL_KEYSTORE $SSL_KEYSTORE_PASS_FILE + cd - +} + +case "$1" in + clean) + cleanup + exit 0 + ;; + generate) + ;; + *) + echo "Usage: $0 [clean|generate]" + exit 1 + ;; +esac + +set -e + +genpass() { + < /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c32 +} + +SSL_KEYSTORE_PASS=$(genpass) + +cd "$CERTS_DIR" +trap "cd -" EXIT + +echo "$SSL_KEYSTORE_PASS" > $SSL_KEYSTORE_PASS_FILE + +keytool \ + -genkeypair -v \ + -alias custom-cryostat \ + -dname "cn=cryostat, o=Cryostat, c=CA" \ + -storetype PKCS12 \ + -validity 365 \ + -keyalg RSA \ + -storepass "$SSL_KEYSTORE_PASS" \ + -keystore "$SSL_KEYSTORE" + +keytool \ + -exportcert -v \ + -alias custom-cryostat \ + -keystore "$SSL_KEYSTORE" \ + -storepass "$SSL_KEYSTORE_PASS" \ + -file server.cer diff --git a/certs/keystore.pass b/src/main/resources/certs/keystore.pass similarity index 100% rename from certs/keystore.pass rename to src/main/resources/certs/keystore.pass diff --git a/certs/server.cer b/src/main/resources/certs/server.cer similarity index 100% rename from certs/server.cer rename to src/main/resources/certs/server.cer