From 0fddc5041e74a86635666f97ad7a861809275343 Mon Sep 17 00:00:00 2001 From: Clement Escoffier Date: Fri, 1 Mar 2024 12:44:57 +0100 Subject: [PATCH] Allows the HTTP server to use PEM truststore Previously, configuring the truststore with PEM files for mTLS (mutual TLS) usage was not supported, limiting options to JKS and P12 formats. This commit addresses this limitation by introducing support for PEM truststores in the HTTP server configuration. Additionally, this commit accomplishes the following tasks: - Removes hand-crafted certificates. - Fixes issues related to alias passwords. - Deprecates the usage of "key" properties, replacing them with "alias" properties for clarity and consistency. --- build-parent/pom.xml | 2 +- .../vertx/http/DisableHttpPortTest.java | 22 +- ...pServerTlsPKCS12CertificateReloadTest.java | 4 +- .../Http2RSTFloodProtectionConfigTest.java | 23 +- .../http2/Http2RSTFloodProtectionTest.java | 19 +- .../quarkus/vertx/http/http2/Http2Test.java | 19 +- .../management/ManagementWithJksTest.java | 22 +- .../management/ManagementWithP12Test.java | 24 +- .../management/ManagementWithPemTest.java | 26 ++- .../MtlsRequestBasicAuthTest.java | 35 ++- .../vertx/http/mtls/MtlsRequestTest.java | 74 +++++++ .../vertx/http/mtls/MtlsRequiredTest.java | 78 +++++++ .../vertx/http/mtls/MtlsWithP12Test.java | 78 +++++++ .../vertx/http/mtls/MtlsWithPemTest.java | 79 +++++++ .../vertx/http/security/MtlsRequestTest.java | 61 ----- .../vertx/http/security/MtlsRequiredTest.java | 60 ----- .../vertx/http/ssl/SslServerWithJksTest.java | 27 +-- .../vertx/http/ssl/SslServerWithP12Test.java | 27 +-- .../vertx/http/ssl/SslServerWithPemTest.java | 40 ++-- .../src/test/resources/conf/README.md | 25 --- .../src/test/resources/conf/disable-http.conf | 4 - .../src/test/resources/conf/localhost.crt | Bin 715 -> 0 bytes .../resources/conf/mtls/client-keystore.jks | Bin 2214 -> 0 bytes .../resources/conf/mtls/client-truststore.jks | Bin 1674 -> 0 bytes .../resources/conf/mtls/mtls-basic-jks.conf | 7 - .../test/resources/conf/mtls/mtls-jks.conf | 9 - .../resources/conf/mtls/mtls-no-auth-jks.conf | 7 - .../resources/conf/mtls/server-keystore.jks | Bin 2423 -> 0 bytes .../resources/conf/mtls/server-truststore.jks | Bin 925 -> 0 bytes .../src/test/resources/conf/server-cert.pem | 22 -- .../src/test/resources/conf/server-key.pem | 28 --- .../test/resources/conf/server-keystore.jks | Bin 2423 -> 0 bytes .../test/resources/conf/server-keystore.p12 | Bin 2423 -> 0 bytes .../conf/ssl-jks-rst-flood-protection.conf | 6 - .../src/test/resources/conf/ssl-jks.conf | 3 - .../src/test/resources/conf/ssl-pem.conf | 6 - .../src/test/resources/conf/ssl-pkcs12.conf | 3 - .../vertx/http/runtime/CertificateConfig.java | 43 +++- .../options/HttpServerOptionsUtils.java | 209 ++++++------------ .../options/TlsCertificateReloader.java | 8 +- .../vertx/http/runtime/options/TlsUtils.java | 159 +++++++++++++ 41 files changed, 769 insertions(+), 490 deletions(-) rename extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/{security => mtls}/MtlsRequestBasicAuthTest.java (54%) create mode 100644 extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/mtls/MtlsRequestTest.java create mode 100644 extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/mtls/MtlsRequiredTest.java create mode 100644 extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/mtls/MtlsWithP12Test.java create mode 100644 extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/mtls/MtlsWithPemTest.java delete mode 100644 extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/security/MtlsRequestTest.java delete mode 100644 extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/security/MtlsRequiredTest.java delete mode 100644 extensions/vertx-http/deployment/src/test/resources/conf/README.md delete mode 100644 extensions/vertx-http/deployment/src/test/resources/conf/disable-http.conf delete mode 100644 extensions/vertx-http/deployment/src/test/resources/conf/localhost.crt delete mode 100644 extensions/vertx-http/deployment/src/test/resources/conf/mtls/client-keystore.jks delete mode 100644 extensions/vertx-http/deployment/src/test/resources/conf/mtls/client-truststore.jks delete mode 100644 extensions/vertx-http/deployment/src/test/resources/conf/mtls/mtls-basic-jks.conf delete mode 100644 extensions/vertx-http/deployment/src/test/resources/conf/mtls/mtls-jks.conf delete mode 100644 extensions/vertx-http/deployment/src/test/resources/conf/mtls/mtls-no-auth-jks.conf delete mode 100644 extensions/vertx-http/deployment/src/test/resources/conf/mtls/server-keystore.jks delete mode 100644 extensions/vertx-http/deployment/src/test/resources/conf/mtls/server-truststore.jks delete mode 100644 extensions/vertx-http/deployment/src/test/resources/conf/server-cert.pem delete mode 100644 extensions/vertx-http/deployment/src/test/resources/conf/server-key.pem delete mode 100644 extensions/vertx-http/deployment/src/test/resources/conf/server-keystore.jks delete mode 100644 extensions/vertx-http/deployment/src/test/resources/conf/server-keystore.p12 delete mode 100644 extensions/vertx-http/deployment/src/test/resources/conf/ssl-jks-rst-flood-protection.conf delete mode 100644 extensions/vertx-http/deployment/src/test/resources/conf/ssl-jks.conf delete mode 100644 extensions/vertx-http/deployment/src/test/resources/conf/ssl-pem.conf delete mode 100644 extensions/vertx-http/deployment/src/test/resources/conf/ssl-pkcs12.conf create mode 100644 extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/options/TlsUtils.java diff --git a/build-parent/pom.xml b/build-parent/pom.xml index d6b4d1f649c4e..1fe653830d0cc 100644 --- a/build-parent/pom.xml +++ b/build-parent/pom.xml @@ -374,7 +374,7 @@ me.escoffier.certs certificate-generator-junit5 - 0.4.0 + 0.4.3 test diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/DisableHttpPortTest.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/DisableHttpPortTest.java index 65e0d23e78197..a8b5de8403c04 100644 --- a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/DisableHttpPortTest.java +++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/DisableHttpPortTest.java @@ -11,6 +11,7 @@ import jakarta.enterprise.event.Observes; import org.assertj.core.api.Assertions; +import org.jboss.shrinkwrap.api.asset.StringAsset; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -19,20 +20,33 @@ import io.quarkus.test.QuarkusUnitTest; import io.restassured.RestAssured; import io.vertx.ext.web.Router; +import me.escoffier.certs.Format; +import me.escoffier.certs.junit5.Certificate; +import me.escoffier.certs.junit5.Certificates; +@Certificates(baseDir = "target/certs", certificates = @Certificate(name = "ssl-test", password = "secret", formats = { + Format.JKS, Format.PKCS12, Format.PEM })) public class DisableHttpPortTest { + private static final String configuration = """ + # Enable SSL, configure the key store + quarkus.http.insecure-requests=REDIRECT + quarkus.http.ssl.certificate.files=server-cert.crt + quarkus.http.ssl.certificate.key-files=server-key.key + """; + @RegisterExtension static final QuarkusUnitTest config = new QuarkusUnitTest() .withApplicationRoot((jar) -> jar .addClasses(MyBean.class) - .addAsResource(new File("src/test/resources/conf/disable-http.conf"), "application.properties") - .addAsResource(new File("src/test/resources/conf/server-key.pem"), "server-key.pem") - .addAsResource(new File("src/test/resources/conf/server-cert.pem"), "server-cert.pem")); + .addAsResource(new StringAsset(configuration), "application.properties") + .addAsResource(new File("target/certs/ssl-test.key"), "server-key.key") + .addAsResource(new File("target/certs/ssl-test.crt"), "server-cert.crt")); @BeforeAll public static void setupRestAssured() { - RestAssured.useRelaxedHTTPSValidation(); + RestAssured + .trustStore(new File("target/certs/ssl-test-truststore.jks"), "secret"); } @AfterAll diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/certReload/MainHttpServerTlsPKCS12CertificateReloadTest.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/certReload/MainHttpServerTlsPKCS12CertificateReloadTest.java index 82473a256a1a4..7f8494bb679cd 100644 --- a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/certReload/MainHttpServerTlsPKCS12CertificateReloadTest.java +++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/certReload/MainHttpServerTlsPKCS12CertificateReloadTest.java @@ -54,9 +54,11 @@ public class MainHttpServerTlsPKCS12CertificateReloadTest { @RegisterExtension static final QuarkusUnitTest config = new QuarkusUnitTest() .withApplicationRoot((jar) -> jar.addClasses(MyBean.class)) - .overrideConfigKey("quarkus.http.ssl.insecure-requests", "redirect") + .overrideConfigKey("quarkus.http.insecure-requests", "redirect") .overrideConfigKey("quarkus.http.ssl.certificate.reload-period", "30s") .overrideConfigKey("quarkus.http.ssl.certificate.key-store-file", temp.getAbsolutePath() + "/tls.p12") + .overrideConfigKey("quarkus.http.ssl.certificate.key-store-password", "password") + .overrideConfigKey("loc", temp.getAbsolutePath()) .setBeforeAllCustomizer(() -> { try { diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/http2/Http2RSTFloodProtectionConfigTest.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/http2/Http2RSTFloodProtectionConfigTest.java index c3abccb5d5512..b141965526b81 100644 --- a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/http2/Http2RSTFloodProtectionConfigTest.java +++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/http2/Http2RSTFloodProtectionConfigTest.java @@ -11,6 +11,7 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.event.Observes; +import org.jboss.shrinkwrap.api.asset.StringAsset; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.Test; @@ -26,14 +27,28 @@ import io.vertx.core.http.HttpClientRequest; import io.vertx.core.http.HttpVersion; import io.vertx.core.net.JdkSSLEngineOptions; +import io.vertx.core.net.JksOptions; import io.vertx.ext.web.Router; +import me.escoffier.certs.Format; +import me.escoffier.certs.junit5.Certificate; +import me.escoffier.certs.junit5.Certificates; /** * Configuration of the RST flood protection (CVE-2023-44487) */ +@Certificates(baseDir = "target/certs", certificates = @Certificate(name = "ssl-test", password = "secret", formats = { + Format.JKS, Format.PKCS12, Format.PEM })) @DisabledOnOs(OS.WINDOWS) public class Http2RSTFloodProtectionConfigTest { + private static final String configuration = """ + quarkus.http.ssl.certificate.key-store-file=server-keystore.jks + quarkus.http.ssl.certificate.key-store-password=secret + + quarkus.http.limits.rst-flood-max-rst-frame-per-window=10 + quarkus.http.limits.rst-flood-window-duration=10s + """; + @TestHTTPResource(value = "/ping", ssl = true) URL sslUrl; @@ -44,9 +59,8 @@ public class Http2RSTFloodProtectionConfigTest { static final QuarkusUnitTest config = new QuarkusUnitTest() .withApplicationRoot((jar) -> jar .addClasses(MyBean.class) - .addAsResource(new File("src/test/resources/conf/ssl-jks-rst-flood-protection.conf"), - "application.properties") - .addAsResource(new File("src/test/resources/conf/server-keystore.jks"), "server-keystore.jks")); + .addAsResource(new StringAsset(configuration), "application.properties") + .addAsResource(new File("target/certs/ssl-test-keystore.jks"), "server-keystore.jks")); @Test void testRstFloodProtectionWithTlsEnabled() throws Exception { @@ -55,7 +69,8 @@ void testRstFloodProtectionWithTlsEnabled() throws Exception { .setUseAlpn(true) .setProtocolVersion(HttpVersion.HTTP_2) .setSsl(true) - .setTrustAll(true); + .setTrustOptions(new JksOptions().setPath(new File("target/certs/ssl-test-truststore.jks").getAbsolutePath()) + .setPassword("secret")); var client = VertxCoreRecorder.getVertx().get().createHttpClient(options); int port = sslUrl.getPort(); diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/http2/Http2RSTFloodProtectionTest.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/http2/Http2RSTFloodProtectionTest.java index 991cc1d57771c..3e676ca2abfa0 100644 --- a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/http2/Http2RSTFloodProtectionTest.java +++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/http2/Http2RSTFloodProtectionTest.java @@ -11,6 +11,7 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.event.Observes; +import org.jboss.shrinkwrap.api.asset.StringAsset; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.Test; @@ -26,14 +27,25 @@ import io.vertx.core.http.HttpClientRequest; import io.vertx.core.http.HttpVersion; import io.vertx.core.net.JdkSSLEngineOptions; +import io.vertx.core.net.JksOptions; import io.vertx.ext.web.Router; +import me.escoffier.certs.Format; +import me.escoffier.certs.junit5.Certificate; +import me.escoffier.certs.junit5.Certificates; /** * Reproduce CVE-2023-44487. */ +@Certificates(baseDir = "target/certs", certificates = @Certificate(name = "ssl-test", password = "secret", formats = { + Format.JKS, Format.PKCS12, Format.PEM })) @DisabledOnOs(OS.WINDOWS) public class Http2RSTFloodProtectionTest { + private static final String configuration = """ + quarkus.http.ssl.certificate.key-store-file=server-keystore.jks + quarkus.http.ssl.certificate.key-store-password=secret + """; + @TestHTTPResource(value = "/ping", ssl = true) URL sslUrl; @@ -44,8 +56,8 @@ public class Http2RSTFloodProtectionTest { static final QuarkusUnitTest config = new QuarkusUnitTest() .withApplicationRoot((jar) -> jar .addClasses(MyBean.class) - .addAsResource(new File("src/test/resources/conf/ssl-jks.conf"), "application.properties") - .addAsResource(new File("src/test/resources/conf/server-keystore.jks"), "server-keystore.jks")); + .addAsResource(new StringAsset(configuration), "application.properties") + .addAsResource(new File("target/certs/ssl-test-keystore.jks"), "server-keystore.jks")); @Test void testRstFloodProtectionWithTlsEnabled() throws Exception { @@ -54,7 +66,8 @@ void testRstFloodProtectionWithTlsEnabled() throws Exception { .setUseAlpn(true) .setProtocolVersion(HttpVersion.HTTP_2) .setSsl(true) - .setTrustAll(true); + .setTrustOptions(new JksOptions().setPath(new File("target/certs/ssl-test-truststore.jks").getAbsolutePath()) + .setPassword("secret")); var client = VertxCoreRecorder.getVertx().get().createHttpClient(options); int port = sslUrl.getPort(); diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/http2/Http2Test.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/http2/Http2Test.java index 8d79b21ab3578..4cf2f94e496ea 100644 --- a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/http2/Http2Test.java +++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/http2/Http2Test.java @@ -21,11 +21,17 @@ import io.vertx.core.buffer.Buffer; import io.vertx.core.http.HttpVersion; import io.vertx.core.net.JdkSSLEngineOptions; +import io.vertx.core.net.JksOptions; import io.vertx.ext.web.Router; import io.vertx.ext.web.client.HttpResponse; import io.vertx.ext.web.client.WebClient; import io.vertx.ext.web.client.WebClientOptions; +import me.escoffier.certs.Format; +import me.escoffier.certs.junit5.Certificate; +import me.escoffier.certs.junit5.Certificates; +@Certificates(baseDir = "target/certs", certificates = @Certificate(name = "ssl-test", password = "secret", formats = { + Format.JKS, Format.PKCS12, Format.PEM })) public class Http2Test { protected static final String PING_DATA = "12345678"; @@ -33,15 +39,16 @@ public class Http2Test { @TestHTTPResource(value = "/ping", ssl = true) URL sslUrl; - @TestHTTPResource(value = "/ping", ssl = false) - URL url; + @TestHTTPResource(value = "/ping") + URL plainUrl; @RegisterExtension static final QuarkusUnitTest config = new QuarkusUnitTest() .withApplicationRoot((jar) -> jar .addClasses(MyBean.class) - .addAsResource(new File("src/test/resources/conf/ssl-jks.conf"), "application.properties") - .addAsResource(new File("src/test/resources/conf/server-keystore.jks"), "server-keystore.jks")); + .addAsResource(new File("target/certs/ssl-test-keystore.jks"), "server-keystore.jks")) + .overrideConfigKey("quarkus.http.ssl.certificate.key-store-file", "server-keystore.jks") + .overrideConfigKey("quarkus.http.ssl.certificate.key-store-password", "secret"); @Test public void testHttp2EnabledSsl() throws ExecutionException, InterruptedException { @@ -50,7 +57,7 @@ public void testHttp2EnabledSsl() throws ExecutionException, InterruptedExceptio .setUseAlpn(true) .setProtocolVersion(HttpVersion.HTTP_2) .setSsl(true) - .setTrustAll(true); + .setTrustOptions(new JksOptions().setPath("target/certs/ssl-test-truststore.jks").setPassword("secret")); WebClient client = WebClient.create(VertxCoreRecorder.getVertx().get(), options); int port = sslUrl.getPort(); @@ -63,7 +70,7 @@ public void testHttp2EnabledPlain() throws ExecutionException, InterruptedExcept .setProtocolVersion(HttpVersion.HTTP_2) .setHttp2ClearTextUpgrade(true); WebClient client = WebClient.create(VertxCoreRecorder.getVertx().get(), options); - runTest(client, url.getPort()); + runTest(client, plainUrl.getPort()); } private void runTest(WebClient client, int port) throws InterruptedException, ExecutionException { diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/management/ManagementWithJksTest.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/management/ManagementWithJksTest.java index 1a0827d198fb4..64d1c9d094aae 100644 --- a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/management/ManagementWithJksTest.java +++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/management/ManagementWithJksTest.java @@ -21,19 +21,25 @@ import io.restassured.RestAssured; import io.vertx.core.Handler; import io.vertx.ext.web.RoutingContext; +import me.escoffier.certs.Format; +import me.escoffier.certs.junit5.Certificate; +import me.escoffier.certs.junit5.Certificates; +@Certificates(baseDir = "target/certs", certificates = @Certificate(name = "ssl-management-interface-test", password = "secret", formats = { + Format.JKS, Format.PKCS12, Format.PEM })) public class ManagementWithJksTest { - private static final String APP_PROPS = "" + - "quarkus.management.enabled=true\n" + - "quarkus.management.root-path=/management\n" + - "quarkus.management.ssl.certificate.key-store-file=server-keystore.jks\n" + - "quarkus.management.ssl.certificate.key-store-password=secret\n"; + private static final String configuration = """ + quarkus.management.enabled=true + quarkus.management.root-path=/management + quarkus.management.ssl.certificate.key-store-file=server-keystore.jks + quarkus.management.ssl.certificate.key-store-password=secret + """; @RegisterExtension static final QuarkusUnitTest config = new QuarkusUnitTest() .withApplicationRoot((jar) -> jar - .addAsResource(new StringAsset(APP_PROPS), "application.properties") - .addAsResource(new File("src/test/resources/conf/server-keystore.jks"), "server-keystore.jks") + .addAsResource(new StringAsset(configuration), "application.properties") + .addAsResource(new File("target/certs/ssl-management-interface-test-keystore.jks"), "server-keystore.jks") .addClasses(MyObserver.class)) .addBuildChainCustomizer(buildCustomizer()); @@ -72,7 +78,7 @@ public void handle(RoutingContext rc) { @Test public void testSslWithJks() { RestAssured.given() - .relaxedHTTPSValidation() + .trustStore(new File("target/certs/ssl-management-interface-test-truststore.jks"), "secret") .get("https://0.0.0.0:9001/management/my-route") .then().statusCode(200).body(Matchers.equalTo("ssl")); } diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/management/ManagementWithP12Test.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/management/ManagementWithP12Test.java index a8e55cedb5608..2dfe139a6948a 100644 --- a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/management/ManagementWithP12Test.java +++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/management/ManagementWithP12Test.java @@ -21,20 +21,26 @@ import io.restassured.RestAssured; import io.vertx.core.Handler; import io.vertx.ext.web.RoutingContext; +import me.escoffier.certs.Format; +import me.escoffier.certs.junit5.Certificate; +import me.escoffier.certs.junit5.Certificates; +@Certificates(baseDir = "target/certs", certificates = @Certificate(name = "ssl-management-interface-test", password = "secret", formats = { + Format.JKS, Format.PKCS12, Format.PEM })) public class ManagementWithP12Test { - private static final String APP_PROPS = "" + - "quarkus.management.enabled=true\n" + - "quarkus.management.root-path=/management\n" + - "quarkus.management.ssl.certificate.key-store-file=server-keystore.p12\n" + - "quarkus.management.ssl.certificate.key-store-password=secret\n"; + private static final String configuration = """ + quarkus.management.enabled=true + quarkus.management.root-path=/management + quarkus.management.ssl.certificate.key-store-file=server-keystore.p12 + quarkus.management.ssl.certificate.key-store-password=secret + """; @RegisterExtension static final QuarkusUnitTest config = new QuarkusUnitTest() .withApplicationRoot((jar) -> jar - .addAsResource(new StringAsset(APP_PROPS), "application.properties") - .addAsResource(new File("src/test/resources/conf/server-keystore.p12"), "server-keystore.p12") - .addClasses(MyObserver.class)) + .addAsResource(new StringAsset(configuration), "application.properties") + .addAsResource(new File("target/certs/ssl-management-interface-test-keystore.p12"), "server-keystore.p12") + .addClasses(ManagementWithJksTest.MyObserver.class)) .addBuildChainCustomizer(buildCustomizer()); static Consumer buildCustomizer() { @@ -72,7 +78,7 @@ public void handle(RoutingContext rc) { @Test public void testSslWithP12() { RestAssured.given() - .relaxedHTTPSValidation() + .trustStore(new File("target/certs/ssl-management-interface-test-truststore.jks"), "secret") .get("https://0.0.0.0:9001/management/my-route") .then().statusCode(200).body(Matchers.equalTo("ssl")); } diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/management/ManagementWithPemTest.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/management/ManagementWithPemTest.java index bc86379e35909..3c5bf89806922 100644 --- a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/management/ManagementWithPemTest.java +++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/management/ManagementWithPemTest.java @@ -21,20 +21,27 @@ import io.restassured.RestAssured; import io.vertx.core.Handler; import io.vertx.ext.web.RoutingContext; +import me.escoffier.certs.Format; +import me.escoffier.certs.junit5.Certificate; +import me.escoffier.certs.junit5.Certificates; +@Certificates(baseDir = "target/certs", certificates = @Certificate(name = "ssl-management-interface-test", password = "secret", formats = { + Format.JKS, Format.PKCS12, Format.PEM })) public class ManagementWithPemTest { - private static final String APP_PROPS = "" + - "quarkus.management.enabled=true\n" + - "quarkus.management.root-path=/management\n" + - "quarkus.management.ssl.certificate.files=server-cert.pem\n" + - "quarkus.management.ssl.certificate.key-files=server-key.pem\n"; + + private static final String configuration = """ + quarkus.management.enabled=true + quarkus.management.root-path=/management + quarkus.management.ssl.certificate.files=server.crt + quarkus.management.ssl.certificate.key-files=server.key + """; @RegisterExtension static final QuarkusUnitTest config = new QuarkusUnitTest() .withApplicationRoot((jar) -> jar - .addAsResource(new StringAsset(APP_PROPS), "application.properties") - .addAsResource(new File("src/test/resources/conf/server-key.pem"), "server-key.pem") - .addAsResource(new File("src/test/resources/conf/server-cert.pem"), "server-cert.pem") + .addAsResource(new StringAsset(configuration), "application.properties") + .addAsResource(new File("target/certs/ssl-management-interface-test.key"), "server.key") + .addAsResource(new File("target/certs/ssl-management-interface-test.crt"), "server.crt") .addClasses(MyObserver.class)) .addBuildChainCustomizer(buildCustomizer()); @@ -73,7 +80,8 @@ public void handle(RoutingContext rc) { @Test public void testSslWithPem() { RestAssured.given() - .relaxedHTTPSValidation() + .given() + .trustStore(new File("target/certs/ssl-management-interface-test-truststore.jks"), "secret") .get("https://0.0.0.0:9001/management/my-route") .then().statusCode(200).body(Matchers.equalTo("ssl")); } diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/security/MtlsRequestBasicAuthTest.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/mtls/MtlsRequestBasicAuthTest.java similarity index 54% rename from extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/security/MtlsRequestBasicAuthTest.java rename to extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/mtls/MtlsRequestBasicAuthTest.java index 2a651111126f0..303c23ab05f29 100644 --- a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/security/MtlsRequestBasicAuthTest.java +++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/mtls/MtlsRequestBasicAuthTest.java @@ -1,4 +1,4 @@ -package io.quarkus.vertx.http.security; +package io.quarkus.vertx.http.mtls; import static org.hamcrest.Matchers.is; @@ -8,6 +8,7 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.event.Observes; +import org.jboss.shrinkwrap.api.asset.StringAsset; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -17,11 +18,27 @@ import io.quarkus.test.QuarkusUnitTest; import io.quarkus.test.common.http.TestHTTPResource; import io.quarkus.vertx.http.runtime.security.QuarkusHttpUser; +import io.quarkus.vertx.http.security.TestTrustedIdentityProvider; import io.restassured.RestAssured; import io.vertx.ext.web.Router; +import me.escoffier.certs.Format; +import me.escoffier.certs.junit5.Certificate; +import me.escoffier.certs.junit5.Certificates; +@Certificates(baseDir = "target/certs", certificates = @Certificate(name = "mtls-test", password = "secret", formats = { + Format.JKS, Format.PKCS12, Format.PEM }, client = true)) public class MtlsRequestBasicAuthTest { + private static final String configuration = """ + quarkus.http.ssl.certificate.key-store-file=server-keystore.jks + quarkus.http.ssl.certificate.key-store-password=secret + quarkus.http.ssl.certificate.trust-store-file=server-truststore.jks + quarkus.http.ssl.certificate.trust-store-password=secret + quarkus.http.ssl.client-auth=REQUEST + quarkus.http.auth.basic=true + quarkus.http.auth.proactive=true + """; + @TestHTTPResource(value = "/mtls", ssl = true) URL url; @@ -30,9 +47,9 @@ public class MtlsRequestBasicAuthTest { .withApplicationRoot((jar) -> jar .addClasses(MyBean.class) .addClasses(TestIdentityProvider.class, TestTrustedIdentityProvider.class, TestIdentityController.class) - .addAsResource("conf/mtls/mtls-basic-jks.conf", "application.properties") - .addAsResource("conf/mtls/server-keystore.jks", "server-keystore.jks") - .addAsResource("conf/mtls/server-truststore.jks", "server-truststore.jks")); + .addAsResource(new StringAsset(configuration), "application.properties") + .addAsResource(new File("target/certs/mtls-test-keystore.jks"), "server-keystore.jks") + .addAsResource(new File("target/certs/mtls-test-server-truststore.jks"), "server-truststore.jks")); @BeforeAll public static void setup() { @@ -43,15 +60,15 @@ public static void setup() { @Test public void testClientAuthentication() { RestAssured.given() - .keyStore(new File("src/test/resources/conf/mtls/client-keystore.jks"), "password") - .trustStore(new File("src/test/resources/conf/mtls/client-truststore.jks"), "password") - .get(url).then().statusCode(200).body(is("CN=client,OU=cert,O=quarkus,L=city,ST=state,C=AU")); + .keyStore("target/certs/mtls-test-client-keystore.jks", "secret") + .trustStore("target/certs/mtls-test-client-truststore.jks", "secret") + .get(url).then().statusCode(200).body(is("CN=localhost")); } @Test public void testNoClientCert() { RestAssured.given() - .trustStore(new File("src/test/resources/conf/mtls/client-truststore.jks"), "password") + .trustStore("target/certs/mtls-test-client-truststore.jks", "secret") .get(url).then().statusCode(200).body(is("")); } @@ -61,7 +78,7 @@ public void testNoClientCertBasicAuth() { .auth() .preemptive() .basic("admin", "admin") - .trustStore(new File("src/test/resources/conf/mtls/client-truststore.jks"), "password") + .trustStore("target/certs/mtls-test-client-truststore.jks", "secret") .get(url).then().statusCode(200).body(is("admin")); } diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/mtls/MtlsRequestTest.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/mtls/MtlsRequestTest.java new file mode 100644 index 0000000000000..e8ac562acc49e --- /dev/null +++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/mtls/MtlsRequestTest.java @@ -0,0 +1,74 @@ +package io.quarkus.vertx.http.mtls; + +import static org.hamcrest.Matchers.is; + +import java.io.File; +import java.net.URL; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.event.Observes; + +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; +import io.quarkus.test.common.http.TestHTTPResource; +import io.quarkus.vertx.http.runtime.security.QuarkusHttpUser; +import io.restassured.RestAssured; +import io.vertx.ext.web.Router; +import me.escoffier.certs.Format; +import me.escoffier.certs.junit5.Certificate; +import me.escoffier.certs.junit5.Certificates; + +@Certificates(baseDir = "target/certs", certificates = @Certificate(name = "mtls-test", password = "secret", formats = { + Format.JKS, Format.PKCS12, Format.PEM }, client = true)) +public class MtlsRequestTest { + + private static final String configuration = """ + quarkus.http.ssl.certificate.key-store-file=server-keystore.jks + quarkus.http.ssl.certificate.key-store-password=secret + quarkus.http.ssl.certificate.trust-store-file=server-truststore.jks + quarkus.http.ssl.certificate.trust-store-password=secret + quarkus.http.ssl.client-auth=REQUEST + quarkus.http.auth.permission.all.paths=/* + quarkus.http.auth.permission.all.policy=authenticated + """; + + @TestHTTPResource(value = "/mtls", ssl = true) + URL url; + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar + .addClasses(MyBean.class) + .addAsResource(new StringAsset(configuration), "application.properties") + .addAsResource(new File("target/certs/mtls-test-keystore.jks"), "server-keystore.jks") + .addAsResource(new File("target/certs/mtls-test-server-truststore.jks"), "server-truststore.jks")); + + @Test + public void testClientAuthentication() { + RestAssured.given() + .keyStore("target/certs/mtls-test-client-keystore.jks", "secret") + .trustStore("target/certs/mtls-test-client-truststore.jks", "secret") + .get(url).then().statusCode(200).body(is("CN=localhost")); + } + + @Test + public void testNoClientCert() { + RestAssured.given() + .trustStore("target/certs/mtls-test-client-truststore.jks", "secret") + .get(url).then().statusCode(401); + } + + @ApplicationScoped + static class MyBean { + + public void register(@Observes Router router) { + router.get("/mtls").handler(rc -> { + rc.response().end(QuarkusHttpUser.class.cast(rc.user()).getSecurityIdentity().getPrincipal().getName()); + }); + } + + } +} diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/mtls/MtlsRequiredTest.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/mtls/MtlsRequiredTest.java new file mode 100644 index 0000000000000..fbbed0c116045 --- /dev/null +++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/mtls/MtlsRequiredTest.java @@ -0,0 +1,78 @@ +package io.quarkus.vertx.http.mtls; + +import static org.hamcrest.Matchers.is; + +import java.io.File; +import java.net.URL; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.event.Observes; + +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; +import io.quarkus.test.common.http.TestHTTPResource; +import io.quarkus.vertx.http.runtime.security.QuarkusHttpUser; +import io.restassured.RestAssured; +import io.vertx.ext.web.Router; +import me.escoffier.certs.Format; +import me.escoffier.certs.junit5.Certificate; +import me.escoffier.certs.junit5.Certificates; + +@Certificates(baseDir = "target/certs", certificates = @Certificate(name = "mtls-test", password = "secret", formats = { + Format.JKS, Format.PKCS12, Format.PEM }, client = true)) +public class MtlsRequiredTest { + + private static final String configuration = """ + quarkus.http.ssl.certificate.key-store-file=server-keystore.jks + quarkus.http.ssl.certificate.key-store-password=secret + quarkus.http.ssl.certificate.trust-store-file=server-truststore.jks + quarkus.http.ssl.certificate.trust-store-password=secret + quarkus.http.ssl.client-auth=REQUIRED + quarkus.http.insecure-requests=enabled + + quarkus.http.auth.permission.default.paths=/* + quarkus.http.auth.permission.default.policy=authenticated + """; + + @TestHTTPResource(value = "/mtls", ssl = true) + URL url; + + @TestHTTPResource(value = "/mtls", ssl = false) + URL urlNoTls; + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar + .addClasses(MyBean.class) + .addAsResource(new StringAsset(configuration), "application.properties") + .addAsResource(new File("target/certs/mtls-test-keystore.jks"), "server-keystore.jks") + .addAsResource(new File("target/certs/mtls-test-server-truststore.jks"), "server-truststore.jks")); + + @Test + public void testClientAuthentication() { + RestAssured.given() + .keyStore("target/certs/mtls-test-client-keystore.jks", "secret") + .trustStore("target/certs/mtls-test-client-truststore.jks", "secret") + .get(url).then().statusCode(200).body(is("CN=localhost")); + } + + @Test + public void testNoClientCert() { + RestAssured.given() + .get(urlNoTls).then().statusCode(401); + } + + @ApplicationScoped + static class MyBean { + + public void register(@Observes Router router) { + router.get("/mtls").handler(rc -> { + rc.response().end(QuarkusHttpUser.class.cast(rc.user()).getSecurityIdentity().getPrincipal().getName()); + }); + } + + } +} diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/mtls/MtlsWithP12Test.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/mtls/MtlsWithP12Test.java new file mode 100644 index 0000000000000..c0cf63e6b0fe1 --- /dev/null +++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/mtls/MtlsWithP12Test.java @@ -0,0 +1,78 @@ +package io.quarkus.vertx.http.mtls; + +import static org.hamcrest.Matchers.is; + +import java.io.File; +import java.net.URL; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.event.Observes; + +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; +import io.quarkus.test.common.http.TestHTTPResource; +import io.quarkus.vertx.http.runtime.security.QuarkusHttpUser; +import io.restassured.RestAssured; +import io.vertx.ext.web.Router; +import me.escoffier.certs.Format; +import me.escoffier.certs.junit5.Certificate; +import me.escoffier.certs.junit5.Certificates; + +@Certificates(baseDir = "target/certs", certificates = @Certificate(name = "mtls-test", password = "secret", formats = { + Format.JKS, Format.PKCS12, Format.PEM }, client = true)) +public class MtlsWithP12Test { + + private static final String configuration = """ + quarkus.http.ssl.certificate.key-store-file=server-keystore.p12 + quarkus.http.ssl.certificate.key-store-password=secret + quarkus.http.ssl.certificate.trust-store-file=server-truststore.p12 + quarkus.http.ssl.certificate.trust-store-password=secret + quarkus.http.ssl.client-auth=REQUIRED + quarkus.http.insecure-requests=enabled + + quarkus.http.auth.permission.default.paths=/* + quarkus.http.auth.permission.default.policy=authenticated + """; + + @TestHTTPResource(value = "/mtls", ssl = true) + URL url; + + @TestHTTPResource(value = "/mtls", ssl = false) + URL urlNoTls; + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar + .addClasses(MyBean.class) + .addAsResource(new StringAsset(configuration), "application.properties") + .addAsResource(new File("target/certs/mtls-test-keystore.p12"), "server-keystore.p12") + .addAsResource(new File("target/certs/mtls-test-server-truststore.p12"), "server-truststore.p12")); + + @Test + public void testClientAuthentication() { + RestAssured.given() + .keyStore("target/certs/mtls-test-client-keystore.jks", "secret") + .trustStore("target/certs/mtls-test-client-truststore.jks", "secret") + .get(url).then().statusCode(200).body(is("CN=localhost")); + } + + @Test + public void testNoClientCert() { + RestAssured.given() + .get(urlNoTls).then().statusCode(401); + } + + @ApplicationScoped + static class MyBean { + + public void register(@Observes Router router) { + router.get("/mtls").handler(rc -> { + rc.response().end(QuarkusHttpUser.class.cast(rc.user()).getSecurityIdentity().getPrincipal().getName()); + }); + } + + } +} diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/mtls/MtlsWithPemTest.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/mtls/MtlsWithPemTest.java new file mode 100644 index 0000000000000..6230f62508515 --- /dev/null +++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/mtls/MtlsWithPemTest.java @@ -0,0 +1,79 @@ +package io.quarkus.vertx.http.mtls; + +import static org.hamcrest.Matchers.is; + +import java.io.File; +import java.net.URL; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.event.Observes; + +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; +import io.quarkus.test.common.http.TestHTTPResource; +import io.quarkus.vertx.http.runtime.security.QuarkusHttpUser; +import io.restassured.RestAssured; +import io.vertx.ext.web.Router; +import me.escoffier.certs.Format; +import me.escoffier.certs.junit5.Certificate; +import me.escoffier.certs.junit5.Certificates; + +@Certificates(baseDir = "target/certs", certificates = @Certificate(name = "mtls-test", password = "secret", formats = { + Format.JKS, Format.PKCS12, Format.PEM }, client = true)) +public class MtlsWithPemTest { + + private static final String configuration = """ + quarkus.http.ssl.certificate.files=server.crt + quarkus.http.ssl.certificate.key-files=server.key + quarkus.http.ssl.certificate.trust-store-file=ca.crt + + quarkus.http.ssl.client-auth=REQUIRED + quarkus.http.insecure-requests=enabled + + quarkus.http.auth.permission.default.paths=/* + quarkus.http.auth.permission.default.policy=authenticated + """; + + @TestHTTPResource(value = "/mtls", ssl = true) + URL url; + + @TestHTTPResource(value = "/mtls", ssl = false) + URL urlNoTls; + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar + .addClasses(MyBean.class) + .addAsResource(new StringAsset(configuration), "application.properties") + .addAsResource(new File("target/certs/mtls-test.key"), "server.key") + .addAsResource(new File("target/certs/mtls-test.crt"), "server.crt") + .addAsResource(new File("target/certs/mtls-test-server-ca.crt"), "ca.crt")); + + @Test + public void testClientAuthentication() { + RestAssured.given() + .keyStore("target/certs/mtls-test-client-keystore.jks", "secret") + .trustStore("target/certs/mtls-test-client-truststore.jks", "secret") + .get(url).then().statusCode(200).body(is("CN=localhost")); + } + + @Test + public void testNoClientCert() { + RestAssured.given() + .get(urlNoTls).then().statusCode(401); + } + + @ApplicationScoped + static class MyBean { + + public void register(@Observes Router router) { + router.get("/mtls").handler(rc -> { + rc.response().end(QuarkusHttpUser.class.cast(rc.user()).getSecurityIdentity().getPrincipal().getName()); + }); + } + + } +} diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/security/MtlsRequestTest.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/security/MtlsRequestTest.java deleted file mode 100644 index 93a2a16e9ad3e..0000000000000 --- a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/security/MtlsRequestTest.java +++ /dev/null @@ -1,61 +0,0 @@ -package io.quarkus.vertx.http.security; - -import static org.hamcrest.Matchers.is; - -import java.io.File; -import java.net.URL; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.event.Observes; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.test.QuarkusUnitTest; -import io.quarkus.test.common.http.TestHTTPResource; -import io.quarkus.vertx.http.runtime.security.QuarkusHttpUser; -import io.restassured.RestAssured; -import io.vertx.ext.web.Router; - -public class MtlsRequestTest { - - @TestHTTPResource(value = "/mtls", ssl = true) - URL url; - - @TestHTTPResource(value = "/mtls", ssl = false) - URL urlNoTls; - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .withApplicationRoot((jar) -> jar - .addClasses(MyBean.class) - .addAsResource(new File("src/test/resources/conf/mtls/mtls-no-auth-jks.conf"), "application.properties") - .addAsResource(new File("src/test/resources/conf/mtls/server-keystore.jks"), "server-keystore.jks") - .addAsResource(new File("src/test/resources/conf/mtls/server-truststore.jks"), "server-truststore.jks")); - - @Test - public void testClientAuthentication() { - RestAssured.given() - .keyStore(new File("src/test/resources/conf/mtls/client-keystore.jks"), "password") - .trustStore(new File("src/test/resources/conf/mtls/client-truststore.jks"), "password") - .get(url).then().statusCode(200).body(is("CN=client,OU=cert,O=quarkus,L=city,ST=state,C=AU")); - } - - @Test - public void testNoClientCert() { - RestAssured.given() - .trustStore(new File("src/test/resources/conf/mtls/client-truststore.jks"), "password") - .get(url).then().statusCode(401); - } - - @ApplicationScoped - static class MyBean { - - public void register(@Observes Router router) { - router.get("/mtls").handler(rc -> { - rc.response().end(QuarkusHttpUser.class.cast(rc.user()).getSecurityIdentity().getPrincipal().getName()); - }); - } - - } -} diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/security/MtlsRequiredTest.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/security/MtlsRequiredTest.java deleted file mode 100644 index 9457f81106d76..0000000000000 --- a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/security/MtlsRequiredTest.java +++ /dev/null @@ -1,60 +0,0 @@ -package io.quarkus.vertx.http.security; - -import static org.hamcrest.Matchers.is; - -import java.io.File; -import java.net.URL; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.event.Observes; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -import io.quarkus.test.QuarkusUnitTest; -import io.quarkus.test.common.http.TestHTTPResource; -import io.quarkus.vertx.http.runtime.security.QuarkusHttpUser; -import io.restassured.RestAssured; -import io.vertx.ext.web.Router; - -public class MtlsRequiredTest { - - @TestHTTPResource(value = "/mtls", ssl = true) - URL url; - - @TestHTTPResource(value = "/mtls", ssl = false) - URL urlNoTls; - - @RegisterExtension - static final QuarkusUnitTest config = new QuarkusUnitTest() - .withApplicationRoot((jar) -> jar - .addClasses(MyBean.class) - .addAsResource(new File("src/test/resources/conf/mtls/mtls-jks.conf"), "application.properties") - .addAsResource(new File("src/test/resources/conf/mtls/server-keystore.jks"), "server-keystore.jks") - .addAsResource(new File("src/test/resources/conf/mtls/server-truststore.jks"), "server-truststore.jks")); - - @Test - public void testClientAuthentication() { - RestAssured.given() - .keyStore(new File("src/test/resources/conf/mtls/client-keystore.jks"), "password") - .trustStore(new File("src/test/resources/conf/mtls/client-truststore.jks"), "password") - .get(url).then().statusCode(200).body(is("CN=client,OU=cert,O=quarkus,L=city,ST=state,C=AU")); - } - - @Test - public void testNoClientCert() { - RestAssured.given() - .get(urlNoTls).then().statusCode(401); - } - - @ApplicationScoped - static class MyBean { - - public void register(@Observes Router router) { - router.get("/mtls").handler(rc -> { - rc.response().end(QuarkusHttpUser.class.cast(rc.user()).getSecurityIdentity().getPrincipal().getName()); - }); - } - - } -} diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/ssl/SslServerWithJksTest.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/ssl/SslServerWithJksTest.java index 0b74e031c0d6b..ffefd7fd6f979 100644 --- a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/ssl/SslServerWithJksTest.java +++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/ssl/SslServerWithJksTest.java @@ -9,8 +9,6 @@ import jakarta.enterprise.event.Observes; import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -18,7 +16,12 @@ import io.quarkus.test.common.http.TestHTTPResource; import io.restassured.RestAssured; import io.vertx.ext.web.Router; +import me.escoffier.certs.Format; +import me.escoffier.certs.junit5.Certificate; +import me.escoffier.certs.junit5.Certificates; +@Certificates(baseDir = "target/certs", certificates = @Certificate(name = "ssl-test", password = "secret", formats = { + Format.JKS, Format.PKCS12, Format.PEM })) public class SslServerWithJksTest { @TestHTTPResource(value = "/ssl", ssl = true) @@ -28,22 +31,16 @@ public class SslServerWithJksTest { static final QuarkusUnitTest config = new QuarkusUnitTest() .withApplicationRoot((jar) -> jar .addClasses(MyBean.class) - .addAsResource(new File("src/test/resources/conf/ssl-jks.conf"), "application.properties") - .addAsResource(new File("src/test/resources/conf/server-keystore.jks"), "server-keystore.jks")); - - @BeforeAll - public static void setupRestAssured() { - RestAssured.useRelaxedHTTPSValidation(); - } - - @AfterAll - public static void restoreRestAssured() { - RestAssured.reset(); - } + .addAsResource(new File("target/certs/ssl-test-keystore.jks"), "server-keystore.jks")) + .overrideConfigKey("quarkus.http.ssl.certificate.key-store-file", "server-keystore.jks") + .overrideConfigKey("quarkus.http.ssl.certificate.key-store-password", "secret"); @Test public void testSslServerWithJKS() { - RestAssured.get(url).then().statusCode(200).body(is("ssl")); + RestAssured + .given() + .trustStore(new File("target/certs/ssl-test-truststore.jks"), "secret") + .get(url).then().statusCode(200).body(is("ssl")); } @ApplicationScoped diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/ssl/SslServerWithP12Test.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/ssl/SslServerWithP12Test.java index 3a3591f20327e..981c9b70cf292 100644 --- a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/ssl/SslServerWithP12Test.java +++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/ssl/SslServerWithP12Test.java @@ -9,8 +9,6 @@ import jakarta.enterprise.event.Observes; import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -18,7 +16,12 @@ import io.quarkus.test.common.http.TestHTTPResource; import io.restassured.RestAssured; import io.vertx.ext.web.Router; +import me.escoffier.certs.Format; +import me.escoffier.certs.junit5.Certificate; +import me.escoffier.certs.junit5.Certificates; +@Certificates(baseDir = "target/certs", certificates = @Certificate(name = "ssl-test", password = "secret", formats = { + Format.JKS, Format.PKCS12, Format.PEM })) public class SslServerWithP12Test { @TestHTTPResource(value = "/ssl", ssl = true) @@ -28,22 +31,16 @@ public class SslServerWithP12Test { static final QuarkusUnitTest config = new QuarkusUnitTest() .withApplicationRoot((jar) -> jar .addClasses(MyBean.class) - .addAsResource(new File("src/test/resources/conf/ssl-pkcs12.conf"), "application.properties") - .addAsResource(new File("src/test/resources/conf/server-keystore.p12"), "server-keystore.pkcs12")); - - @BeforeAll - public static void setupRestAssured() { - RestAssured.useRelaxedHTTPSValidation(); - } - - @AfterAll - public static void restoreRestAssured() { - RestAssured.reset(); - } + .addAsResource(new File("target/certs/ssl-test-keystore.p12"), "server-keystore.pkcs12")) + .overrideConfigKey("quarkus.http.ssl.certificate.key-store-file", "server-keystore.pkcs12") + .overrideConfigKey("quarkus.http.ssl.certificate.key-store-password", "secret"); @Test public void testSslServerWithPkcs12() { - RestAssured.get(url).then().statusCode(200).body(is("ssl")); + RestAssured + .given() + .trustStore(new File("target/certs/ssl-test-truststore.jks"), "secret") + .get(url).then().statusCode(200).body(is("ssl")); } @ApplicationScoped diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/ssl/SslServerWithPemTest.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/ssl/SslServerWithPemTest.java index 448ba943f9e4e..a9580ab8491f5 100644 --- a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/ssl/SslServerWithPemTest.java +++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/ssl/SslServerWithPemTest.java @@ -9,8 +9,7 @@ import jakarta.enterprise.event.Observes; import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; +import org.jboss.shrinkwrap.api.asset.StringAsset; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; @@ -18,13 +17,27 @@ import io.quarkus.test.common.http.TestHTTPResource; import io.restassured.RestAssured; import io.vertx.ext.web.Router; +import me.escoffier.certs.Format; +import me.escoffier.certs.junit5.Certificate; +import me.escoffier.certs.junit5.Certificates; /** * We also set quarkus.http.insecure-requests=disabled in order to test that server starts correctly - see - * https://github.com/quarkusio/quarkus/issues/8336. + * #8336. */ +@Certificates(baseDir = "target/certs", certificates = @Certificate(name = "ssl-test", password = "secret", formats = { + Format.JKS, Format.PKCS12, Format.PEM })) public class SslServerWithPemTest { + private static final String configuration = """ + # Enable SSL, configure the key store + quarkus.http.ssl.certificate.files=server-cert.pem + quarkus.http.ssl.certificate.key-files=server-key.pem + # Test that server starts with this option + # See https://github.com/quarkusio/quarkus/issues/8336 + quarkus.http.insecure-requests=disabled + """; + @TestHTTPResource(value = "/ssl", ssl = true) URL url; @@ -32,23 +45,16 @@ public class SslServerWithPemTest { static final QuarkusUnitTest config = new QuarkusUnitTest() .withApplicationRoot((jar) -> jar .addClasses(MyBean.class) - .addAsResource(new File("src/test/resources/conf/ssl-pem.conf"), "application.properties") - .addAsResource(new File("src/test/resources/conf/server-key.pem"), "server-key.pem") - .addAsResource(new File("src/test/resources/conf/server-cert.pem"), "server-cert.pem")); - - @BeforeAll - public static void setupRestAssured() { - RestAssured.useRelaxedHTTPSValidation(); - } - - @AfterAll - public static void restoreRestAssured() { - RestAssured.reset(); - } + .addAsResource(new StringAsset((configuration)), "application.properties") + .addAsResource(new File("target/certs/ssl-test.key"), "server-key.pem") + .addAsResource(new File("target/certs/ssl-test.crt"), "server-cert.pem")); @Test public void testSslServerWithPem() { - RestAssured.get(url).then().statusCode(200).body(is("ssl")); + RestAssured + .given() + .trustStore(new File("target/certs/ssl-test-truststore.jks"), "secret") + .get(url).then().statusCode(200).body(is("ssl")); } @ApplicationScoped diff --git a/extensions/vertx-http/deployment/src/test/resources/conf/README.md b/extensions/vertx-http/deployment/src/test/resources/conf/README.md deleted file mode 100644 index 5345acc890d29..0000000000000 --- a/extensions/vertx-http/deployment/src/test/resources/conf/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# Generate the Self signed PEM, JKS and P12 certificates - -To renew the certificate, run the following script: - -```bash -export SECRET=secret - -# 1. Create RSA private keys and certificates as a key store and export -export JKS_FILE=server-keystore.jks -export CERT_FILE=localhost.crt -export PKCS_FILE=server-keystore.p12 -export PEM_FILE_CERT=server-cert.pem -export PEM_FILE_KEY=server-key.pem -keytool -genkey -alias test-store -keyalg RSA -keystore ${JKS_FILE} -keysize 2048 -validity 1095 -dname CN=localhost -keypass ${SECRET} -storepass ${SECRET} -keytool -export -alias test-store -file ${CERT_FILE} -keystore ${JKS_FILE} -keypass ${SECRET} -storepass ${SECRET} - - -#2. Transform JSK into PKCS12 -keytool -importkeystore -srckeystore ${JKS_FILE} -srcstorepass ${SECRET} -destkeystore ${PKCS_FILE} -deststoretype PKCS12 -deststorepass ${SECRET} - -# 3. Export the PKCS12 into PEM files -openssl pkcs12 -in ${PKCS_FILE} -nodes -passin pass:${SECRET} | openssl pkcs8 -topk8 -inform PEM -outform PEM -out ${PEM_FILE_KEY} -nocrypt -openssl pkcs12 -name test-store -in ${PKCS_FILE} -nokeys -passin pass:${SECRET} -out ${PEM_FILE_CERT} | echo test-store - -``` diff --git a/extensions/vertx-http/deployment/src/test/resources/conf/disable-http.conf b/extensions/vertx-http/deployment/src/test/resources/conf/disable-http.conf deleted file mode 100644 index 580909ea73575..0000000000000 --- a/extensions/vertx-http/deployment/src/test/resources/conf/disable-http.conf +++ /dev/null @@ -1,4 +0,0 @@ -# Enable SSL, configure the key store -quarkus.http.insecure-requests=REDIRECT -quarkus.http.ssl.certificate.files=server-cert.pem -quarkus.http.ssl.certificate.key-files=server-key.pem diff --git a/extensions/vertx-http/deployment/src/test/resources/conf/localhost.crt b/extensions/vertx-http/deployment/src/test/resources/conf/localhost.crt deleted file mode 100644 index f096c251e25c082f63711349d3f36bb1570eea0a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 715 zcmXqLVmfZn#JGL|GZP~d6HDOtw5#+MlP=ZpUmt=DS~>bkvBzT?^I=B6K4Oy3JG zYJRkg?8Z3^~jADB2dhmi$QTLMQKZjcc{_(#&Zn!qT;r*%Avn8v#yTZOmGVg54 ze-wH9S^UYYYfJb4y}N&#PSCegq26l`o{!H9-6yYaSH691c}qoV3n?;Ug0>BLm}NMFV*QSzw6E^0A1qi0pAHvgur+aj7w4^}$K+m&F`D zdG9@PAOhnE7>JAvve7z6!a@sA@>v=DzadaNNl~70-Gf}^7c(~dY3F~s75q_E$GEzB z+Lv#ecfPl_n{AM!Rk8Tng{bL|>dM)5{knPQwamSkE}iC7SMl;h%`?-$`B!7V@yyt6 zdwJet1%DIwwH{mM{rh_;`rnczZE3o*KS(uPQtFbs*V^2?<(}>t&1Zin-c;_fQ&lqV z;7@LuQ@Z}a^gBC+_)lcz6ekL=t(ug)Yw|9k`pOG(iPyEa*z0t;9dZ6C5dUP|v&AbP zKH0v>LGj>o?OZ>n@H@9}%g<3Ucv|bQIb>IZa+>3`iX)MnQjuAPAC&Kfd=zIrB%*L{ azjkC8&-w{Ta!()03z&F6SJ`WOxgP-MnKbDD diff --git a/extensions/vertx-http/deployment/src/test/resources/conf/mtls/client-keystore.jks b/extensions/vertx-http/deployment/src/test/resources/conf/mtls/client-keystore.jks deleted file mode 100644 index cf6d6ba454864d18322799afac37f520673193d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2214 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 diff --git a/extensions/vertx-http/deployment/src/test/resources/conf/mtls/mtls-basic-jks.conf b/extensions/vertx-http/deployment/src/test/resources/conf/mtls/mtls-basic-jks.conf deleted file mode 100644 index 9cdaf4679f8e7..0000000000000 --- a/extensions/vertx-http/deployment/src/test/resources/conf/mtls/mtls-basic-jks.conf +++ /dev/null @@ -1,7 +0,0 @@ -quarkus.http.ssl.certificate.key-store-file=server-keystore.jks -quarkus.http.ssl.certificate.key-store-password=secret -quarkus.http.ssl.certificate.trust-store-file=server-truststore.jks -quarkus.http.ssl.certificate.trust-store-password=password -quarkus.http.ssl.client-auth=REQUEST -quarkus.http.auth.basic=true -quarkus.http.auth.proactive=true \ No newline at end of file diff --git a/extensions/vertx-http/deployment/src/test/resources/conf/mtls/mtls-jks.conf b/extensions/vertx-http/deployment/src/test/resources/conf/mtls/mtls-jks.conf deleted file mode 100644 index a78a34793096e..0000000000000 --- a/extensions/vertx-http/deployment/src/test/resources/conf/mtls/mtls-jks.conf +++ /dev/null @@ -1,9 +0,0 @@ -quarkus.http.ssl.certificate.key-store-file=server-keystore.jks -quarkus.http.ssl.certificate.key-store-password=secret -quarkus.http.ssl.certificate.trust-store-file=server-truststore.jks -quarkus.http.ssl.certificate.trust-store-password=password -quarkus.http.ssl.client-auth=REQUIRED -quarkus.http.insecure-requests=enabled - -quarkus.http.auth.permission.default.paths=/* -quarkus.http.auth.permission.default.policy=authenticated \ No newline at end of file diff --git a/extensions/vertx-http/deployment/src/test/resources/conf/mtls/mtls-no-auth-jks.conf b/extensions/vertx-http/deployment/src/test/resources/conf/mtls/mtls-no-auth-jks.conf deleted file mode 100644 index e1f95f0d7b8f5..0000000000000 --- a/extensions/vertx-http/deployment/src/test/resources/conf/mtls/mtls-no-auth-jks.conf +++ /dev/null @@ -1,7 +0,0 @@ -quarkus.http.ssl.certificate.key-store-file=server-keystore.jks -quarkus.http.ssl.certificate.key-store-password=secret -quarkus.http.ssl.certificate.trust-store-file=server-truststore.jks -quarkus.http.ssl.certificate.trust-store-password=password -quarkus.http.ssl.client-auth=REQUEST -quarkus.http.auth.permission.all.paths=/* -quarkus.http.auth.permission.all.policy=authenticated \ No newline at end of file diff --git a/extensions/vertx-http/deployment/src/test/resources/conf/mtls/server-keystore.jks b/extensions/vertx-http/deployment/src/test/resources/conf/mtls/server-keystore.jks deleted file mode 100644 index da33e8e7a16683d421c7a541bf0013521efb605e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2423 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 aH~3Ca%|*I@e88To>+D>~J`lt~rv3-)J!2gJ diff --git a/extensions/vertx-http/deployment/src/test/resources/conf/mtls/server-truststore.jks b/extensions/vertx-http/deployment/src/test/resources/conf/mtls/server-truststore.jks deleted file mode 100644 index 8ec8e126507b61e0e602b71d9f67b3d7e3c7cae3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 925 zcmezO_TO6u1_mY|W(3o$xs}0Ue&dE&8D>0B0 z=QXr6G&C?YG&M3ZGLI7HHL^4`0AdK2=Jq!+Dj|EBk(GhDiIJbdpox)-sfm%1VUF3s zo}9*=J}DCyv6d_>miqhX+0BER7vzr=weLB0SI~-EN4Tx;+oAX3sZu+AreC;W+rDov z-#5*V51%D8KX(20xaE+MMC5UqlCZ}&*8kY~jW=TIFRK(mcF!wJ^TT7)vd&p~1Uy)$ z`pW;@Uk~HZlKvCjci1|P$j&@8Uwi5_z2paTO5a=hS@rqWe0&n}OLbn_nKBuLad&4PoF%w@U!d89 z+LCrv&mDH_wWWUYJ`36D%^-U7h-9RXpo^<=ZFc0HX`&2UWMlL9lv%uVR}CpmJg{;8 zx_~1U?x&fU85tNCD;mff$O0oymXAe@MTGhL(rFKW9uTVSSw3Zn;O1#zMYmj$0}+^R zfPu)!z}8XzuI^>`BBZaSb80!?+r7pc#`09np_Lozt4zJ}{d+W?|#aPK1E8H9tc&p84 z9$uW3|Ks-G6^q-888qdu-^`O)?fLIsY>e9J3v8=pk6rP))@~NVdhf7^xr%i0hj$v? zKacmOG&aO636*{EblS9x!(U?iHAU{$t+Riy#c;{YELD{*se2PT}_AU?Y+Xxvefqh07{ov?f?J) diff --git a/extensions/vertx-http/deployment/src/test/resources/conf/server-cert.pem b/extensions/vertx-http/deployment/src/test/resources/conf/server-cert.pem deleted file mode 100644 index 837702dd2ab8d..0000000000000 --- a/extensions/vertx-http/deployment/src/test/resources/conf/server-cert.pem +++ /dev/null @@ -1,22 +0,0 @@ -Bag Attributes - friendlyName: test-store - localKeyID: 54 69 6D 65 20 31 35 36 38 30 34 30 37 34 37 35 34 31 -subject=/CN=localhost -issuer=/CN=localhost ------BEGIN CERTIFICATE----- -MIICxzCCAa+gAwIBAgIEUfdmtTANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDEwls -b2NhbGhvc3QwHhcNMTkwOTA5MTQ1MjI1WhcNMjIwOTA4MTQ1MjI1WjAUMRIwEAYD -VQQDEwlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCM -Zh82steZt+2yANuCR1xMe5hb+zPSAb9vF/oVfy6DUorbqR+I5quDgvjUNe8RooPr -u5R1d/m0Rm4SEQETMJTUnvYUGTDMKZVCTfFuthM+/+jvFCXC8RdZ4VrQ9NpPWd8p -vVfo3tCC7+5Sabrqd25g4c0FI4oFdECjzeaxCvO3YrBr6XNjlH3RTE0NC6QgbCYR -vHsfTVzstRkwo1kpWgLrRcHQInKLpFv8w4QQ/g/pxzGtb4DvyqubGXqLilb0GQO5 -gm/iWdvmX8lq1qW//d2/tixS9spVS63Bz19uVb4fLz53t61XXaxtzfy/3/rseid1 -+ZWB4smPkyjSk2KuQADxAgMBAAGjITAfMB0GA1UdDgQWBBS8QnI8iaQo0oFYq8GS -76Zcw8ne7zANBgkqhkiG9w0BAQsFAAOCAQEAHVssxFZVcckOOjD/2BB9kiEfAa7g -bSPomLNOK2/y2lPxJSwze3uW9Pazue87PpswYip4o/bQWpfifncHLU6LDZ6EndFn -G2ZCfnjpyHzmNVGf1V32DJi3PdOe4yBPNEetSLSe/v3CW/6kpIZmLZvwGoDSIooe -3oWDg7TeLcwp5v2R2SOMPiUiM4gPY4Scda/gl9y5Eg/IamxzYROtepJjupO6En95 -0B5h1yu0PyyKRsRD+RBf5K7mo6nh5LeyQCHB5yttTkJX3NvbH5wkMOV9QLNUuoAj -ZkGWeMRZCRpZajHwI95U8RcFwhQg3r8rWVYMr5BiHuXiHxA0S+ckvT3Tjw== ------END CERTIFICATE----- diff --git a/extensions/vertx-http/deployment/src/test/resources/conf/server-key.pem b/extensions/vertx-http/deployment/src/test/resources/conf/server-key.pem deleted file mode 100644 index 3bb409cf39a2a..0000000000000 --- a/extensions/vertx-http/deployment/src/test/resources/conf/server-key.pem +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCMZh82steZt+2y -ANuCR1xMe5hb+zPSAb9vF/oVfy6DUorbqR+I5quDgvjUNe8RooPru5R1d/m0Rm4S -EQETMJTUnvYUGTDMKZVCTfFuthM+/+jvFCXC8RdZ4VrQ9NpPWd8pvVfo3tCC7+5S -abrqd25g4c0FI4oFdECjzeaxCvO3YrBr6XNjlH3RTE0NC6QgbCYRvHsfTVzstRkw -o1kpWgLrRcHQInKLpFv8w4QQ/g/pxzGtb4DvyqubGXqLilb0GQO5gm/iWdvmX8lq -1qW//d2/tixS9spVS63Bz19uVb4fLz53t61XXaxtzfy/3/rseid1+ZWB4smPkyjS -k2KuQADxAgMBAAECggEAFHNDlKoUMXXTD5yEXMOcNB/En5FFiQ9sHPh3Gu59je9V -/ozx5PUEgpFvQSnh+sWbRZj7FOk23AVuPv9vEqZ+50GIQoEw1GwyK4hC5Ids4j5Q -ZZKftXd8mUD0A3/G1MwYb3H+/hKGeKwOIL751PE0iLQbMuZsUkMOr01sjtkzisCD -RyweFnD/NmlGYJyxZo2/iQi/PD2szkWftL+fkwLQZD0hlYbvJZTZ6rWd68FN+Hg6 -afveOrCgkaH9rsXdodahOUP+fUUPDIJAmSGY0Z+P4t9piBHbdY+4b0dKu2MJzhHz -ZaBIewnWor7yX05UinhPhjFruo0Rf1obZtttvr0XiQKBgQDf5YwKCu+BNZFEkaEq -wwgD9qjYqGEzblVCX+HDvmcgJ7neWBSB4FYRzj9JKZ6jFQbHYHMvb+oO1WbGWF5J -R0YJ9m6qLsRgQKpW3/RFFWzCYHA1NdCxUicHeUVqsA7C/E8TvckAVEUGpZ+8cHsZ -fwyNfkOYW3nADBo+aTFpi8l+awKBgQCgh6sYSetdfTL+WR1K/Z8u2ZSsXEuM/PEH -nQQwkSBiYxHfpKo26s9LpEIHDjmsZQZHKgINNQiXIjQXB11HjiNK3Gn4aAY3HQMH -Ew7zHF7BvIKCJlY4kLU/68HzYlpda2WSTpBGeuiLsx0BHwzQ4utt63TugiiRCbs9 -8vzonEydEwKBgQCCpO3W+lSQn5I5YYSacB0gOvCBI5c8LHhBd7NDxbllEOkq7Vhi -BGYUk7Vn2oo/fMhs1EHB/1qi9zC2MeAqgBVFQO+IDCv4QiNi9+EP4pWIwj8XPWSd -42L0wHWZ8EtcyV7XFRnRQFraqxAPI88grHrFoVSN9WqQfj9eBYGYpcGYKwKBgQCD -3c47PoV8H5ti+jso3dwENTF+wLZDE4i/U0kcyCpNB8qn5vD3+bzdCwo+F35i0f3t -OWHEDZuH4s3dWOxUGjt9hD/8kR8B6PASwKIYLGbeSIcAeJN9Fcn9vyFsV4+Zi948 -6BJ2AwLBtxmNUT9K3Ay/F5rPTdYbBl5sTg1Y2wPIRwKBgQCNJpTTgWXo1o2Ol1nQ -Ju/Asw2HlYmMZIYqOPzXLUqPhTU0SA+M4jod/zQX1RGLb5KE+GQ1gKpU4iz64q3x -3qiNxXghuP3beV/+bSVvcdF9wW/1CJOwV1nVwNjFmdiBZUAJPv6yBeKf+pIZ9nrE -cSuSQnddeA0ojQOLbK6nyaARBw== ------END PRIVATE KEY----- diff --git a/extensions/vertx-http/deployment/src/test/resources/conf/server-keystore.jks b/extensions/vertx-http/deployment/src/test/resources/conf/server-keystore.jks deleted file mode 100644 index da33e8e7a16683d421c7a541bf0013521efb605e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2423 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 aH~3Ca%|*I@e88To>+D>~J`lt~rv3-)J!2gJ diff --git a/extensions/vertx-http/deployment/src/test/resources/conf/server-keystore.p12 b/extensions/vertx-http/deployment/src/test/resources/conf/server-keystore.p12 deleted file mode 100644 index 2a2ba3a17a8df51b9ddf0d7a0b0aecbe62979d2c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2423 zcmY+Ec{Ce{7RHlELee0uC3c}D)dmStYN@4`sH&}~R8U(fio_PxGND?fu{CNJ`(A5N zk5X$XrFgcfb*gqcnc4=O=goO<=FA`WyXSo0ckiD+934gl0XcAV7#0e<5KWBU;|6j9 zS#+2EBh5z3^c`gd( z=Q#J0>vY>h5_invX@485nVwGNS0D~Rr#YAoe&28Rq4V^?uo!kg>p4_6FBl4~)o0bW zp&n;LoJ$l^<#l`%CASrmD4?~QQ6j~|j161>P%FfxEU4>Nzi7%Qyh|IQ!)WU)U~Py^ z^iA2gGBQrfVAggCALMd5zP4QBqo+#H8v(zr zcxRbnpULP=Zv-3P5JdLKVS+CS%_f%Nnnr7xr;cI-e@e&k3ZB?s62eJ;Y(2sLr#=^ zesD!2Q&Ev~xkbc5UNcUu4lr&*n13ZfikdBbo;-Foi}c>Yy**w)QPdj=&$?Fc_3OJw zPZ?98W25Q-T|x)qEplJxumxdkHViGXAdR;tjT_qDrXsmxv}m9=RaCx&7n+4TjSPJ= zqbq&IvV$miEraG|ytIbEV!)%C?>{v8PF?ijTHz&r))`5!GW)WBnburi6`1Wxs}#;{ zP~AyR*F`yV+wKSY+`P0*t$_7CBkopNDPx}+fKc2{o$mSGk)LTlOXet+KDT|tI4u_u zP;6HgSMu?JLmV|0Gph#1RtdP+jC={w&3vfuXrVYh-l;J<5BwB(Y#M<={){m(+}&n$ z+-BEV&3u)~?W=a>JJWBPR~c?GDX+CNhiOU|*K{$mMqKhBH(EqY+6l%`pR8a6wLy~* z2FLL zO%BoP^vf}iRn%$k>_olo*gyJvJ-I9FcDjc$9!n@1M3$g8L8F8{&i;_k5zU;`R{E+#F@}1`j7!HmI8zzQ(a*11tdRcs4%pSm$V<|RIQn){_;n(j{8*5Z7Gz8z~!SFnR3S4?ad0# zwq)xx1vcI(THw9j>vDF$+K*h^p^TfGT@l1{Y_{3~LiFuwc&zy2!f>Okt@)x?)7QO@ zxXR>(ys2)?IOe?0BOO_ql)|!4V?t9eVi#8eSbSOW@hJV?b=g>)xJ?@;_pa*l{^i_f z>GU;Cc8&zzJ$5XSYm|A7BQwEtnV)Z%oq=cZ-X{s)IzK5NzLBc2Ll)l4I)ogCfin`9 zjN0);+}XcS3FF5LO7H^$0B!*4iOT<}z5oiq4JY+?NdV6eK6BI4#|@1qTvEfS;8ayq z2`YFTog?$F5+{^J=Xic%#ejf-lSThK0se!u(EpN_z*h!mpPd%F)4pLYhS0xjPGX+= zle7_Z4&t4ySBL1Ec0=LK>LGKY0fe8ouNww$jpU0vT}%6DLznVbBmeYAuT2DB0m#aj zh*Ap*T(RKmt#obdQVLP`ChYjEAD#E_td*2KC$c11ta#2=e8OBy7y`M|l~MORIH3Y7 zs;V8UPjT|^k#$P_QQ58Hl%%Br09o?0O8T_#l`t9RsTvI;L)J*9470X-61yGvQ`8rH+`HbZMF7-Y#EtNxLYilEft`nL zsj6K}y0gC(EnFu4;k_OMi_KkBe5tb3!eaE->8_fdH7XNFP+>g^JvexpRBFxp%xgEs zT8|rL%7C{%LF}&;a=YjS*>dMsX>ODd)1=gpGm(P4Luyv{w_Z0GJA)xcme2*bM*2v^bS&or~iO#&( z$`YnnCpwR~^NALHQ<$2j6!IQEIBs;F%N>~3u(+`C_IQc4d2s#d!bVk<6j1V)+|v2C zjM-WT$5Hu*y_pwX@W0KOG%%3>K4e%zT%Cs)t%P#I0`@HM3ALr)Ew+yXH#f5F14f>&F(b*Le#VO4e7f>_Saxog2#D z-EEoe7=wYB=|_%!2YnvdN%MIZi+fr-_fe`*FMV=XS0bHUpj9kJ4Wt$Ix@8# zQatoZrF9T>B(zJIOj3o)&}>74M3voq{i!MNn*qU5@4C%MuGp<2Ub{X&vZt=pDMaBw zo=Dem?X#2My&SZ5?!H`&sJ=`JtUHhEF& z7Im7Z+xJ7!Mgj@BxSV530+ keyStoreKeyAlias; + /** + * An optional parameter to select a specific key in the keystore. + * When SNI is disabled, and the keystore contains multiple + * keys and no alias is specified; the behavior is undefined. + */ + @ConfigItem + public Optional keyStoreAlias; + /** * An optional parameter to define the password for the key, * in case it is different from {@link #keyStorePassword} * If not given, it might be retrieved from {@linkplain CredentialsProvider}. * * @see {@link #credentialsProvider}. + * @deprecated Use {@link #keyStoreAliasPassword} instead. */ + @Deprecated @ConfigItem public Optional keyStoreKeyPassword; + /** + * An optional parameter to define the password for the key, + * in case it is different from {@link #keyStorePassword} + * If not given, it might be retrieved from {@linkplain CredentialsProvider}. + * + * @see {@link #credentialsProvider}. + */ + @ConfigItem + public Optional keyStoreAliasPassword; + /** * A parameter to specify a {@linkplain CredentialsProvider} property key, - * which can be used to get the password for the key from {@linkplain CredentialsProvider}. + * which can be used to get the password for the alias from {@linkplain CredentialsProvider}. * * @see {@link #credentialsProvider} + * @deprecated Use {@link #keyStoreAliasPasswordKey} instead. */ @ConfigItem + @Deprecated public Optional keyStoreKeyPasswordKey; + /** + * A parameter to specify a {@linkplain CredentialsProvider} property key, + * which can be used to get the password for the alias from {@linkplain CredentialsProvider}. + * + * @see {@link #credentialsProvider} + */ + @ConfigItem + public Optional keyStoreAliasPasswordKey; + /** * An optional trust store that holds the certificate information of the trusted certificates. */ @ConfigItem public Optional trustStoreFile; + /** + * An optional list of trusted certificates using the PEM format. + * If you pass multiple files, you must use the PEM format. + */ + @ConfigItem + public Optional> trustStoreFiles; + /** * An optional parameter to specify the type of the trust store file. * If not given, the type is automatically detected based on the file name. diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/options/HttpServerOptionsUtils.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/options/HttpServerOptionsUtils.java index d53c444263d20..a16c972884260 100644 --- a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/options/HttpServerOptionsUtils.java +++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/options/HttpServerOptionsUtils.java @@ -1,15 +1,13 @@ package io.quarkus.vertx.http.runtime.options; +import static io.quarkus.vertx.http.runtime.options.TlsUtils.computeKeyStoreOptions; +import static io.quarkus.vertx.http.runtime.options.TlsUtils.computeTrustOptions; + import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import java.util.*; import java.util.concurrent.TimeUnit; import org.jboss.logging.Logger; @@ -24,15 +22,11 @@ import io.quarkus.vertx.http.runtime.ServerSslConfig; import io.quarkus.vertx.http.runtime.management.ManagementInterfaceBuildTimeConfig; import io.quarkus.vertx.http.runtime.management.ManagementInterfaceConfiguration; -import io.vertx.core.buffer.Buffer; import io.vertx.core.http.ClientAuth; import io.vertx.core.http.Http2Settings; import io.vertx.core.http.HttpServerOptions; import io.vertx.core.http.HttpVersion; -import io.vertx.core.net.JdkSSLEngineOptions; -import io.vertx.core.net.KeyStoreOptions; -import io.vertx.core.net.PemKeyCertOptions; -import io.vertx.core.net.TrafficShapingOptions; +import io.vertx.core.net.*; @SuppressWarnings("OptionalIsPresent") public class HttpServerOptionsUtils { @@ -49,15 +43,6 @@ public static HttpServerOptions createSslOptions(HttpBuildTimeConfig buildTimeCo ServerSslConfig sslConfig = httpConfiguration.ssl; - final List keys = new ArrayList<>(); - final List certificates = new ArrayList<>(); - if (sslConfig.certificate.keyFiles.isPresent()) { - keys.addAll(sslConfig.certificate.keyFiles.get()); - } - if (sslConfig.certificate.files.isPresent()) { - certificates.addAll(sslConfig.certificate.files.get()); - } - // credentials provider Map credentials = Map.of(); if (sslConfig.certificate.credentialsProvider.isPresent()) { @@ -66,14 +51,33 @@ public static HttpServerOptions createSslOptions(HttpBuildTimeConfig buildTimeCo String name = sslConfig.certificate.credentialsProvider.get(); credentials = credentialsProvider.getCredentials(name); } - final Optional keyStoreFile = sslConfig.certificate.keyStoreFile; + final Optional keyStorePassword = getCredential(sslConfig.certificate.keyStorePassword, credentials, sslConfig.certificate.keyStorePasswordKey); - final Optional keyStoreKeyPassword = getCredential(sslConfig.certificate.keyStoreKeyPassword, credentials, - sslConfig.certificate.keyStoreKeyPasswordKey); - final Optional trustStoreFile = sslConfig.certificate.trustStoreFile; + + Optional keyStoreAliasPassword = Optional.empty(); + if (sslConfig.certificate.keyStoreAliasPassword.isPresent() || sslConfig.certificate.keyStoreKeyPassword.isPresent() + || sslConfig.certificate.keyStoreKeyPasswordKey.isPresent() + || sslConfig.certificate.keyStoreAliasPasswordKey.isPresent()) { + if (sslConfig.certificate.keyStoreKeyPasswordKey.isPresent() + && sslConfig.certificate.keyStoreAliasPasswordKey.isPresent()) { + throw new ConfigurationException( + "You cannot specify both `keyStoreKeyPasswordKey` and `keyStoreAliasPasswordKey` - Use `keyStoreAliasPasswordKey` instead"); + } + if (sslConfig.certificate.keyStoreAliasPassword.isPresent() + && sslConfig.certificate.keyStoreKeyPassword.isPresent()) { + throw new ConfigurationException( + "You cannot specify both `keyStoreKeyPassword` and `keyStoreAliasPassword` - Use `keyStoreAliasPassword` instead"); + } + keyStoreAliasPassword = getCredential( + or(sslConfig.certificate.keyStoreAliasPassword, sslConfig.certificate.keyStoreKeyPassword), + credentials, + or(sslConfig.certificate.keyStoreAliasPasswordKey, sslConfig.certificate.keyStoreKeyPasswordKey)); + } + final Optional trustStorePassword = getCredential(sslConfig.certificate.trustStorePassword, credentials, sslConfig.certificate.trustStorePasswordKey); + final HttpServerOptions serverOptions = new HttpServerOptions(); //ssl @@ -85,32 +89,14 @@ public static HttpServerOptions createSslOptions(HttpBuildTimeConfig buildTimeCo } setIdleTimeout(httpConfiguration, serverOptions); - if (!certificates.isEmpty() && !keys.isEmpty()) { - createPemKeyCertOptions(certificates, keys, serverOptions); - } else if (keyStoreFile.isPresent()) { - - KeyStoreOptions options = createKeyStoreOptions( - keyStoreFile.get(), - keyStorePassword.orElse("password"), - sslConfig.certificate.keyStoreFileType, - sslConfig.certificate.keyStoreProvider, - sslConfig.certificate.keyStoreKeyAlias, - keyStoreKeyPassword); - serverOptions.setKeyCertOptions(options); + var kso = computeKeyStoreOptions(sslConfig.certificate, keyStorePassword, keyStoreAliasPassword); + if (kso != null) { + serverOptions.setKeyCertOptions(kso); } - if (trustStoreFile.isPresent()) { - if (!trustStorePassword.isPresent()) { - throw new IllegalArgumentException("No trust store password provided"); - } - KeyStoreOptions options = createKeyStoreOptions( - trustStoreFile.get(), - trustStorePassword.get(), - sslConfig.certificate.trustStoreFileType, - sslConfig.certificate.trustStoreProvider, - sslConfig.certificate.trustStoreCertAlias, - Optional.empty()); - serverOptions.setTrustOptions(options); + var to = computeTrustOptions(sslConfig.certificate, trustStorePassword); + if (to != null) { + serverOptions.setTrustOptions(to); } for (String cipher : sslConfig.cipherSuites.orElse(Collections.emptyList())) { @@ -143,15 +129,6 @@ public static HttpServerOptions createSslOptionsForManagementInterface(Managemen ServerSslConfig sslConfig = httpConfiguration.ssl; - final List keys = new ArrayList<>(); - final List certificates = new ArrayList<>(); - if (sslConfig.certificate.keyFiles.isPresent()) { - keys.addAll(sslConfig.certificate.keyFiles.get()); - } - if (sslConfig.certificate.files.isPresent()) { - certificates.addAll(sslConfig.certificate.files.get()); - } - // credentials provider Map credentials = Map.of(); if (sslConfig.certificate.credentialsProvider.isPresent()) { @@ -160,14 +137,33 @@ public static HttpServerOptions createSslOptionsForManagementInterface(Managemen String name = sslConfig.certificate.credentialsProvider.get(); credentials = credentialsProvider.getCredentials(name); } - final Optional keyStoreFile = sslConfig.certificate.keyStoreFile; + final Optional keyStorePassword = getCredential(sslConfig.certificate.keyStorePassword, credentials, sslConfig.certificate.keyStorePasswordKey); - final Optional keyStoreKeyPassword = getCredential(sslConfig.certificate.keyStoreKeyPassword, credentials, - sslConfig.certificate.keyStoreKeyPasswordKey); - final Optional trustStoreFile = sslConfig.certificate.trustStoreFile; + + Optional keyStoreAliasPassword = Optional.empty(); + if (sslConfig.certificate.keyStoreAliasPassword.isPresent() || sslConfig.certificate.keyStoreKeyPassword.isPresent() + || sslConfig.certificate.keyStoreKeyPasswordKey.isPresent() + || sslConfig.certificate.keyStoreAliasPasswordKey.isPresent()) { + if (sslConfig.certificate.keyStoreKeyPasswordKey.isPresent() + && sslConfig.certificate.keyStoreAliasPasswordKey.isPresent()) { + throw new ConfigurationException( + "You cannot specify both `keyStoreKeyPasswordKey` and `keyStoreAliasPasswordKey` - Use `keyStoreAliasPasswordKey` instead"); + } + if (sslConfig.certificate.keyStoreAliasPassword.isPresent() + && sslConfig.certificate.keyStoreKeyPassword.isPresent()) { + throw new ConfigurationException( + "You cannot specify both `keyStoreKeyPassword` and `keyStoreAliasPassword` - Use `keyStoreAliasPassword` instead"); + } + keyStoreAliasPassword = getCredential( + or(sslConfig.certificate.keyStoreAliasPassword, sslConfig.certificate.keyStoreKeyPassword), + credentials, + or(sslConfig.certificate.keyStoreAliasPasswordKey, sslConfig.certificate.keyStoreKeyPasswordKey)); + } + final Optional trustStorePassword = getCredential(sslConfig.certificate.trustStorePassword, credentials, sslConfig.certificate.trustStorePasswordKey); + final HttpServerOptions serverOptions = new HttpServerOptions(); //ssl @@ -179,31 +175,14 @@ public static HttpServerOptions createSslOptionsForManagementInterface(Managemen serverOptions.setIdleTimeout(idleTimeout); serverOptions.setIdleTimeoutUnit(TimeUnit.MILLISECONDS); - if (!certificates.isEmpty() && !keys.isEmpty()) { - createPemKeyCertOptions(certificates, keys, serverOptions); - } else if (keyStoreFile.isPresent()) { - KeyStoreOptions options = createKeyStoreOptions( - keyStoreFile.get(), - keyStorePassword.orElse("password"), - sslConfig.certificate.keyStoreFileType, - sslConfig.certificate.keyStoreProvider, - sslConfig.certificate.keyStoreKeyAlias, - keyStoreKeyPassword); - serverOptions.setKeyCertOptions(options); + var kso = computeKeyStoreOptions(sslConfig.certificate, keyStorePassword, keyStoreAliasPassword); + if (kso != null) { + serverOptions.setKeyCertOptions(kso); } - if (trustStoreFile.isPresent()) { - if (!trustStorePassword.isPresent()) { - throw new IllegalArgumentException("No trust store password provided"); - } - KeyStoreOptions options = createKeyStoreOptions( - trustStoreFile.get(), - trustStorePassword.get(), - sslConfig.certificate.trustStoreFileType, - sslConfig.certificate.trustStoreProvider, - sslConfig.certificate.trustStoreCertAlias, - Optional.empty()); - serverOptions.setTrustOptions(options); + var to = computeTrustOptions(sslConfig.certificate, trustStorePassword); + if (to != null) { + serverOptions.setTrustOptions(to); } for (String cipher : sslConfig.cipherSuites.orElse(Collections.emptyList())) { @@ -350,26 +329,6 @@ public static void applyCommonOptionsForManagementInterface(HttpServerOptions op options.setUseProxyProtocol(httpConfiguration.proxy.useProxyProtocol); } - private static KeyStoreOptions createKeyStoreOptions(Path path, String password, Optional fileType, - Optional provider, Optional alias, Optional aliasPassword) throws IOException { - final String type; - if (fileType.isPresent()) { - type = fileType.get().toLowerCase(); - } else { - type = findKeystoreFileType(path); - } - - byte[] data = getFileContent(path); - KeyStoreOptions options = new KeyStoreOptions() - .setPassword(password) - .setValue(Buffer.buffer(data)) - .setType(type.toUpperCase()) - .setProvider(provider.orElse(null)) - .setAlias(alias.orElse(null)) - .setAliasPassword(aliasPassword.orElse(null)); - return options; - } - static byte[] getFileContent(Path path) throws IOException { byte[] data; final InputStream resource = Thread.currentThread().getContextClassLoader() @@ -386,43 +345,6 @@ static byte[] getFileContent(Path path) throws IOException { return data; } - private static void createPemKeyCertOptions(List certFile, List keyFile, - HttpServerOptions serverOptions) throws IOException { - - if (certFile.size() != keyFile.size()) { - throw new ConfigurationException("Invalid certificate configuration - `files` and `keyFiles` must have the " - + "same number of elements"); - } - - List certificates = new ArrayList<>(); - List keys = new ArrayList<>(); - - for (Path p : certFile) { - final byte[] cert = getFileContent(p); - certificates.add(Buffer.buffer(cert)); - } - - for (Path p : keyFile) { - final byte[] key = getFileContent(p); - keys.add(Buffer.buffer(key)); - } - - PemKeyCertOptions pemKeyCertOptions = new PemKeyCertOptions() - .setCertValues(certificates) - .setKeyValues(keys); - serverOptions.setPemKeyCertOptions(pemKeyCertOptions); - } - - private static String findKeystoreFileType(Path storePath) { - final String pathName = storePath.toString(); - if (pathName.endsWith(".p12") || pathName.endsWith(".pkcs12") || pathName.endsWith(".pfx")) { - return "pkcs12"; - } else { - // assume jks - return "jks"; - } - } - private static byte[] doRead(InputStream is) throws IOException { return is.readAllBytes(); } @@ -453,4 +375,9 @@ public static HttpConfiguration.InsecureRequests getInsecureRequestStrategy(Http } return HttpConfiguration.InsecureRequests.ENABLED; } + + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") + static Optional or(Optional a, Optional b) { + return a.isPresent() ? a : b; + } } diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/options/TlsCertificateReloader.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/options/TlsCertificateReloader.java index 07dc2d73259b3..fcf993863b739 100644 --- a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/options/TlsCertificateReloader.java +++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/options/TlsCertificateReloader.java @@ -149,12 +149,8 @@ private static SSLOptions reloadFileContent(SSLOptions ssl, ServerSslConfig conf final List keys = new ArrayList<>(); final List certificates = new ArrayList<>(); - if (configuration.certificate.keyFiles.isPresent()) { - keys.addAll(configuration.certificate.keyFiles.get()); - } - if (configuration.certificate.files.isPresent()) { - certificates.addAll(configuration.certificate.files.get()); - } + configuration.certificate.keyFiles.ifPresent(keys::addAll); + configuration.certificate.files.ifPresent(certificates::addAll); if (!certificates.isEmpty() && !keys.isEmpty()) { List certBuffer = new ArrayList<>(); diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/options/TlsUtils.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/options/TlsUtils.java new file mode 100644 index 0000000000000..7b2a08c729cb6 --- /dev/null +++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/options/TlsUtils.java @@ -0,0 +1,159 @@ +package io.quarkus.vertx.http.runtime.options; + +import static io.quarkus.vertx.http.runtime.options.HttpServerOptionsUtils.getFileContent; +import static io.quarkus.vertx.http.runtime.options.HttpServerOptionsUtils.or; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import io.quarkus.vertx.http.runtime.CertificateConfig; +import io.vertx.core.buffer.Buffer; +import io.vertx.core.net.*; + +/** + * Utility class for TLS configuration. + */ +public class TlsUtils { + + private TlsUtils() { + // Avoid direct instantiation + } + + public static KeyCertOptions computeKeyStoreOptions(CertificateConfig certificates, Optional keyStorePassword, + Optional keyStoreAliasPassword) throws IOException { + if (certificates.keyFiles.isPresent() || certificates.files.isPresent()) { + if (certificates.keyFiles.isEmpty()) { + throw new IllegalArgumentException("You must specify the key files when specifying the certificate files"); + } + if (certificates.files.isEmpty()) { + throw new IllegalArgumentException("You must specify the certificate files when specifying the key files"); + } + if (certificates.files.get().size() != certificates.keyFiles.get().size()) { + throw new IllegalArgumentException( + "The number of certificate files and key files must be the same, and be given in the same order"); + } + + return createPemKeyCertOptions(certificates.files.get(), certificates.keyFiles.get()); + } else if (certificates.keyStoreFile.isPresent()) { + return createKeyStoreOptions( + certificates.keyStoreFile.get(), + keyStorePassword, + certificates.keyStoreFileType, + certificates.keyStoreProvider, + or(certificates.keyStoreAlias, certificates.keyStoreKeyAlias), + keyStoreAliasPassword); + } + return null; + } + + public static TrustOptions computeTrustOptions(CertificateConfig certificates, Optional trustStorePassword) + throws IOException { + // Decide if we have a single trust store file or multiple trust store files (PEM) + Path singleTrustStoreFile = null; + if (certificates.trustStoreFile.isPresent()) { + singleTrustStoreFile = certificates.trustStoreFile.get(); + } + if (certificates.trustStoreFiles.isPresent()) { + if (singleTrustStoreFile != null) { + throw new IllegalArgumentException("You cannot specify both `trustStoreFile` and `trustStoreFiles`"); + } + if (certificates.trustStoreFiles.get().size() == 1) { + singleTrustStoreFile = certificates.trustStoreFiles.get().get(0); + } + } + + if (singleTrustStoreFile != null) { // We have a single trust store file. + String type = certificates.trustStoreFileType.orElse(getTypeFromFileName(singleTrustStoreFile)); + if (type.equalsIgnoreCase("pem")) { + byte[] cert = getFileContent(singleTrustStoreFile); + return new PemTrustOptions() + .addCertValue(Buffer.buffer(cert)); + } + + if ((type.equalsIgnoreCase("pkcs12") || type.equalsIgnoreCase("jks"))) { + // We cannot assume that custom type configured by the user requires a password. + if (certificates.trustStorePassword.isEmpty() && trustStorePassword.isEmpty()) { + throw new IllegalArgumentException("No trust store password provided"); + } + } + + return createKeyStoreOptions( + singleTrustStoreFile, + trustStorePassword, + certificates.trustStoreFileType, + certificates.trustStoreProvider, + certificates.trustStoreCertAlias, + Optional.empty()); + } + + // We have multiple trust store files (PEM). + if (certificates.trustStoreFiles.isPresent() && !certificates.trustStoreFiles.get().isEmpty()) { + // Assuming PEM, as it's the only format with multiple files + PemTrustOptions pemKeyCertOptions = new PemTrustOptions(); + for (Path path : certificates.trustStoreFiles.get()) { + byte[] cert = getFileContent(path); + pemKeyCertOptions.addCertValue(Buffer.buffer(cert)); + } + return pemKeyCertOptions; + } + + return null; + } + + private static String getTypeFromFileName(Path path) { + String name = path.getFileName().toString().toLowerCase(); + if (name.endsWith(".p12") || name.endsWith(".pkcs12") || name.endsWith(".pfx")) { + return "pkcs12"; + } else if (name.endsWith(".jks")) { + return "jks"; + } else if (name.endsWith(".key") || name.endsWith(".crt") || name.endsWith(".pem")) { + return "pem"; + } else { + throw new IllegalArgumentException("Could not determine the trust store type from the file name: " + path + + ". Configure the file type property."); + } + + } + + private static KeyStoreOptions createKeyStoreOptions(Path path, Optional password, Optional fileType, + Optional provider, Optional alias, Optional aliasPassword) throws IOException { + final String type; + if (fileType.isPresent()) { + type = fileType.get().toLowerCase(); + } else { + type = getTypeFromFileName(path); + } + + byte[] data = getFileContent(path); + return new KeyStoreOptions() + .setPassword(password.orElse(null)) + .setValue(Buffer.buffer(data)) + .setType(type.toUpperCase()) + .setProvider(provider.orElse(null)) + .setAlias(alias.orElse(null)) + .setAliasPassword(aliasPassword.orElse(null)); + } + + private static PemKeyCertOptions createPemKeyCertOptions(List certFile, List keyFile) throws IOException { + List certificates = new ArrayList<>(); + List keys = new ArrayList<>(); + + for (Path p : certFile) { + final byte[] cert = getFileContent(p); + certificates.add(Buffer.buffer(cert)); + } + + for (Path p : keyFile) { + final byte[] key = getFileContent(p); + keys.add(Buffer.buffer(key)); + } + + return new PemKeyCertOptions() + .setCertValues(certificates) + .setKeyValues(keys); + } + +}