-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Commit
Previously, utilizing JKS or P12 keystores and truststores in gRPC clients was restricted due to limitations inherent in legacy gRPC-Java-based clients. However, this commit expands upon the existing configuration by introducing support for JKS and P12 in the Quarkus (Vert.x based) gRPC client. This commit also extends the tests for both clients and servers using various certificate formats and configuration (like mTLS)
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,232 @@ | ||
//// | ||
This guide is maintained in the main Quarkus repository | ||
and pull requests should be submitted there: | ||
https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc | ||
//// | ||
= gRPC reference guide | ||
include::_attributes.adoc[] | ||
:categories: Serialization | ||
:diataxis-type: Reference | ||
:summary: Learn how to configure gRPC server and clients. | ||
:topics: grpc | ||
:extensions: io.quarkus:quarkus-grpc | ||
|
||
|
||
== Using gRPC with Quarkus | ||
|
||
If you need to implement a gRPC service or consume it, you need the `quarkus-grpc` extension. | ||
Check warning on line 17 in docs/src/main/asciidoc/grpc-reference.adoc
|
||
It handles both sides. | ||
|
||
=== Using Maven | ||
|
||
To enable gRPC, add the following dependency to your project: | ||
|
||
[source,xml,subs=attributes+] | ||
---- | ||
<dependency> | ||
<groupId>io.quarkus</groupId> | ||
<artifactId>quarkus-grpc</artifactId> | ||
</dependency> | ||
---- | ||
|
||
Next, ensure that the `generate-code` phase is enabled in the Quarkus Maven plugin: | ||
|
||
[source,xml,subs=attributes+] | ||
---- | ||
<plugin> | ||
<groupId>${quarkus.platform.group-id}</groupId> | ||
<artifactId>quarkus-maven-plugin</artifactId> | ||
<version>${quarkus.platform.version}</version> | ||
<extensions>true</extensions> | ||
<executions> | ||
<execution> | ||
<goals> | ||
<goal>build</goal> | ||
<goal>generate-code</goal> | ||
<goal>generate-code-tests</goal> | ||
</goals> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
---- | ||
|
||
=== Using Gradle | ||
|
||
For Gradle, add the following dependency to your project: | ||
|
||
[source,gradle,subs=attributes+] | ||
---- | ||
implementation 'io.quarkus:quarkus-grpc' | ||
---- | ||
|
||
== Selecting a gRPC server | ||
|
||
Quarkus provides two implementation of the gRPC server: gRPC Java (based on Netty) and Vert.x. | ||
Both of them support TLS. | ||
|
||
One of the advantage of the Vert.x based server is the ability to use a single server to handle HTTP requests and gRPC requests. This is useful if you want to expose both REST and gRPC endpoints on the same port. This is not possible with the gRPC Java server (using a separate server). | ||
|
||
To select the gRPC server implementation, set the `quarkus.grpc.server.use-separate-server` property in your `application.properties` file: | ||
|
||
[source,properties,subs=attributes+] | ||
---- | ||
quarkus.grpc.server.use-separate-server=false # Use the Vert.x based server | ||
---- | ||
|
||
We recommend the usage of the Vert.x based gRPC server, as it is more flexible and better integrated in the Quarkus ecosystem. | ||
Check warning on line 76 in docs/src/main/asciidoc/grpc-reference.adoc
|
||
|
||
IMPORTANT: You cannot use both servers at the same time. | ||
|
||
== Selecting gRPC clients | ||
|
||
As for the server, Quarkus proposes two alternatives for the gRPC clients: gRPC Java and Vert.x. | ||
Unlike for the server, you can select the transport for each client: | ||
|
||
[source,properties,subs=attributes+] | ||
---- | ||
quarkus.grpc.clients.hello.use-quarkus-grpc-client=true # Use client using the Vert.x based transport | ||
---- | ||
Check warning on line 88 in docs/src/main/asciidoc/grpc-reference.adoc
|
||
|
||
While it's not the default, we recommend using the Vert.x based client, as it is more flexible and better integrated in the Quarkus ecosystem. | ||
Check warning on line 90 in docs/src/main/asciidoc/grpc-reference.adoc
|
||
It does not change the stubs you can use, as they are generated by the gRPC framework. | ||
However, it changes the way the client communicates with the server. | ||
|
||
== Configuring TLS for gRPC services | ||
|
||
=== With the Vert.x based server | ||
|
||
If you use the Vert.x based server, you can configure TLS by setting the following properties in your `application.properties` file: | ||
|
||
[source,properties,subs=attributes+] | ||
---- | ||
quarkus.grpc.server.use-separate-server=false | ||
quarkus.grpc.server.plain-text=false | ||
quarkus.http.ssl.certificate.key-store-file=target/certs/grpc-tls-keystore.p12 | ||
quarkus.http.ssl.certificate.key-store-password=***** | ||
quarkus.http.insecure-requests=disabled | ||
---- | ||
|
||
You can use `key-store-file` and `key-store-password` to configure the keystore file and its password when using JKS or P12. For PEM, use the `certificate` and `key` properties: | ||
Check warning on line 110 in docs/src/main/asciidoc/grpc-reference.adoc
|
||
|
||
[source,properties,subs=attributes+] | ||
---- | ||
quarkus.grpc.server.use-separate-server=false | ||
quarkus.grpc.server.plain-text=false | ||
quarkus.http.ssl.certificate.files=target/certs/grpc-tls.crt | ||
quarkus.http.ssl.certificate.key-files=target/certs/grpc-tls.key | ||
quarkus.http.insecure-requests=disabled | ||
---- | ||
|
||
NOTE: The `quarkus.http.insecure-requests` property is used to disable insecure requests. | ||
|
||
NOTE: When TLS is enabled, it covers both HTTP and gRPC traffic. | ||
|
||
=== With the gRPC Java server | ||
|
||
If you use the gRPC Java server, you can configure TLS by setting the following properties in your `application.properties` file: | ||
|
||
[source,properties,subs=attributes+] | ||
---- | ||
quarkus.grpc.server.ssl.certificate=tls/server.pem | ||
quarkus.grpc.server.ssl.key=tls/server.key | ||
quarkus.grpc.server.plain-text=false | ||
---- | ||
|
||
This server only supports `PEM` format for the certificate and the key. | ||
|
||
== Configuring TLS for gRPC clients | ||
|
||
When using the Vert.x based client, you can configure TLS by setting the following properties in your `application.properties` file: | ||
Check warning on line 142 in docs/src/main/asciidoc/grpc-reference.adoc
|
||
|
||
[source,properties,subs=attributes+] | ||
---- | ||
quarkus.grpc.clients.hello.plain-text=false # Use TLS | ||
quarkus.grpc.clients.hello.use-quarkus-grpc-client=true # Use client using the Vert.x based transport | ||
quarkus.grpc.clients.hello.tls.enabled=true | ||
quarkus.grpc.clients.hello.tls.trust-certificate-p12.path=target/certs/grpc-tls-truststore.jks | ||
quarkus.grpc.clients.hello.tls.trust-certificate-p12.password=**** | ||
---- | ||
|
||
If you use JKS trust-store, use the following configuration: | ||
|
||
[source,properties,subs=attributes+] | ||
---- | ||
quarkus.grpc.clients.hello.plain-text=false # Use TLS | ||
quarkus.grpc.clients.hello.use-quarkus-grpc-client=true # Use client using the Vert.x based transport | ||
quarkus.grpc.clients.hello.tls.enabled=true | ||
quarkus.grpc.clients.hello.tls.trust-certificate-jks.path=target/certs/grpc-tls-truststore.jks | ||
quarkus.grpc.clients.hello.tls.trust-certificate-jks.password=**** | ||
---- | ||
|
||
If you use PEM certificates as trust-store, use the following configuration: | ||
Check warning on line 164 in docs/src/main/asciidoc/grpc-reference.adoc
|
||
|
||
[source,properties,subs=attributes+] | ||
---- | ||
quarkus.grpc.clients.hello.plain-text=false # Use TLS | ||
quarkus.grpc.clients.hello.use-quarkus-grpc-client=true # Use client using the Vert.x based transport | ||
quarkus.grpc.clients.hello.tls.enabled=true | ||
quarkus.grpc.clients.hello.tls.trust-certificate-pem.certs=target/certs/grpc-client-ca.crt | ||
---- | ||
|
||
When using the gRPC Java client, you can configure TLS by setting the following properties in your `application.properties` file: | ||
Check warning on line 174 in docs/src/main/asciidoc/grpc-reference.adoc
|
||
|
||
[source,properties,subs=attributes+] | ||
---- | ||
quarkus.grpc.clients.hello.ssl.trust-store=target/certs/grpc-client-tls-ca.crt | ||
---- | ||
|
||
gRPC Java client only support the `PEM` format for the trust-store. | ||
|
||
== Configuring mTLS | ||
|
||
When using the Vert.x based server and Vert.x-based client, you can configure mTLS by setting the following properties in your `application.properties` file: | ||
|
||
[source,properties,subs=attributes+] | ||
---- | ||
# Server side: | ||
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.certificate.key-store-file=target/certs/grpc-keystore.jks | ||
quarkus.http.ssl.certificate.key-store-password=**** | ||
quarkus.http.ssl.certificate.trust-store-file=target/certs/grpc-server-truststore.jks | ||
quarkus.http.ssl.certificate.trust-store-password=**** | ||
quarkus.http.ssl.client-auth=REQUIRED # Force the client to authenticate, aka mTLS | ||
quarkus.http.insecure-requests=disabled | ||
# Client side: | ||
quarkus.grpc.clients.hello.plain-text=false | ||
quarkus.grpc.clients.hello.tls.trust-certificate-jks.path=target/certs/grpc-client-truststore.jks | ||
quarkus.grpc.clients.hello.tls.trust-certificate-jks.password=**** | ||
quarkus.grpc.clients.hello.tls.key-certificate-jks.path=target/certs/grpc-client-keystore.jks | ||
quarkus.grpc.clients.hello.tls.key-certificate-jks.password=**** | ||
quarkus.grpc.clients.hello.tls.enabled=true | ||
quarkus.grpc.clients.hello.use-quarkus-grpc-client=true | ||
---- | ||
|
||
If you use P12 format for the trust-store and the key-certificate, use the following configuration: | ||
|
||
[source,properties,subs=attributes+] | ||
---- | ||
# Server side | ||
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.certificate.key-store-file=target/certs/grpc-keystore.p12 | ||
quarkus.http.ssl.certificate.key-store-password=**** | ||
quarkus.http.ssl.certificate.trust-store-file=target/certs/grpc-server-truststore.p12 | ||
quarkus.http.ssl.certificate.trust-store-password=**** | ||
quarkus.http.ssl.client-auth=REQUIRED # Force the client to authenticate, aka mTLS | ||
quarkus.http.insecure-requests=disabled | ||
# Client side | ||
quarkus.grpc.clients.hello.plain-text=false | ||
quarkus.grpc.clients.hello.tls.trust-certificate-p12.path=target/certs/grpc-client-truststore.p12 | ||
quarkus.grpc.clients.hello.tls.trust-certificate-p12.password=**** | ||
quarkus.grpc.clients.hello.tls.key-certificate-p12.path=target/certs/grpc-client-keystore.p12 | ||
quarkus.grpc.clients.hello.tls.key-certificate-p12.password=**** | ||
quarkus.grpc.clients.hello.tls.enabled=true | ||
quarkus.grpc.clients.hello.use-quarkus-grpc-client=true | ||
---- | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
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 MtlsWithJKSTrustStoreWithHttpServerTest { | ||
|
||
private static final String configuration = """ | ||
quarkus.grpc.clients.hello.plain-text=false | ||
quarkus.grpc.clients.hello.tls.trust-certificate-jks.path=target/certs/grpc-client-truststore.jks | ||
quarkus.grpc.clients.hello.tls.trust-certificate-jks.password=password | ||
quarkus.grpc.clients.hello.tls.key-certificate-jks.path=target/certs/grpc-client-keystore.jks | ||
quarkus.grpc.clients.hello.tls.key-certificate-jks.password=password | ||
quarkus.grpc.clients.hello.tls.enabled=true | ||
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.certificate.key-store-file=target/certs/grpc-keystore.jks | ||
quarkus.http.ssl.certificate.key-store-password=password | ||
quarkus.http.ssl.certificate.trust-store-file=target/certs/grpc-server-truststore.jks | ||
quarkus.http.ssl.certificate.trust-store-password=password | ||
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"); | ||
} | ||
} |