Événements, journaux et SOC
Distinguer événements utilisateur et événements d'administration, régler leur conservation, et choisir comment les faire parvenir à un SIEM : journaux serveur, API ou event listener.
Sur cette page
Un SOC (centre opérationnel de sécurité) attend d’un fournisseur d’identité deux choses : savoir qui s’est connecté ou a échoué, et savoir qui a modifié la configuration ou les comptes. Keycloak produit ces traces sous forme d’événements. Ce cours explique leurs deux familles, leur conservation, et les trois manières de les faire sortir de Keycloak vers un SIEM (outil de collecte et de corrélation des journaux de sécurité).
Deux familles d’événements
| Événements utilisateur | Événements d’administration | |
|---|---|---|
| Déclencheur | Connexion, échange de code, rafraîchissement, changement de mot de passe, liaison d’IdP | Toute modification par la console ou l’Admin REST API |
| Exemples | LOGIN, LOGIN_ERROR, LOGOUT, CODE_TO_TOKEN, UPDATE_CREDENTIAL, USER_DISABLED_BY_TEMPORARY_LOCKOUT | CREATE sur USER, UPDATE sur CLIENT, CREATE sur REALM_ROLE_MAPPING |
| Contenu | Type, client, utilisateur, session, adresse IP, erreur, détails | Opération, type et chemin de la ressource, auteur, IP, et éventuellement le JSON envoyé |
| Réglage | Realm settings, Events, User events settings | Realm settings, Events, Admin events settings |
Chaque événement utilisateur a son pendant en erreur (LOGIN_ERROR, UPDATE_PROFILE_ERROR…). Un événement d’erreur porte un code, par exemple invalid_user_credentials ou user_not_found. Le type UPDATE_CREDENTIAL remplace les anciens types dédiés au mot de passe et au TOTP, désormais dépréciés : le type de credential figure dans les détails.
Conservation en base : utile, mais pas un SIEM
Par défaut, Keycloak ne stocke pas les événements. Seules les erreurs sont écrites dans le journal serveur. L’activation se fait par realm :
- Save events pour les événements utilisateur, avec la liste des types à enregistrer et une expiration en secondes (
eventsExpiration) qui purge les plus anciens ; - Save events pour les événements d’administration, et l’option Include representation qui conserve le corps JSON de chaque requête.
kcadm.sh update events/config -r approfondir \
-s eventsEnabled=true \
-s eventsExpiration=604800 \
-s adminEventsEnabled=true \
-s adminEventsDetailsEnabled=true
Les événements stockés se consultent dans la console (menu Events) ou par l’API, avec le rôle view-events :
curl -s -H "Authorization: Bearer $TOKEN" \
"http://localhost:8080/admin/realms/approfondir/events?type=LOGIN_ERROR&max=20"
Le stockage en base sert le support et le diagnostic : retrouver pourquoi un utilisateur a échoué hier. Pour la conservation longue, la corrélation entre systèmes et l’alerte, la référence est le SIEM. Fixez l’expiration en conséquence, par exemple quelques jours à quelques semaines, et faites valider la durée de conservation côté SIEM par le délégué à la protection des données.
Les event listeners
Chaque événement est transmis aux event listeners déclarés pour le realm (Realm settings, Events, onglet Event listeners). Un listener est un fournisseur de l’Event Listener SPI (Service Provider Interface, point d’extension Java de Keycloak). Deux listeners sont fournis :
- jboss-logging, actif par défaut : il écrit les événements dans la catégorie de journal
org.keycloak.events. Les erreurs sortent enWARN, les succès enDEBUG, donc invisibles par défaut. - email : il prévient l’utilisateur de certains événements (erreur de connexion, changement de credential), si son e-mail est vérifié.
Pour que les succès apparaissent dans les journaux, relevez leur niveau au démarrage :
bin/kc.sh start \
--spi-events-listener--jboss-logging--success-level=info \
--spi-events-listener--jboss-logging--error-level=warn \
--log-console-output=json \
--log-console-json-format=ecs
La syntaxe à double tiret entre SPI, fournisseur et option est celle de la documentation actuelle ; d’anciennes versions de la branche 26 documentent une forme à tiret simple. La sortie JSON au format ECS (Elastic Common Schema) facilite l’ingestion par la plupart des SIEM. Keycloak sait aussi envoyer ses journaux à un serveur syslog (--log=console,syslog et --log-syslog-endpoint).
Écrire son propre listener
Quand le SIEM attend autre chose qu’un flux de journaux (un bus Kafka, une API HTTP, un format imposé), on écrit un listener. Le contrat tient en deux méthodes :
public class SiemEventListenerProvider implements EventListenerProvider {
private final SiemSender sender;
public SiemEventListenerProvider(SiemSender sender) {
this.sender = sender;
}
@Override
public void onEvent(Event event) {
sender.send(Map.of(
"type", event.getType().name(),
"realm", event.getRealmId(),
"client", String.valueOf(event.getClientId()),
"user", String.valueOf(event.getUserId()),
"ip", String.valueOf(event.getIpAddress()),
"error", String.valueOf(event.getError())));
}
@Override
public void onEvent(AdminEvent event, boolean includeRepresentation) {
sender.send(Map.of(
"operation", event.getOperationType().name(),
"resource", event.getResourcePath(),
"admin", String.valueOf(event.getAuthDetails().getUserId())));
}
@Override
public void close() {
}
}
Une EventListenerProviderFactory crée ce provider à chaque requête et expose son identifiant (getId()), qui apparaît ensuite dans la liste des listeners du realm. Le JAR est déposé dans providers/.
Trois précautions de conception :
- Ne pas bloquer la connexion. Le listener s’exécute dans la requête de l’utilisateur. Un SIEM lent ne doit pas ralentir les connexions : file d’attente locale, envoi asynchrone, délais courts.
- Prévoir la perte. Si le SIEM est indisponible, que deviennent les événements ? Tampon, rejeu, ou acceptation de la perte : c’est une décision à écrire.
- Accepter le coût de maintenance. La documentation classe l’Event Listener SPI comme interne : stable jusqu’ici, mais modifiable à chaque version sans préavis. Le listener doit être retesté à chaque montée de version.
Choisir la voie vers le SIEM
| Voie | Natif ou extension | Temps réel | Avantages | Limites |
|---|---|---|---|---|
| Journaux serveur (jboss-logging, JSON, syslog ou collecte) | Natif | Oui | Rien à développer, couvre aussi les erreurs techniques | Dépend de la collecte de l’hébergeur ; format à normaliser côté SIEM |
| Lecture périodique de l’API events | Natif côté Keycloak, script côté SOC | Non (intervalle) | Simple, pas de code dans Keycloak | Exige le stockage en base ; risque de trous si l’expiration est trop courte |
| Event listener maison | Extension | Oui | Format et destination maîtrisés | Code Java à maintenir ; SPI interne ; déploiement soumis à l’hébergeur |
En première intention, la voie des journaux serveur est la plus sobre. Le listener se justifie quand le SOC impose un format ou un transport que la collecte de journaux ne sait pas produire.
Ce que propose l’hébergeur : à vérifier
Avec un Keycloak managé, vous ne contrôlez ni les options de démarrage ni la collecte des journaux. Avant de concevoir quoi que ce soit, posez ces questions à l’hébergeur :
- Les journaux serveur (dont
org.keycloak.events) sont-ils collectés ? Peut-on relever le niveau des succès ? - Sous quel format et par quel transport sont-ils transmis (syslog, HTTPS, connecteur SIEM), avec quel délai ?
- Les événements d’administration sont-ils inclus ? Le filtrage par realm est-il possible ?
- Un event listener maison peut-il être déployé, et selon quelles conditions de recette ?
- Quelle est la durée de conservation de leur côté, et qui y a accès ?
Aucune réponse ne doit être supposée : notez-les comme hypothèses dans le document d’architecture tant qu’elles ne sont pas confirmées.
Des événements aux indicateurs
Les mêmes événements alimentent le suivi du déploiement. Depuis 26.2, Keycloak expose des métriques d’événements utilisateur sur son endpoint de métriques (--metrics-enabled=true et --event-metrics-user-enabled=true), agrégées par realm et, en option, par client ou IdP. Exemples d’indicateurs :
- taux d’échec de connexion par application (
LOGIN_ERRORrapporté àLOGIN) ; - adoption du second facteur (
UPDATE_CREDENTIALdont le type estotpouwebauthn) ; - verrouillages par force brute (
USER_DISABLED_BY_TEMPORARY_LOCKOUT) ; - volume de réinitialisations de mot de passe, signe d’un parcours mal compris.
Tracer connexions et actions d'administration
25 min
Installer le lab-
Dans le realm
approfondir(créez-le s’il n’existe pas), ouvrez Realm settings, Events. Dans User events settings, activez Save events et fixez l’expiration à 7 jours. Dans Admin events settings, activez Save events et Include representation. Enregistrez. -
Créez un utilisateur
caroleavec un mot de passe non temporaire. -
En fenêtre privée, ouvrez http://localhost:8080/realms/approfondir/account et échouez deux fois la connexion de
carole, puis réussissez-la. -
Récupérez un jeton d’administration et listez les événements :
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 -H "Authorization: Bearer $TOKEN" \ "$KC/admin/realms/approfondir/events?max=10" | jq '.[] | {type, clientId, ipAddress, error}' -
Vérifiez la présence de deux
LOGIN_ERRORavec l’erreurinvalid_user_credentials, puis d’unLOGIN. -
Modifiez le prénom de
caroledans la console, puis listez les événements d’administration et repérez la représentation JSON. Le jeton d’administration expire au bout d’une minute : relancez la commandeTOKEN=…si l’API répond 401.curl -s -H "Authorization: Bearer $TOKEN" \ "$KC/admin/realms/approfondir/admin-events?max=5" | jq '.[] | {operationType, resourcePath, representation}' -
Regardez le journal de votre conteneur Keycloak (
docker logsoudocker compose logs) : lesLOGIN_ERRORy figurent enWARN, lesLOGINréussis n’y sont pas. Notez ce qu’il faudrait changer au démarrage pour les y voir.
À retenir pour l’architecture
Activez le stockage en base avec une expiration courte pour le support. Visez les journaux serveur en JSON comme voie principale vers le SOC, sous réserve de ce que l’hébergeur collecte réellement. Réservez l’event listener maison aux exigences de format ou de transport que les journaux ne couvrent pas, en chiffrant son coût de maintenance.
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 |
|---|---|---|
| Enregistrement des événements utilisateur et d'administration en base | Natif | Désactivé par défaut. Activation, types enregistrés et expiration se règlent par realm. |
| Événements dans les journaux serveur (listener jboss-logging, sortie JSON, syslog) | Natif | Listener actif par défaut. Niveaux, format JSON (dont ECS) et handler syslog se règlent au démarrage. |
| Métriques agrégées des événements utilisateur | Natif | Depuis 26.2, options event-metrics-user-* avec les métriques activées. |
| Envoi direct des événements vers un SIEM, un bus ou une API | Extension | Event listener à écrire. SPI classée interne par Keycloak : peut changer sans préavis. |
| Collecte des journaux et transmission au SOC | Hébergeur | Dépend de l'hébergeur : format, transport, filtrage et délai de mise à disposition sont à vérifier avec lui. |
Vérifier ce que vous avez retenu
4 questions
-
Le SOC veut recevoir les échecs de connexion en quasi temps réel. Keycloak est hébergé par un tiers qui collecte déjà les journaux serveur. Quelle option examiner en premier ?
Les erreurs de connexion sont déjà journalisées nativement. Si l'hébergeur transmet les journaux, aucune extension n'est nécessaire : il reste à valider le format et le transport.
-
Vous activez Include representation sur les événements d'administration. Quel risque devez-vous traiter ?
La représentation contient le corps JSON des requêtes d'administration : volume plus important, et données personnelles à couvrir par la politique de conservation.
-
Pourquoi ne pas faire de la base de Keycloak le stockage de référence des journaux de sécurité ?
Le stockage en base sert la consultation opérationnelle. La conservation longue, la corrélation et l'alerte relèvent du SIEM.
-
Le chef de projet veut suivre chaque semaine le nombre d'utilisateurs ayant enrôlé un second facteur. Quelle source est la plus simple ?
L'enrôlement d'un facteur produit un événement de credential qui précise son type. C'est une source fiable pour un indicateur de conduite du changement.