diff --git a/docs/src/main/asciidoc/tls-registry-reference.adoc b/docs/src/main/asciidoc/tls-registry-reference.adoc index 955917ba94063..a279f1f3988d7 100644 --- a/docs/src/main/asciidoc/tls-registry-reference.adoc +++ b/docs/src/main/asciidoc/tls-registry-reference.adoc @@ -14,17 +14,18 @@ include::_attributes.adoc[] :extensions: io.quarkus:quarkus-tls-registry The TLS registry is a Quarkus extension centralizing the TLS configuration for the application. -It allows to define the TLS configuration in a single place and to reference it from multiple places in the application. +You can use the TLS registry to define the configuration in one place and reference it from multiple places in the application. -The TLS extension should be automatically added to your project as soon as you use a compatible extension. -For example, if your application uses Quarkus REST, gRPC or reactive routes, the TLS registry is automatically added to your project. +The TLS extension is automatically added to your project when you use a compatible extension. +For example, if your application uses Quarkus REST, gRPC, or reactive routes, the TLS registry is automatically added to your project. == Using TLS registry -To configure a TLS connection, and more specifically the key stores and trust stores, you use the `quarkus.tls.*` properties. +To configure a TLS connection, including key and trust stores, use the `quarkus.tls.*` properties. -Configuration directly under `quarkus.tls` is the default configuration that will be used by all the TLS connections in the application. -However, you can also have specific configurations for specific connections by using the `quarkus.tls..*` properties. +The configuration model always contains a default (unnamed) TLS configuration that is configured by properties directly under `quarkus.tls.*`. +In addition, it allows you to define separate named configurations; these use `quarkus.tls..*` properties. +However, by using the `quarkus.tls..*` properties, you can also have specific configurations for specific connections. === Configure the HTTP server to use https:// @@ -37,7 +38,7 @@ quarkus.tls.key-store.pem.0.key=server.key quarkus.http.insecure-requests=disabled # Reject HTTP requests ---- -So you a `p12` (PKCS12) key store, use the following configuration: +With a `p12` (PKCS12) keystore, use the following configuration: [source,properties] ---- @@ -71,13 +72,13 @@ quarkus.grpc.clients.hello.use-quarkus-grpc-client=true === Configuring mTLS -To configure mTLS, you need to configure both the server and the client. -Both will receive a key store and a trust store: +To configure mTLS, set up both the server and the client. +Each will require a keystore and a truststore: -- the server key store contains the server certificate and private key -- the client key store contains the client certificate and private key -- the server trust store contains the client certificate (to authenticate the client) -- the client trust store contains the server certificate (to authenticate the server) +- the server keystore contains the server certificate and private key +- the client keystore contains the client certificate and private key +- the server truststore contains the client certificate (to authenticate the client) +- the client truststore contains the server certificate (to authenticate the server) [source,properties] ---- @@ -105,8 +106,7 @@ quarkus.grpc.server.plain-text=false [#referencing-a-tls-configuration] == Referencing a TLS configuration -Once you have configured a _named_ configuration using `quarkus.tls.`, you need to reference it. -This is done using the `tls-configuration-name` property: +After you have configured a _named_ configuration by using `quarkus.tls.`, reference it by using the `tls-configuration-name` property: [source,properties] ---- @@ -124,17 +124,18 @@ The configuration depends on the format (`pem`, `p12`, `jks`...). There are other important properties too. This section details the various properties you can use to configure TLS. + === Key stores Key stores are used to store the private key and the certificate. -They are mainly used on the server-side, but can also be used on the client-side when mTLS is used. +They are mainly used on the server side but can also be used on the client side when mTLS is used. ==== PEM key stores -PEM key stores are composed of a list of pair of two files: the certificate and the private key. -The certificate file is a `.crt` or `.pem` file, and the private key file is often a `.key` file. +Privacy Enhanced Mail (PEM) keystores are composed of a list of pairs of two files: the certificate and the private key. +The certificate file is a `.crt` or `.pem` file; the private key file is often a `.key` file. -To configure a PEM key store, use the following properties: +To configure a PEM keystore, use the following properties: [source,properties] ---- @@ -144,35 +145,39 @@ quarkus.tls.key-store.pem.b.cert=my-second-cert.crt quarkus.tls.key-store.pem.b.key=my-second-key.key ---- -In general, you will only need one pair of certificate and private key. -The certificate may contain multiple certificates (a chain), but there should be one private key. +In general, you only need a single pair consisting of a certificate and a private key. +Even if the certificate is part of a certificate chain, it includes only one private key corresponding to the end-entity certificate. -When multiple pairs are configured, the selection is done using SNI (Server Name Indication). -The client will send the server name it wants to connect to, and the server will select the appropriate pair of certificate and private key. -Make sure xref:./tls-registry-reference.adoc#sni[SNI] is enabled on both the client and server to use this feature. +When multiple pairs are configured, the selection is based on Server Name Indication (SNI). +The client sends the server name it wants to connect to, and the server selects the appropriate pair of certificates and private keys. +To use this feature, ensure xref:./tls-registry-reference.adoc#sni[SNI] is enabled on both the client and server. -IMPORTANT: When configuring multiple key/cert pairs, the order is following the lexicographical order of the name (`a` and `b` in the previous snippet). So, the first pair is the one with the lowest lexicographical order. You can define the order by using the `quarkus.tls.key-store.pem.order` property, for example: `quarkus.tls.key-store.pem.order=b,c,a`. This is important when using SNI, as the first pair is the default one. +IMPORTANT: When configuring multiple key or certificate pairs, the order follows the lexicographical order of their names, as demonstrated with `a` and `b` in the previous example. +The pair with the lowest lexicographical order is considered the first. +You can define the order by using the `quarkus.tls.key-store.pem.order` property. +For example, `quarkus.tls.key-store.pem.order=b,c,a`. +This setting is crucial when using SNI, where the first specified pair is used as the default. ==== PKCS12 key stores PKCS12 key stores are a single file containing the certificate and the private key. -To configure a PKCS12 key store, use the following properties: +To configure a PKCS12 keystore, use the following properties: [source,properties] ---- quarkus.tls.key-store.p12.path=server-keystore.p12 quarkus.tls.key-store.p12.password=secret ---- -`.p12` files are password-protected, so you need to provide the password to open the key store. -Also, they can include more than one certificate and private key. -In this case, you can: +`.p12` files are password-protected, so you need to provide the password to open the keystore. +These files can include more than one certificate and private key. -- either provide the alias of the certificate and private key you want to use -- or use SNI to select the appropriate certificate and private key (all keys must use the same password) +If this is the case, take either of the following actions: +* Provide the alias of the certificate and the private key you want to use. ++ To configure the alias, use the following properties: - ++ [source,properties] ---- quarkus.tls.key-store.p12.path=server-keystore.p12 @@ -181,11 +186,15 @@ quarkus.tls.key-store.p12.alias=my-alias quarkus.tls.key-store.p12.alias-password=my-alias-password ---- +* Alternatively, use SNI to select the appropriate certificate and private key. +Note that all keys must use the same password. + + ==== JKS key stores JKS key stores are a single file containing the certificate and the private key. Note that the JKS format should be avoided as it is less secure than PKCS12. -To configure a JKS key store, use the following properties: +To configure a JKS keystore, use the following properties: [source,properties] ---- @@ -193,15 +202,14 @@ quarkus.tls.key-store.jks.path=server-keystore.jks quarkus.tls.key-store.jks.password=secret ---- -`.jks` files are password-protected, so you need to provide the password to open the key store. +`.jks` files are password-protected, so you need to provide the password to open the keystore. Also, they can include more than one certificate and private key. -In this case, you can: - -- either provide the alias of the certificate and private key you want to use -- or use SNI to select the appropriate certificate and private key (all keys must use the same password) +If this is the case: +* Provide the alias of the certificate and the private key you want to use. ++ To configure the alias, use the following properties: - ++ [source,properties] ---- quarkus.tls.key-store.jks.path=server-keystore.jks @@ -210,10 +218,15 @@ quarkus.tls.key-store.jks.alias=my-alias quarkus.tls.key-store.jks.alias-password=my-alias-password ---- +* Alternatively, use SNI to select the appropriate certificate and private key. +Note that all keys must use the same password. + + + [#sni] ==== SNI -Server Name Indication (SNI) is a TLS extension that allows a client to specify the hostname it is attempting to connect to during the TLS handshake. +Server Name Indication (SNI) is a TLS extension allowing a client to specify the hostname it attempts to connect to during the TLS handshake. It enables a server to present different TLS certificates for multiple domains on a single IP address, facilitating secure communication for virtual hosting scenarios. To enable SNI, use the following property: @@ -223,17 +236,20 @@ To enable SNI, use the following property: quarkus.tls.key-store.sni=true # Disabled by default ---- -With this setting enabled, the client indicate the server name during the TLS handshake, allowing the server to select the right certificate: +With this setting enabled, the client indicates the server name during the TLS handshake, allowing the server to select the appropriate certificate: + +* When configuring the keystore with PEM files, multiple certificate (CRT) and key files must be provided. CRT is a common file extension for X.509 certificate files, typically in PEM (Privacy-Enhanced Mail) format. These files contain the public certificate. -- When configuring the keystore with PEM files, multiple CRT/Key must be given. -- When configuring the keystore with a JKS or a P12 file, it selects one alias based on the SNI hostname. In this case, all the keystore password and alias password must be the same. Do not set the `alias` property in this case. +* When configuring the keystore with a JKS or P12 file, the server selects the appropriate certificate based on the SNI (Server Name Indication) hostname provided by the client during the TLS handshake. +The server matches the SNI hostname with the common name (CN) or subject alternative names (SAN) configured in the certificates stored in the keystore. +All keystore and alias passwords must be identical, and there is no need to set the alias property. ==== Credential providers -Instead of passing the key store password and alias password in the configuration, you can use a credential provider. +You can use a credential provider instead of passing the keystore password and alias password in the configuration. -A credential provider offers a way to retrieve the key store password and alias password. -Note that the credential provider is only used if the password / alias password are not set in the configuration. +A credential provider offers a way to retrieve the keystore and alias password. +Note that the credential provider is only used if the password or alias password is not set in the configuration. To configure a credential provider, use the following properties: @@ -245,7 +261,7 @@ quarkus.tls.key-store.credentials-provider.name=my-credentials # The name of the bean providing the credential provider (optional, using the default credential provider if not set) quarkus.tls.key-store.credentials-provider.bean-name=my-credentials-provider -# The key used to retrieve the key store password, `password` by default +# The key used to retrieve the keystore password, `password` by default quarkus.tls.key-store.credentials-provider.password-key=password # The key used to retrieve the alias password, `alias-password` by default @@ -257,14 +273,15 @@ IMPORTANT: The credential provider can only be used with PKCS12 and JKS key stor === Trust stores Trust stores are used to store the certificates of the trusted parties. -They are generally used on the client-side, and on the server-side when mTLS is used. +In regular TLS, the client uses a truststore to authenticate the server. +With mutual TLS (mTLS), both the server and the client use truststores to authenticate each other. ==== PEM trust stores PEM trust stores are composed of a list of `.crt` or `.pem` files. Each of them contains a certificate. -To configure a PEM trust store, use the following properties: +To configure a PEM truststore, use the following properties: [source,properties] ---- @@ -274,9 +291,9 @@ quarkus.tls.trust-store.pem.certs=ca.crt,ca2.pem ==== PKCS12 trust stores PKCS12 trust stores are a single file containing the certificates. -When multiple certificates are included, you can use the alias to select the appropriate certificate. +You can use the alias to select the appropriate certificate when multiple certificates are included. -To configure a PKCS12 trust store, use the following properties: +To configure a PKCS12 truststore, use the following properties: [source,properties] ---- @@ -285,16 +302,16 @@ quarkus.tls.trust-store.p12.password=password quarkus.tls.trust-store.p12.alias=my-alias ---- -`.p12` files are password-protected, so you need to provide the password to open the trust store. -However, unlike for key stores, the alias does not require a password (because it's the public certificate and not a private key). +`.p12` files are password-protected, so you need to provide the password to open the truststore. +However, unlike key stores, the alias does not require a password because it contains a public certificate, not a private key. ==== JKS trust stores -JKS trust stores are a single file containing the certificates. -When multiple certificates are included, you can use the alias to select the appropriate certificate. -Note that the JKS format should be avoided as it is less secure than PKCS12. +JKS truststores are single files containing multiple certificates. +You can use the alias to select the appropriate certificate when multiple certificates are present. +However, avoid using the JKS format as it is less secure than PKCS12. -To configure a JKS trust store, use the following properties: +To configure a JKS truststore, use the following properties: [source,properties] ---- @@ -303,15 +320,14 @@ quarkus.tls.trust-store.jks.password=password quarkus.tls.trust-store.jks.alias=my-alias ---- -`.jks` files are password-protected, so you need to provide the password to open the trust store. -However, unlike for key stores, the alias does not require a password (because it's the public certificate and not a private key). +`.jks` files are password-protected, so you need to provide the password to open the truststore. +However, unlike keystores, the alias does not require a password because it contains a public certificate, not a private key. ==== Credential providers -Instead of passing the trust store password in the configuration, you can use a credential provider. - -A credential provider offers a way to retrieve passwords and other credentials. -Note that the credential provider is only used if the password is not set in the configuration. +Instead of passing the truststore password in the configuration, you can use a credential provider. +A credential provider allows you to retrieve passwords and other credentials. +Note that the credential provider is used only if the password is not set in the configuration. To configure a credential provider, use the following properties: @@ -323,7 +339,7 @@ quarkus.tls.trust-store.credentials-provider.name=my-credentials # The name of the bean providing the credential provider (optional, using the default credential provider if not set) quarkus.tls.trust-store.credentials-provider.bean-name=my-credentials-provider -# The key used to retrieve the trust store password, `password` by default +# The key used to retrieve the truststore password, `password` by default quarkus.tls.trust-store.credentials-provider.password-key=password ---- @@ -333,14 +349,14 @@ IMPORTANT: The credential provider can only be used with PKCS12 and JKS trust st While key stores and trust stores are the most important properties, there are other properties you can use to configure TLS. -NOTE: while the following examples use the _default_ configuration, you can use the _named_ configuration by prefixing the properties with the name of the configuration. +NOTE: While the following examples use the _default_ configuration, you can use the _named_ configuration by prefixing the properties with the configuration's name. ==== Cipher suites -The cipher suites are the list of ciphers that can be used during the TLS handshake. -You can configure the ordered list of enabled cipher suites. +Cipher suites are the list of ciphers that you can use during the TLS handshake. +You can configure the ordered list of enabled cipher suites. If not configured, a reasonable default is selected from the built-in ciphers. -However, when configured, it takes precedence over the default suite defined by the SSL engine in use. +However, when specified, your configuration precedes the default suite defined by the SSL engine in use. To configure the cipher suites, use the following property: @@ -352,10 +368,11 @@ quarkus.tls.cipher-suites=TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384 ==== TLS protocol versions The TLS protocol versions are the list of protocols that can be used during the TLS handshake. -You can configure the ordered list of enabled TLS protocols. -If not configured , it defaults to `TLSv1.3`, `TLSv1.2`. +Enabled TLS protocol versions are specified as an ordered list separated by commas. +The relevant configuration property is `quarkus.tls.protocols` (or `quarkus.tls..protocols` for named TLS configurations). +It defaults to `TLSv1.3, TLSv1.2` if not configured. -Are supported: `TLSv1`, `TLSv1.1`, `TLSv1.2`, `TLSv1.3`. +The supported values are: `TLSv1`, `TLSv1.1`, `TLSv1.2`, `TLSv1.3`. To only enable `TLSv1.3`, configure the following property: @@ -367,7 +384,7 @@ quarkus.tls.protocols=TLSv1.3 ==== Handshake timeout When a TLS connection is established, the handshake phase is the first step. -During this phase, the client and server exchange information to establish the connection, typically the cipher suite, the TLS protocol version, the certification validation and so on. +During this phase, the client and server exchange information to establish the connection, typically the cipher suite, the TLS protocol version, the certification validation, and so on. To configure the timeout for the handshake phase, use the following property: @@ -378,10 +395,10 @@ quarkus.tls.handshake-timeout=10S # Default. ==== ALPN -Application-Layer Protocol Negotiation (ALPN) is a TLS extension that allows the client and server during the TLS handshake to negotiate which protocol they will use for communication. -ALPN enables more efficient communication by allowing the client to indicate its preferred application protocol to the server before the TLS connection is established. +Application-Layer Protocol Negotiation (ALPN) is a TLS extension that allows the client and server to negotiate which protocol they will use for communication during the TLS handshake. +ALPN enables more efficient communication by allowing the client to indicate its preferred application protocol to the server before establishing the TLS connection. -This helps in scenarios such as HTTP/2 where multiple protocols may be available, allowing for faster protocol selection. +This helps in scenarios like HTTP/2, where multiple protocols might be available, allowing for faster protocol selection. ALPN is enabled by default. To disable it, use the following property: @@ -391,19 +408,19 @@ To disable it, use the following property: quarkus.tls.alpn=false ---- + ==== Certificate Revocation List (CRL) -A Certificate Revocation List (CRL) is a list of certificates that have been revoked by the issuing Certificate Authority (CA) before their scheduled expiration date. -When a certificate is compromised, no longer needed, or deemed invalid for any reason, the CA adds it to the CRL to inform relying parties not to trust the certificate anymore. +A Certificate Revocation List (CRL) is a list of certificates the issuing Certificate Authority (CA) revoked before their scheduled expiration date. +When a certificate is compromised, no longer needed, or deemed invalid, the CA adds it to the CRL to inform relying parties not to trust it anymore. You can configure the CRL with the list of certificate files you do not trust anymore. -Two formats are allowed: DER and PKCS#7 (also known as P7B). +Two formats are allowed: DER and PKCS#7 (P7B). * When using the DER format, you must pass DER-encoded CRLs. -* When using the PKCS#7 format, you must pass PKCS#7 `SignedData` object, with the only significant field being `crls`. +* When using the PKCS#7 format, you must pass the PKCS#7 `SignedData` object, with the only significant field being `crls`. To configure the CRL, use the following property: - [source,properties] ---- quarkus.tls.certificate-revocation-list=ca.crl, ca2.crl @@ -411,13 +428,20 @@ quarkus.tls.certificate-revocation-list=ca.crl, ca2.crl ==== Trusting all certificates and hostname verification -IMPORTANT: These two properties should not be used in production. +[IMPORTANT] +==== +These two properties should not be used in production. + +You can configure your TLS connection to trust all certificates and disable the hostname verification. + +Note that these are two different processes: -You can configure your TLS connection to trust all certificates and to disable the hostname verification. -These are two different steps: +* Trusting all certificates ignores the certificate validation, so all certificates are trusted. +This method is useful for testing with self-signed certificates, but it should not be used in production. -- trusting all certificates ignores the certificate validation, so all certificates are trusted. It is useful for testing with self-signed certificates, but should not be used in production. -- hostname verification is the process of verifying the server's identity. It is useful to prevent man-in-the-middle attacks. It often defaults to `HTTPS` or `LDAPS`. +* Hostname verification is the process of verifying the server's identity. +It is useful to prevent man-in-the-middle attacks and often defaults to `HTTPS` or `LDAPS`. +==== To trust all certificates, use the following property: @@ -441,9 +465,10 @@ include::{generated-dir}/config/quarkus-tls-registry.adoc[opts=optional, levelof == The registry API -While extensions will automatically use the TLS registry, you can also use the registry API to access the TLS configuration programmatically. +While extensions automatically use the TLS registry, you can also access the TLS configuration programmatically through the registry API. -To access the TLS configuration, inject the `TlsConfigurationRegistry` bean and gets the TLS configuration by name (or the default one): +To access the TLS configuration, inject the `TlsConfigurationRegistry` bean. +You can retrieve a named TLS configuration by calling `get("")` or the default configuration by calling `getDefault()`. [source,java] ---- @@ -475,7 +500,7 @@ TlsCertificateBuildItem item = new TlsCertificateBuildItem("named", new MyCertificateSupplier()); ---- -The certificate supplier is a runtime object that is generally retrieved using a recorder method. +The certificate supplier is a runtime object generally retrieved by using a recorder method. Here is an example of a certificate supplier: [source,java] @@ -511,15 +536,15 @@ public class MyCertificateSupplier implements Supplier { == Startup checks -When the application starts, the TLS registry performs some checks to ensure the configuration is correct: +When the application starts, the TLS registry performs several checks to ensure the configuration is correct: -- the key stores and trust stores are accessible -- the aliases are available and accessible in the key stores and trust stores -- the certificates are valid -- the cipher suites and protocols are valid -- the CRLs are valid +* Key stores and trust stores are accessible. +* Aliases are available and accessible in the key stores and trust stores. +* Certificates are valid. +* Cipher suites and protocols are valid. +* Certificate Revocation Lists (CRLs) are valid. -If any of these checks fail, the application will fail to start. +If any of these checks fail, the application will not start. [#reloading-certificates] == Reloading certificates @@ -561,9 +586,9 @@ These APIs provide a way to implement custom certificate reloading. === Periodic reloading -The TLS registry does include a built-in mechanism for periodically checking the file system for changes and reloading the certificates. -You can configure periodic reloading of certificates using properties. -The `reload-period` property specifies the interval at which certificates are reloaded, and it will emit a `CertificateReloadedEvent`. +The TLS registry includes a built-in mechanism for periodically checking the file system for changes and reloading certificates. +You can configure periodic certificate reloading by using properties. +The `reload-period` property specifies the interval for reloading certificates and will emit a `CertificateReloadedEvent` each time certificates are reloaded. [source, properties] ---- @@ -582,7 +607,7 @@ quarkus.tls.http.key-store.pem.0.key=tls.key ---- Remember that the impacted server and client may need to listen to the `CertificateReloadedEvent` to apply the new certificates. -This is automatically done for the Quarkus HTTP server (including the management interface if enabled). +This is automatically done for the Quarkus HTTP server, including the management interface if it is enabled. == Using Kubernetes secrets or cert-manager @@ -591,7 +616,7 @@ When running in Kubernetes, you can use Kubernetes secrets to store the key stor === Using Kubernetes secrets To use Kubernetes secrets, you need to create a secret with the key stores and trust stores. -Let's take the following secret as an example: +Consider the following secret as an example: [source, yaml] ---- @@ -605,7 +630,7 @@ metadata: type: kubernetes.io/tls ---- -The easiest way to uses these certificates is to mount the secret as a volume in the pod: +The easiest way to use these certificates is to mount the secret as a volume in the pod: [source, yaml] ---- @@ -672,14 +697,14 @@ You can combine this with the periodic reloading to automatically reload the cer === Using cert-manager -When running in Kubernetes, you can use cert-manager to automatically generate and renew certificates. -Cert-manager will produce a secret with the key stores and trust stores. -So, configuring the TLS registry is the same as when using Kubernetes secrets. -The generated secret uses the following files: +When running in Kubernetes, you can use cert-manager to generate and renew certificates automatically. +Cert-manager produces a secret containing the keystores and truststores. +Configuring the TLS registry is the same as when using Kubernetes secrets. +The generated secret includes the following files: -- `tls.crt` for the certificate -- `tls.key` for the private key -- `ca.crt` for the CA certificate (if needed) +* `tls.crt` for the certificate +* `tls.key` for the private key +* `ca.crt` for the CA certificate (if needed) To handle the renewal, you can use the periodic reloading mechanism: @@ -696,14 +721,14 @@ To handle the renewal, you can use the periodic reloading mechanism: %prod.quarkus.http.insecure-requests=disabled ---- -== Utilizing OpenShift serving certificates +== Working with OpenShift serving certificates -When running your application in OpenShift, you can leverage the https://docs.openshift.com/container-platform/4.16/security/certificates/service-serving-certificate.html[OpenShift serving certificates] to automatically generate and renew TLS certificates. -The Quarkus TLS registry can use these certificates and Certificate Authority (CA) files to handle HTTPS traffic securely and to validate certificates. +When running your application in OpenShift, you can leverage the https://docs.openshift.com/container-platform/4.16/security/certificates/service-serving-certificate.html[OpenShift serving certificates] to generate and renew TLS certificates automatically. +The Quarkus TLS registry can use these certificates and Certificate Authority (CA) files to handle HTTPS traffic and validate certificates securely. === Acquiring a certificate -To have OpenShift generate a certificate, you need to annotate an existing _Service_ object. +To have OpenShift generate a certificate, annotate an existing _Service_ object. The generated certificate will be stored in a secret, which you can then mount in your pod. Consider the following _Service_ example: @@ -733,16 +758,20 @@ spec: type: ClusterIP ---- -The annotation `service.beta.openshift.io/serving-cert-secret-name` instructs OpenShift to generate a certificate and store it in a secret named `my-tls-secret`. If your service is already running, you can add this annotation with the following command: +The annotation `service.beta.openshift.io/serving-cert-secret-name` instructs OpenShift to generate a certificate and store it in a secret named `my-tls-secret`. +To use the stored certificate: + +. Add this annotation to your already running service: ++ [source, shell] ---- oc annotate service hero-service \ service.beta.openshift.io/serving-cert-secret-name=my-tls-secret ---- -Next, mount the secret in your pod by updating your _Deployment_ configuration to include a volume and mount the secret: - +. Mount the secret as a volume in your pod by updating your _Deployment_ configuration: ++ [source, yaml] ---- apiVersion: apps/v1 @@ -791,25 +820,26 @@ spec: protocol: TCP ---- <1> Define a volume to mount the secret. Use the same name as the secret declared above. -<2> Set up the key store with the paths to the certificate and private key. This can be configured using environment variables or configuration files. Here, we use environment variables. OpenShift serving certificates always create the `tls.crt` and `tls.key` files. +<2> Set up the keystore with the paths to the certificate and private key. This can be configured using environment variables or configuration files. Here, we use environment variables. OpenShift serving certificates always create the `tls.crt` and `tls.key` files. <3> Mount the secret in the container. Ensure the path matches the one used in the configuration (here `/etc/tls`). <4> Configure the port to serve HTTPS. ++ +NOTE: By setting the `quarkus.tls.key-store.pem.acme.cert` and `quarkus.tls.key-store.pem.acme.key` variables (or their environment variable variant as done above), the TLS registry will use the certificate and private key from the secret. +This configures the default keystore for the Quarkus HTTP server, allowing it to use the certificate. +For information about using this certificate in a named configuration, see <>. -By setting the `quarkus.tls.key-store.pem.acme.cert` and `quarkus.tls.key-store.pem.acme.key` variables (or their environment variable variant as done above), the TLS registry will use the certificate and private key from the secret. This configures the default key store for the Quarkus HTTP server, allowing it to use the certificate. -For using this certificate in a named configuration, refer to <>. - -Deploy your application, and it will utilize the certificate generated by OpenShift, making the service available over HTTPS. +. Deploy your application to use the certificate generated by OpenShift. +This will make the service available over HTTPS. === Trusting the Certificate Authority (CA) -Now that your service uses a certificate issued by OpenShift, you might need to configure your client applications to trust this certificate. -To accomplish this, create a _ConfigMap_ that holds the CA certificate and mount it in the application's pod. - -In this example, we'll use a Quarkus REST client, but the same principle applies to any client. +Now that your service uses a certificate issued by OpenShift, configure your client applications to trust this certificate. +To do so, create a ConfigMap that holds the CA certificate, and then configure the pod to mount it. -First, create a _ConfigMap_ for the CA certificate. -Start by defining an _empty_ ConfigMap, which will be populated with the CA certificate: +As demonstrated below with a Quarkus REST client, the same principle applies to any client. +. Start by defining an _empty_ ConfigMap, which will be populated with the CA certificate: ++ [source, yaml] ---- apiVersion: v1 @@ -819,13 +849,13 @@ metadata: annotations: service.beta.openshift.io/inject-cabundle: "true" ---- - ++ The `service.beta.openshift.io/inject-cabundle` annotation is used to inject the CA certificate into the ConfigMap. Note that the ConfigMap initially has no data — it is empty. During its processing, OpenShift injects the CA certificate into the ConfigMap in the `service-ca.crt` file. -Next, mount the ConfigMap by adding a volume and mount it in your _Deployment_ configuration: - +. Mount the ConfigMap by adding a volume and mounting it in your _Deployment_ configuration: ++ [source, yaml] ---- apiVersion: apps/v1 @@ -865,8 +895,10 @@ spec: <1> Mount the ConfigMap in the container. Ensure the path matches the one used in the configuration (here `/deployments/tls`). <2> Define a volume to mount the ConfigMap and reference the ConfigMap that receives the CA certificate. -Finally, configure the REST client to use this CA certificate. Consider the following REST client interface: - +. Configure the REST client to use this CA certificate. ++ +Consider the following REST client interface: ++ [source, java] ---- package org.acme; @@ -887,19 +919,21 @@ public interface HeroClient { } ---- -<1> Configure the base URI and the configuration key. The name must be in the format `..svc`, otherwise the certificate will not be trusted. Ensure to also configure the `configKey`. - -Next, configure the REST client to trust the CA certificate: +<1> Configure the base URI and the configuration key. +The name must be in the format `..svc`; otherwise, the certificate will not be trusted. +Ensure that the `configKey` is also configured. +. Configure the REST client to trust the CA certificate generated by OpenShift: ++ [source, properties] ---- quarkus.rest-client.hero.tls-configuration-name=my-service-tls # <1> quarkus.tls.my-service-tls.trust-store.pem.certs=/deployments/tls/service-ca.crt # <2> ---- <1> Configure the `hero` REST client with the TLS configuration named `my-service-tls`. -<2> Set up the `my-service-tls` TLS configuration, specifically the trust store with the CA certificate. Ensure the path matches the one used in the Kubernetes _Deployment_ configuration. The file is always named `service-ca.crt`. - -Now, the REST client is configured to trust the certificate generated by OpenShift. +<2> Set up the `my-service-tls` TLS configuration, specifically the truststore with the CA certificate. +Ensure the path matches the one used in the Kubernetes _Deployment_ configuration. +The file is always named `service-ca.crt`. === Certificate renewal @@ -933,74 +967,76 @@ Commands: available. ---- -In most cases, you generate the Quarkus Development CA once, and then generate certificates signed by this CA. +In most cases, you generate the Quarkus Development CA once and then generate certificates signed by this CA. The Quarkus Development CA is a Certificate Authority that can be used to sign certificates locally. It is only valid for development purposes and only trusted on the local machine. -The generated CA is located in `$HOME/.quarkus/quarkus-dev-root-ca.pem`, and installed in the system trust store. +The generated CA is located in `$HOME/.quarkus/quarkus-dev-root-ca.pem`, and installed in the system truststore. -=== CA, signed vs. self-signed certificates +=== Understanding self-signed versus CA-signed certificates When developing with TLS, you can use two types of certificates: - - a self-signed certificate: the certificate is signed by the same entity that uses it. It is not trusted by default. It's generally what we use when we don't have a CA, or don't want to dig too much into TLS. This is not a production setup, and may be used only for development. -- a signed certificate: the certificate is signed by a Certificate Authority (CA). The CA is a trusted entity that signs the certificate. The certificate is trusted by default. This is what we use in production. +* **Self-signed certificate**: The certificate is signed by the same entity that uses it. +It is not trusted by default. +This type of certificate is typically used when a Certificate Authority (CA) is unavailable or you want a simple setup. +It is not suitable for production and should only be used for development. + +* **CA-signed certificate**: The certificate is signed by a Certificate CA, a trusted entity. +This certificate is trusted by default and is the standard choice for production environments. -We could use self-signed certificate when running application locally, but it's not always convenient. -Typically, browsers will not trust the certificate, and you will have to import it manually. -`curl`, `wget`, `httpie` and other tools will also not trust the certificate. +While you can use a self-signed certificate for local development, it has limitations. +Browsers and tools like `curl`, `wget`, and `httpie` typically do not trust self-signed certificates, requiring manual import. -To avoid this, we can use a development CA to sign the certificates, and install it into the system trust store. -Thus, every certificate signed by this CA will be trusted by the system. +To avoid this issue, you can use a development CA to sign certificates and install the CA in the system truststore. +This ensures that the system trusts all certificates signed by the CA. -Quarkus makes it easy to generate a development CA and certificates signed by this CA. +Quarkus simplifies the generation of a development CA and the certificates that are signed by this CA. === Generate a development CA The development CA is a Certificate Authority that can be used to sign certificates locally. -Note that the generated CA is only valid for development purposes, and only trusted on the local machine. - -To generate a development CA, use the following command: +Note that the generated CA is only valid for development purposes and can only be trusted on the local machine. +. Generate a development CA: ++ [source, shell] ---- -quarkus tls generate-ca-certificate --install --renew --truststore +quarkus tls generate-ca-certificate --install --renew --truststore <1> <2> <3> ---- - -`--install` installs the CA in the system trust store. -Windows, Mac and Linux (Fedora and Ubuntu) are supported. -However, depending on your browser, you may need to import the generated CA manually. -Refer to the browser documentation for more information. +<1> `--install` installs the CA in the system truststore. +Windows, Mac, and Linux (Fedora and Ubuntu) are supported. +However, depending on your browser, you might need to import the generated CA manually. +Refer to your browser's documentation for more information. The generated CA is located in `$HOME/.quarkus/quarkus-dev-root-ca.pem`. +<2> `--renew` renews the CA if it already exists. +When this option is used, the private key is changed, so you need to regenerate the certificates signed by the CA. +If the CA expires, it will automatically renew without requiring the `--renew` option. +<3> `--truststore` also generates a PKCS12 truststore containing the CA certificate. -WARNING: When installing the certificate, your system may ask for your password to install the certificate in the system trust store, or ask for confirmation in a dialog (on Windows). +WARNING: When installing the certificate, your system might ask for your password to install the certificate in the system truststore or ask for confirmation in a dialog on Windows. -IMPORTANT: On Windows, makes sure you run from an elevated terminal (run as administrator) to install the CA in the system trust store. - -`--renew` renews the CA if it already exists. -When this option is used, you need to re-generate the certificates that were signed by the CA, as the private key is changed. -Note that if the CA expires, it will automatically be renewed (without passing `--renew`). - -`--truststore` also generates a PKCS12 trust store containing the CA certificate. +IMPORTANT: On Windows, run as administrator from an elevated terminal to install the CA in the system truststore. === Generate a trusted (signed) certificate -Once you have installed the Quarkus Development CA, you can generate a trusted certificate. -It will be signed by the Quarkus Development CA, and so trusted by your system. +After installing the Quarkus Development CA, you can generate a trusted certificate. +This certificate will be signed by the Quarkus Development CA and trusted by your system. [source, shell] ---- quarkus tls generate-certificate --name my-cert ---- -This generates a certificate signed by the Quarkus Development CA, and so if properly installed / imported, will be trusted by your system. +This command generates a certificate signed by the Quarkus Development CA, which your system will trust if properly installed or imported. The certificate is stored in `./.certs/`. Two files are generated: -- `$NAME-keystore.p12` - contains the private key and the certificate. It's password protected. -- `$NAME-truststore.p12` - contains the CA certificate, that you can used as trust store (for test, for instance). +* `$NAME-keystore.p12`: Contains the private key and the certificate. +It is password-protected. +* `$NAME-truststore.p12`: Contains the CA certificate, which you can use as a truststore, for example, for testing. -More options are available: +Additional options are available: [source, shell] ---- @@ -1018,7 +1054,7 @@ Generate a TLS certificate with the Quarkus Dev CA if available. -r, --renew Whether existing certificates will need to be replaced ---- -When generating the certificate, a `.env` file is also generated making the Quarkus dev mode aware of these certificates. +A `.env` file is also generated when generating the certificate, making the Quarkus dev mode aware of these certificates. So, then, if you run your application in dev mode, it will use these certificates: [source, shell] @@ -1028,7 +1064,7 @@ So, then, if you run your application in dev mode, it will use these certificate INFO [io.quarkus] (Quarkus Main Thread) demo 1.0.0-SNAPSHOT on JVM (powered by Quarkus 999-SNAPSHOT) started in 1.286s. Listening on: http://localhost:8080 and https://localhost:8443 ---- -Now, you can open the Dev UI using HTTPS: `https://localhost:8443/q/dev`, or issue a request using `curl`: +Now, you can open the Dev UI using HTTPS: `https://localhost:8443/q/dev` or issue a request using `curl`: [source, shell] ---- @@ -1036,7 +1072,7 @@ curl https://localhost:8443/hello Hello from Quarkus REST% ---- -IMPORTANT: If the Quarkus Development CA is not installed, a self-signed certificate is generated. +IMPORTANT: A self-signed certificate is generated if the Quarkus Development CA is not installed. === Generating a self-signed certificate @@ -1048,7 +1084,7 @@ Even if the Quarkus Development CA is installed, you can generate a self-signed quarkus tls generate-certificate --name my-cert --self-signed ---- -This generates a self-signed certificate, not signed by the Quarkus Development CA. +This generates a self-signed certificate that the Quarkus Development CA does not sign. === Uninstalling the Quarkus Development CA @@ -1113,19 +1149,20 @@ sudo security -v remove-trusted-cert -d /Users/clement/.quarkus/quarkus-dev-root https://letsencrypt.org[Let's Encrypt] is a free, automated certificate authority provided by https://www.abetterinternet.org/[Internet Security Research Group]. -Let's Encrypt uses https://datatracker.ietf.org/doc/html/rfc8555[Automated certificate management environment (ACME) protocol] to support an automatic certificate issuance and renewal. Please read https://letsencrypt.org/docs/[Let's Encrypt documentation] to learn more about Let's Encrypt and ACME. +Let's Encrypt uses https://datatracker.ietf.org/doc/html/rfc8555[Automated certificate management environment (ACME) protocol] to support automatic certificate issuance and renewal. +To learn more about Let's Encrypt and ACME, see https://letsencrypt.org/docs/[Let's Encrypt documentation]. -TLS registry project provides a CLI ACME client to issue and renew Let's Encrypt certificates. -Your application uses TLS registry to resolve ACME protocol challenges. +The TLS registry extension allows a CLI ACME client to issue and renew Let's Encrypt certificates. +Your application uses this TLS registry extension to resolve ACME protocol challenges. Follow the steps below to have your Quarkus application prepared and automatically updated with new and renewed Let's Encrypt certificates. [[lets-encrypt-prerequisites]] === Prerequisites -Make sure that a fully resolvable DNS domain name is available and can be used to access your application. -This domain name is used for creating a Let's Encrypt account, and supporting Let's Encrypt ACME challenges to prove that you own this domain. -You can use https://ngrok.com/[Ngrok] to start experimenting with the Quarkus Let's Encrypt ACME feature, see <> section below for more information. +Ensure that a fully resolvable DNS domain name is available that you can use to access your application. +You can use this domain name to create a Let's Encrypt account and support Let's Encrypt ACME challenges to prove that you own this domain. +You can use https://ngrok.com/[ngrok] to start experimenting with the Quarkus Let's Encrypt ACME feature; for more information, see the <> section below. Your Quarkus HTTPS application must use a _build-time_ property to enable a Let's Encrypt ACME challenge route: @@ -1134,8 +1171,8 @@ Your Quarkus HTTPS application must use a _build-time_ property to enable a Let' quarkus.tls.lets-encrypt.enabled=true ---- -The TLS registry can manage the challenge process from either the main HTTP interface or from the management interface. -Using a management interface is **strongly** recommended to let Quarkus deal with ACME challenge configuration separately to the main application's deployment and security requirements: +The TLS registry can manage the challenge process from either the main HTTP interface or the management interface. +Using a management interface is **strongly** recommended to let Quarkus deal with ACME challenge configuration separately from the main application's deployment and security requirements: [source, properties] ---- @@ -1143,13 +1180,13 @@ quarkus.tls.lets-encrypt.enabled=true quarkus.management.enabled=true ---- -The challenge itself is served from the primary HTTP interface (the one accessible from your DNS domain name). +The challenge is served from the primary HTTP interface (accessible from your DNS domain name). IMPORTANT: Do not start your application yet. === Application preparation -Before you request a Let's Encrypt certificate, you must run TLS registry Let's Encrypt CLI `prepare` command to prepare your application: +Before you request a Let's Encrypt certificate, you must run the TLS registry Let's Encrypt CLI `prepare` command to prepare your application: [source, shell] ---- @@ -1160,9 +1197,9 @@ IMPORTANT: Make sure you run a prepare command in the root directory of your app The `prepare` command does the following: -- Creates a `.letsencrypt` folder in your application's root directory -- Creates a self-signed domain certificate and private key for your application configured in the previous <> step to be able to start and accept HTTPS requests. -- Create a `.env` configuration file in your application's root directory configure the application to use the self-signed domain certificate and private key (until we get the Let's Encrypt certificate). +* Creates a `.letsencrypt` folder in your application's root directory +* Creates a self-signed domain certificate and private key for your application configured in the previous <> step to be able to start and accept HTTPS requests +* Creates a `.env` configuration file in your application's root directory and configures the application to use the self-signed domain certificate and private key (until we get the Let's Encrypt certificate) The following snippet shows an example of the generated `.env` file: @@ -1172,7 +1209,7 @@ quarkus.tls.key-store.pem.acme.cert=.letsencrypt/lets-encrypt.crt quarkus.tls.key-store.pem.acme.key=.letsencrypt/lets-encrypt.key ---- -NOTE: The `.env` file does not contain the `quarkus.tls.lets-encrypt.enabled` and `quarkus.management.enabled` properties as they are build-time properties requiring a rebuild of the application. +NOTE: The `.env` file does not contain the `quarkus.tls.lets-encrypt.enabled` and `quarkus.management.enabled` properties as they are build-time properties that require a rebuild of the application. === Start your application @@ -1183,7 +1220,7 @@ You can start your application: java -jar quarkus-run.jar ---- -Access your application endpoint using `https://your-domain-name:8443/`, for example, `https://your-domain-name:8443/hello`, accept a self-signed certificate in the browser. +Access your application endpoint by using `https://your-domain-name:8443/`; for example, `https://your-domain-name:8443/hello`, and accept a self-signed certificate in the browser. Next, keep the application running and request your first Let's Encrypt certificate. @@ -1201,17 +1238,23 @@ quarkus tls lets-encrypt issue-certificate \ ---- <1> Set your domain name. <2> Provide your contact email address that Let's Encrypt can use to contact you in case of any issues with your Let's Encrypt account. -<3> Set your application management URL which can be used to handle ACME challenges. Use `https://localhost:8443/` if you chose not to enable a management router in the <> step. +<3> Set your application management URL, which you can use to handle ACME challenges. +Use `https://localhost:8443/` if you choose not to enable a management router in the <> step. -During this command, the TLS registry CLI checks if the application is prepared to serve the challenge, creates and records Let's Encrypt account information, issues a Let's Encrypt certificate request, and interacts with the Quarkus application to resolve ACME challenges. +During the processing of the `issue-certificate` command, the TLS registry CLI performs the following tasks: + +* Checks if the application is prepared to serve the challenge. +* Creates and records Let's Encrypt account information. +* Issues a Let's Encrypt certificate request. +* Interacts with the Quarkus application to resolve ACME challenges. Once the Let's Encrypt certificate chain and private key have been successfully acquired, they are converted to PEM format and copied to your application's `.letsencrypt` folder. -The TLS registry is informed that a new certificate and private key are ready, and reloads them automatically. +The TLS registry is informed that a new certificate and private key are ready and reloads them automatically. Now, access your application's endpoint using `https://your-domain-name:8443/` again. -Confirm in the browser that your domain certificate is now signed by the Let's Encrypt certificate authority. +Confirm in the browser that the Let's Encrypt certificate authority is now signing your domain certificate. -Note that currently, a Let's Encrypt account is created implicitly by the `issue-certificate` command to make it easy for users to get started with the ACME protocol. +Note that currently, the `issue-certificate` command implicitly creates a Let's Encrypt account to make it easy for users to get started with the ACME protocol. Support for the Let's Encrypt account management will evolve further. [[lets-encrypt-renew-certificate]] @@ -1231,37 +1274,36 @@ quarkus tls lets-encrypt renew-certificate \ During this command, TLS registry CLI reads a Let's Encrypt account information recorded during the <> step, issues a Let's Encrypt certificate request, and communicates with a Quarkus application to have ACME challenges resolved. Once the Let's Encrypt certificate chain and private key have been successfully renewed, they are converted to PEM format and copied to your application's `.letsencrypt` folder. -TLS registry is informed that a new certificate and private key are ready and it reloads them automatically. +The TLS registry is notified when a new certificate and private key are ready, and it automatically reloads them. [[lets-encrypt-ngrok]] -=== Use NGrok for testing +=== Use ngrok for testing -https://ngrok.com/[Ngrok] can be used to provide a secure HTTPS tunnel to your application running on localhost, and make it easy to test HTTPS based applications. +https://ngrok.com/[ngrok] can be used to provide a secure HTTPS tunnel to your application running on localhost, and make it easy to test HTTPS based applications. -Using Ngrok provides an easiest option to get started with the Quarkus Let's Encrypt ACME feature. +ngrok provides a simplified way of getting started with the Quarkus Let's Encrypt ACME feature. -The first thing you have to do with Ngrok is to ask it to reserve a domain. -You can use https://github.com/quarkiverse/quarkus-ngrok[Quarkiverse NGrok] in devmode, or have it reserved directly in the NGrok dashboard. +The first thing you have to do with ngrok is to ask it to reserve a domain. +You can use https://github.com/quarkiverse/quarkus-ngrok[Quarkiverse ngrok] in dev mode or reserve it directly in the ngrok dashboard. -Unfortunately, you can't use your NGrok domain to test the Quarkus Let's Encrypt ACME feature immediately. -This is due to the fact that Ngrok is itself using Let's Encrypt and intercepts ACME challenges which are meant to be handled by the Quarkus application instead. +Unfortunately, you cannot use your ngrok domain to test the Quarkus Let's Encrypt ACME feature immediately. +This is because ngrok itself uses Let's Encrypt and intercepts ACME challenges that are meant to be handled by the Quarkus application instead. -Therefore, you need to remove an NGrok Let's Encrypt certificate policy from your NGrok domain: +Therefore, remove the ngrok Let's Encrypt certificate policy from your ngrok domain: [source, shell] ---- ngrok api --api-key reserved-domains delete-certificate-management-policy ---- -`YOUR-RESERVED-DOMAIN-ID` is your reserved domain's id which starts from `rd_`, you can find it in the https://dashboard.ngrok.com/cloud-edge/domains[NGrok dashboard domains section]. +`YOUR-RESERVED-DOMAIN-ID` is your reserved domain's id which starts from `rd_`, you can find it in the https://dashboard.ngrok.com/cloud-edge/domains[ngrok dashboard domains section]. -Now, NGrok will forward ACME challenges over HTTP only, therefore you need to start Ngrok like this: +Now, because ngrok only forwards ACME challenges over HTTP, start ngrok as follows: [source, shell] ---- -ngrok http --domain 8080 --scheme http +ngrok http --domain 8080 --scheme http <1> ---- - -where `8080` is the localhost HTTP port that your application is listening on. +<1> `8080` is the localhost HTTP port your application is listening on. You can now test the Quarkus Let's Encrypt ACME feature from your local machine.