Keycloak Clients als Kubernetes-Ressource: KeycloakOIDCClient im Keycloak Operator
Wer Keycloak auf Kubernetes mit dem offiziellen Operator betreibt, beschreibt den Server selbst längst als Custom Resource.
Die Clients, also die Anwendungen, die sich über Keycloak anmelden, blieben bisher außen vor.
Sie wurden in der Admin-Konsole angelegt, per Realm-Import einmalig eingespielt oder mit externen Werkzeugen gepflegt.
Seit Keycloak 26.7 bringt der Operator dafür eigene Ressourcen mit: KeycloakOIDCClient und KeycloakSAMLClient.
Mit Keycloak 26.8 sind sie vom experimentellen Stand in den Preview-Status aufgerückt.
Dieser Beitrag zeigt, wie die Ressourcen funktionieren, wie sie sich im Betrieb verhalten und wann die bekannten Alternativen besser passen.
Das Problem: Clients leben neben dem Deployment
Eine Anwendung, die sich per OpenID Connect anmeldet, braucht in Keycloak einen passenden Client. Dazu gehören die Client ID, erlaubte Redirect URIs, die aktivierten Flows und bei vertraulichen Clients ein Secret. Die Anwendung selbst wird auf Kubernetes deklarativ ausgerollt, meist über Helm oder Kustomize und oft per GitOps mit Argo CD oder Flux. Der Client in Keycloak entsteht dagegen häufig von Hand.
Daraus ergeben sich bekannte Probleme. Eine neue Umgebung braucht einen manuellen Schritt, bevor die Anwendung funktioniert. Redirect URIs in Test und Produktion laufen auseinander, ohne dass es jemand bemerkt. Das Client Secret wird aus der Admin-Konsole kopiert und landet irgendwo in einem Kubernetes Secret, ohne dass klar ist, welche Seite die führende ist. Und wer in der Konsole eine Einstellung ändert, hinterlässt keine Spur in Git.
Was KeycloakOIDCClient macht
Ein KeycloakOIDCClient beschreibt genau einen OIDC-Client in einem Realm, als Kubernetes-Ressource neben dem Deployment der Anwendung.
Der Operator legt den Client in Keycloak an, aktualisiert ihn bei Änderungen an der Ressource und löscht ihn, wenn die Ressource gelöscht wird.
Für SAML gibt es mit KeycloakSAMLClient das Gegenstück.
Technisch baut das auf der neuen Admin API v2 von Keycloak auf.
Sie ist zunächst nur für Clients verfügbar und unterscheidet sich deutlich von der bisherigen Admin REST API.
Die API validiert Eingaben streng, arbeitet deklarativ mit der vollständigen Zielkonfiguration und wird durch eine OpenAPI-Spezifikation beschrieben.
Die Felder unter spec.client folgen genau diesem Schema, nicht der alten ClientRepresentation.
Neben dem Operator gibt es für die Admin API v2 einen Java-Client, einen generierten JavaScript-Client und Unterstützung in der Kommandozeile.
Status und Voraussetzungen
| Version | Stand |
|---|---|
Keycloak 26.7 |
Admin API v2 und die Client-Ressourcen erscheinen als experimentelles Feature. |
Keycloak 26.8 |
Admin API v2, |
Preview bedeutet bei Keycloak: Das Feature ist für den Test gedacht, Schnittstelle und Verhalten können sich noch ändern.
Das zeigt auch die API-Version der Ressourcen, k8s.keycloak.org/v2alpha1.
Die Keycloak-CR selbst liegt weiterhin unter k8s.keycloak.org/v2beta1.
Auf dem Server muss das Feature client-admin-api:v2 aktiv sein.
Ab 26.8 ist es auch in --features=preview enthalten.
Über die Keycloak-CR sieht das so aus:
apiVersion: k8s.keycloak.org/v2beta1
kind: Keycloak
metadata:
name: example-kc
spec:
features:
enabled:
- client-admin-api:v2
Der Operator braucht außerdem Zugangsdaten, mit denen er die Admin API aufruft.
Er meldet sich per Client Credentials Flow am master-Realm an.
Client ID und Secret liest er aus einem Kubernetes Secret mit dem Namen <name-der-keycloak-cr>-admin im selben Namespace, hier also example-kc-admin, mit den Schlüsseln client-id und client-secret.
Dieses Secret und den zugehörigen Service-Account-Client legt der Operator derzeit nicht selbst an, das gehört zur Einrichtung des Bootstrap-Admins.
Laut Dokumentation soll das in einer späteren Version automatisiert werden.
apiVersion: v1
kind: Secret
metadata:
name: example-kc-admin
stringData:
client-id: operator-admin
client-secret: "<secret des service-account-clients>"
Wie Service Accounts in Keycloak funktionieren, beschreibt der Beitrag Keycloak Service Accounts statt technischer Benutzer.
Ein Client als Ressource
Ein vertraulicher Client mit Authorization Code Flow sieht so aus.
Das Client Secret kommt aus einem Kubernetes Secret, das der Operator nur verwendet, wenn es das Label operator.keycloak.org/kind: KeycloakOIDCClient trägt:
apiVersion: v1
kind: Secret
metadata:
name: my-app-credentials
labels:
operator.keycloak.org/kind: KeycloakOIDCClient
stringData:
client-secret-key: "<client secret>"
---
apiVersion: k8s.keycloak.org/v2alpha1
kind: KeycloakOIDCClient
metadata:
name: my-oidc-app # wird zur clientId, nicht änderbar
spec:
keycloakCRName: example-kc # Name der Keycloak-CR, nicht änderbar
realm: my-realm # nicht änderbar
client:
loginFlows:
- STANDARD
redirectUris:
- "https://my-app.example.com/*"
auth:
method: client-secret
secretRef:
name: my-app-credentials
key: client-secret-key
Damit ist die Richtung beim Secret klar: Kubernetes ist die führende Seite. Das Secret kann aus einem Secret Store kommen, etwa über den External Secrets Operator, und die Anwendung liest dasselbe Secret. Ändert sich der Wert, übernimmt der Operator ihn innerhalb seines Polling-Intervalls nach Keycloak.
Ob der Abgleich funktioniert hat, zeigt die Bedingung HasErrors im Status der Ressource:
kubectl get keycloakoidcclients/my-oidc-app \
-o go-template='{{range .status.conditions}}{{.type}}={{.status}} {{.message}}{{"\n"}}{{end}}'
Typische Ursachen für Fehler sind ein nicht aktiviertes Feature client-admin-api:v2, ein fehlendes oder nicht gelabeltes Secret und ein Keycloak, der noch nicht bereit ist.
Der Operator wiederholt fehlgeschlagene Abgleiche, bis sie gelingen.
Verhalten im Betrieb
Die Ressource muss die vollständige gewünschte Konfiguration des Clients enthalten. Was nicht drinsteht, gilt nicht als "nicht verwaltet", sondern als nicht gesetzt.
Der Operator erkennt Änderungen in Keycloak nicht und überschreibt sie beim nächsten Abgleich. Das betrifft Änderungen in der Admin-Konsole genauso wie Änderungen über die API. Ausdrücklich gilt das auch für die serverseitige Rotation des Client Secrets. Die Client Secret Rotation über Client Policies ist mit 26.8 zwar offiziell unterstützt, passt aber nicht zu Clients, die der Operator verwaltet. Rotiert wird hier über das Kubernetes Secret.
Drei Angaben lassen sich nach dem Anlegen nicht mehr ändern: der Name der Ressource, der zur clientId wird, keycloakCRName und realm.
Wer einen Client umbenennen oder in einen anderen Realm verschieben will, legt eine neue Ressource an.
Beim Löschen entfernt der Operator zuerst den Client in Keycloak und dann die Ressource. Wird die Keycloak-CR vor den Client-Ressourcen gelöscht, erreicht der Operator den Server nicht mehr, und der Client bleibt in Keycloak zurück. Bei GitOps-Werkzeugen lohnt sich daher eine passende Reihenfolge, etwa über Sync Waves in Argo CD.
Den Realm selbst legt der Operator über diese Ressourcen nicht an.
Er muss vorher existieren, etwa über einen KeycloakRealmImport.
Sicherheit
Die Zugangsdaten im Admin-Secret sind mächtig.
Wer eine KeycloakOIDCClient- oder KeycloakSAMLClient-Ressource anlegen oder ändern darf, kann damit jeden Client anlegen oder ändern, den diese Zugangsdaten erreichen.
Eine Zuordnung, welche Ressource welche Clients besitzen darf, gibt es noch nicht, sie ist für eine spätere Version angekündigt.
Daraus folgen zwei Empfehlungen.
Erstens sollte das Recht auf diese Ressourcen per Kubernetes RBAC eng vergeben werden, nicht pauschal an jedes Team mit Zugriff auf den Namespace.
Zweitens sollte der Service-Account-Client des Operators nur so viele Rechte haben wie nötig.
Welche Rollen mindestens erforderlich sind, nennt die Dokumentation nicht.
Naheliegend ist ein eigener Client im master-Realm, der statt voller Admin-Rechte nur manage-clients für die betroffenen Realms erhält.
Wie sich Admin-Rechte in Keycloak einschränken lassen, zeigt der Beitrag Keycloak-Admins mit reduzierten Rechten.
Alternativen
Clients deklarativ zu verwalten ist kein neuer Wunsch, und es gibt etablierte Wege dafür.
Realm-Import
Keycloak kann beim Start Realms aus JSON-Dateien importieren, der Operator bietet dafür die Ressource KeycloakRealmImport.
Ein Import legt einen Realm samt Clients an, überschreibt aber einen bereits vorhandenen Realm nicht.
Für die Ersteinrichtung ist das gut geeignet, für die laufende Pflege einzelner Clients nicht.
keycloak-config-cli
Das Open-Source-Werkzeug keycloak-config-cli von adorsys gleicht Realm-Konfigurationen aus JSON- oder YAML-Dateien mit einem laufenden Keycloak ab. Es arbeitet idempotent, kann den ganzen Realm verwalten und läuft gut als Job in einer Pipeline oder als Helm-Hook. Es nutzt die bisherige Admin REST API und ist damit unabhängig vom Preview-Status der Admin API v2.
Terraform und OpenTofu
Der Terraform-Provider für Keycloak, inzwischen unter dem Dach des Keycloak-Projekts, deckt Realms, Clients, Rollen, Mapper und Identity Provider ab. Für Teams, die ihre Infrastruktur ohnehin mit Terraform oder OpenTofu verwalten, ist das der naheliegende Weg. Er bringt Plan und State mit, also eine Vorschau auf Änderungen und eine Erkennung von Abweichungen. Läuft daneben der Operator auf denselben Clients, überschreiben sich beide gegenseitig, ein Client sollte also genau ein Werkzeug als Eigentümer haben.
Crossplane
Mit dem Crossplane-Provider für Keycloak lassen sich Keycloak-Objekte ebenfalls als Kubernetes-Ressourcen beschreiben. Er basiert auf dem Terraform-Provider und deckt deutlich mehr ab als Clients. Wer Crossplane bereits einsetzt, bekommt damit einen ähnlichen Ablauf wie mit dem Operator, aber mit einem zusätzlichen System im Cluster.
Dynamic Client Registration
Die OpenID Connect Dynamic Client Registration nach RFC 7591 löst ein anderes Problem. Hier registriert sich der Client selbst zur Laufzeit über einen Endpunkt in Keycloak. Abgesichert wird das über Initial Access Tokens oder über Client Registration Policies, die zum Beispiel nur bestimmte Hosts zulassen. Für spätere Änderungen erhält der Client ein Registration Access Token nach RFC 7592.
Das passt, wenn die Clients vorab nicht bekannt sind, etwa bei Plattformen, auf denen Dritte Anwendungen anbinden, oder bei Agenten und Werkzeugen im MCP-Umfeld. Für die eigenen Anwendungen eines Teams ist es meist unpassend: Die Konfiguration liegt dann bei der Anwendung, nicht in Git, und das Token für die Registrierung muss selbst sicher verteilt werden. Eine neuere Variante für solche Szenarien ist das Client ID Metadata Document, das der Beitrag Keycloak als OAuth-Autorisierungsserver für MCP-Server beschreibt.
Skripte gegen die Admin API
Mit kcadm.sh oder eigenen Skripten gegen die Admin REST API lässt sich alles automatisieren.
Idempotenz, Fehlerbehandlung und das Erkennen von Abweichungen muss man dann aber selbst bauen.
Überblick
| Ansatz | Laufende Pflege | Status in Keycloak | Passt für |
|---|---|---|---|
|
ja, kontinuierlicher Abgleich |
Preview |
Clients neben dem Deployment der Anwendung, GitOps |
|
nein, nur beim Anlegen |
unterstützt |
Ersteinrichtung von Realms |
keycloak-config-cli |
ja, bei jedem Lauf |
externes Werkzeug |
ganzer Realm aus Dateien, Pipelines |
Terraform / OpenTofu, Crossplane |
ja, mit Plan bzw. Abgleich |
externes Werkzeug |
Infrastruktur als Code über Keycloak hinaus |
Dynamic Client Registration |
durch den Client selbst |
unterstützt |
Clients, die vorab nicht bekannt sind |
Was es bringt
Der größte Gewinn ist, dass der Client dort beschrieben wird, wo auch die Anwendung beschrieben wird. Ein Helm-Chart oder ein Kustomize-Overlay kann Deployment, Service, Ingress und Keycloak-Client gemeinsam ausliefern, mit den passenden Redirect URIs je Umgebung. Das Secret hat eine klare Quelle, und eine Änderung am Client ist ein Commit wie jede andere Änderung. Außerdem fällt kein zusätzliches Werkzeug an, der Operator ist ohnehin im Cluster.
Dem stehen der Preview-Status, die API-Version v2alpha1 und die noch fehlende Zuordnung von Ressourcen zu Clients gegenüber.
Für produktive Umgebungen sind keycloak-config-cli oder der Terraform-Provider derzeit die verlässlichere Wahl.
Für neue Projekte und Testumgebungen lohnt es sich, die Ressourcen jetzt auszuprobieren und die eigenen Anforderungen an das Projekt zurückzumelden, solange sich die Schnittstelle noch formen lässt.
Wer Keycloak vor dem Produktivbetrieb prüfen lassen möchte, findet dazu unser Production Readiness Review für Keycloak. Für den Einstieg in Keycloak, Kubernetes und die Anbindung eigener Anwendungen gibt es passende Schulungen.