quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.4k stars 2.57k forks source link

Improve TLS support in the reactive rest client #22293

Open cescoffier opened 2 years ago

cescoffier commented 2 years ago

Description

Currently, the TLS configuration is limited to JKS (which is not the Java default anymore). We should add support for PEM and P12 for key stores and trust stores. SNI and alias support (including alias password) should also be added.

Implementation ideas

All these parameters are supported by the underlying HTTP client.

quarkus-bot[bot] commented 2 years ago

/cc @michalszynkiewicz

TomasHofman commented 2 years ago

I'm checking this out to find out what current support actually is like.

The first impression from checking the all-config guide is that there is not much consistency in naming related properties. There are all kinds of notations - keystore.location vs key-store.file vs just key-store.

Some extensions have different set of properties for PEM files and for binary key stores (by binary key stores I mean JKS and P12), some extensions use the same properties to support both PEM and binary key stores, and some only support binary key stores.

There is a number of extensions that use some kind of key store or trust store:

I mainly investigated HTTP server and rest clients for now.

HTTP server

Supports JKS, P12: yes Supports PEM: yes

JKS and P12 can be configured as such:

# key store:
quarkus.http.ssl.certificate.key-store-file=META-INF/resources/server.keystore.p12
quarkus.http.ssl.certificate.key-store-file-type=PKCS12 # or JKS
quarkus.http.ssl.certificate.key-store-password=password

# trust store
quarkus.http.ssl.client-auth=REQUIRED
quarkus.http.ssl.certificate.trust-store-file=META-INF/resources/server.truststore.p12
quarkus.http.ssl.certificate.trust-store-file-type=PKCS12 # or JKS
quarkus.http.ssl.certificate.trust-store-password=password

The PEM files can be used instead of key store, and are configured with different properties:

quarkus.http.ssl.certificate.files=META-INF/resources/server.crt
quarkus.http.ssl.certificate.key-files=META-INF/resources/server.key

It doesn't seem to be possible to configure PEM file as a trust store.

REST clients (classic and reactive)

Supports JKS, P12: yes Supports PEM: no

# truststore config
org.acme.client.mtls.GreetingService/mp-rest/trustStore=classpath:/META-INF/resources/client.truststore.p12
org.acme.client.mtls.GreetingService/mp-rest/trustStoreType=PKCS12 # or JKS
org.acme.client.mtls.GreetingService/mp-rest/trustStorePassword=password

# keystore config
org.acme.client.mtls.GreetingService/mp-rest/keyStore=classpath:/META-INF/resources/client.keystore.p12
org.acme.client.mtls.GreetingService/mp-rest/keyStoreType=PKCS12 # or JKS
org.acme.client.mtls.GreetingService/mp-rest/keyStorePassword=password

OIDC & OIDC client

Supports JKS, P12: yes Supports PEM: yes, but only for "credential key"?

# PEM
quarkus.oidc.credentials.jwt.key-file
# keystore
quarkus.oidc.credentials.jwt.key-store-file
quarkus.oidc.credentials.jwt.key-store-password

quarkus.oidc.tls.key-store-file
quarkus.oidc.tls.key-store-file-type
quarkus.oidc.tls.key-store-password

quarkus.oidc.tls.trust-store-file
quarkus.oidc.tls.trust-store-file-type
quarkus.oidc.tls.trust-store-password

Spring Cloud config client

Supports JKS, P12: probably both Supports PEM: ?

quarkus.spring-cloud-config.trust-store
quarkus.spring-cloud-config.trust-store-password
quarkus.spring-cloud-config.key-store
quarkus.spring-cloud-config.key-store-password

GraphQL client

Supports JKS, P12: yes Supports PEM: ?

quarkus.smallrye-graphql-client."clients".trust-store
quarkus.smallrye-graphql-client."clients".trust-store-password
quarkus.smallrye-graphql-client."clients".trust-store-type
quarkus.smallrye-graphql-client."clients".key-store
quarkus.smallrye-graphql-client."clients".key-store-password
quarkus.smallrye-graphql-client."clients".key-store-type

gRPC server

Supports JKS, P12: yes Supports PEM: yes

# PEM:
quarkus.grpc.server.ssl.certificate
quarkus.grpc.server.ssl.key

# keystores:
quarkus.grpc.server.ssl.key-store
quarkus.grpc.server.ssl.key-store-type
quarkus.grpc.server.ssl.key-store-password

quarkus.grpc.server.ssl.trust-store
quarkus.grpc.server.ssl.trust-store-type
quarkus.grpc.server.ssl.trust-store-password

gRPC client

Supports JKS, P12: ? Supports PEM: yes

# PEM:
quarkus.grpc.clients."client-name".ssl.certificate
quarkus.grpc.clients."client-name".ssl.key

quarkus.grpc.clients."client-name".ssl.trust-store

Kafka Streams

Supports JKS, P12: yes Supports PEM: ?

quarkus.kafka-streams.ssl.truststore.type
quarkus.kafka-streams.ssl.truststore.location
quarkus.kafka-streams.ssl.truststore.password
quarkus.kafka-streams.ssl.truststore.certificates

quarkus.kafka-streams.ssl.keystore.type
quarkus.kafka-streams.ssl.keystore.location
quarkus.kafka-streams.ssl.keystore.password
quarkus.kafka-streams.ssl.keystore.key
quarkus.kafka-streams.ssl.keystore.certificate-chain

Mailer (trust store support)

Supports JKS, P12: yes Supports PEM: yes

quarkus.mailer.truststore.password
quarkus.mailer.truststore.paths # single KS or multiple PEM files
quarkus.mailer.truststore.type # if not set, determined by filename suffix
TomasHofman commented 2 years ago

What I would like to do is add PEM support to REST client extensions, I'm not sure about details yet.

cescoffier commented 2 years ago

Some part of this is also addressed in https://github.com/quarkusio/quarkus/issues/17038. Unfortunately, I'm not making any success on that feature (for almost a year).

the main idea is to have a "registry of certs" which can be queried and populated by the various extension. That would provide a single configuration model. Of course, PEM, JKS, and PCK12 would have built-in support.

kdubb commented 2 years ago

@cescoffier Have you looked at my old PR #22094. It was for Dynamic mTLS but if you skip to the "Ideas" section of my comments you can see, I think this is essentially what you're suggesting here.

cescoffier commented 2 years ago

@kdubb After trying to find time to implement this a few times, I ended up with a global certs registry that extensions can populate and query to retrieve the certs. It would enable extensions to provide and validate certs (like Let's encrypt). I still believe it's the most flexible approach, as we need to handle lots of different cases/providers and formats.

Because lots of things in Quarkus are Vert.x based, it is also essential that we provide the Vert.x structures when we can.

Recent requirements also show that certs must be in memory and read-only once from the FS, with potentially some re-sync happening periodically (I don't know how we will handle this for servers (for clients it's easy)).