Merge pull request 'feat(keycloak): one hostname per realm, in both routing modes' (#125) from feat/keycloak-realm-hosts into main
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 11s
Publish Keycloak Helm Chart / Publish Keycloak Helm Chart (push) Successful in 11s
SonarQube Analysis / SonarQube Analysis (push) Successful in 47s

This commit was merged in pull request #125.
This commit is contained in:
jklein committed 2026-10-13 10:38:09 +00:00
commit 649417b428
10 files changed
+629 -16

No files matched your search

+20 -2
View File
@@ -30,11 +30,29 @@
# parentRefs fall back to httpRoute.parentRefs below - the empty-admin
# branch, which is the one an installation hits unless it wants an
# internal Gateway.
# - both routes' backendRef is checked against the serving Service of the
# same render. Both point at the SAME Service, by PORT NUMBER
# - every route's backendRef is checked against the serving Service of the
# same render. They all point at the SAME Service, by PORT NUMBER
# (keycloak.ports.http) rather than by the name "http" the Ingress uses,
# because backendRefs takes a PortNumber - so this overlay is what holds
# that number against the Service's.
# - THE TWO REALM ROUTES (Gitea #122), which come from keycloak.realmHosts in
# the fixture rather than from this file. Nothing is repeated here on
# purpose: the fixture installs them as Ingress objects and this overlay
# turns the same two entries into HTTPRoutes, so one definition covers both
# modes and the two halves cannot drift into describing different hostnames.
# What the routes add to the two above is a SECOND RULE SHAPE - an Exact
# match on / carrying a RequestRedirect filter and no backendRefs at all.
# That rule is reported as "not checked" by this test, correctly and by
# design: a filter-only rule has no backend to resolve. The assertion it
# does earn is on its sibling rule, the PathPrefix one that points at the
# Service. The prefix/redirect pairing check of #118 does NOT fire for these
# routes and must not: it is scoped to rules that STRIP a prefix with a
# ReplacePrefixMatch rewrite, and these strip nothing - they redirect the
# bare root of a hostname that serves one realm.
# The entries also cover the two Ingress-mode forms (one with a
# clusterIssuer, one without) and what this test holds about them is their
# INERTNESS: neither tlsSecretName nor clusterIssuer nor the per-entry
# annotation may appear anywhere in a rendered route.
#
# NOT covered here, and it cannot be: that either hostname answers. No Gateway
# controller runs in CI, no route reaches "Accepted: True", and the
+37
View File
@@ -203,6 +203,43 @@ keycloak:
mountPath: /opt/keycloak/themes/ci-theme
readOnly: true
# TWO REALM HOSTNAMES (Gitea #122), and they are set HERE rather than in the
# Gateway overlay on purpose: ci/httproute/keycloak.yaml is applied on top of
# this file, so one definition covers BOTH modes - two Ingress objects in this
# install, two HTTPRoutes in the render-only test, from the same two entries.
# Defining them in the overlay instead would leave the Ingress half of the
# feature with no coverage at all, and it is the half that carries the
# required value and the convention deviation.
#
# WHAT THIS INSTALL ADDS TO THE RENDER TEST, which is the part a cluster-less
# check cannot reach: the API server accepts both objects, including the
# Service port named BY NAME ("http") - a typo there is invisible until
# somebody opens the URL - and the second entry's cert-manager annotation does
# not make the apply fail in a cluster without cert-manager. No ingress
# controller answers in CI, so neither app-root nor the proxy buffers are
# exercised; that is the same gap the two objects above have.
#
# THE TWO ENTRIES ARE THE TWO FORMS, deliberately:
# [0] NO clusterIssuer - the normal case, where the certificate comes from
# elsewhere (a wildcard, another release) and this object only consumes
# the secret. It also carries a per-entry annotation, which is what
# makes the per-entry (rather than chart-global) annotations block a
# tested shape rather than an intended one.
# [1] WITH clusterIssuer - the case where the certificate is issued for this
# entry's own secret.
# Both are inert in Gateway mode, and the render test is what holds that: the
# routes it renders from these entries must show no trace of either field.
realmHosts:
- host: realm-one.ci.example.com
realm: ci-realm-one
tlsSecretName: tls-ci-realm-shared-ingress
annotations:
nginx.ingress.kubernetes.io/proxy-buffer-size: 16k
- host: realm-two.ci.example.com
realm: ci-realm-two
tlsSecretName: tls-ci-realm-two-ingress
clusterIssuer: ci-selfsigned
ingress:
# Left ON although no ingress controller answers in CI: the point is that
# both objects are accepted and that the Service port they name BY NAME