1b613768e7
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>
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-modelsest chargé au démarrage via l'option--import-realmdepuis leConfigMapmonté 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/