Skip to content

Commit

Permalink
Merge pull request quarkusio#39106 from cescoffier/vertx-http-pem-tru…
Browse files Browse the repository at this point in the history
…ststore

Allows the HTTP server to use PEM truststore
  • Loading branch information
cescoffier authored Mar 4, 2024
2 parents 9a710df + 0fddc50 commit 23b87f6
Show file tree
Hide file tree
Showing 41 changed files with 769 additions and 490 deletions.
2 changes: 1 addition & 1 deletion build-parent/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@
<dependency>
<groupId>me.escoffier.certs</groupId>
<artifactId>certificate-generator-junit5</artifactId>
<version>0.4.0</version>
<version>0.4.3</version>
<scope>test</scope>
</dependency>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand All @@ -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 {
Expand All @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand All @@ -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 {
Expand All @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,34 @@
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";

@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 {
Expand All @@ -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();

Expand All @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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());

Expand Down Expand Up @@ -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"));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<BuildChainBuilder> buildCustomizer() {
Expand Down Expand Up @@ -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"));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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());

Expand Down Expand Up @@ -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"));
}
Expand Down
Loading

0 comments on commit 23b87f6

Please sign in to comment.