Confidentialite¶
Keycloak manipule des données classees Restreint : identités, mots de passe hashes, secrets MFA, sessions actives. Ce chapitre detaille les mesures de protection correspondantes, en référence au cadre de Classification et zones de confiance.
Rappel de classification¶
| Donnée | Classification | Justification |
|---|---|---|
| Identités (noms, emails) | Confidentiel | Données personnelles (RGPD) |
| Mots de passe hashes | Restreint | Compromission = accès total |
| Secrets TOTP / WebAuthn | Restreint | Facteur d'authentification |
| Sessions actives (tokens) | Restreint | Usurpation d'identité possible |
| Logs d'authentification | Confidentiel | Révèlent les patterns d'usage |
| Configuration des realms | Confidentiel | Révèlent l'architecture de sécurité |
Impact d'une compromission
La compromission de Keycloak donne accès a tous les services de la DSI. L'IAM est le SPOF de sécurité. Les mesures ci-dessous sont obligatoires, pas optionnelles.
Chiffrement des credentials via Vault¶
Les secrets de Keycloak (mots de passe de base de données, cles de signature, client secrets) ne doivent jamais etre stockes en clair.
Architecture Vault + Keycloak¶
graph LR
KC["Keycloak<br/>vault:// ref"] --> Vault["Vault<br/>Transit<br/>KV v2"]
Vault --> HSM["HSM / KMS<br/>(cles racines)"] Configuration du Vault SPI¶
Keycloak supporte un SPI (Service Provider Interface) pour charger les secrets depuis Vault :
# Variables d'environnement pour le provider Vault
KC_VAULT_URL=https://vault.example.com
KC_VAULT_TOKEN_FILE=/run/secrets/vault_token
KC_VAULT_MOUNT=secret
KC_VAULT_PREFIX=keycloak
Les secrets sont références dans la configuration Keycloak par ${vault.secret-name} :
# Exemple : mot de passe LDAP stocke dans Vault
kcadm.sh create components -r organization \
-s 'config.bindCredential=["${vault.ldap-bind-password}"]'
Secrets a stocker dans Vault¶
| Secret | Chemin Vault | Rotation |
|---|---|---|
| Mot de passe PostgreSQL | secret/keycloak/db-password | 90 jours |
| Bind password LDAP | secret/keycloak/ldap-bind-password | 90 jours |
| Cle de signature JWT (realm key) | secret/keycloak/realm-signing-key | 1 an |
| Client secrets OIDC | secret/keycloak/clients/<client-id> | 90 jours |
| Cookie encryption key | secret/keycloak/cookie-key | 1 an |
Rotation automatique
Utiliser le moteur de secrets dynamiques de Vault pour PostgreSQL (database/) afin de générer automatiquement des credentials a courte duree de vie.
Audit des événements¶
Événements a journaliser¶
Keycloak produit deux types d'événements :
| Type | Exemples | Retention |
|---|---|---|
| Login events | LOGIN, LOGIN_ERROR, LOGOUT, REGISTER, MFA_VERIFY | 1 an |
| Admin events | CREATE_USER, UPDATE_REALM, DELETE_CLIENT, GRANT_ROLE | 5 ans |
Activer l'audit complet¶
# Activer les login events
kcadm.sh update events/config -r organization \
-s eventsEnabled=true \
-s 'enabledEventTypes=["LOGIN","LOGIN_ERROR","LOGOUT","REGISTER","CODE_TO_TOKEN","CODE_TO_TOKEN_ERROR","CLIENT_LOGIN","CLIENT_LOGIN_ERROR","FEDERATED_IDENTITY_LINK","REMOVE_FEDERATED_IDENTITY","UPDATE_EMAIL","UPDATE_PROFILE","VERIFY_EMAIL","CUSTOM_REQUIRED_ACTION","GRANT_CONSENT","UPDATE_CONSENT","REVOKE_GRANT","SEND_RESET_PASSWORD","UPDATE_TOTP","REMOVE_TOTP","SEND_VERIFY_EMAIL","VERIFY_PROFILE"]' \
-s eventsExpiration=31536000
# Activer les admin events
kcadm.sh update events/config -r organization \
-s adminEventsEnabled=true \
-s adminEventsDetailsEnabled=true
Exporter les événements vers le SIEM¶
Keycloak peut exporter ses événements vers un système de log externe via un SPI custom ou via les logs stdout :
# Configuration du format de log pour Loki/Alloy
KC_LOG: console
KC_LOG_CONSOLE_FORMAT: "%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p [%c] (%t) %s%e%n"
KC_LOG_CONSOLE_OUTPUT: json
Exemple de log d'événement structure :
{
"timestamp": "2026-04-16T14:32:15.123Z",
"level": "INFO",
"logger": "org.keycloak.events",
"message": "type=LOGIN, realmId=organization, clientId=svc-gitea, userId=abc-123, ipAddress=10.20.1.45, auth_method=openid-connect, auth_type=code, username=fabien"
}
Alertes de sécurité¶
| Alerte | Condition | Sévérité | Action |
|---|---|---|---|
| Brute force | > 5 LOGIN_ERROR en 5 min pour un même utilisateur | Warning | Notification SOC |
| Compte verrouille | ACCOUNT_DISABLED | Warning | Vérification manuelle |
| Admin login | LOGIN sur le realm master | Critical | Notification immédiate |
| Nouveau device MFA | UPDATE_TOTP ou REGISTER_TOTP | Info | Notification a l'utilisateur |
| Client secret modifie | Admin event UPDATE_CLIENT | Warning | Vérification d'autorisation |
Isolation réseau¶
Segment dedie¶
Keycloak est déployé dans un segment réseau isole au sein de la zone Entreprise :
graph TD
subgraph Zone["Zone Entreprise"]
subgraph IAM["Segment IAM (10.20.1.0/24)"]
KC1["Keycloak #1"]
KC2["Keycloak #2"]
PG["PostgreSQL"]
end
Mail
Collab
VDI
end Regles de flux¶
| Source | Destination | Port | Protocole | Justification |
|---|---|---|---|---|
| Toutes les zones | Keycloak | 443/TCP | OIDC/SAML | Authentification |
| Keycloak | PostgreSQL | 5432/TCP | PostgreSQL + TLS | Persistance |
| Keycloak | LDAP | 636/TCP | LDAPS | Fédération |
| Keycloak | Vault | 8200/TCP | HTTPS | Secrets |
| Keycloak | SMTP | 587/TCP | STARTTLS | Emails (reset password, MFA) |
| Management | Keycloak | 9000/TCP | HTTPS | Health checks, metriques |
Aucun accès direct a PostgreSQL
La base de données Keycloak ne doit etre accessible que depuis les instances Keycloak. Aucun autre service ne doit pouvoir s'y connecter directement.
Backup chiffre¶
Stratégie de sauvegarde¶
| Composant | Méthode | Fréquence | Retention | Chiffrement |
|---|---|---|---|---|
| Base PostgreSQL | pg_dump + WAL archiving | Toutes les 6h + continu | 30 jours | AES-256 (Vault Transit) |
| Configuration realms | Export JSON via kcadm.sh | Quotidien | 90 jours | AES-256 |
| Cles de signature | Backup Vault | Selon politique Vault | 1 an | HSM-backed |
Script de backup chiffre¶
#!/bin/bash
# /home/keycloak/scripts/backup.sh
set -euo pipefail
DATE=$(date +%Y%m%d-%H%M%S)
BACKUP_DIR="/backup/keycloak"
VAULT_ADDR="https://vault.example.com"
# Dump PostgreSQL
pg_dump -h localhost -U keycloak keycloak | \
vault write -field=ciphertext transit/encrypt/keycloak-backup \
plaintext=@- > "${BACKUP_DIR}/db-${DATE}.enc"
# Export des realms
podman exec keycloak /opt/keycloak/bin/kcadm.sh export \
--dir /tmp/export --realm organization
podman cp keycloak:/tmp/export/organization-realm.json - | \
vault write -field=ciphertext transit/encrypt/keycloak-backup \
plaintext=@- > "${BACKUP_DIR}/realm-${DATE}.enc"
# Nettoyage des backups > 30 jours
find "${BACKUP_DIR}" -name "*.enc" -mtime +30 -delete
echo "Backup completed: ${DATE}"
Vérification de restauration¶
Tester la restauration
Un backup non teste est un faux sentiment de sécurité. Planifier un test de restauration trimestriel dans un environnement isole.
# Dechiffrer et restaurer
vault write -field=plaintext transit/decrypt/keycloak-backup \
ciphertext=@"${BACKUP_DIR}/db-${DATE}.enc" | \
pg_restore -h localhost -U keycloak -d keycloak_restore
Politique de retention¶
| Donnée | Retention active | Retention archivee | Suppression |
|---|---|---|---|
| Comptes actifs | Duree d'emploi | N/A | A la desactivation |
| Comptes desactives | 90 jours | 1 an (anonymise) | Apres archivage |
| Sessions | Duree de la session | 30 jours (logs) | Automatique |
| Login events | 1 an | 2 ans (anonymise) | Automatique |
| Admin events | 5 ans | 5 ans | Sur decision RSSI |
MFA obligatoire pour les administrateurs¶
Les comptes administrateurs Keycloak (realm admin, master admin) doivent avoir le MFA active et une politique renforcee.
Configuration¶
# Creer un groupe admin avec politique MFA stricte
kcadm.sh create groups -r organization -s name=keycloak-admins
# Creer une politique d'authentification admin
kcadm.sh update realms/organization \
-s 'browserFlow=browser-admin-mfa'
Politique de compte admin¶
| Parametre | Valeur |
|---|---|
| MFA | WebAuthn obligatoire (pas TOTP seul) |
| Session idle timeout | 15 minutes |
| Session max lifespan | 4 heures |
| Mot de passe | 16 caractères minimum |
| Rotation | 60 jours |
| Accès | Uniquement depuis le segment management |
Comptes admin nominatifs
Ne jamais utiliser un compte admin generique partage. Chaque administrateur doit avoir son propre compte pour la traçabilité. Supprimer le compte admin par defaut apres avoir cree les comptes nominatifs.