From afa427d1a976a51e00033160b25c58246b555e44 Mon Sep 17 00:00:00 2001 From: Gilvan Filho Date: Sat, 28 Mar 2026 19:04:54 -0300 Subject: [PATCH 1/4] documents the operator's support for TLS re-encryption. closes #20128 Signed-off-by: Gilvan Filho --- docs/guides/operator/basic-deployment.adoc | 155 +++++++++++++++++---- 1 file changed, 131 insertions(+), 24 deletions(-) diff --git a/docs/guides/operator/basic-deployment.adoc b/docs/guides/operator/basic-deployment.adoc index f14afc609183..7287f38de553 100644 --- a/docs/guides/operator/basic-deployment.adoc +++ b/docs/guides/operator/basic-deployment.adoc @@ -219,17 +219,71 @@ spec: NOTE: The operator annotates the Ingress to match expectations for TLS passthrough or TLS termination on OpenShift with the default IngressClass. See below for more on TLS termination. -==== Proxy modes with the basic Ingress +==== TLS Termination with default Ingress -The operator annotates the Ingress to match expectations for TLS termination or passthrough on OpenShift with the default IngressClass. -For this reason TLS reencryption is not yet considered supported by basic Ingress, but you may be able to specify the `tlsSecret` on both the `http` and `ingress` specs as a starting point. -You should double check the requirements of your IngressClass and platform to see if additional Ingress or Service annotations are needed in your desired scenario. +When using the operator-provided ingress (`spec.ingress.enabled: true`) there are a lot of Keycloak CR options (like service and ingress labels and annotations) which allows you to customize your ingress behaviour. This section show how to achive below TLS Termination when using Openshift: -TLS passthrough is shown in the preceding `example-kc` example. It is enabled when you associate a `tlsSecret` with the `http` configuration and leave Ingress enabled without specifying a `tlsSecret` on it. +- <> +- <> +- <> +- <> +- <> -TLS termination, or edge mode, is enabled by associating a `tlsSecret` with the `ingress` spec and by enabling HTTP access. - -Example TLS Termination YAML: +For other platforms or IngressControllers, you can use the provided examples as a starting point. + +[[passthrough]] +===== Passthrough + +It is enabled when you associate a `tlsSecret` with the `http` configuration and leave Ingress enabled without specifying a `tlsSecret` on it. + +[source,yaml] +---- +apiVersion: k8s.keycloak.org/v2alpha1 +kind: Keycloak +metadata: + name: example-kc +spec: + http: + tlsSecret: example-tls-secret + ingress: + enabled: true + hostname: + hostname: test.keycloak.org +---- + +NOTE: On OpenShift you are not allowed to use wildcard certificates on passthrough Routes with HTTP/2 enabled. For wildcard certificates use edge or reencrypt termination. + +===== Edge + +There are two ways to achieve TLS Edge. In both it is needed to enable HTTP access. + +[[edge_cluster_domain]] +*Using cluster domain and certificate* + +To use cluster domain do not provide a tls secret for the `ingress` and ensure to use cluster domain as `hostname`. Since no certificate is provided to the `ingress` the cluster certificate is used. + +[source,yaml] +---- +apiVersion: k8s.keycloak.org/v2alpha1 +kind: Keycloak +metadata: + name: example-kc +spec: + http: + httpEnabled: true + ingress: + enabled: true + hostname: + hostname: keycloak. <1> + proxy: + headers: xforwarded # double check your reverse proxy sets and overwrites the X-Forwarded-* headers +---- +<1> Must use the cluster domain + +[[edge_custom_domain]] +*Using custom domain and certificate* + +To use custom domain provide a tls secrets for the `ingress` and ensure that `hostname` matches the `ingress` certificate. [source,yaml] ---- @@ -238,16 +292,6 @@ kind: Keycloak metadata: name: example-kc spec: - instances: 1 - db: - vendor: postgres - host: postgres-db - usernameSecret: - name: keycloak-db-secret - key: username - passwordSecret: - name: keycloak-db-secret - key: password http: httpEnabled: true ingress: @@ -258,6 +302,74 @@ spec: headers: xforwarded # double check your reverse proxy sets and overwrites the X-Forwarded-* headers ---- + +===== Reencrypt + +There are two ways to achieve TLS Reencryption. In both it is needed to annotate the `ingress` to specify the desired termination type since operator still lacks logic to set itself the reencrypt termination. + +[[reencrypt_cluster_domain]] +*Using cluster domain and certificate* + +To use cluster domain do not provide a tls secret for the `ingress` and ensure to use cluster domain as `hostname`. Since no certificate is provided to the `ingress` the cluster certificate is used. + +[source,yaml] +---- +apiVersion: k8s.keycloak.org/v2alpha1 +kind: Keycloak +metadata: + name: example-kc +spec: + http: + annotations: + service.alpha.openshift.io/serving-cert-secret-name: svc-tls-secret <1> + tlsSecret: svc-tls-secret <2> + ingress: + annotations: + route.openshift.io/termination: reencrypt <3> + enabled: true + hostname: + hostname: keycloak. <4> + proxy: + headers: xforwarded # double check your reverse proxy sets and overwrites the X-Forwarded-* headers +---- +<1> This will add the annotation to the service generated by the operator, so cluster will create a tls secret named svc-tls-secret +<2> name of the tls secret created by the cluster, as defined in <1> +<3> required because the operator only has built-in openshift logic for passthrough and edge. +<4> Must use the cluster domain + +[[reencrypt_custom_domain]] +*Using custom domain and certificate* + +To use custom domain provide distinct tls secrets for the `ingress` and `http` and ensure that `hostname` matches the `ingress` certificate. + +[source,yaml] +---- +apiVersion: k8s.keycloak.org/v2alpha1 +kind: Keycloak +metadata: + name: example-kc +spec: + http: + annotations: + service.alpha.openshift.io/serving-cert-secret-name: svc-tls-secret <1> + tlsSecret: svc-tls-secret <2> + ingress: + annotations: + route.openshift.io/termination: reencrypt <3> + tlsSecret: ingress-tls-secret <4> + enabled: true + hostname: + hostname: test.keycloak.org <5> + proxy: + headers: xforwarded # double check your reverse proxy sets and overwrites the X-Forwarded-* headers +---- + +<1> this will add the annotation to the service generated by the operator, so cluster will create a tls secret named svc-tls-secret +<2> name of the tls secret created by the cluster, as defined in <1> +<3> required because the operator only has built-in openshift logic for passthrough and edge. +<4> certificate to be used at the ingress/route +<5> domain must match the provided certificate + ==== Custom Access If the default ingress does not fit your use case, disable it by setting `ingress` spec with `enabled` property to `false` value: @@ -282,12 +394,7 @@ Apply the changes: ---- kubectl apply -f example-kc.yaml ---- -You can then provide an alternative ingress resource pointing to the service `-service`. For example, on OpenShift you are not allowed to use wildcard certificates on passthrough Routes with HTTP/2 enabled. A Keycloak CR on OpenShift with TLS enabled using a wildcard certificate with the default IngressClass creates such a Route. In this case, you must disable the built-in ingress with `.spec.ingress.enabled: false`. Access may then be provided by creating a reencrypt Route instead: - -[source,yaml] ----- -$ oc create route reencrypt --service=-service --cert= --key= --dest-ca-cert= --ca-cert= --hostname= ----- +You can then provide an alternative ingress resource pointing to the service named `-service` by default. For debugging and development purposes, consider directly connecting to the {project_name} service using a port forward. For example, enter this command: From e74c5692adb6f4f4f4538667eaa66cbe740b8b9f Mon Sep 17 00:00:00 2001 From: Gilvan Filho Date: Fri, 10 Apr 2026 16:16:58 -0300 Subject: [PATCH 2/4] Update docs/guides/operator/basic-deployment.adoc Co-authored-by: Steven Hawkins Signed-off-by: Gilvan Filho --- docs/guides/operator/basic-deployment.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guides/operator/basic-deployment.adoc b/docs/guides/operator/basic-deployment.adoc index 7287f38de553..7f5824a079d3 100644 --- a/docs/guides/operator/basic-deployment.adoc +++ b/docs/guides/operator/basic-deployment.adoc @@ -221,7 +221,7 @@ See below for more on TLS termination. ==== TLS Termination with default Ingress -When using the operator-provided ingress (`spec.ingress.enabled: true`) there are a lot of Keycloak CR options (like service and ingress labels and annotations) which allows you to customize your ingress behaviour. This section show how to achive below TLS Termination when using Openshift: +When using the operator-provided ingress (`spec.ingress.enabled: true`) there are a lot of Keycloak CR options (like service and ingress labels and annotations) which allow you to customize your ingress behaviour. This section shows how to achieve the following TLS Termination when using Openshift: - <> - <> From 5f5716c7eb50d9ba6890a973b4d6eae23ad23ed1 Mon Sep 17 00:00:00 2001 From: Gilvan Filho Date: Thu, 7 May 2026 09:32:30 -0300 Subject: [PATCH 3/4] Apply suggestions from code review Co-authored-by: Alexander Schwartz Signed-off-by: Gilvan Filho --- docs/guides/operator/basic-deployment.adoc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/guides/operator/basic-deployment.adoc b/docs/guides/operator/basic-deployment.adoc index 7f5824a079d3..06e22678fe73 100644 --- a/docs/guides/operator/basic-deployment.adoc +++ b/docs/guides/operator/basic-deployment.adoc @@ -221,7 +221,7 @@ See below for more on TLS termination. ==== TLS Termination with default Ingress -When using the operator-provided ingress (`spec.ingress.enabled: true`) there are a lot of Keycloak CR options (like service and ingress labels and annotations) which allow you to customize your ingress behaviour. This section shows how to achieve the following TLS Termination when using Openshift: +When using the operator-provided ingress (`spec.ingress.enabled: true`) there are a lot of Keycloak CR options (like service and ingress labels and annotations) which allow you to customize your ingress behaviour. This section shows how to achieve the following TLS Termination when using OpenShift: - <> - <> @@ -334,7 +334,7 @@ spec: ---- <1> This will add the annotation to the service generated by the operator, so cluster will create a tls secret named svc-tls-secret <2> name of the tls secret created by the cluster, as defined in <1> -<3> required because the operator only has built-in openshift logic for passthrough and edge. +<3> required because the operator only has built-in OpenShift logic for passthrough and edge. <4> Must use the cluster domain [[reencrypt_custom_domain]] @@ -366,7 +366,7 @@ spec: <1> this will add the annotation to the service generated by the operator, so cluster will create a tls secret named svc-tls-secret <2> name of the tls secret created by the cluster, as defined in <1> -<3> required because the operator only has built-in openshift logic for passthrough and edge. +<3> required because the operator only has built-in OpenShift logic for passthrough and edge. <4> certificate to be used at the ingress/route <5> domain must match the provided certificate From 037f918d9f0e6797779bd2fb0d8e06c5f48c1a59 Mon Sep 17 00:00:00 2001 From: Alexander Schwartz Date: Mon, 11 May 2026 21:45:49 -0400 Subject: [PATCH 4/4] Moving updated text to a callout Signed-off-by: Alexander Schwartz --- docs/guides/operator/basic-deployment.adoc | 46 ++++++++++++---------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/docs/guides/operator/basic-deployment.adoc b/docs/guides/operator/basic-deployment.adoc index 06e22678fe73..aeee921e733f 100644 --- a/docs/guides/operator/basic-deployment.adoc +++ b/docs/guides/operator/basic-deployment.adoc @@ -127,7 +127,7 @@ To deploy {project_name}, you create a Custom Resource (CR) based on the Keycloa [NOTE] ==== -If you are on OpenShift, you cannot use wildcard certificates on passthrough Routes with HTTP/2 enabled. The following Keycloak CR on OpenShift if you are using a wildcard certificate with the default IngressClass, creates such a Route. In this situation, modify the yaml based on "Accessing the {project_name} deployment" later in this topic to use TLS Termination or an OpenShift re-encrypt Route. +If you are on OpenShift, you cannot use wildcard certificates on passthrough Routes with HTTP/2 enabled. The following Keycloak CR on OpenShift if you are using a wildcard certificate with the default IngressClass, creates such a Route. In this situation, modify the YAML based on "Accessing the {project_name} deployment" later in this topic to use TLS Termination or an OpenShift re-encrypt Route. ==== Consider storing the Database credentials in a separate Secret. Enter the following commands: @@ -141,6 +141,9 @@ kubectl create secret generic keycloak-db-secret \ You can customize several fields using the Keycloak CRD. For a basic deployment, you can stick to the following approach: Create YAML file `example-kc.yaml`: + +:check-lb-forwarded-header: pass:quotes[Check your load balancer or reverse proxy configuration to determine whether it utilizes the `Forwarded` (RFC 7239) or `X-Forwarded-*` (e.g., `X-Forwarded-For`) mechanism for header propagation.] + [source,yaml] ---- apiVersion: k8s.keycloak.org/v2alpha1 @@ -163,8 +166,9 @@ spec: hostname: hostname: test.keycloak.org proxy: - headers: xforwarded # double check your reverse proxy sets and overwrites the X-Forwarded-* headers + headers: xforwarded # <1> ---- +<1> {check-lb-forwarded-header} Apply the changes: @@ -216,12 +220,12 @@ spec: className: openshift-default ---- -NOTE: The operator annotates the Ingress to match expectations for TLS passthrough or TLS termination on OpenShift with the default IngressClass. -See below for more on TLS termination. +NOTE: The operator annotates the Ingress to match expectations for TLS passthrough or TLS termination on OpenShift with the default IngressClass. +See below for more on TLS termination. ==== TLS Termination with default Ingress -When using the operator-provided ingress (`spec.ingress.enabled: true`) there are a lot of Keycloak CR options (like service and ingress labels and annotations) which allow you to customize your ingress behaviour. This section shows how to achieve the following TLS Termination when using OpenShift: +When using the operator-provided ingress (`spec.ingress.enabled: true`) there are a lot of Keycloak CR options (like service and ingress labels and annotations) which allow you to customize your ingress behavior. This section shows how to achieve the following TLS Termination when using OpenShift: - <> - <> @@ -234,7 +238,7 @@ For other platforms or IngressControllers, you can use the provided examples as [[passthrough]] ===== Passthrough -It is enabled when you associate a `tlsSecret` with the `http` configuration and leave Ingress enabled without specifying a `tlsSecret` on it. +It is enabled when you associate a `tlsSecret` with the `http` configuration and leave Ingress enabled without specifying a `tlsSecret` on it. [source,yaml] ---- @@ -276,9 +280,10 @@ spec: hostname: hostname: keycloak. <1> proxy: - headers: xforwarded # double check your reverse proxy sets and overwrites the X-Forwarded-* headers + headers: xforwarded <2> ---- -<1> Must use the cluster domain +<1> Must use the cluster domain. +<2> {check-lb-forwarded-header} [[edge_custom_domain]] *Using custom domain and certificate* @@ -299,9 +304,9 @@ spec: hostname: hostname: test.keycloak.org proxy: - headers: xforwarded # double check your reverse proxy sets and overwrites the X-Forwarded-* headers + headers: xforwarded # <1> ---- - +<1> {check-lb-forwarded-header} ===== Reencrypt @@ -330,12 +335,13 @@ spec: hostname: hostname: keycloak. <4> proxy: - headers: xforwarded # double check your reverse proxy sets and overwrites the X-Forwarded-* headers + headers: xforwarded # <5> ---- <1> This will add the annotation to the service generated by the operator, so cluster will create a tls secret named svc-tls-secret <2> name of the tls secret created by the cluster, as defined in <1> -<3> required because the operator only has built-in OpenShift logic for passthrough and edge. +<3> required because the operator only has built-in OpenShift logic for passthrough and edge. <4> Must use the cluster domain +<5> {check-lb-forwarded-header} [[reencrypt_custom_domain]] *Using custom domain and certificate* @@ -361,14 +367,14 @@ spec: hostname: hostname: test.keycloak.org <5> proxy: - headers: xforwarded # double check your reverse proxy sets and overwrites the X-Forwarded-* headers + headers: xforwarded # <6> ---- - -<1> this will add the annotation to the service generated by the operator, so cluster will create a tls secret named svc-tls-secret -<2> name of the tls secret created by the cluster, as defined in <1> -<3> required because the operator only has built-in OpenShift logic for passthrough and edge. -<4> certificate to be used at the ingress/route -<5> domain must match the provided certificate +<1> This will add the annotation to the service generated by the operator, so cluster will create a tls secret named `svc-tls-secret`. +<2> Name of the tls secret created by the cluster, as defined in callout 1. +<3> Required because the operator only has built-in OpenShift logic for passthrough and edge. +<4> Certificate to be used at the ingress/route. +<5> Domain must match the provided certificate. +<6> {check-lb-forwarded-header} ==== Custom Access @@ -421,7 +427,7 @@ spec: proxy: headers: forwarded|xforwarded ---- -NOTE: If the `proxy.headers` field is not specified, the Operator falls back to legacy behaviour by implicitly setting +NOTE: If the `proxy.headers` field is not specified, the Operator falls back to legacy behavior by implicitly setting `proxy=passthrough` by default. This results in deprecation warnings in the server log. This fallback will be removed in a future release.