Skip to content

Commit

Permalink
Merge pull request #1769 from michalvavrik/feature/fips-http
Browse files Browse the repository at this point in the history
Fix and enable HTTP module tests in FIPS-enabled environment
  • Loading branch information
gtroitsk authored Apr 25, 2024
2 parents 1f6b3d2 + b7dc62b commit 7b12a56
Show file tree
Hide file tree
Showing 24 changed files with 43 additions and 88 deletions.
5 changes: 0 additions & 5 deletions http/http-advanced-reactive/README.md

This file was deleted.

Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ quarkus.http.non-application-root-path=/q
quarkus.swagger-ui.always-include=true
quarkus.health.openapi.included=true
quarkus.http.http2=true
quarkus.http.ssl.certificate.key-store-file=META-INF/resources/server.keystore
quarkus.http.ssl.certificate.key-store-file-type=JKS
quarkus.http.ssl.certificate.key-store-password=password
# HttpClient config
HealthClientService/mp-rest/url=http://localhost:${quarkus.http.port}
HealthClientService/mp-rest/scope=jakarta.inject.Singleton
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Paths;
import java.time.Duration;
import java.util.Arrays;
Expand All @@ -65,6 +63,7 @@
import io.quarkus.test.bootstrap.Protocol;
import io.quarkus.test.bootstrap.RestService;
import io.quarkus.test.scenarios.annotations.EnabledOnQuarkusVersion;
import io.quarkus.test.security.certificate.CertificateBuilder;
import io.restassured.http.Header;
import io.restassured.response.ValidatableResponse;
import io.smallrye.mutiny.Uni;
Expand All @@ -83,7 +82,6 @@ public abstract class BaseHttpAdvancedReactiveIT {
private static final int TIMEOUT_SEC = 3;
private static final int RETRY = 3;
private static final String PASSWORD = "password";
private static final String KEY_STORE_PATH = "META-INF/resources/server.keystore";
private static final String UTF_8_CHARSET = ";charset=UTF-8";
private static final String CONTENT = "content";

Expand All @@ -105,7 +103,7 @@ public void testGrpc() {

@Test
@DisplayName("Http/2 Server test")
public void http2Server() throws InterruptedException, URISyntaxException {
public void http2Server() throws InterruptedException {
CountDownLatch done = new CountDownLatch(1);
Uni<JsonObject> content = getApp().mutiny(defaultVertxHttpClientOptions())
.getAbs(getAppEndpoint() + "/hello")
Expand Down Expand Up @@ -147,24 +145,6 @@ public void microprofileHttpClientRedirection() throws Exception {
assertEquals(HttpStatus.SC_OK, health.statusCode());
}

@Test
@EnabledOnQuarkusVersion(version = "1\\..*", reason = "Redirection is no longer supported in 2.x")
public void vertxHttpClientRedirection() throws InterruptedException, URISyntaxException {
CountDownLatch done = new CountDownLatch(1);
Uni<Integer> statusCode = getApp().mutiny(defaultVertxHttpClientOptions())
.getAbs(getAppEndpoint() + "/health").send()
.map(HttpResponse::statusCode).ifNoItem()
.after(Duration.ofSeconds(TIMEOUT_SEC)).fail().onFailure().retry().atMost(RETRY);

statusCode.subscribe().with(httpStatusCode -> {
assertEquals(SC_OK, httpStatusCode);
done.countDown();
});

done.await(TIMEOUT_SEC, TimeUnit.SECONDS);
assertThat(done.getCount(), equalTo(0L));
}

/**
* This test use special characters in {@link Path#value()}, that previously caused a validation error and build failure.
* The bug was fixed in 2.8.3. Disable test in previous Quarkus versions with property
Expand Down Expand Up @@ -355,14 +335,17 @@ private ResponsePredicateResult isHttp2x(HttpResponse<Void> resp) {
: ResponsePredicateResult.failure("Expected HTTP/2");
}

private WebClientOptions defaultVertxHttpClientOptions() throws URISyntaxException {
private WebClientOptions defaultVertxHttpClientOptions() {
return new WebClientOptions().setProtocolVersion(HttpVersion.HTTP_2).setSsl(true).setVerifyHost(false)
.setUseAlpn(true)
.setTrustStoreOptions(new JksOptions().setPassword(PASSWORD).setPath(defaultTruststore()));
}

private String defaultTruststore() throws URISyntaxException {
URL res = getClass().getClassLoader().getResource(KEY_STORE_PATH);
return Paths.get(res.toURI()).toFile().getAbsolutePath();
private String defaultTruststore() {
return getApp()
.<CertificateBuilder> getPropertyFromContext(CertificateBuilder.INSTANCE_KEY)
.certificates()
.get(0)
.truststorePath();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import io.quarkus.test.services.QuarkusApplication;
import io.restassured.RestAssured;

@Tag("fips-incompatible") // native-mode
@Tag("QUARKUS-1546")
@QuarkusScenario
public class ContainerRequestFilterReactiveIT {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
import io.quarkus.test.bootstrap.Protocol;
import io.quarkus.test.bootstrap.RestService;
import io.quarkus.test.scenarios.QuarkusScenario;
import io.quarkus.test.services.Certificate;
import io.quarkus.test.services.DevModeQuarkusApplication;
import io.quarkus.test.services.URILike;

@QuarkusScenario
public class DevModeHttpsIT extends AbstractDevModeIT {

@DevModeQuarkusApplication(ssl = true)
@DevModeQuarkusApplication(ssl = true, certificates = @Certificate(configureKeystore = true))
static RestService app = new DevModeQuarkusService()
.withProperty("quarkus.oidc.enabled", "false")
.withProperty("quarkus.keycloak.policy-enforcer.enable", "false")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import io.quarkus.test.bootstrap.Protocol;
import io.quarkus.test.bootstrap.RestService;
import io.quarkus.test.scenarios.QuarkusScenario;
import io.quarkus.test.security.certificate.CertificateBuilder;
import io.quarkus.test.services.Certificate;
import io.quarkus.test.services.QuarkusApplication;
import io.quarkus.test.services.URILike;
import io.vertx.core.Vertx;
Expand All @@ -41,7 +43,7 @@
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class Http2IT {
@QuarkusApplication(ssl = true, classes = { MorningResource.class,
CustomFramesResource.class }, properties = "http2.properties")
CustomFramesResource.class }, properties = "http2.properties", certificates = @Certificate(configureKeystore = true))
static RestService app = new RestService();

private static URILike baseUri;
Expand Down Expand Up @@ -86,7 +88,7 @@ public void httpClientVertxHttp2(Vertx vertx, VertxTestContext vertxTestContext)
HttpClientOptions httpClientOptions = new HttpClientOptions();
httpClientOptions.setSsl(true)
.setUseAlpn(true)
.setTrustOptions(new JksOptions().setPath("keystore.jks").setPassword("password"))
.setTrustOptions(new JksOptions().setPath(getTruststorePath()).setPassword("password"))
.setProtocolVersion(HttpVersion.HTTP_2);
httpClient = vertx.httpClientBuilder().with(httpClientOptions).build();

Expand Down Expand Up @@ -114,7 +116,7 @@ public void httpClientVertxHttp2(Vertx vertx, VertxTestContext vertxTestContext)
@DisplayName("HttpClient Vertx just with HTTP/2 protocol option set and default port")
void http2ProtocolTest(Vertx vertx, VertxTestContext vertxTestContext) {
HttpClientOptions httpClientOptions = new HttpClientOptions()
.setTrustOptions(new JksOptions().setPath("keystore.jks").setPassword("password"))
.setTrustOptions(new JksOptions().setPath(getTruststorePath()).setPassword("password"))
.setProtocolVersion(HttpVersion.HTTP_2);
httpClient = vertx.httpClientBuilder().with(httpClientOptions).build();
httpClient.request(HttpMethod.GET, baseUri.getPort(), baseUri.getHost(), BASE_ENDPOINT)
Expand All @@ -138,7 +140,7 @@ void testMaxHeaderSizeExceeded(Vertx vertx, VertxTestContext testContext) {
HttpClientOptions options = new HttpClientOptions()
.setSsl(true)
.setUseAlpn(true)
.setTrustOptions(new JksOptions().setPath("keystore.jks").setPassword("password"))
.setTrustOptions(new JksOptions().setPath(getTruststorePath()).setPassword("password"))
.setProtocolVersion(HttpVersion.HTTP_2);
httpClient = vertx.httpClientBuilder().with(options).build();
// Define the expected maximum header size limit
Expand Down Expand Up @@ -184,7 +186,7 @@ void verifyXContentTypeOptionsHeader(Vertx vertx, VertxTestContext vertxTestCont
HttpClientOptions options = new HttpClientOptions()
.setSsl(true)
.setUseAlpn(true)
.setTrustOptions(new JksOptions().setPath("keystore.jks").setPassword("password"))
.setTrustOptions(new JksOptions().setPath(getTruststorePath()).setPassword("password"))
.setProtocolVersion(HttpVersion.HTTP_2);
httpClient = vertx.httpClientBuilder().with(options).build();
httpClient.request(HttpMethod.GET, app.getURI(Protocol.HTTPS).getPort(), baseUri.getHost(), BASE_ENDPOINT)
Expand Down Expand Up @@ -216,7 +218,7 @@ void sendCustomFramesTest(Vertx vertx, VertxTestContext context) {
.setSsl(true)
.setUseAlpn(true)
.setProtocolVersion(HttpVersion.HTTP_2)
.setTrustOptions(new JksOptions().setPath("keystore.jks").setPassword("password"))
.setTrustOptions(new JksOptions().setPath(getTruststorePath()).setPassword("password"))
.setVerifyHost(false);
httpClient = vertx.httpClientBuilder().with(options).build();

Expand Down Expand Up @@ -245,4 +247,11 @@ public void closeConnections() {
httpClient.close();
}

private String getTruststorePath() {
return app
.<CertificateBuilder> getPropertyFromContext(CertificateBuilder.INSTANCE_KEY)
.certificates()
.get(0)
.truststorePath();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@
import static io.quarkus.test.bootstrap.KeycloakService.DEFAULT_REALM_BASE_PATH;
import static io.quarkus.test.bootstrap.KeycloakService.DEFAULT_REALM_FILE;

import org.junit.jupiter.api.Tag;

import io.quarkus.test.bootstrap.KeycloakService;
import io.quarkus.test.bootstrap.RestService;
import io.quarkus.test.scenarios.QuarkusScenario;
import io.quarkus.test.services.Certificate;
import io.quarkus.test.services.KeycloakContainer;
import io.quarkus.test.services.QuarkusApplication;

@Tag("fips-incompatible") // native-mode
@QuarkusScenario
public class HttpAdvancedReactiveIT extends BaseHttpAdvancedReactiveIT {

Expand All @@ -21,7 +19,7 @@ public class HttpAdvancedReactiveIT extends BaseHttpAdvancedReactiveIT {
static KeycloakService keycloak = new KeycloakService(DEFAULT_REALM_FILE, DEFAULT_REALM, DEFAULT_REALM_BASE_PATH)
.withProperty("JAVA_OPTS", "-Dcom.redhat.fips=false");

@QuarkusApplication(ssl = true)
@QuarkusApplication(ssl = true, certificates = @Certificate(configureKeystore = true))
static RestService app = new RestService().withProperty("quarkus.oidc.auth-server-url",
keycloak::getRealmUrl);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import io.quarkus.test.bootstrap.Protocol;
import io.quarkus.test.bootstrap.RestService;
import io.quarkus.test.scenarios.OpenShiftScenario;
import io.quarkus.test.services.Certificate;
import io.quarkus.test.services.KeycloakContainer;
import io.quarkus.test.services.QuarkusApplication;

Expand All @@ -22,7 +23,7 @@ public class OpenShiftHttpAdvancedReactiveIT extends BaseHttpAdvancedReactiveIT
static KeycloakService keycloak = new KeycloakService(DEFAULT_REALM_FILE, DEFAULT_REALM, DEFAULT_REALM_BASE_PATH)
.withProperty("JAVA_OPTS", "-Dcom.redhat.fips=false");

@QuarkusApplication(ssl = true)
@QuarkusApplication(ssl = true, certificates = @Certificate(configureKeystore = true))
static RestService app = new RestService().withProperty("quarkus.oidc.auth-server-url",
keycloak::getRealmUrl);

Expand Down
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
quarkus.oidc.enabled=false
quarkus.http.ssl.certificate.key-store-file=keystore.jks
quarkus.http.ssl.certificate.key-store-file-type=JKS
quarkus.http.ssl.certificate.key-store-password=password
quarkus.http.ssl-port=8443
quarkus.http.header."X-Content-Type-Options".value=nosniff
quarkus.http.limits.max-header-list-size=2048
Binary file not shown.
Binary file not shown.
Binary file not shown.
3 changes: 0 additions & 3 deletions http/http-advanced/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ quarkus.http.non-application-root-path=/q
quarkus.swagger-ui.always-include=true
quarkus.health.openapi.included=true
quarkus.http.http2=true
quarkus.http.ssl.certificate.key-store-file=META-INF/resources/server.keystore
quarkus.http.ssl.certificate.key-store-file-type=JKS
quarkus.http.ssl.certificate.key-store-password=password
# HttpClient config
HealthClientService/mp-rest/url=http://localhost:${quarkus.http.port}
HealthClientService/mp-rest/scope=jakarta.inject.Singleton
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Paths;
import java.time.Duration;
import java.util.Arrays;
import java.util.List;
Expand All @@ -40,6 +37,7 @@
import io.quarkus.test.scenarios.OpenShiftScenario;
import io.quarkus.test.scenarios.QuarkusScenario;
import io.quarkus.test.scenarios.annotations.EnabledOnQuarkusVersion;
import io.quarkus.test.security.certificate.CertificateBuilder;
import io.smallrye.mutiny.Uni;
import io.vertx.core.http.HttpVersion;
import io.vertx.core.json.JsonObject;
Expand All @@ -55,7 +53,6 @@ public abstract class BaseHttpAdvancedIT {
private static final int TIMEOUT_SEC = 3;
private static final int RETRY = 3;
private static final String PASSWORD = "password";
private static final String KEY_STORE_PATH = "META-INF/resources/server.keystore";
private static final String SSE_ERROR_MESSAGE = "java.lang.ClassNotFoundException: Provider for jakarta.ws.rs.sse.SseEventSource.Builder cannot be found";

protected abstract RestService getApp();
Expand Down Expand Up @@ -128,7 +125,7 @@ public void testGrpcGlobalInterceptors() {

@Test
@DisplayName("Http/2 Server test")
public void http2Server() throws InterruptedException, URISyntaxException {
public void http2Server() throws InterruptedException {
CountDownLatch done = new CountDownLatch(1);
Uni<JsonObject> content = getApp().mutiny(defaultVertxHttpClientOptions())
.getAbs(getAppEndpoint() + "/hello")
Expand Down Expand Up @@ -170,24 +167,6 @@ public void microprofileHttpClientRedirection() {
assertEquals(HttpStatus.SC_OK, health.statusCode());
}

@Test
@EnabledOnQuarkusVersion(version = "1\\..*", reason = "Redirection is no longer supported in 2.x")
public void vertxHttpClientRedirection() throws InterruptedException, URISyntaxException {
CountDownLatch done = new CountDownLatch(1);
Uni<Integer> statusCode = getApp().mutiny(defaultVertxHttpClientOptions())
.getAbs(getAppEndpoint() + "/health").send()
.map(HttpResponse::statusCode).ifNoItem()
.after(Duration.ofSeconds(TIMEOUT_SEC)).fail().onFailure().retry().atMost(RETRY);

statusCode.subscribe().with(httpStatusCode -> {
assertEquals(HttpStatus.SC_OK, httpStatusCode);
done.countDown();
});

done.await(TIMEOUT_SEC, TimeUnit.SECONDS);
assertThat(done.getCount(), equalTo(0L));
}

@Test
@Tag("QUARKUS-2004")
public void constraintsExist() throws JsonProcessingException {
Expand Down Expand Up @@ -262,15 +241,18 @@ private ResponsePredicateResult isHttp2x(HttpResponse<Void> resp) {
: ResponsePredicateResult.failure("Expected HTTP/2");
}

private WebClientOptions defaultVertxHttpClientOptions() throws URISyntaxException {
private WebClientOptions defaultVertxHttpClientOptions() {
return new WebClientOptions().setProtocolVersion(HttpVersion.HTTP_2).setSsl(true).setVerifyHost(false)
.setUseAlpn(true)
.setTrustStoreOptions(new JksOptions().setPassword(PASSWORD).setPath(defaultTruststore()));
}

private String defaultTruststore() throws URISyntaxException {
URL res = getClass().getClassLoader().getResource(KEY_STORE_PATH);
return Paths.get(res.toURI()).toFile().getAbsolutePath();
private String defaultTruststore() {
return getApp()
.<CertificateBuilder> getPropertyFromContext(CertificateBuilder.INSTANCE_KEY)
.certificates()
.get(0)
.truststorePath();
}

private void wait(Duration timeout) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import io.quarkus.test.services.QuarkusApplication;
import io.restassured.RestAssured;

@Tag("fips-incompatible") // native-mode
@Tag("QUARKUS-1546")
@QuarkusScenario
public class ContainerRequestFilterIT {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@
import static io.quarkus.test.bootstrap.KeycloakService.DEFAULT_REALM_BASE_PATH;
import static io.quarkus.test.bootstrap.KeycloakService.DEFAULT_REALM_FILE;

import org.junit.jupiter.api.Tag;

import io.quarkus.test.bootstrap.KeycloakService;
import io.quarkus.test.bootstrap.RestService;
import io.quarkus.test.scenarios.QuarkusScenario;
import io.quarkus.test.services.Certificate;
import io.quarkus.test.services.KeycloakContainer;
import io.quarkus.test.services.QuarkusApplication;

@Tag("fips-incompatible") // native-mode
@QuarkusScenario
public class HttpAdvancedIT extends BaseHttpAdvancedIT {

Expand All @@ -21,7 +19,7 @@ public class HttpAdvancedIT extends BaseHttpAdvancedIT {
static KeycloakService keycloak = new KeycloakService(DEFAULT_REALM_FILE, DEFAULT_REALM, DEFAULT_REALM_BASE_PATH)
.withProperty("JAVA_OPTS", "-Dcom.redhat.fips=false");

@QuarkusApplication(ssl = true)
@QuarkusApplication(ssl = true, certificates = @Certificate(configureKeystore = true))
static RestService app = new RestService().withProperty("quarkus.oidc.auth-server-url", keycloak::getRealmUrl);

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import io.quarkus.test.bootstrap.Protocol;
import io.quarkus.test.bootstrap.RestService;
import io.quarkus.test.scenarios.OpenShiftScenario;
import io.quarkus.test.services.Certificate;
import io.quarkus.test.services.KeycloakContainer;
import io.quarkus.test.services.QuarkusApplication;

Expand All @@ -22,7 +23,7 @@ public class OpenShiftHttpAdvancedIT extends BaseHttpAdvancedIT {
static KeycloakService keycloak = new KeycloakService(DEFAULT_REALM_FILE, DEFAULT_REALM, DEFAULT_REALM_BASE_PATH)
.withProperty("JAVA_OPTS", "-Dcom.redhat.fips=false");

@QuarkusApplication(ssl = true)
@QuarkusApplication(ssl = true, certificates = @Certificate(configureKeystore = true))
static RestService app = new RestService().withProperty("quarkus.oidc.auth-server-url", keycloak::getRealmUrl);

@Override
Expand Down
Binary file not shown.
Binary file not shown.
Loading

0 comments on commit 7b12a56

Please sign in to comment.