Skip to content

Commit

Permalink
Support TLS registry and cert reloading
Browse files Browse the repository at this point in the history
  • Loading branch information
michalvavrik committed Aug 29, 2024
1 parent 34b0081 commit 42d43ab
Show file tree
Hide file tree
Showing 21 changed files with 633 additions and 73 deletions.
4 changes: 4 additions & 0 deletions examples/https/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-security</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-tls-registry</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus.qe</groupId>
<artifactId>quarkus-test-core</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

@QuarkusScenario
public class DevModeGreetingResourceIT {
@DevModeQuarkusApplication(ssl = true, certificates = @Certificate(configureKeystore = true))
@DevModeQuarkusApplication(ssl = true, certificates = @Certificate(configureKeystore = true, configureHttpServer = true, useTlsRegistry = false))
static DevModeQuarkusService app = new DevModeQuarkusService();

@Test
Expand Down
2 changes: 1 addition & 1 deletion examples/https/src/test/java/io/quarkus/qe/HttpIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class HttpIT {

private final RequestSpecification spec = given();

@QuarkusApplication(ssl = true, certificates = @Certificate(configureKeystore = true, format = JKS))
@QuarkusApplication(ssl = true, certificates = @Certificate(configureKeystore = true, format = JKS, configureHttpServer = true, useTlsRegistry = false))
static final RestService app = new RestService();

@Test
Expand Down
2 changes: 1 addition & 1 deletion examples/https/src/test/java/io/quarkus/qe/HttpsIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class HttpsIT {
private static final String CLIENT_CN_2 = "my-client-2";
private static final String CLIENT_CN_3 = "my-client-3";

@QuarkusApplication(ssl = true, certificates = @Certificate(configureKeystore = true, configureTruststore = true, clientCertificates = {
@QuarkusApplication(ssl = true, certificates = @Certificate(configureKeystore = true, configureTruststore = true, configureHttpServer = true, useTlsRegistry = false, clientCertificates = {
@Certificate.ClientCertificate(cnAttribute = CLIENT_CN_1),
@Certificate.ClientCertificate(cnAttribute = CLIENT_CN_2),
@Certificate.ClientCertificate(cnAttribute = CLIENT_CN_3, unknownToServer = true)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package io.quarkus.qe;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.apache.http.HttpStatus;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

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

@QuarkusScenario
public class HttpsTlsRegistryNamedConfigIT {

static final String CLIENT_CN_1 = "my-client-1";
static final String CLIENT_CN_2 = "my-client-2";
static final String CLIENT_CN_3 = "my-client-3";

@QuarkusApplication(ssl = true, certificates = @Certificate(configureKeystore = true, clientCertificates = {
@Certificate.ClientCertificate(cnAttribute = CLIENT_CN_1),
@Certificate.ClientCertificate(cnAttribute = CLIENT_CN_2),
@Certificate.ClientCertificate(cnAttribute = CLIENT_CN_3, unknownToServer = true)
}, configureTruststore = true, configureHttpServer = true, tlsConfigName = "my-name"))
static final RestService app = new RestService()
.withProperty("quarkus.http.ssl.client-auth", "request")
.withProperty("quarkus.http.insecure-requests", "DISABLED");

@Test
public void testTLS() {
// mTLS auth is not required, but the communication must be secured
sayHello();
}

@Test
public void testMutualTLS() {
// mTLS required
sayHello(CLIENT_CN_1);
sayHello(CLIENT_CN_2);
}

@Test
public void testFailureAsServerUnknownToClient() {
try {
app.mutinyHttps(true, CLIENT_CN_1, false).get("/greeting/mutual-tls").sendAndAwait();
} catch (Exception e) {
return;
}
Assertions.fail("HTTP request should had failed as server is unknown to the client");
}

@Test
public void testAuthNFailureAsClientUnknownToServer() {
var resp = app.mutinyHttps(CLIENT_CN_3).get("/greeting/mutual-tls").sendAndAwait();
assertEquals(401, resp.statusCode());
}

private static void sayHello() {
sayHello(CLIENT_CN_1, false);
}

private static void sayHello(String clientCn) {
sayHello(clientCn, true);
}

private static void sayHello(String clientCn, boolean requireMutualTLS) {
var path = "/greeting" + (requireMutualTLS ? "/mutual-tls" : "");
var response = app.mutinyHttps(clientCn).get(path).sendAndAwait();
assertEquals(HttpStatus.SC_OK, response.statusCode());
if (requireMutualTLS) {
assertEquals("Hello CN=%s!".formatted(clientCn), response.bodyAsString());
} else {
assertEquals("Hello World!", response.bodyAsString());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package io.quarkus.qe;

import static io.quarkus.qe.HttpsTlsRegistryNamedConfigIT.CLIENT_CN_1;
import static org.junit.jupiter.api.Assertions.assertEquals;

import org.apache.http.HttpStatus;
import org.junit.jupiter.api.Test;

import io.quarkus.test.bootstrap.RestService;
import io.quarkus.test.scenarios.QuarkusScenario;
import io.quarkus.test.security.certificate.CertificateBuilder;
import io.quarkus.test.security.certificate.ClientCertificateRequest;
import io.quarkus.test.services.Certificate;
import io.quarkus.test.services.QuarkusApplication;
import io.quarkus.test.utils.AwaitilityUtils;

@QuarkusScenario
public class TlsRegistryCertificateReloadingIT {

private static final String CERT_PREFIX = "reload-test";
private static final String NEW_CLIENT_CN = "my-new-client";

@QuarkusApplication(ssl = true, certificates = @Certificate(clientCertificates = {
@Certificate.ClientCertificate(cnAttribute = CLIENT_CN_1)
}, configureTruststore = true, configureHttpServer = true, configureKeystore = true, prefix = CERT_PREFIX))
static RestService app = new RestService()
.withProperty("quarkus.http.ssl.client-auth", "request")
.withProperty("quarkus.http.insecure-requests", "DISABLED")
.withProperty("quarkus.tls.reload-period", "2s");

@Test
public void testCertificateReload() {
var path = "/greeting/mutual-tls";

var response = app.mutinyHttps(CLIENT_CN_1).get(path).sendAndAwait();
assertEquals(HttpStatus.SC_OK, response.statusCode());
assertEquals("Hello CN=%s!".formatted(CLIENT_CN_1), response.bodyAsString());

var clientReq = new ClientCertificateRequest(NEW_CLIENT_CN, false);
app
.<CertificateBuilder> getPropertyFromContext(CertificateBuilder.INSTANCE_KEY)
.regenerateCertificate(CERT_PREFIX, certReq -> certReq.withClientRequests(clientReq));

AwaitilityUtils.untilAsserted(() -> {
var response1 = app.mutinyHttps(NEW_CLIENT_CN).get(path).sendAndAwait();
assertEquals(HttpStatus.SC_OK, response1.statusCode());
assertEquals("Hello CN=%s!".formatted(NEW_CLIENT_CN), response1.bodyAsString());
});
}
}
4 changes: 4 additions & 0 deletions examples/management/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
<artifactId>quarkus-test-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-tls-registry</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus.qe</groupId>
<artifactId>quarkus-test-openshift</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// todo Merge with LocalIT when https://github.com/quarkusio/quarkus/issues/32225 is fixed
public class LocalTLSIT {

@QuarkusApplication(certificates = @Certificate(configureKeystoreForManagementInterface = true))
@QuarkusApplication(certificates = @Certificate(configureManagementInterface = true, configureKeystore = true, useTlsRegistry = false))
static final RestService service = new RestService()
.withProperty("quarkus.management.port", "9003");

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package io.quarkus.qe;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;

import io.quarkus.test.bootstrap.RestService;
import io.quarkus.test.scenarios.QuarkusScenario;
import io.quarkus.test.services.Certificate;
import io.quarkus.test.services.QuarkusApplication;
import io.restassured.response.Response;

@QuarkusScenario
public class LocalTlsRegistryIT {

@QuarkusApplication(certificates = @Certificate(configureManagementInterface = true, configureKeystore = true))
static final RestService service = new RestService()
.withProperty("quarkus.management.port", "9003");

@Test
public void greeting() {
Response response = service.given().get("/ping");
assertEquals(200, response.statusCode());
assertEquals("pong", response.body().asString());
}

@Test
public void tls() {
var statusCode = service.mutinyHttps().get("/q/health").sendAndAwait().statusCode();
assertEquals(200, statusCode);
}
}
6 changes: 0 additions & 6 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@
<consul.image>docker.io/bitnami/consul:1.19.1</consul.image>
<reruns>2</reruns>
<flaky-run-reporter.version>0.1.2.Beta1</flaky-run-reporter.version>
<certificate-generator.version>0.7.1</certificate-generator.version>
</properties>
<distributionManagement>
<snapshotRepository>
Expand Down Expand Up @@ -214,11 +213,6 @@
<artifactId>quarkus-test-maven</artifactId>
<version>${quarkus.platform.version}</version>
</dependency>
<dependency>
<groupId>me.escoffier.certs</groupId>
<artifactId>certificate-generator</artifactId>
<version>${certificate-generator.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
Expand Down
4 changes: 2 additions & 2 deletions quarkus-test-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@
<artifactId>smallrye-mutiny-vertx-web-client</artifactId>
</dependency>
<dependency>
<groupId>me.escoffier.certs</groupId>
<artifactId>certificate-generator</artifactId>
<groupId>io.smallrye.certs</groupId>
<artifactId>smallrye-certificate-generator</artifactId>
</dependency>
<!-- used by our own SureFire debug provider -->
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;

Expand Down Expand Up @@ -135,6 +136,14 @@ public T withProperty(String key, Supplier<String> value) {
return (T) this;
}

/**
* The runtime configuration property to be configured based on type variable {@code U} from context.
*/
public <U> T withProperty(String configKey, String contextKey, Function<U, String> configValue) {
futureProperties.add(() -> properties.put(configKey, configValue.apply(getPropertyFromContext(contextKey))));
return (T) this;
}

@Override
public boolean isRunning() {
Log.debug(this, "Checking if resource is running");
Expand Down
Loading

0 comments on commit 42d43ab

Please sign in to comment.