Configuration en code et environnements
Comparer export et import de realm, provider Terraform et keycloak-config-cli pour décrire la configuration de Keycloak en code, la promouvoir d'un environnement à l'autre et tenir les secrets hors du dépôt.
Sur cette page
Configurer Keycloak à la main dans la console fonctionne pour un essai. Dès qu’il y a plusieurs environnements (développement, recette, production) et plusieurs personnes, la configuration doit vivre dans un dépôt Git : relue, versionnée, rejouable. Ce cours compare les trois approches les plus courantes, puis traite la promotion entre environnements et les secrets.
Ce qu’on décrit en code, et ce qu’on n’y met pas
La configuration couvre le realm et ses réglages, les clients, les client scopes et protocol mappers, les rôles, les groupes, les flux d’authentification, les fournisseurs d’identité et la fédération d’annuaire. Elle exclut les comptes des usagers, qui relèvent du provisionnement, ainsi que les sessions et les événements. Seuls quelques comptes techniques, comme des comptes de test en recette, ont leur place dans le dépôt.
Export et import de realm
Keycloak sait exporter et importer un realm complet en JSON :
bin/kc.sh export --realm socle --dir /tmp/export --users skip
bin/kc.sh import --dir /tmp/export --override false
Ces commandes s’exécutent avec le serveur arrêté, sur la même base de données. Au démarrage, l’option --import-realm importe les fichiers JSON du dossier data/import, mais ignore un realm déjà présent. Les fichiers importés peuvent contenir des placeholders résolus depuis l’environnement, par exemple "secret": "${PORTAIL_SECRET}".
L’export partiel de la console (Realm settings, menu Action) n’exporte pas les utilisateurs et masque les secrets par des astérisques. La documentation précise qu’il ne convient ni aux sauvegardes ni aux transferts entre serveurs.
L’export est un bon point de départ et un bon outil de sauvegarde, mais un mauvais format de travail. Il contient tous les identifiants internes et toutes les valeurs par défaut, et il ne sait pas faire évoluer un realm existant par différence.
Le provider Terraform
Le provider Terraform pour Keycloak est maintenu dans l’organisation GitHub keycloak et publié sur le registry sous keycloak/keycloak (il s’appelait auparavant mrparkers/keycloak). Un état existant migre avec terraform state replace-provider mrparkers/keycloak keycloak/keycloak. Le projet annonce supporter officiellement les trois dernières versions mineures de Keycloak.
terraform {
required_providers {
keycloak = {
source = "keycloak/keycloak"
version = "~> 5.10"
}
}
}
provider "keycloak" {
url = var.keycloak_url
realm = "master"
client_id = "terraform"
client_secret = var.terraform_client_secret
}
resource "keycloak_realm" "socle" {
realm = "socle"
enabled = true
ssl_required = "external"
login_theme = var.login_theme
}
resource "keycloak_openid_client" "portail" {
realm_id = keycloak_realm.socle.id
client_id = "portail"
access_type = "CONFIDENTIAL"
standard_flow_enabled = true
pkce_code_challenge_method = "S256"
valid_redirect_uris = ["${var.portail_url}/callback"]
}
Forces : terraform plan montre l’écart avant d’agir, ce qui détecte les modifications manuelles (la dérive) ; les références entre ressources sont typées ; Terraform est souvent déjà utilisé pour l’infrastructure. Limites : chaque ressource Keycloak doit avoir son équivalent dans le provider, avec parfois un temps de retard sur les nouveautés ; l’état contient des secrets.
keycloak-config-cli
keycloak-config-cli, projet communautaire d’adorsys, applique un état décrit en JSON ou YAML au format d’export de realm. Il est idempotent : relancé sur un realm déjà conforme, il ne change rien. Il mémorise dans le realm ce qu’il a créé (remote state), ce qui lui permet de supprimer une ressource retirée du fichier sans toucher à ce qui a été créé autrement (comportement par défaut, réglable par les options import.managed.* et import.remote-state.*). Le projet vise les quatre dernières versions de Keycloak et publie des images Docker étiquetées par version de Keycloak.
realm: "socle"
enabled: true
loginTheme: "keycloak"
roles:
realm:
- name: "agent"
groups:
- name: "agents"
realmRoles:
- "agent"
clients:
- clientId: "portail"
protocol: "openid-connect"
publicClient: false
standardFlowEnabled: true
redirectUris:
- "$(env:PORTAIL_URL)/callback"
secret: "$(env:PORTAIL_SECRET)"
attributes:
pkce.code.challenge.method: "S256"
La substitution $(env:…) n’est active qu’avec IMPORT_VARSUBSTITUTION_ENABLED=true, et elle s’exécute là où tourne l’outil. Forces : le format est celui que la console exporte, donc familier ; pas d’état externe à stocker ; un fichier par realm ou par domaine fonctionnel. Limites : pas de plan préalable aussi lisible que celui de Terraform ; l’outil dépend d’un tiers et doit suivre les versions de Keycloak.
Choisir son outillage
| Critère | Export / import natif | Terraform | keycloak-config-cli |
|---|---|---|---|
| Faire évoluer un realm existant | Non (écrasement ou rien) | Oui, par différence | Oui, par convergence |
| Voir l’écart avant d’appliquer | Non | Oui (plan) | Partiel (journaux) |
| Format | JSON complet et bruité | HCL | JSON ou YAML au format d’export |
| Stockage d’un état | Aucun | État Terraform, contient des secrets | Dans le realm, chiffrable |
| Dépendance | Aucune | Provider externe | Outil communautaire |
| Cas d’usage type | Sauvegarde, initialisation d’un poste | Équipe déjà outillée Terraform, infrastructure et IAM ensemble | Équipe proche de Keycloak, migration d’une configuration existante |
Les deux outils couvrent le besoin. Le critère décisif est souvent l’existant de l’équipe d’exploitation. Évitez de mélanger deux outils sur le même realm : chacun croirait que l’autre crée de la dérive.
Promouvoir d’un environnement à l’autre
Une chaîne saine suit trois règles :
- Une source unique. Les mêmes fichiers servent à tous les environnements. Ce qui varie (URL, redirect URIs, thème, secrets, durées) passe par des variables.
- Un ordre fixe. Développement, puis recette, puis production, avec relecture des changements avant chaque passage.
- Pas de modification manuelle en production. Les droits de la console de production sont limités à la consultation pour l’équipe projet. Toute correction passe par le dépôt, sinon la prochaine application l’écrase.
Les identifiants internes (UUID) diffèrent d’un environnement à l’autre : les fichiers doivent référencer les objets par leur nom (clientId, nom de rôle), jamais par UUID.
Les secrets
Trois familles de secrets circulent dans cette chaîne :
- Les secrets des clients confidentiels. Ils n’entrent pas dans le dépôt. Soit ils sont injectés depuis un coffre au moment de l’application, soit Keycloak les génère et l’outil les lit pour les transmettre à l’application. Depuis 26.8, la rotation des secrets clients est supportée : deux secrets peuvent être actifs pendant la transition. Quand l’application le permet, l’authentification par clé privée signée évite tout secret partagé.
- Le secret de l’outil lui-même. L’outil s’authentifie avec un compte de service. S’il crée des realms, il lui faut le rôle
admindu realm master, un droit très large à protéger comme tel. S’il ne gère qu’un realm, le rôlerealm-adminde ce realm suffit. - L’état. L’état Terraform contient les secrets en clair : backend distant chiffré, accès restreint. keycloak-config-cli peut chiffrer son état distant avec une clé dédiée.
Appliquer un realm décrit en YAML
30 min
Installer le lab-
Créez un dossier
kccet un fichierkcc/socle-lab.yamlreprenant l’exemple YAML du cours, en remplaçantsocleparsocle-lab. -
Appliquez-le avec keycloak-config-cli (sous macOS ou Windows, remplacez
--network hostetlocalhostparhost.docker.internal) :docker run --rm --network host \ -e KEYCLOAK_URL=http://localhost:8080 \ -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin \ -e IMPORT_FILES_LOCATIONS='/config/*' \ -e IMPORT_VARSUBSTITUTION_ENABLED=true \ -e PORTAIL_URL=http://localhost:3000 \ -e PORTAIL_SECRET=secret-de-dev-uniquement \ -v "$PWD/kcc":/config \ adorsys/keycloak-config-cli:latest-26 -
Dans la console, vérifiez le realm
socle-lab, le clientportail(PKCE en S256, redirect URI résolue), le rôleagentet le groupeagents. -
Relancez exactement la même commande : les journaux indiquent qu’il n’y a rien à modifier.
-
Ajoutez un rôle
superviseurau fichier, relancez, puis retirez-le et relancez encore. Observez la création puis la suppression du rôle. -
Créez à la main un rôle
manueldans la console, puis relancez l’outil : avec le remote state actif (réglage par défaut), il n’est pas supprimé, car l’outil ne l’a pas créé. -
Faites un export partiel par l’API et regardez le secret du client :
KC=http://localhost:8080 TOKEN=$(curl -s -d client_id=admin-cli -d username=admin -d password=admin \ -d grant_type=password "$KC/realms/master/protocol/openid-connect/token" | jq -r .access_token) curl -s -X POST -H "Authorization: Bearer $TOKEN" \ "$KC/admin/realms/socle-lab/partial-export?exportClients=true&exportGroupsAndRoles=true" \ | jq '.clients[] | select(.clientId=="portail") | {clientId, secret}' -
Le secret est masqué. Notez pourquoi cet export ne peut pas servir à promouvoir la configuration vers un autre environnement.
À retenir pour l’architecture
Le document d’architecture doit trancher un outil (Terraform ou keycloak-config-cli), décrire la chaîne de promotion et ses validations, interdire la modification manuelle en production, et dire où vivent les secrets. Vérifiez avec l’hébergeur que la chaîne de déploiement peut joindre l’Admin REST API de chaque environnement, et avec quel compte technique.
Natif, extension ou hébergeur
Natif : fourni par Keycloak, à configurer. Extension : demande du code à maintenir (un SPI, le mécanisme de plugin de Keycloak). Hébergeur : dépend de la plateforme qui héberge Keycloak, à vérifier avec elle.
| Capacité | Verdict | Précision |
|---|---|---|
| Export et import de realm (commandes kc.sh, import au démarrage) | Natif | Fiable pour sauvegarder ou initialiser un environnement. L'import au démarrage ignore un realm déjà présent. |
| Variables d'environnement dans les fichiers de realm importés | Natif | Syntaxe de placeholder documentée dans le guide Importing and exporting realms. |
| Provider Terraform keycloak/keycloak | Extension | Outil externe au serveur, maintenu dans l'organisation GitHub keycloak. Supporte officiellement les trois dernières versions mineures. |
| keycloak-config-cli | Extension | Outil communautaire (adorsys) qui applique un état décrit en JSON ou YAML au format d'export de realm. |
| Rotation des secrets clients | Natif | Supportée et activée par défaut depuis 26.8, pilotée par les client policies. |
| Accès à l'Admin REST API depuis la chaîne de déploiement | Hébergeur | Ouverture réseau, comptes techniques et environnements disponibles sont à vérifier avec l'hébergeur. |
Vérifier ce que vous avez retenu
4 questions
-
Vous voulez que la recette et la production aient la même configuration de clients, avec des URL et des secrets différents. Quelle approche retenez-vous ?
La promotion repose sur une source unique, des variables par environnement et un outil qui converge vers l'état décrit. L'export de console masque les secrets et contient des identifiants internes propres à l'environnement d'origine.
-
L'équipe veut utiliser --import-realm au démarrage pour appliquer chaque modification de configuration en production. Quel est le problème ?
L'import au démarrage sert à initialiser. Pour faire évoluer un realm existant, il faut un outil qui calcule les différences (Terraform, keycloak-config-cli).
-
Avec Terraform, où se retrouvent les secrets des clients confidentiels ?
Les attributs sensibles, dont client_secret, sont écrits dans l'état. Un backend distant chiffré avec des droits d'accès restreints est indispensable.
-
Quelle population ne devrait pas être gérée par l'outil de configuration en code ?
Les comptes des usagers relèvent du provisionnement et du cycle de vie, pas de la configuration. Seuls quelques comptes techniques peuvent être décrits en code.