diff --git a/STATUS.adoc b/STATUS.adoc index 964d066f..b5b72037 100644 --- a/STATUS.adoc +++ b/STATUS.adoc @@ -549,6 +549,12 @@ h|nativeTest |image:https://ci.spring.io/api/v1/teams/spring-aot-smoke-tests/pipelines/spring-aot-smoke-tests-1.0.x/jobs/webmvc-undertow-test/badge[link=https://ci.spring.io/teams/spring-aot-smoke-tests/pipelines/spring-aot-smoke-tests-1.0.x/jobs/webmvc-undertow-test] |image:https://ci.spring.io/api/v1/teams/spring-aot-smoke-tests/pipelines/spring-aot-smoke-tests-1.0.x/jobs/webmvc-undertow-native-test/badge[link=https://ci.spring.io/teams/spring-aot-smoke-tests/pipelines/spring-aot-smoke-tests-1.0.x/jobs/webmvc-undertow-native-test] +|webmvc-undertow-tls +|image:https://ci.spring.io/api/v1/teams/spring-aot-smoke-tests/pipelines/spring-aot-smoke-tests-1.0.x/jobs/webmvc-undertow-tls-app-test/badge[link=https://ci.spring.io/teams/spring-aot-smoke-tests/pipelines/spring-aot-smoke-tests-1.0.x/jobs/webmvc-undertow-tls-app-test] +|image:https://ci.spring.io/api/v1/teams/spring-aot-smoke-tests/pipelines/spring-aot-smoke-tests-1.0.x/jobs/webmvc-undertow-tls-native-app-test/badge[link=https://ci.spring.io/teams/spring-aot-smoke-tests/pipelines/spring-aot-smoke-tests-1.0.x/jobs/webmvc-undertow-tls-native-app-test] +| +| + |websocket-jetty |image:https://ci.spring.io/api/v1/teams/spring-aot-smoke-tests/pipelines/spring-aot-smoke-tests-1.0.x/jobs/websocket-jetty-app-test/badge[link=https://ci.spring.io/teams/spring-aot-smoke-tests/pipelines/spring-aot-smoke-tests-1.0.x/jobs/websocket-jetty-app-test] |image:https://ci.spring.io/api/v1/teams/spring-aot-smoke-tests/pipelines/spring-aot-smoke-tests-1.0.x/jobs/websocket-jetty-native-app-test/badge[link=https://ci.spring.io/teams/spring-aot-smoke-tests/pipelines/spring-aot-smoke-tests-1.0.x/jobs/websocket-jetty-native-app-test] diff --git a/ci/smoke-tests.yml b/ci/smoke-tests.yml index fa42d450..ddc6063f 100644 --- a/ci/smoke-tests.yml +++ b/ci/smoke-tests.yml @@ -267,6 +267,9 @@ groups: - name: webmvc-undertow app_test: true test: true + - name: webmvc-undertow-tls + app_test: true + test: false - name: websocket-jetty app_test: true test: false diff --git a/framework/webmvc-undertow-tls/README.adoc b/framework/webmvc-undertow-tls/README.adoc new file mode 100644 index 00000000..fc98a8f5 --- /dev/null +++ b/framework/webmvc-undertow-tls/README.adoc @@ -0,0 +1 @@ +Tests if WebMVC with Undertow with TLS is working diff --git a/framework/webmvc-undertow-tls/build.gradle b/framework/webmvc-undertow-tls/build.gradle new file mode 100644 index 00000000..7a165283 --- /dev/null +++ b/framework/webmvc-undertow-tls/build.gradle @@ -0,0 +1,25 @@ +plugins { + id 'java' + id 'org.springframework.boot' + id 'org.springframework.aot.smoke-test' + id 'org.graalvm.buildtools.native' +} + +dependencies { + implementation(platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)) + implementation("org.springframework.boot:spring-boot-starter-web") + implementation("org.springframework.boot:spring-boot-starter-undertow") + modules { + module("org.springframework.boot:spring-boot-starter-tomcat") { + replacedBy("org.springframework.boot:spring-boot-starter-undertow", "Use Undertow instead of Tomcat") + } + } + + testImplementation("org.springframework.boot:spring-boot-starter-test") + + appTestImplementation(project(":aot-smoke-test-support")) +} + +aotSmokeTest { + webApplication = true +} diff --git a/framework/webmvc-undertow-tls/src/appTest/java/com/example/webmvc/undertow/tls/WebMvcUndertowTlsApplicationAotTests.java b/framework/webmvc-undertow-tls/src/appTest/java/com/example/webmvc/undertow/tls/WebMvcUndertowTlsApplicationAotTests.java new file mode 100644 index 00000000..7cb6f115 --- /dev/null +++ b/framework/webmvc-undertow-tls/src/appTest/java/com/example/webmvc/undertow/tls/WebMvcUndertowTlsApplicationAotTests.java @@ -0,0 +1,75 @@ +/* + * Copyright 2022 the original author or authors. + * + * Licensed 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 + * + * https://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 com.example.webmvc.undertow.tls; + +import java.io.InputStream; +import java.net.URI; +import java.net.http.HttpClient; +import java.security.KeyStore; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; + +import org.junit.jupiter.api.Test; + +import org.springframework.aot.smoketest.support.junit.ApplicationTest; +import org.springframework.aot.smoketest.support.junit.ApplicationUrl; +import org.springframework.aot.smoketest.support.junit.ApplicationUrl.Scheme; +import org.springframework.http.client.reactive.ClientHttpConnector; +import org.springframework.http.client.reactive.JdkClientHttpConnector; +import org.springframework.test.web.reactive.server.WebTestClient; + +import static org.assertj.core.api.Assertions.assertThat; + +@ApplicationTest +class WebMvcUndertowTlsApplicationAotTests { + + @Test + void stringResponseBody(@ApplicationUrl(scheme = Scheme.HTTPS) URI applicationUrl) throws Exception { + WebTestClient client = buildWebClient(applicationUrl); + + client.get().exchange().expectStatus().isOk().expectBody().consumeWith( + (result) -> assertThat(new String(result.getResponseBodyContent())).isEqualTo("Hello World TLS")); + } + + /** + * Builds a web client for the running application. This web client is configured to + * trust the TLS certificate of the server. + * @param applicationUrl the URL to the application + * @return web client + * @throws Exception if something went wrong + */ + private static WebTestClient buildWebClient(URI applicationUrl) throws Exception { + KeyStore trustStore = KeyStore.getInstance("jks"); + try (InputStream stream = WebMvcUndertowTlsApplicationAotTests.class.getResourceAsStream("/truststore.jks")) { + assertThat(stream).as("Trust store on test classpath").isNotNull(); + trustStore.load(stream, null); + } + + TrustManagerFactory trustManagerFactory = TrustManagerFactory + .getInstance(TrustManagerFactory.getDefaultAlgorithm()); + trustManagerFactory.init(trustStore); + + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, trustManagerFactory.getTrustManagers(), null); + + HttpClient httpClient = HttpClient.newBuilder().sslContext(sslContext).build(); + ClientHttpConnector connector = new JdkClientHttpConnector(httpClient); + return WebTestClient.bindToServer(connector).baseUrl(applicationUrl.toString()).build(); + } + +} diff --git a/framework/webmvc-undertow-tls/src/appTest/resources/truststore.jks b/framework/webmvc-undertow-tls/src/appTest/resources/truststore.jks new file mode 100644 index 00000000..06318674 Binary files /dev/null and b/framework/webmvc-undertow-tls/src/appTest/resources/truststore.jks differ diff --git a/framework/webmvc-undertow-tls/src/main/java/com/example/webmvc/undertow/tls/TestController.java b/framework/webmvc-undertow-tls/src/main/java/com/example/webmvc/undertow/tls/TestController.java new file mode 100644 index 00000000..7d352024 --- /dev/null +++ b/framework/webmvc-undertow-tls/src/main/java/com/example/webmvc/undertow/tls/TestController.java @@ -0,0 +1,15 @@ +package com.example.webmvc.undertow.tls; + +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class TestController { + + @GetMapping(value = "/", produces = MediaType.TEXT_PLAIN_VALUE) + public String index() { + return "Hello World TLS"; + } + +} diff --git a/framework/webmvc-undertow-tls/src/main/java/com/example/webmvc/undertow/tls/WebMvcUndertowTlsApplication.java b/framework/webmvc-undertow-tls/src/main/java/com/example/webmvc/undertow/tls/WebMvcUndertowTlsApplication.java new file mode 100644 index 00000000..438c2216 --- /dev/null +++ b/framework/webmvc-undertow-tls/src/main/java/com/example/webmvc/undertow/tls/WebMvcUndertowTlsApplication.java @@ -0,0 +1,28 @@ +package com.example.webmvc.undertow.tls; + +import com.example.webmvc.undertow.tls.WebMvcUndertowTlsApplication.KeyStoreRuntimeHints; + +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.aot.hint.RuntimeHintsRegistrar; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ImportRuntimeHints; + +@SpringBootApplication +@ImportRuntimeHints(KeyStoreRuntimeHints.class) +public class WebMvcUndertowTlsApplication { + + public static void main(String[] args) { + SpringApplication.run(WebMvcUndertowTlsApplication.class, args); + } + + static class KeyStoreRuntimeHints implements RuntimeHintsRegistrar { + + @Override + public void registerHints(RuntimeHints hints, ClassLoader classLoader) { + hints.resources().registerPattern("keystore.jks"); + } + + } + +} diff --git a/framework/webmvc-undertow-tls/src/main/resources/application.properties b/framework/webmvc-undertow-tls/src/main/resources/application.properties new file mode 100644 index 00000000..b2dbf04e --- /dev/null +++ b/framework/webmvc-undertow-tls/src/main/resources/application.properties @@ -0,0 +1,4 @@ +server.ssl.key-store=classpath:keystore.jks +server.ssl.key-store-password=secret +server.ssl.key-alias=localhost +server.ssl.key-password=secret diff --git a/framework/webmvc-undertow-tls/src/main/resources/keystore.jks b/framework/webmvc-undertow-tls/src/main/resources/keystore.jks new file mode 100644 index 00000000..cad0ed8d Binary files /dev/null and b/framework/webmvc-undertow-tls/src/main/resources/keystore.jks differ