Files
infra-keycloak/k8s
Stéphane Tailland 1b613768e7 Realign the realm seed with what Keycloak actually runs
This file is a bootstrap seed, not the live realm. Keycloak starts with
--import-realm under IGNORE_EXISTING and logs "Realm 'classic-models'
already exists. Import skipped", so editing it changes nothing on a
restart and the truth lives in Keycloak's database.

That divergence had already opened, in the direction that hurts: four
authorisations existed only in the running realm, granted through the
admin API while working out which audiences the gateway actually needs.

  classic-models-agent-catalogue  +catalog-api-audience
                                  +sales-api-audience
                                  +kong-token-exchange-broker-audience
  librechat                       +classic-models-agent-catalogue-audience

Rebuilding the realm from this file would have left the Catalogue agent
with two of its five scopes and no indication why it stopped working.

Compared object by object against the live realm: the inventories already
matched — 21 clients, 38 client scopes, none missing either way — so the
drift was in contents, not in the lists. optionalClientScopes are now
copied back for every client that differed, and a re-comparison reports no
remaining gap.

This closes today's drift; it does not fix the mechanism that allows it.
Keeping a seed honest by hand is the same arrangement the Flux entrypoints
had before they were made self-reconciling, and it will drift again.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-28 09:18:09 +02:00
..
2026-08-25 07:30:20 +02:00

Infra Keycloak (Kubernetes / CaC)

Déploiement de Keycloak 26.6.0 et PostgreSQL 16 en Configuration-as-Code (CaC) sous Kubernetes dans le namespace keycloak.

Structure du Répertoire

k8s/
├── kustomization.yaml             # Manifeste Kustomize principal
├── namespace.yaml                 # Namespace keycloak
├── secret.yaml                    # Secrets (Admin, DB, OIDC secrets)
├── secret.example.yaml            # Gabarit des secrets
├── postgresql/
│   ├── pvc.yaml                   # Stockage persistant PostgreSQL (2Gi)
│   ├── statefulset.yaml           # Base de données PostgreSQL 16
│   └── service.yaml               # Service PostgreSQL (port 5432)
├── keycloak/
│   ├── configmap-realm.yaml       # Realm classic-models (Configuration-as-Code)
│   ├── deployment.yaml            # Déploiement Keycloak 26.6.0 (--import-realm)
│   └── service.yaml               # Service Keycloak (ports 8080, 9000)
└── ingress/
    ├── tls.yaml                   # Secret TLS wildcard (*.sttlab.local)
    └── ingress.yaml               # Ingress NGINX (keycloak.sttlab.local)

Fonctionnalités Clés

  • Version Keycloak : quay.io/keycloak/keycloak:26.6.0 (Runtime Quarkus).
  • Import Automatique du Realm (CaC) : Le realm classic-models est chargé au démarrage via l'option --import-realm depuis le ConfigMap monté dans /opt/keycloak/data/import/.
  • Token Exchange RFC 8693 : Activé via KC_FEATURES: "token-exchange,admin-fine-grained-authz".
  • Clients Configurés :
    • librechat : Client OIDC pour le login et le flux OAuth MCP.
    • mcp-catalog : Audience du serveur MCP.
    • kong-token-exchange-broker : Échangeur de jetons RFC 8693 de Kong Gateway.
    • catalog-api & classic-models-api : Audiences des services backend.
  • Utilisateurs & Rôles :
    • admin-user (admin)
    • pm-user (product_manager)
    • ro-user (read_only)
    • customer-user (customer)
    • support-user (support)

Déploiement

k8s/secret.yaml n'est pas versionné : il porte les mots de passe réels (base PostgreSQL, admin Keycloak, secrets clients OIDC). Le créer une fois depuis le gabarit, puis renseigner chaque <CHANGE_ME> :

cp k8s/secret.example.yaml k8s/secret.yaml
$EDITOR k8s/secret.yaml

k8s/kustomization.yaml le référence, donc le déploiement échoue tant qu'il est absent.

kubectl apply -k k8s/