From a9bee1bd524b23b476faa7f5b170832f752f1a66 Mon Sep 17 00:00:00 2001 From: James Netherton Date: Wed, 4 Sep 2024 09:44:44 +0100 Subject: [PATCH] Enable vertx-websocket extension to handle Quarkus TLS Registry configuration --- .../deployment/VertxWebsocketProcessor.java | 3 ++ .../websocket/VertxWebsocketRecorder.java | 54 +++++++++++++------ ...le.java => VertxWebsocketLegacySslIT.java} | 14 ++--- .../it/VertxWebsocketLegacySslTest.java | 43 +++++++++++++++ .../websocket/it/VertxWebsocketSslTest.java | 23 ++++---- .../websocket/it/VertxWebsocketTest.java | 4 +- ...ketSslIT.java => VertxWebsocketTlsIT.java} | 2 +- .../it/VertxWebsocketTlsNamedConfigIT.java | 24 +++++++++ .../it/VertxWebsocketTlsNamedConfigTest.java | 44 +++++++++++++++ .../websocket/it/VertxWebsocketTlsTest.java | 43 +++++++++++++++ 10 files changed, 214 insertions(+), 40 deletions(-) rename integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/{VertxWebsocketSslTestProfile.java => VertxWebsocketLegacySslIT.java} (63%) create mode 100644 integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketLegacySslTest.java rename integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/{VertxWebsocketSslIT.java => VertxWebsocketTlsIT.java} (94%) create mode 100644 integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketTlsNamedConfigIT.java create mode 100644 integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketTlsNamedConfigTest.java create mode 100644 integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketTlsTest.java diff --git a/extensions/vertx-websocket/deployment/src/main/java/org/apache/camel/quarkus/component/vertx/websocket/deployment/VertxWebsocketProcessor.java b/extensions/vertx-websocket/deployment/src/main/java/org/apache/camel/quarkus/component/vertx/websocket/deployment/VertxWebsocketProcessor.java index 41e950fe5d29..7b434f4d75c0 100644 --- a/extensions/vertx-websocket/deployment/src/main/java/org/apache/camel/quarkus/component/vertx/websocket/deployment/VertxWebsocketProcessor.java +++ b/extensions/vertx-websocket/deployment/src/main/java/org/apache/camel/quarkus/component/vertx/websocket/deployment/VertxWebsocketProcessor.java @@ -16,7 +16,9 @@ */ package org.apache.camel.quarkus.component.vertx.websocket.deployment; +import io.quarkus.arc.deployment.SyntheticBeansRuntimeInitBuildItem; import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.annotations.Consume; import io.quarkus.deployment.annotations.ExecutionTime; import io.quarkus.deployment.annotations.Record; import io.quarkus.deployment.builditem.FeatureBuildItem; @@ -38,6 +40,7 @@ FeatureBuildItem feature() { } @BuildStep + @Consume(SyntheticBeansRuntimeInitBuildItem.class) @Record(ExecutionTime.RUNTIME_INIT) CamelRuntimeBeanBuildItem configureVertxWebsocketComponent( VertxBuildItem vertx, diff --git a/extensions/vertx-websocket/runtime/src/main/java/org/apache/camel/quarkus/component/vertx/websocket/VertxWebsocketRecorder.java b/extensions/vertx-websocket/runtime/src/main/java/org/apache/camel/quarkus/component/vertx/websocket/VertxWebsocketRecorder.java index 9c6c6ed0b295..f1186656bc58 100644 --- a/extensions/vertx-websocket/runtime/src/main/java/org/apache/camel/quarkus/component/vertx/websocket/VertxWebsocketRecorder.java +++ b/extensions/vertx-websocket/runtime/src/main/java/org/apache/camel/quarkus/component/vertx/websocket/VertxWebsocketRecorder.java @@ -17,11 +17,15 @@ package org.apache.camel.quarkus.component.vertx.websocket; import java.net.URI; +import java.util.Optional; import java.util.concurrent.ExecutionException; +import io.quarkus.arc.Arc; import io.quarkus.runtime.LaunchMode; import io.quarkus.runtime.RuntimeValue; import io.quarkus.runtime.annotations.Recorder; +import io.quarkus.tls.TlsConfiguration; +import io.quarkus.tls.TlsConfigurationRegistry; import io.quarkus.vertx.http.runtime.CertificateConfig; import io.quarkus.vertx.http.runtime.HttpConfiguration; import io.quarkus.vertx.http.runtime.ServerSslConfig; @@ -51,24 +55,10 @@ public RuntimeValue createVertxWebsocketComponent( LaunchMode launchMode, HttpConfiguration httpConfig) { - boolean sslEnabled = false; + boolean sslEnabled = isHttpSeverSecureTransportConfigured(httpConfig); int httpPort = httpConfig.determinePort(launchMode); int httpsPort = httpConfig.determineSslPort(launchMode); - ServerSslConfig ssl = httpConfig.ssl; - if (ssl != null) { - CertificateConfig certificate = ssl.certificate; - if (certificate != null) { - if (certificate.files.isPresent() && certificate.keyFiles.isPresent()) { - sslEnabled = true; - } - - if (certificate.keyStoreFile.isPresent() && certificate.keyStorePassword.isPresent()) { - sslEnabled = true; - } - } - } - HOST = httpConfig.host; PORT = sslEnabled ? httpsPort : httpPort; @@ -80,6 +70,40 @@ public RuntimeValue createVertxWebsocketComponent( return new RuntimeValue<>(component); } + private boolean isHttpSeverSecureTransportConfigured(HttpConfiguration httpConfig) { + return httpServerTlsRegistryConfigurationExists(httpConfig) || httpServerLegacySslConfigurationExists(httpConfig); + } + + private boolean httpServerTlsRegistryConfigurationExists(HttpConfiguration httpConfig) { + if (Arc.container() != null) { + TlsConfigurationRegistry tlsConfigurationRegistry = Arc.container().select(TlsConfigurationRegistry.class).orNull(); + if (tlsConfigurationRegistry != null) { + Optional tlsConfigurationName = httpConfig.tlsConfigurationName; + Optional defaultTlsConfiguration = tlsConfigurationRegistry.getDefault(); + if (tlsConfigurationName.isPresent() && tlsConfigurationRegistry.get(tlsConfigurationName.get()).isPresent()) { + return true; + } else { + return defaultTlsConfiguration.isPresent() && defaultTlsConfiguration.get().getKeyStoreOptions() != null; + } + } + } + return false; + } + + private boolean httpServerLegacySslConfigurationExists(HttpConfiguration httpConfig) { + ServerSslConfig ssl = httpConfig.ssl; + if (ssl != null) { + CertificateConfig certificate = ssl.certificate; + if (certificate != null) { + if (certificate.files.isPresent() && certificate.keyFiles.isPresent()) { + return true; + } + return certificate.keyStoreFile.isPresent() && certificate.keyStorePassword.isPresent(); + } + } + return false; + } + @Component("vertx-websocket") static final class QuarkusVertxWebsocketComponent extends VertxWebsocketComponent { @Override diff --git a/integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketSslTestProfile.java b/integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketLegacySslIT.java similarity index 63% rename from integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketSslTestProfile.java rename to integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketLegacySslIT.java index 14664213c3cd..b51916451878 100644 --- a/integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketSslTestProfile.java +++ b/integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketLegacySslIT.java @@ -16,17 +16,9 @@ */ package org.apache.camel.quarkus.component.vertx.websocket.it; -import java.util.Map; +import io.quarkus.test.junit.QuarkusIntegrationTest; -import io.quarkus.test.junit.QuarkusTestProfile; +@QuarkusIntegrationTest +class VertxWebsocketLegacySslIT extends VertxWebsocketLegacySslTest { -public class VertxWebsocketSslTestProfile implements QuarkusTestProfile { - - @Override - public Map getConfigOverrides() { - return Map.of( - "quarkus.http.ssl.certificate.files", "target/certs/vertx-websocket.crt", - "quarkus.http.ssl.certificate.key-files", "target/certs/vertx-websocket.key", - "quarkus.http.insecure-requests", "disabled"); - } } diff --git a/integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketLegacySslTest.java b/integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketLegacySslTest.java new file mode 100644 index 000000000000..32f33fedc34c --- /dev/null +++ b/integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketLegacySslTest.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.quarkus.component.vertx.websocket.it; + +import java.util.Map; + +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.QuarkusTestProfile; +import io.quarkus.test.junit.TestProfile; +import me.escoffier.certs.Format; +import me.escoffier.certs.junit5.Certificate; +import org.apache.camel.quarkus.test.support.certificate.TestCertificates; + +@TestCertificates(certificates = { + @Certificate(name = "vertx-websocket", formats = { + Format.PKCS12, Format.PEM }, password = "changeit") }) +@TestProfile(VertxWebsocketLegacySslTest.VertxWebsocketLegacySslTestProfile.class) +@QuarkusTest +class VertxWebsocketLegacySslTest extends VertxWebsocketSslTest { + public static class VertxWebsocketLegacySslTestProfile implements QuarkusTestProfile { + @Override + public Map getConfigOverrides() { + return Map.of( + "quarkus.http.ssl.certificate.files", "target/certs/vertx-websocket.crt", + "quarkus.http.ssl.certificate.key-files", "target/certs/vertx-websocket.key", + "quarkus.http.insecure-requests", "disabled"); + } + } +} diff --git a/integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketSslTest.java b/integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketSslTest.java index 895702349f6e..869310ac59f4 100644 --- a/integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketSslTest.java +++ b/integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketSslTest.java @@ -20,24 +20,15 @@ import java.util.List; import io.quarkus.test.common.http.TestHTTPResource; -import io.quarkus.test.junit.QuarkusTest; -import io.quarkus.test.junit.TestProfile; import io.restassured.RestAssured; -import me.escoffier.certs.Format; -import me.escoffier.certs.junit5.Certificate; -import org.apache.camel.quarkus.test.support.certificate.TestCertificates; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import static org.hamcrest.Matchers.matchesPattern; import static org.junit.jupiter.api.Assertions.assertEquals; -@TestCertificates(certificates = { - @Certificate(name = "vertx-websocket", formats = { - Format.PKCS12, Format.PEM }, password = "changeit") }) -@TestProfile(VertxWebsocketSslTestProfile.class) -@QuarkusTest -public class VertxWebsocketSslTest { - @TestHTTPResource(value = "/", ssl = true) +public abstract class VertxWebsocketSslTest { + @TestHTTPResource(value = "/", tls = true) URI root; @BeforeAll @@ -50,6 +41,14 @@ public void ssl() throws Exception { URI uri = URI.create(root.toString().replace("https", "wss")); String message = "SSL Vert.x WebSocket Route"; + RestAssured.given() + .queryParam("hostPort", "localhost:8441") + .get("/vertx-websocket/invalid/consumer/uri") + .then() + .statusCode(500) + .body(matchesPattern( + "Invalid host/port localhost:8441.*can only be configured as (localhost|0.0.0.0):" + uri.getPort())); + try (VertxWebsocketTest.WebSocketConnection connection = new VertxWebsocketTest.WebSocketConnection(uri, null)) { connection.connect(); diff --git a/integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketTest.java b/integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketTest.java index c2a053622d23..dd7af097e2b3 100644 --- a/integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketTest.java +++ b/integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketTest.java @@ -42,6 +42,7 @@ import org.junit.jupiter.params.provider.ValueSource; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.matchesPattern; import static org.hamcrest.Matchers.startsWith; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -88,7 +89,8 @@ public void testInvalidHostPortConfig(String hostPort) throws Exception { .get("/vertx-websocket/invalid/consumer/uri") .then() .statusCode(500) - .body(startsWith("Invalid host/port")); + .body(matchesPattern( + "Invalid host/port " + hostPort + ".*can only be configured as (localhost|0.0.0.0):" + root.getPort())); } @Test diff --git a/integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketSslIT.java b/integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketTlsIT.java similarity index 94% rename from integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketSslIT.java rename to integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketTlsIT.java index 2e96aabff86d..560d5ca62f25 100644 --- a/integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketSslIT.java +++ b/integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketTlsIT.java @@ -19,6 +19,6 @@ import io.quarkus.test.junit.QuarkusIntegrationTest; @QuarkusIntegrationTest -class VertxWebsocketSslIT extends VertxWebsocketSslTest { +class VertxWebsocketTlsIT extends VertxWebsocketTlsTest { } diff --git a/integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketTlsNamedConfigIT.java b/integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketTlsNamedConfigIT.java new file mode 100644 index 000000000000..985bfcbd6d5b --- /dev/null +++ b/integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketTlsNamedConfigIT.java @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.quarkus.component.vertx.websocket.it; + +import io.quarkus.test.junit.QuarkusIntegrationTest; + +@QuarkusIntegrationTest +class VertxWebsocketTlsNamedConfigIT extends VertxWebsocketTlsNamedConfigTest { + +} diff --git a/integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketTlsNamedConfigTest.java b/integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketTlsNamedConfigTest.java new file mode 100644 index 000000000000..d3e256a52bf6 --- /dev/null +++ b/integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketTlsNamedConfigTest.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.quarkus.component.vertx.websocket.it; + +import java.util.Map; + +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.QuarkusTestProfile; +import io.quarkus.test.junit.TestProfile; +import me.escoffier.certs.Format; +import me.escoffier.certs.junit5.Certificate; +import org.apache.camel.quarkus.test.support.certificate.TestCertificates; + +@TestCertificates(certificates = { + @Certificate(name = "vertx-websocket", formats = { + Format.PKCS12, Format.PEM }, password = "changeit") }) +@TestProfile(VertxWebsocketTlsNamedConfigTest.VertxWebsocketTlsNamedConfigTestProfile.class) +@QuarkusTest +class VertxWebsocketTlsNamedConfigTest extends VertxWebsocketSslTest { + public static class VertxWebsocketTlsNamedConfigTestProfile implements QuarkusTestProfile { + @Override + public Map getConfigOverrides() { + return Map.of( + "quarkus.tls.https.key-store.pem.0.cert", "target/certs/vertx-websocket.crt", + "quarkus.tls.https.key-store.pem.0.key", "target/certs/vertx-websocket.key", + "quarkus.http.insecure-requests", "disabled", + "quarkus.http.tls-configuration-name", "https"); + } + } +} diff --git a/integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketTlsTest.java b/integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketTlsTest.java new file mode 100644 index 000000000000..f066753c4767 --- /dev/null +++ b/integration-tests/vertx-websocket/src/test/java/org/apache/camel/quarkus/component/vertx/websocket/it/VertxWebsocketTlsTest.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.quarkus.component.vertx.websocket.it; + +import java.util.Map; + +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.QuarkusTestProfile; +import io.quarkus.test.junit.TestProfile; +import me.escoffier.certs.Format; +import me.escoffier.certs.junit5.Certificate; +import org.apache.camel.quarkus.test.support.certificate.TestCertificates; + +@TestCertificates(certificates = { + @Certificate(name = "vertx-websocket", formats = { + Format.PKCS12, Format.PEM }, password = "changeit") }) +@TestProfile(VertxWebsocketTlsTest.VertxWebsocketTlsTestProfile.class) +@QuarkusTest +class VertxWebsocketTlsTest extends VertxWebsocketSslTest { + public static class VertxWebsocketTlsTestProfile implements QuarkusTestProfile { + @Override + public Map getConfigOverrides() { + return Map.of( + "quarkus.tls.key-store.pem.0.cert", "target/certs/vertx-websocket.crt", + "quarkus.tls.key-store.pem.0.key", "target/certs/vertx-websocket.key", + "quarkus.http.insecure-requests", "disabled"); + } + } +}