diff --git a/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/client/tls/MtlsWithJKSTrustStoreWithHttpServerWithTlsRegistryTest.java b/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/client/tls/MtlsWithJKSTrustStoreWithHttpServerWithTlsRegistryTest.java new file mode 100644 index 00000000000000..3c1f1fc1b6e296 --- /dev/null +++ b/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/client/tls/MtlsWithJKSTrustStoreWithHttpServerWithTlsRegistryTest.java @@ -0,0 +1,63 @@ +package io.quarkus.grpc.client.tls; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.grpc.examples.helloworld.GreeterGrpc; +import io.grpc.examples.helloworld.HelloReply; +import io.grpc.examples.helloworld.HelloRequest; +import io.quarkus.grpc.GrpcClient; +import io.quarkus.test.QuarkusUnitTest; +import me.escoffier.certs.Format; +import me.escoffier.certs.junit5.Certificate; +import me.escoffier.certs.junit5.Certificates; + +@Certificates(baseDir = "target/certs", certificates = { + @Certificate(name = "grpc", password = "password", formats = { Format.JKS, Format.PEM, Format.PKCS12 }, client = true) +}) +class MtlsWithJKSTrustStoreWithHttpServerWithTlsRegistryTest { + + private static final String configuration = """ + quarkus.tls.key-store.jks.path=target/certs/grpc-keystore.jks + quarkus.tls.key-store.jks.password=password + quarkus.tls.trust-store.jks.path=target/certs/grpc-server-truststore.jks + quarkus.tls.trust-store.jks.password=password + + quarkus.tls.my-client.trust-store.jks.path=target/certs/grpc-client-truststore.jks + quarkus.tls.my-client.trust-store.jks.password=password + quarkus.tls.my-client.key-store.jks.path=target/certs/grpc-client-keystore.jks + quarkus.tls.my-client.key-store.jks.password=password + + quarkus.grpc.clients.hello.plain-text=false + + quarkus.grpc.clients.hello.tls-configuration-name=my-client + quarkus.grpc.clients.hello.use-quarkus-grpc-client=true + + quarkus.grpc.server.use-separate-server=false + quarkus.grpc.server.plain-text=false # Force the client to use TLS for the tests + + quarkus.http.ssl.client-auth=REQUIRED + quarkus.http.insecure-requests=disabled + """; + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest().setArchiveProducer( + () -> ShrinkWrap.create(JavaArchive.class) + .addPackage(HelloWorldTlsEndpoint.class.getPackage()) + .addPackage(GreeterGrpc.class.getPackage()) + .add(new StringAsset(configuration), "application.properties")); + + @GrpcClient("hello") + GreeterGrpc.GreeterBlockingStub blockingHelloService; + + @Test + void testClientTlsConfiguration() { + HelloReply reply = blockingHelloService.sayHello(HelloRequest.newBuilder().setName("neo").build()); + assertThat(reply.getMessage()).isEqualTo("Hello neo"); + } +} diff --git a/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/client/tls/MtlsWithP12TrustStoreWithHttpServerWithTlsRegistryTest.java b/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/client/tls/MtlsWithP12TrustStoreWithHttpServerWithTlsRegistryTest.java new file mode 100644 index 00000000000000..cc0c2abb2ef356 --- /dev/null +++ b/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/client/tls/MtlsWithP12TrustStoreWithHttpServerWithTlsRegistryTest.java @@ -0,0 +1,63 @@ +package io.quarkus.grpc.client.tls; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.grpc.examples.helloworld.GreeterGrpc; +import io.grpc.examples.helloworld.HelloReply; +import io.grpc.examples.helloworld.HelloRequest; +import io.quarkus.grpc.GrpcClient; +import io.quarkus.test.QuarkusUnitTest; +import me.escoffier.certs.Format; +import me.escoffier.certs.junit5.Certificate; +import me.escoffier.certs.junit5.Certificates; + +@Certificates(baseDir = "target/certs", certificates = { + @Certificate(name = "grpc", password = "password", formats = { Format.JKS, Format.PEM, Format.PKCS12 }, client = true) +}) +class MtlsWithP12TrustStoreWithHttpServerWithTlsRegistryTest { + + private static final String configuration = """ + quarkus.tls.key-store.p12.path=target/certs/grpc-keystore.p12 + quarkus.tls.key-store.p12.password=password + quarkus.tls.trust-store.p12.path=target/certs/grpc-server-truststore.p12 + quarkus.tls.trust-store.p12.password=password + + quarkus.tls.my-client.trust-store.p12.path=target/certs/grpc-client-truststore.p12 + quarkus.tls.my-client.trust-store.p12.password=password + quarkus.tls.my-client.key-store.p12.path=target/certs/grpc-client-keystore.p12 + quarkus.tls.my-client.key-store.p12.password=password + + quarkus.grpc.clients.hello.plain-text=false + + quarkus.grpc.clients.hello.tls-configuration-name=my-client + quarkus.grpc.clients.hello.use-quarkus-grpc-client=true + + quarkus.grpc.server.use-separate-server=false + quarkus.grpc.server.plain-text=false # Force the client to use TLS for the tests + + quarkus.http.ssl.client-auth=REQUIRED + quarkus.http.insecure-requests=disabled + """; + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest().setArchiveProducer( + () -> ShrinkWrap.create(JavaArchive.class) + .addPackage(HelloWorldTlsEndpoint.class.getPackage()) + .addPackage(GreeterGrpc.class.getPackage()) + .add(new StringAsset(configuration), "application.properties")); + + @GrpcClient("hello") + GreeterGrpc.GreeterBlockingStub blockingHelloService; + + @Test + void testClientTlsConfiguration() { + HelloReply reply = blockingHelloService.sayHello(HelloRequest.newBuilder().setName("neo").build()); + assertThat(reply.getMessage()).isEqualTo("Hello neo"); + } +} diff --git a/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/client/tls/MtlsWithPemTrustStoreWithHttpServerWithTlsRegistryTest.java b/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/client/tls/MtlsWithPemTrustStoreWithHttpServerWithTlsRegistryTest.java new file mode 100644 index 00000000000000..640fabddcc50d4 --- /dev/null +++ b/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/client/tls/MtlsWithPemTrustStoreWithHttpServerWithTlsRegistryTest.java @@ -0,0 +1,62 @@ +package io.quarkus.grpc.client.tls; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.grpc.examples.helloworld.GreeterGrpc; +import io.grpc.examples.helloworld.HelloReply; +import io.grpc.examples.helloworld.HelloRequest; +import io.quarkus.grpc.GrpcClient; +import io.quarkus.test.QuarkusUnitTest; +import me.escoffier.certs.Format; +import me.escoffier.certs.junit5.Certificate; +import me.escoffier.certs.junit5.Certificates; + +@Certificates(baseDir = "target/certs", certificates = { + @Certificate(name = "grpc", password = "password", formats = { Format.JKS, Format.PEM, Format.PKCS12 }, client = true) +}) +class MtlsWithPemTrustStoreWithHttpServerWithTlsRegistryTest { + + private static final String configuration = """ + quarkus.tls.key-store.jks.path=target/certs/grpc-keystore.jks + quarkus.tls.key-store.jks.password=password + quarkus.tls.trust-store.jks.path=target/certs/grpc-server-truststore.jks + quarkus.tls.trust-store.jks.password=password + + quarkus.tls.my-client.trust-store.pem.certs=target/certs/grpc-client-ca.crt + quarkus.tls.my-client.key-store.pem.0.cert=target/certs/grpc-client.crt + quarkus.tls.my-client.key-store.pem.0.key=target/certs/grpc-client.key + + quarkus.grpc.clients.hello.plain-text=false + + quarkus.grpc.clients.hello.tls-configuration-name=my-client + quarkus.grpc.clients.hello.use-quarkus-grpc-client=true + + quarkus.grpc.server.use-separate-server=false + quarkus.grpc.server.plain-text=false # Force the client to use TLS for the tests + + quarkus.http.ssl.client-auth=REQUIRED + quarkus.http.insecure-requests=disabled + """; + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest().setArchiveProducer( + () -> ShrinkWrap.create(JavaArchive.class) + .addPackage(HelloWorldTlsEndpoint.class.getPackage()) + .addPackage(GreeterGrpc.class.getPackage()) + .add(new StringAsset(configuration), "application.properties")); + + @GrpcClient("hello") + GreeterGrpc.GreeterBlockingStub blockingHelloService; + + @Test + void testClientTlsConfiguration() { + HelloReply reply = blockingHelloService.sayHello(HelloRequest.newBuilder().setName("neo").build()); + assertThat(reply.getMessage()).isEqualTo("Hello neo"); + } +} diff --git a/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/client/tls/TlsWithJKSTrustStoreAndTlsRegistryTest.java b/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/client/tls/TlsWithJKSTrustStoreAndTlsRegistryTest.java new file mode 100644 index 00000000000000..438140cb832334 --- /dev/null +++ b/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/client/tls/TlsWithJKSTrustStoreAndTlsRegistryTest.java @@ -0,0 +1,48 @@ +package io.quarkus.grpc.client.tls; + +import static io.restassured.RestAssured.get; +import static org.assertj.core.api.Assertions.assertThat; + +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; +import me.escoffier.certs.Format; +import me.escoffier.certs.junit5.Certificate; +import me.escoffier.certs.junit5.Certificates; + +@Certificates(baseDir = "target/certs", certificates = { + @Certificate(name = "grpc", password = "password", formats = { Format.JKS, Format.PEM, Format.PKCS12 }, client = true) +}) +class TlsWithJKSTrustStoreAndTlsRegistryTest { + + private static final String configuration = """ + quarkus.tls.trust-store.jks.path=target/certs/grpc-client-truststore.jks + quarkus.tls.trust-store.jks.password=password + + quarkus.grpc.clients.hello.host=localhost + quarkus.grpc.clients.hello.port=9001 + quarkus.grpc.clients.hello.plain-text=false + quarkus.grpc.clients.hello.use-quarkus-grpc-client=true + + # Legacy server + quarkus.grpc.server.ssl.certificate=target/certs/grpc.crt + quarkus.grpc.server.ssl.key=target/certs/grpc.key + """; + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest().setArchiveProducer( + () -> ShrinkWrap.create(JavaArchive.class) + .addPackage(HelloWorldTlsEndpoint.class.getPackage()) + .addPackage(io.grpc.examples.helloworld.GreeterGrpc.class.getPackage()) + .add(new StringAsset(configuration), "application.properties")); + + @Test + void testClientTlsConfiguration() { + String response = get("/hello/blocking/neo").asString(); + assertThat(response).isEqualTo("Hello neo"); + } +} diff --git a/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/client/tls/TlsWithJKSTrustStoreWithHttpServerAndTlsRegistryTest.java b/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/client/tls/TlsWithJKSTrustStoreWithHttpServerAndTlsRegistryTest.java new file mode 100644 index 00000000000000..9d1c40f5ca2f0d --- /dev/null +++ b/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/client/tls/TlsWithJKSTrustStoreWithHttpServerAndTlsRegistryTest.java @@ -0,0 +1,57 @@ +package io.quarkus.grpc.client.tls; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.grpc.examples.helloworld.GreeterGrpc; +import io.grpc.examples.helloworld.HelloReply; +import io.grpc.examples.helloworld.HelloRequest; +import io.quarkus.grpc.GrpcClient; +import io.quarkus.test.QuarkusUnitTest; +import me.escoffier.certs.Format; +import me.escoffier.certs.junit5.Certificate; +import me.escoffier.certs.junit5.Certificates; + +@Certificates(baseDir = "target/certs", certificates = { + @Certificate(name = "grpc", password = "password", formats = { Format.JKS, Format.PEM, Format.PKCS12 }, client = true) +}) +class TlsWithJKSTrustStoreWithHttpServerAndTlsRegistryTest { + + private static final String configuration = """ + quarkus.tls.my-client.trust-store.jks.path=target/certs/grpc-client-truststore.jks + quarkus.tls.my-client.trust-store.jks.password=password + + quarkus.grpc.clients.hello.plain-text=false + quarkus.grpc.clients.hello.tls-configuration-name=my-client + quarkus.grpc.clients.hello.use-quarkus-grpc-client=true + + quarkus.grpc.server.use-separate-server=false + quarkus.grpc.server.plain-text=false # Force the client to use TLS for the tests + + quarkus.tls.key-store.jks.path=target/certs/grpc-keystore.jks + quarkus.tls.key-store.jks.password=password + + quarkus.http.insecure-requests=disabled + """; + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest().setArchiveProducer( + () -> ShrinkWrap.create(JavaArchive.class) + .addPackage(HelloWorldTlsEndpoint.class.getPackage()) + .addPackage(GreeterGrpc.class.getPackage()) + .add(new StringAsset(configuration), "application.properties")); + + @GrpcClient("hello") + GreeterGrpc.GreeterBlockingStub blockingHelloService; + + @Test + void testClientTlsConfiguration() { + HelloReply reply = blockingHelloService.sayHello(HelloRequest.newBuilder().setName("neo").build()); + assertThat(reply.getMessage()).isEqualTo("Hello neo"); + } +} diff --git a/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/client/tls/TlsWithP12TrustStoreAndTlsRegistryTest.java b/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/client/tls/TlsWithP12TrustStoreAndTlsRegistryTest.java new file mode 100644 index 00000000000000..24d4218cf5568b --- /dev/null +++ b/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/client/tls/TlsWithP12TrustStoreAndTlsRegistryTest.java @@ -0,0 +1,48 @@ +package io.quarkus.grpc.client.tls; + +import static io.restassured.RestAssured.get; +import static org.assertj.core.api.Assertions.assertThat; + +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; +import me.escoffier.certs.Format; +import me.escoffier.certs.junit5.Certificate; +import me.escoffier.certs.junit5.Certificates; + +@Certificates(baseDir = "target/certs", certificates = { + @Certificate(name = "grpc", password = "password", formats = { Format.JKS, Format.PEM, Format.PKCS12 }, client = true) +}) +class TlsWithP12TrustStoreAndTlsRegistryTest { + + private static final String configuration = """ + quarkus.tls.trust-store.p12.path=target/certs/grpc-client-truststore.p12 + quarkus.tls.trust-store.p12.password=password + + quarkus.grpc.clients.hello.host=localhost + quarkus.grpc.clients.hello.port=9001 + quarkus.grpc.clients.hello.plain-text=false + quarkus.grpc.clients.hello.use-quarkus-grpc-client=true + + # Legacy server + quarkus.grpc.server.ssl.certificate=target/certs/grpc.crt + quarkus.grpc.server.ssl.key=target/certs/grpc.key + """; + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest().setArchiveProducer( + () -> ShrinkWrap.create(JavaArchive.class) + .addPackage(HelloWorldTlsEndpoint.class.getPackage()) + .addPackage(io.grpc.examples.helloworld.GreeterGrpc.class.getPackage()) + .add(new StringAsset(configuration), "application.properties")); + + @Test + void testClientTlsConfiguration() { + String response = get("/hello/blocking/neo").asString(); + assertThat(response).isEqualTo("Hello neo"); + } +} diff --git a/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/client/tls/TlsWithP12TrustStoreWithHttpServerAndTlsRegistryTest.java b/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/client/tls/TlsWithP12TrustStoreWithHttpServerAndTlsRegistryTest.java new file mode 100644 index 00000000000000..ddcc27846fcee1 --- /dev/null +++ b/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/client/tls/TlsWithP12TrustStoreWithHttpServerAndTlsRegistryTest.java @@ -0,0 +1,57 @@ +package io.quarkus.grpc.client.tls; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.grpc.examples.helloworld.GreeterGrpc; +import io.grpc.examples.helloworld.HelloReply; +import io.grpc.examples.helloworld.HelloRequest; +import io.quarkus.grpc.GrpcClient; +import io.quarkus.test.QuarkusUnitTest; +import me.escoffier.certs.Format; +import me.escoffier.certs.junit5.Certificate; +import me.escoffier.certs.junit5.Certificates; + +@Certificates(baseDir = "target/certs", certificates = { + @Certificate(name = "grpc", password = "password", formats = { Format.JKS, Format.PEM, Format.PKCS12 }, client = true) +}) +class TlsWithP12TrustStoreWithHttpServerAndTlsRegistryTest { + + private static final String configuration = """ + quarkus.tls.my-client.trust-store.p12.path=target/certs/grpc-client-truststore.p12 + quarkus.tls.my-client.trust-store.p12.password=password + + quarkus.grpc.clients.hello.plain-text=false + quarkus.grpc.clients.hello.tls-configuration-name=my-client + quarkus.grpc.clients.hello.use-quarkus-grpc-client=true + + quarkus.grpc.server.use-separate-server=false + quarkus.grpc.server.plain-text=false # Force the client to use TLS for the tests + + quarkus.tls.key-store.jks.path=target/certs/grpc-keystore.jks + quarkus.tls.key-store.jks.password=password + + quarkus.http.insecure-requests=disabled + """; + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest().setArchiveProducer( + () -> ShrinkWrap.create(JavaArchive.class) + .addPackage(HelloWorldTlsEndpoint.class.getPackage()) + .addPackage(GreeterGrpc.class.getPackage()) + .add(new StringAsset(configuration), "application.properties")); + + @GrpcClient("hello") + GreeterGrpc.GreeterBlockingStub blockingHelloService; + + @Test + void testClientTlsConfiguration() { + HelloReply reply = blockingHelloService.sayHello(HelloRequest.newBuilder().setName("neo").build()); + assertThat(reply.getMessage()).isEqualTo("Hello neo"); + } +} diff --git a/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/client/tls/TlsWithPemTrustStoreWithHttpServerWithTlsRegistryTest.java b/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/client/tls/TlsWithPemTrustStoreWithHttpServerWithTlsRegistryTest.java new file mode 100644 index 00000000000000..0105cc9e513a77 --- /dev/null +++ b/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/client/tls/TlsWithPemTrustStoreWithHttpServerWithTlsRegistryTest.java @@ -0,0 +1,56 @@ +package io.quarkus.grpc.client.tls; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.grpc.examples.helloworld.GreeterGrpc; +import io.grpc.examples.helloworld.HelloReply; +import io.grpc.examples.helloworld.HelloRequest; +import io.quarkus.grpc.GrpcClient; +import io.quarkus.test.QuarkusUnitTest; +import me.escoffier.certs.Format; +import me.escoffier.certs.junit5.Certificate; +import me.escoffier.certs.junit5.Certificates; + +@Certificates(baseDir = "target/certs", certificates = { + @Certificate(name = "grpc", password = "password", formats = { Format.JKS, Format.PEM, Format.PKCS12 }, client = true) +}) +class TlsWithPemTrustStoreWithHttpServerWithTlsRegistryTest { + + private static final String configuration = """ + quarkus.tls.my-client.trust-store.pem.certs=target/certs/grpc-client-ca.crt + + quarkus.grpc.clients.hello.plain-text=false + quarkus.grpc.clients.hello.tls-configuration-name=my-client + quarkus.grpc.clients.hello.use-quarkus-grpc-client=true + + quarkus.grpc.server.use-separate-server=false + quarkus.grpc.server.plain-text=false # Force the client to use TLS for the tests + + quarkus.tls.key-store.jks.path=target/certs/grpc-keystore.jks + quarkus.tls.key-store.jks.password=password + + quarkus.http.insecure-requests=disabled + """; + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest().setArchiveProducer( + () -> ShrinkWrap.create(JavaArchive.class) + .addPackage(HelloWorldTlsEndpoint.class.getPackage()) + .addPackage(GreeterGrpc.class.getPackage()) + .add(new StringAsset(configuration), "application.properties")); + + @GrpcClient("hello") + GreeterGrpc.GreeterBlockingStub blockingHelloService; + + @Test + void testClientTlsConfiguration() { + HelloReply reply = blockingHelloService.sayHello(HelloRequest.newBuilder().setName("neo").build()); + assertThat(reply.getMessage()).isEqualTo("Hello neo"); + } +} diff --git a/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/client/tls/TlsWithPemTrustStoreWithTlsRegistryTest.java b/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/client/tls/TlsWithPemTrustStoreWithTlsRegistryTest.java new file mode 100644 index 00000000000000..0aac854462fe31 --- /dev/null +++ b/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/client/tls/TlsWithPemTrustStoreWithTlsRegistryTest.java @@ -0,0 +1,47 @@ +package io.quarkus.grpc.client.tls; + +import static io.restassured.RestAssured.get; +import static org.assertj.core.api.Assertions.assertThat; + +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusUnitTest; +import me.escoffier.certs.Format; +import me.escoffier.certs.junit5.Certificate; +import me.escoffier.certs.junit5.Certificates; + +@Certificates(baseDir = "target/certs", certificates = { + @Certificate(name = "grpc", password = "password", formats = { Format.JKS, Format.PEM, Format.PKCS12 }, client = true) +}) +class TlsWithPemTrustStoreWithTlsRegistryTest { + + private static final String configuration = """ + quarkus.tls.trust-store.pem.certs=target/certs/grpc-client-ca.crt + + quarkus.grpc.clients.hello.host=localhost + quarkus.grpc.clients.hello.port=9001 + quarkus.grpc.clients.hello.plain-text=false + quarkus.grpc.clients.hello.use-quarkus-grpc-client=true + + # Legacy server + quarkus.grpc.server.ssl.certificate=target/certs/grpc.crt + quarkus.grpc.server.ssl.key=target/certs/grpc.key + """; + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest().setArchiveProducer( + () -> ShrinkWrap.create(JavaArchive.class) + .addPackage(HelloWorldTlsEndpoint.class.getPackage()) + .addPackage(io.grpc.examples.helloworld.GreeterGrpc.class.getPackage()) + .add(new StringAsset(configuration), "application.properties")); + + @Test + void testClientTlsConfiguration() { + String response = get("/hello/blocking/neo").asString(); + assertThat(response).isEqualTo("Hello neo"); + } +} diff --git a/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/server/tls/TlsWithHttpServerUsingJKSAndTlsRegistryTest.java b/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/server/tls/TlsWithHttpServerUsingJKSAndTlsRegistryTest.java new file mode 100644 index 00000000000000..67fc717e63d258 --- /dev/null +++ b/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/server/tls/TlsWithHttpServerUsingJKSAndTlsRegistryTest.java @@ -0,0 +1,76 @@ +package io.quarkus.grpc.server.tls; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.File; + +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.grpc.ManagedChannel; +import io.grpc.examples.helloworld.GreeterGrpc; +import io.grpc.examples.helloworld.HelloReply; +import io.grpc.examples.helloworld.HelloRequest; +import io.grpc.netty.GrpcSslContexts; +import io.grpc.netty.NettyChannelBuilder; +import io.netty.handler.ssl.SslContext; +import io.quarkus.grpc.server.services.HelloService; +import io.quarkus.test.QuarkusUnitTest; +import me.escoffier.certs.Format; +import me.escoffier.certs.junit5.Certificate; +import me.escoffier.certs.junit5.Certificates; + +@Certificates(baseDir = "target/certs", certificates = { + @Certificate(name = "grpc", password = "password", formats = { Format.JKS, Format.PEM, Format.PKCS12 }, client = true) +}) +public class TlsWithHttpServerUsingJKSAndTlsRegistryTest { + + static String configuration = """ + quarkus.grpc.server.use-separate-server=false + + quarkus.tls.key-store.jks.path=target/certs/grpc-keystore.jks + quarkus.tls.key-store.jks.password=password + quarkus.http.insecure-requests=disabled + """; + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest().setArchiveProducer( + () -> ShrinkWrap.create(JavaArchive.class) + .addPackage(GreeterGrpc.class.getPackage()) + .addClass(HelloService.class) + .add(new StringAsset(configuration), "application.properties")); + + protected ManagedChannel channel; + + @BeforeEach + public void init() throws Exception { + File certs = new File("target/certs/grpc-client-ca.crt"); + SslContext sslcontext = GrpcSslContexts.forClient() + .trustManager(certs) + .build(); + channel = NettyChannelBuilder.forAddress("localhost", 8444) + .sslContext(sslcontext) + .useTransportSecurity() + .build(); + } + + @AfterEach + public void shutdown() { + if (channel != null) { + channel.shutdownNow(); + } + } + + @Test + public void testInvokingGrpcServiceUsingTls() { + HelloReply reply = GreeterGrpc.newBlockingStub(channel) + .sayHello(HelloRequest.newBuilder().setName("neo").build()); + assertThat(reply.getMessage()).isEqualTo("Hello neo"); + } + +} diff --git a/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/server/tls/TlsWithHttpServerUsingP12AndTlsRegistryTest.java b/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/server/tls/TlsWithHttpServerUsingP12AndTlsRegistryTest.java new file mode 100644 index 00000000000000..3659a20016eab6 --- /dev/null +++ b/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/server/tls/TlsWithHttpServerUsingP12AndTlsRegistryTest.java @@ -0,0 +1,77 @@ +package io.quarkus.grpc.server.tls; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.File; + +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.grpc.ManagedChannel; +import io.grpc.examples.helloworld.GreeterGrpc; +import io.grpc.examples.helloworld.HelloReply; +import io.grpc.examples.helloworld.HelloRequest; +import io.grpc.netty.GrpcSslContexts; +import io.grpc.netty.NettyChannelBuilder; +import io.netty.handler.ssl.SslContext; +import io.quarkus.grpc.server.services.HelloService; +import io.quarkus.test.QuarkusUnitTest; +import me.escoffier.certs.Format; +import me.escoffier.certs.junit5.Certificate; +import me.escoffier.certs.junit5.Certificates; + +@Certificates(baseDir = "target/certs", certificates = { + @Certificate(name = "grpc", password = "password", formats = { Format.JKS, Format.PEM, Format.PKCS12 }, client = true) +}) +public class TlsWithHttpServerUsingP12AndTlsRegistryTest { + + static String configuration = """ + quarkus.grpc.server.use-separate-server=false + + quarkus.tls.key-store.p12.path=target/certs/grpc-keystore.p12 + quarkus.tls.key-store.p12.password=password + + quarkus.http.insecure-requests=disabled + """; + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest().setArchiveProducer( + () -> ShrinkWrap.create(JavaArchive.class) + .addPackage(GreeterGrpc.class.getPackage()) + .addClass(HelloService.class) + .add(new StringAsset(configuration), "application.properties")); + + protected ManagedChannel channel; + + @BeforeEach + public void init() throws Exception { + File certs = new File("target/certs/grpc-client-ca.crt"); + SslContext sslcontext = GrpcSslContexts.forClient() + .trustManager(certs) + .build(); + channel = NettyChannelBuilder.forAddress("localhost", 8444) + .sslContext(sslcontext) + .useTransportSecurity() + .build(); + } + + @AfterEach + public void shutdown() { + if (channel != null) { + channel.shutdownNow(); + } + } + + @Test + public void testInvokingGrpcServiceUsingTls() { + HelloReply reply = GreeterGrpc.newBlockingStub(channel) + .sayHello(HelloRequest.newBuilder().setName("neo").build()); + assertThat(reply.getMessage()).isEqualTo("Hello neo"); + } + +} diff --git a/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/server/tls/TlsWithHttpServerUsingPemAndTlsRegistryTest.java b/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/server/tls/TlsWithHttpServerUsingPemAndTlsRegistryTest.java new file mode 100644 index 00000000000000..9a019491fa7439 --- /dev/null +++ b/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/server/tls/TlsWithHttpServerUsingPemAndTlsRegistryTest.java @@ -0,0 +1,77 @@ +package io.quarkus.grpc.server.tls; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.File; + +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.grpc.ManagedChannel; +import io.grpc.examples.helloworld.GreeterGrpc; +import io.grpc.examples.helloworld.HelloReply; +import io.grpc.examples.helloworld.HelloRequest; +import io.grpc.netty.GrpcSslContexts; +import io.grpc.netty.NettyChannelBuilder; +import io.netty.handler.ssl.SslContext; +import io.quarkus.grpc.server.services.HelloService; +import io.quarkus.test.QuarkusUnitTest; +import me.escoffier.certs.Format; +import me.escoffier.certs.junit5.Certificate; +import me.escoffier.certs.junit5.Certificates; + +@Certificates(baseDir = "target/certs", certificates = { + @Certificate(name = "grpc", password = "password", formats = { Format.JKS, Format.PEM, Format.PKCS12 }, client = true) +}) +public class TlsWithHttpServerUsingPemAndTlsRegistryTest { + + static String configuration = """ + quarkus.grpc.server.use-separate-server=false + + quarkus.tls.key-store.pem.0.cert=target/certs/grpc.crt + quarkus.tls.key-store.pem.0.key=target/certs/grpc.key + + quarkus.http.insecure-requests=disabled + """; + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest().setArchiveProducer( + () -> ShrinkWrap.create(JavaArchive.class) + .addPackage(GreeterGrpc.class.getPackage()) + .addClass(HelloService.class) + .add(new StringAsset(configuration), "application.properties")); + + protected ManagedChannel channel; + + @BeforeEach + public void init() throws Exception { + File certs = new File("target/certs/grpc-client-ca.crt"); + SslContext sslcontext = GrpcSslContexts.forClient() + .trustManager(certs) + .build(); + channel = NettyChannelBuilder.forAddress("localhost", 8444) + .sslContext(sslcontext) + .useTransportSecurity() + .build(); + } + + @AfterEach + public void shutdown() { + if (channel != null) { + channel.shutdownNow(); + } + } + + @Test + public void testInvokingGrpcServiceUsingTls() { + HelloReply reply = GreeterGrpc.newBlockingStub(channel) + .sayHello(HelloRequest.newBuilder().setName("neo").build()); + assertThat(reply.getMessage()).isEqualTo("Hello neo"); + } + +} diff --git a/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/server/tls/TlsWithJksKeyStoreTest.java b/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/server/tls/TlsWithJksKeyStoreTest.java index 17097fff7bed92..0b7aa8de51aaa4 100644 --- a/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/server/tls/TlsWithJksKeyStoreTest.java +++ b/extensions/grpc/deployment/src/test/java/io/quarkus/grpc/server/tls/TlsWithJksKeyStoreTest.java @@ -12,7 +12,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; -import io.grpc.*; +import io.grpc.ManagedChannel; import io.grpc.examples.helloworld.GreeterGrpc; import io.grpc.examples.helloworld.HelloReply; import io.grpc.examples.helloworld.HelloRequest; diff --git a/extensions/grpc/runtime/src/main/java/io/quarkus/grpc/runtime/config/GrpcClientConfiguration.java b/extensions/grpc/runtime/src/main/java/io/quarkus/grpc/runtime/config/GrpcClientConfiguration.java index 80a9092fcb07b9..903af86158e1a3 100644 --- a/extensions/grpc/runtime/src/main/java/io/quarkus/grpc/runtime/config/GrpcClientConfiguration.java +++ b/extensions/grpc/runtime/src/main/java/io/quarkus/grpc/runtime/config/GrpcClientConfiguration.java @@ -64,6 +64,21 @@ public class GrpcClientConfiguration { */ public SslClientConfig ssl; + /** + * The name of the TLS configuration to use. + *

+ * If not set and the default TLS configuration is configured ({@code quarkus.tls.*}) then that will be used. + * If a name is configured, it uses the configuration from {@code quarkus.tls..*} + * If a name is configured, but no TLS configuration is found with that name then an error will be thrown. + *

+ * If no TLS configuration is set, and {@code quarkus.tls.*} is not configured, then, + * `quarkus.grpc.clients.$client-name.tls` will be used. + *

+ * Important: This is only supported when using the Quarkus (Vert.x-based) gRPC client. + */ + @ConfigItem + public Optional tlsConfigurationName; + /** * The TLS config. * Only use this if you want to use the Quarkus gRPC client. diff --git a/extensions/grpc/runtime/src/main/java/io/quarkus/grpc/runtime/supports/Channels.java b/extensions/grpc/runtime/src/main/java/io/quarkus/grpc/runtime/supports/Channels.java index aafa71bdbb8807..248592ca448ba3 100644 --- a/extensions/grpc/runtime/src/main/java/io/quarkus/grpc/runtime/supports/Channels.java +++ b/extensions/grpc/runtime/src/main/java/io/quarkus/grpc/runtime/supports/Channels.java @@ -67,6 +67,8 @@ import io.quarkus.grpc.spi.GrpcBuilderProvider; import io.quarkus.runtime.LaunchMode; import io.quarkus.runtime.util.ClassPathUtils; +import io.quarkus.tls.TlsConfiguration; +import io.quarkus.tls.TlsConfigurationRegistry; import io.smallrye.mutiny.infrastructure.Infrastructure; import io.smallrye.stork.Stork; import io.vertx.core.Vertx; @@ -74,6 +76,7 @@ import io.vertx.core.http.HttpClientOptions; import io.vertx.core.net.PemKeyCertOptions; import io.vertx.core.net.PemTrustOptions; +import io.vertx.core.net.SSLOptions; import io.vertx.core.net.SocketAddress; import io.vertx.grpc.client.GrpcClientChannel; @@ -262,12 +265,56 @@ public static Channel createChannel(String name, Set perClientIntercepto options.setHttp2ClearTextUpgrade(false); // this fixes i30379 if (!plainText) { + TlsConfigurationRegistry registry = Arc.container().select(TlsConfigurationRegistry.class).get(); + // always set ssl + alpn for plain-text=false options.setSsl(true); options.setUseAlpn(true); - TlsClientConfig tls = config.tls; - if (tls.enabled) { + TlsConfiguration configuration = null; + if (config.tlsConfigurationName.isPresent()) { + Optional maybeConfiguration = registry.get(config.tlsConfigurationName.get()); + if (!maybeConfiguration.isPresent()) { + throw new IllegalStateException("Unable to find the TLS configuration " + + config.tlsConfigurationName.get() + " for the gRPC client " + name + "."); + } + configuration = maybeConfiguration.get(); + } else if (registry.getDefault().isPresent() && (registry.getDefault().get().getTrustStoreOptions() != null + || registry.getDefault().get().isTrustAll())) { + configuration = registry.getDefault().get(); + } + + if (configuration != null) { + if (configuration.getTrustStoreOptions() != null) { + options.setTrustOptions(configuration.getTrustStoreOptions()); + } + if (configuration.getKeyStoreOptions() != null) { + options.setKeyCertOptions(configuration.getKeyStoreOptions()); + } + + options.setForceSni(configuration.usesSni()); + if (configuration.isTrustAll()) { + options.setTrustAll(true); + } + if (configuration.getHostnameVerificationAlgorithm().isPresent() + && configuration.getHostnameVerificationAlgorithm().get().equals("NONE")) { + // Only disable hostname verification if the algorithm is explicitly set to NONE + options.setVerifyHost(false); + } + + SSLOptions sslOptions = configuration.getSSLOptions(); + options.setSslHandshakeTimeout(sslOptions.getSslHandshakeTimeout()); + options.setSslHandshakeTimeoutUnit(sslOptions.getSslHandshakeTimeoutUnit()); + for (String suite : sslOptions.getEnabledCipherSuites()) { + options.addEnabledCipherSuite(suite); + } + for (Buffer buffer : sslOptions.getCrlValues()) { + options.addCrlValue(buffer); + } + options.setEnabledSecureTransportProtocols(sslOptions.getEnabledSecureTransportProtocols()); + + } else if (config.tls.enabled) { + TlsClientConfig tls = config.tls; options.setSsl(true).setTrustAll(tls.trustAll); configurePemTrustOptions(options, tls.trustCertificatePem); @@ -281,11 +328,9 @@ public static Channel createChannel(String name, Set perClientIntercepto } else { if (config.ssl.trustStore.isPresent()) { Optional trustStorePath = config.ssl.trustStore; - if (trustStorePath.isPresent()) { - PemTrustOptions to = new PemTrustOptions(); - to.addCertValue(bufferFor(trustStorePath.get(), "trust store")); - options.setTrustOptions(to); - } + PemTrustOptions to = new PemTrustOptions(); + to.addCertValue(bufferFor(trustStorePath.get(), "trust store")); + options.setTrustOptions(to); Optional certificatePath = config.ssl.certificate; Optional keyPath = config.ssl.key; if (certificatePath.isPresent() && keyPath.isPresent()) { diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/options/HttpServerOptionsUtils.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/options/HttpServerOptionsUtils.java index e0270aa328fd94..5d9994b9c0780b 100644 --- a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/options/HttpServerOptionsUtils.java +++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/options/HttpServerOptionsUtils.java @@ -231,7 +231,6 @@ public static void applyTlsConfigurationToHttpServerOptions(TlsConfiguration buc serverOptions.addCrlValue(buffer); } if (!other.isUseAlpn()) { - System.out.println("disabling alpn."); serverOptions.setUseAlpn(false); } serverOptions.setEnabledSecureTransportProtocols(other.getEnabledSecureTransportProtocols());