Aller au contenu

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.