feat(keycloak): Login-Theme einhaengbar machen (extraVolumes/extraVolumeMounts) #88

Closed
opened 2026-10-05 17:54:37 +02:00 by jlab-bot · 1 comment
Member

Der keycloak-Chart kann derzeit kein eigenes Login-Theme in den Pod bringen. Das blockiert jede Theme-Anpassung — Anmeldeseite, Konto-Konsole, E-Mail-Vorlagen, Branding — und war konkret daran aufgefallen, dass ein Icon für einen Identity Provider sich nicht setzen lässt.

Woran es hängt

Keycloak hat für Identity Provider kein Logo-Feld. Das Icon auf dem Anmeldeknopf kommt ausschließlich aus einem Login-Theme, über kcLogoIdP-<alias> in dessen theme.properties:

kcLogoIdP-bekemeyer-klein = fa fa-lock

Ein Theme muss dafür unter /opt/keycloak/themes/ im Container liegen. Der Chart bietet dafür keinen Weg.

Gemessener Stand (Chart 1.0.0+up26.8.0)

Die values.yaml hat genau vier Top-Level-Schlüssel: scaleDown, secrets, keycloak, ingress. Kein extraVolumes, kein extraVolumeMounts, kein Theme-Schlüssel, kein zusätzliches env.

Die gute Nachricht: Das Deployment-Template hat bereits einen volumes:-Abschnitt mit drei emptyDirs (quarkus-build, data, tmp) und die passenden volumeMounts am Hauptcontainer. Es ist also keine neue Mechanik zu bauen, sondern eine additive Erweiterung bestehender Listen.

Vorschlag

Ein generisches Paar keycloak.extraVolumes / keycloak.extraVolumeMounts, durchgereicht mit toYaml | nindent, statt eines Theme-spezifischen Schlüssels. Begründung: Dasselbe Paar löst weitere Fälle, die ohnehin kommen — zusätzliche Wurzel-CAs und SPI-Erweiterungen —, und der Chart muss sich nicht festlegen, wie ein Theme ausgeliefert wird (ConfigMap, Secret, PVC, initContainer).

Ein dokumentiertes Beispiel für den Theme-Fall gehört in die values.yaml dazu, denn der Fall hat eine Falle, die man genau einmal falsch macht (siehe unten).

Die wichtigste Falle, und der Chart dokumentiert sie schon einmal

Nicht auf /opt/keycloak/themes mounten. Dort liegen die mitgelieferten Themes (base, keycloak, keycloak.v2) — ein Volume an diesem Pfad versteckt sie alle, und die Anmeldeseite ist dann komplett kaputt. Der Mount gehört auf einen Unterpfad, also /opt/keycloak/themes/<name>, der im Abbild nicht existiert und damit nichts verdeckt.

Das ist genau dieselbe Überlegung, die im Template schon für einen anderen Pfad steht und die man nicht zweimal lernen muss:

# DELIBERATELY NOT MOUNTED: /opt/keycloak/conf. It is not empty in the image - it carries keycloak.conf and, more importantly, cache-ispn.xml ... An emptyDir there would hide it and the cluster would come up with no cache configuration.

Dieselbe Klasse Fehler, derselbe Mechanismus. Ein Beispiel in der values.yaml sollte den Unterpfad deshalb ausdrücklich zeigen und begründen.

Weitere Punkte, die zum Umsetzen gehören

  • Verträgt sich ein Runtime-Theme mit --optimized? Themes werden zur Laufzeit gelesen, Provider zur Bauzeit — ein gemountetes Theme sollte also trotz der vorgezogenen Augmentation greifen. Das ist begründete Erwartung, nicht geprüft, und gehört wegen der ungewöhnlichen Zwei-Init-Container-Konstruktion dieses Charts einmal belegt.
  • Ein ConfigMap trägt keine Binärdaten im data-Feld. Ein PNG braucht binaryData (base64); SVG ist Text und passt in data. Dazu das Limit von 1 MiB pro ConfigMap — für ein Theme mit SVG reichlich, für mitgelieferte Schriften nicht.
  • Themes werden gecacht. In Produktion ist das gewollt, heißt aber: Eine Theme-Änderung wirkt erst nach einem Pod-Neustart. Gehört dokumentiert, nicht wegkonfiguriert.
  • Der Chart kann das Theme nicht aktivieren. Die Auswahl liegt je Realm in Keycloaks Datenbank (Realm settings → Themes → Login theme). Das sollte in der values.yaml beim neuen Schlüssel stehen, damit niemand ein wirkungsloses Theme sucht.
  • Ein eigenes Theme kann die Identity-Provider-Knöpfe ganz verschwinden lassen, wenn das Template das Social-Fragment nicht korrekt einbindet — mehrfach im Keycloak-Issue-Tracker gemeldet (keycloak/keycloak#42711). Nach dem Umstellen die Anmeldeseite tatsächlich ansehen, nicht nur den Pod.

Abnahme

  • helm template mit einem Beispiel, das ein ConfigMap-Theme auf /opt/keycloak/themes/<name> einhängt, rendert korrekt.
  • Die mitgelieferten Themes sind danach noch vorhanden (Anmeldeseite lädt).
  • kcLogoIdP-<alias> wirkt, nachdem das Theme im Realm ausgewählt und der Pod neu gestartet wurde.

Dringlichkeit

Niedrig. Der konkrete Anlass — ein Icon auf einem Anmeldeknopf — ist kosmetisch, und ein aussagekräftiger displayName am Provider erfüllt denselben Zweck ohne jede Änderung. Die allgemeine Lücke ist es nicht: Ohne extraVolumes lässt sich in diesen Pod grundsätzlich keine Datei bringen, und der nächste Fall dieser Art ist absehbar.

Der `keycloak`-Chart kann derzeit kein eigenes Login-Theme in den Pod bringen. Das blockiert jede Theme-Anpassung — Anmeldeseite, Konto-Konsole, E-Mail-Vorlagen, Branding — und war konkret daran aufgefallen, dass ein Icon für einen Identity Provider sich nicht setzen lässt. ## Woran es hängt Keycloak hat für Identity Provider **kein Logo-Feld**. Das Icon auf dem Anmeldeknopf kommt ausschließlich aus einem Login-Theme, über `kcLogoIdP-<alias>` in dessen `theme.properties`: ```properties kcLogoIdP-bekemeyer-klein = fa fa-lock ``` Ein Theme muss dafür unter `/opt/keycloak/themes/` im Container liegen. Der Chart bietet dafür keinen Weg. ## Gemessener Stand (Chart `1.0.0+up26.8.0`) Die `values.yaml` hat genau vier Top-Level-Schlüssel: `scaleDown`, `secrets`, `keycloak`, `ingress`. Kein `extraVolumes`, kein `extraVolumeMounts`, kein Theme-Schlüssel, kein zusätzliches `env`. **Die gute Nachricht:** Das Deployment-Template hat bereits einen `volumes:`-Abschnitt mit drei emptyDirs (`quarkus-build`, `data`, `tmp`) und die passenden `volumeMounts` am Hauptcontainer. Es ist also keine neue Mechanik zu bauen, sondern eine additive Erweiterung bestehender Listen. ## Vorschlag Ein generisches Paar `keycloak.extraVolumes` / `keycloak.extraVolumeMounts`, durchgereicht mit `toYaml | nindent`, statt eines Theme-spezifischen Schlüssels. Begründung: Dasselbe Paar löst weitere Fälle, die ohnehin kommen — zusätzliche Wurzel-CAs und SPI-Erweiterungen —, und der Chart muss sich nicht festlegen, wie ein Theme ausgeliefert wird (ConfigMap, Secret, PVC, initContainer). Ein dokumentiertes Beispiel für den Theme-Fall gehört in die `values.yaml` dazu, denn der Fall hat eine Falle, die man genau einmal falsch macht (siehe unten). ## Die wichtigste Falle, und der Chart dokumentiert sie schon einmal **Nicht auf `/opt/keycloak/themes` mounten.** Dort liegen die mitgelieferten Themes (`base`, `keycloak`, `keycloak.v2`) — ein Volume an diesem Pfad **versteckt sie alle**, und die Anmeldeseite ist dann komplett kaputt. Der Mount gehört auf einen **Unterpfad**, also `/opt/keycloak/themes/<name>`, der im Abbild nicht existiert und damit nichts verdeckt. Das ist genau dieselbe Überlegung, die im Template schon für einen anderen Pfad steht und die man nicht zweimal lernen muss: > `# DELIBERATELY NOT MOUNTED: /opt/keycloak/conf. It is not empty in the image - it carries keycloak.conf and, more importantly, cache-ispn.xml ... An emptyDir there would hide it and the cluster would come up with no cache configuration.` Dieselbe Klasse Fehler, derselbe Mechanismus. Ein Beispiel in der `values.yaml` sollte den Unterpfad deshalb ausdrücklich zeigen und begründen. ## Weitere Punkte, die zum Umsetzen gehören - **Verträgt sich ein Runtime-Theme mit `--optimized`?** Themes werden zur Laufzeit gelesen, Provider zur Bauzeit — ein gemountetes Theme sollte also trotz der vorgezogenen Augmentation greifen. **Das ist begründete Erwartung, nicht geprüft**, und gehört wegen der ungewöhnlichen Zwei-Init-Container-Konstruktion dieses Charts einmal belegt. - **Ein ConfigMap trägt keine Binärdaten im `data`-Feld.** Ein PNG braucht `binaryData` (base64); SVG ist Text und passt in `data`. Dazu das Limit von 1 MiB pro ConfigMap — für ein Theme mit SVG reichlich, für mitgelieferte Schriften nicht. - **Themes werden gecacht.** In Produktion ist das gewollt, heißt aber: Eine Theme-Änderung wirkt erst nach einem Pod-Neustart. Gehört dokumentiert, nicht wegkonfiguriert. - **Der Chart kann das Theme nicht aktivieren.** Die Auswahl liegt je Realm in Keycloaks Datenbank (Realm settings → Themes → Login theme). Das sollte in der `values.yaml` beim neuen Schlüssel stehen, damit niemand ein wirkungsloses Theme sucht. - **Ein eigenes Theme kann die Identity-Provider-Knöpfe ganz verschwinden lassen**, wenn das Template das Social-Fragment nicht korrekt einbindet — mehrfach im Keycloak-Issue-Tracker gemeldet (keycloak/keycloak#42711). Nach dem Umstellen die Anmeldeseite tatsächlich ansehen, nicht nur den Pod. ## Abnahme - `helm template` mit einem Beispiel, das ein ConfigMap-Theme auf `/opt/keycloak/themes/<name>` einhängt, rendert korrekt. - Die mitgelieferten Themes sind danach noch vorhanden (Anmeldeseite lädt). - `kcLogoIdP-<alias>` wirkt, nachdem das Theme im Realm ausgewählt und der Pod neu gestartet wurde. ## Dringlichkeit **Niedrig.** Der konkrete Anlass — ein Icon auf einem Anmeldeknopf — ist kosmetisch, und ein aussagekräftiger `displayName` am Provider erfüllt denselben Zweck ohne jede Änderung. Die allgemeine Lücke ist es nicht: Ohne `extraVolumes` lässt sich in diesen Pod grundsätzlich keine Datei bringen, und der nächste Fall dieser Art ist absehbar.
jlab-bot added the inhouse-chart label 2026-10-05 17:54:37 +02:00
Author
Member

Freigegeben — mit drei Ergänzungen, eine davon ändert die Umsetzung

Der Issue-Body ist ein vollständiger Plan und bleibt gültig: ein generisches Paar keycloak.extraVolumes / keycloak.extraVolumeMounts, durchgereicht mit toYaml | nindent, mit dokumentiertem Theme-Beispiel und der Falle, nicht auf /opt/keycloak/themes zu mounten, sondern auf einen Unterpfad. Gemessener Stand bestätigt: das Deployment hat bereits volumes: mit drei emptyDirs und zwei Init-Container (seed, build) mit eigenen volumeMounts.

Drei Dinge kommen hinzu.

1. Die Mounts müssen auch an den build-Init-Container — sonst trägt die eigene Begründung nicht

Der Issue-Body rechtfertigt das generische Paar damit, dass es weitere Fälle löst, „die ohnehin kommen — zusätzliche Wurzel-CAs und SPI-Erweiterungen". Für SPI-Erweiterungen trägt es in der naiven Form nicht, und zwar still.

Upstream, wörtlich: Provider gehören in das providers-Verzeichnis, und „After that if you are using --optimized, you must run the build command in order to update the server's provider registry with the implementations from the JAR file." Dieser Chart fährt start --optimized, und kc.sh build läuft im build-Init-Container. Ein Provider-JAR, das nur im Hauptcontainer hängt, ist zur Augmentierungszeit nicht da — es landet nie in der Registry, die Datei liegt zur Laufzeit herum und tut nichts.

Festgelegt: dieselbe extraVolumeMounts-Liste wird am build-Init-Container und am Hauptcontainer gerendert. Eine Liste, zwei Stellen. Begründung an den Wert, denn es ist genau der Grund, warum Erweiterungen funktionieren — und ohne diesen Satz baut die nächste Runde es „sauber" auf den Hauptcontainer zurück.

Nicht an den seed-Init-Container: der mountet nur quarkus-build auf /quarkus-build und hat ein anderes Layout, dort wäre es sinnlos.

Nebenwirkung, die an den Wert gehört: ein Mount ist damit auch zur Bauzeit vorhanden. Für ein Theme ist das folgenlos, für ein Geheimnis bedeutet es, dass es ein Init-Container ebenfalls sieht — derselbe Pod, aber es gehört gesagt.

2. Wurzel-CAs brauchen mehr als einen Mount

Der zweite im Issue genannte Folgefall ist mit extraVolumes allein nicht erledigt: eine Datei in den Pod zu legen fügt sie keinem Truststore hinzu. Keycloak braucht dafür zusätzlich --truststore-paths beziehungsweise KC_TRUSTSTORE_PATHS auf das eingehängte Verzeichnis.

Zu entscheiden bei der Umsetzung, begründet: entweder gleich ein Wert dafür mit, oder die Grenze ausdrücklich an extraVolumes schreiben („legt Dateien ab, richtet keinen Truststore ein"). Ich neige zum Zweiten — dieser PR soll das Mounten lösen, nicht zwei Themen —, aber ohne den Satz entsteht genau die Erwartung, die das Issue selbst weckt.

3. Der Install-Test soll es wirklich gehen

Der Issue-Body nennt die Verträglichkeit eines Laufzeit-Themes mit --optimized „begründete Erwartung, nicht geprüft". Das lässt sich im selben Durchgang schließen und soll es: ein ConfigMap-Theme in die Fixture, eingehängt auf /opt/keycloak/themes/<name>, und der Lauf belegt dann drei Dinge auf einmal — der Pod wird Ready (die Augmentierung stört das Theme nicht), die mitgelieferten Themes sind noch da (der Unterpfad verdeckt nichts), und die neuen Werte rendern gegen echte Werte statt nur gegen die Vorgaben.

Das ist die Lehre aus #78/#80: ein Pfad, den der Install-Test nicht geht, ist unbelegt. Hier kostet er fast nichts.

Umfang und Version

Additiv, neue optionale Werte mit unveränderten Vorgaben → Minor: 1.0.0+up26.8.0 → 1.1.0+up26.8.0.

Dazu im values.schema.json: die beiden neuen Schlüssel müssen deklariert sein, weil die oberste Ebene additionalProperties: false trägt. Die Elemente selbst bleiben bewusst locker typisiert — eine Volume-Quelle kann jede der Kubernetes-Formen sein, und ein zu strenges Schema würde gültige Konfigurationen abweisen. Der Grund gehört als Kommentar dazu, sonst zieht die nächste Runde es „nach".

Die vier Punkte aus dem Issue-Body bleiben als Dokumentationspflicht: ConfigMaps tragen Binärdaten nur in binaryData (PNG ja, SVG passt in data) mit 1 MiB Grenze; Themes werden gecacht, eine Änderung wirkt erst nach einem Pod-Neustart; der Chart kann das Theme nicht aktivieren, die Auswahl liegt je Realm in der Datenbank; und ein eigenes Theme kann die Identity-Provider-Knöpfe verschwinden lassen, wenn das Social-Fragment fehlt — nach dem Umstellen die Anmeldeseite ansehen, nicht nur den Pod.

Wiki: die keycloak-Seite um die beiden Werte, das Theme-Beispiel und die Falle erweitern. Kein neuer Eintrag in Charts oder _Sidebar — der Chart existiert schon. Lessons-Learned nur, falls bei der Umsetzung etwas auffällt, das sich wiederholt; der Build-Zeit-Fall aus Punkt 1 ist ein Kandidat, weil er bei jedem Chart mit vorgezogener Augmentierung wiederkehrt.

# Freigegeben — mit drei Ergänzungen, eine davon ändert die Umsetzung Der Issue-Body ist ein vollständiger Plan und bleibt gültig: ein generisches Paar `keycloak.extraVolumes` / `keycloak.extraVolumeMounts`, durchgereicht mit `toYaml | nindent`, mit dokumentiertem Theme-Beispiel und der Falle, nicht auf `/opt/keycloak/themes` zu mounten, sondern auf einen Unterpfad. Gemessener Stand bestätigt: das Deployment hat bereits `volumes:` mit drei emptyDirs und zwei Init-Container (`seed`, `build`) mit eigenen `volumeMounts`. Drei Dinge kommen hinzu. ## 1. Die Mounts müssen auch an den `build`-Init-Container — sonst trägt die eigene Begründung nicht Der Issue-Body rechtfertigt das generische Paar damit, dass es weitere Fälle löst, „die ohnehin kommen — zusätzliche Wurzel-CAs und **SPI-Erweiterungen**". Für SPI-Erweiterungen trägt es in der naiven Form **nicht**, und zwar still. Upstream, wörtlich: Provider gehören in das `providers`-Verzeichnis, und *„After that if you are using `--optimized`, you must run the `build` command in order to update the server's provider registry with the implementations from the JAR file."* Dieser Chart fährt `start --optimized`, und `kc.sh build` läuft im **`build`-Init-Container**. Ein Provider-JAR, das nur im Hauptcontainer hängt, ist zur Augmentierungszeit nicht da — es landet nie in der Registry, die Datei liegt zur Laufzeit herum und tut nichts. **Festgelegt: dieselbe `extraVolumeMounts`-Liste wird am `build`-Init-Container *und* am Hauptcontainer gerendert.** Eine Liste, zwei Stellen. Begründung an den Wert, denn es ist genau der Grund, warum Erweiterungen funktionieren — und ohne diesen Satz baut die nächste Runde es „sauber" auf den Hauptcontainer zurück. Nicht an den `seed`-Init-Container: der mountet nur `quarkus-build` auf `/quarkus-build` und hat ein anderes Layout, dort wäre es sinnlos. Nebenwirkung, die an den Wert gehört: ein Mount ist damit auch zur Bauzeit vorhanden. Für ein Theme ist das folgenlos, für ein Geheimnis bedeutet es, dass es ein Init-Container ebenfalls sieht — derselbe Pod, aber es gehört gesagt. ## 2. Wurzel-CAs brauchen mehr als einen Mount Der zweite im Issue genannte Folgefall ist mit `extraVolumes` allein **nicht** erledigt: eine Datei in den Pod zu legen fügt sie keinem Truststore hinzu. Keycloak braucht dafür zusätzlich `--truststore-paths` beziehungsweise `KC_TRUSTSTORE_PATHS` auf das eingehängte Verzeichnis. Zu entscheiden bei der Umsetzung, begründet: entweder gleich ein Wert dafür mit, oder die Grenze ausdrücklich an `extraVolumes` schreiben („legt Dateien ab, richtet keinen Truststore ein"). Ich neige zum Zweiten — dieser PR soll das Mounten lösen, nicht zwei Themen —, aber **ohne** den Satz entsteht genau die Erwartung, die das Issue selbst weckt. ## 3. Der Install-Test soll es wirklich gehen Der Issue-Body nennt die Verträglichkeit eines Laufzeit-Themes mit `--optimized` „begründete Erwartung, nicht geprüft". Das lässt sich im selben Durchgang schließen und soll es: **ein ConfigMap-Theme in die Fixture**, eingehängt auf `/opt/keycloak/themes/<name>`, und der Lauf belegt dann drei Dinge auf einmal — der Pod wird `Ready` (die Augmentierung stört das Theme nicht), die mitgelieferten Themes sind noch da (der Unterpfad verdeckt nichts), und die neuen Werte rendern gegen echte Werte statt nur gegen die Vorgaben. Das ist die Lehre aus #78/#80: ein Pfad, den der Install-Test nicht geht, ist unbelegt. Hier kostet er fast nichts. ## Umfang und Version Additiv, neue optionale Werte mit unveränderten Vorgaben → **Minor**: `1.0.0+up26.8.0` → **`1.1.0+up26.8.0`**. Dazu im `values.schema.json`: die beiden neuen Schlüssel müssen deklariert sein, weil die oberste Ebene `additionalProperties: false` trägt. Die Elemente selbst bleiben bewusst locker typisiert — eine Volume-Quelle kann jede der Kubernetes-Formen sein, und ein zu strenges Schema würde gültige Konfigurationen abweisen. Der Grund gehört als Kommentar dazu, sonst zieht die nächste Runde es „nach". Die vier Punkte aus dem Issue-Body bleiben als Dokumentationspflicht: ConfigMaps tragen Binärdaten nur in `binaryData` (PNG ja, SVG passt in `data`) mit 1 MiB Grenze; Themes werden gecacht, eine Änderung wirkt erst nach einem Pod-Neustart; **der Chart kann das Theme nicht aktivieren**, die Auswahl liegt je Realm in der Datenbank; und ein eigenes Theme kann die Identity-Provider-Knöpfe verschwinden lassen, wenn das Social-Fragment fehlt — nach dem Umstellen die Anmeldeseite ansehen, nicht nur den Pod. Wiki: die `keycloak`-Seite um die beiden Werte, das Theme-Beispiel und die Falle erweitern. Kein neuer Eintrag in `Charts` oder `_Sidebar` — der Chart existiert schon. `Lessons-Learned` nur, falls bei der Umsetzung etwas auffällt, das sich wiederholt; der Build-Zeit-Fall aus Punkt 1 ist ein Kandidat, weil er bei jedem Chart mit vorgezogener Augmentierung wiederkehrt.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: jlab-cluster/helm-charts#88