É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.

Approfondir Cours 13 sur 17 de Keycloak Academy 35 min 4 questions de quiz Cours suivant : Thèmes, parcours et accessibilité

Sur cette page
  1. Deux familles d’événements
  2. Conservation en base : utile, mais pas un SIEM
  3. Les event listeners
  4. Écrire son propre listener
  5. Choisir la voie vers le SIEM
  6. Ce que propose l’hébergeur : à vérifier
  7. Des événements aux indicateurs
  8. À retenir pour l’architecture
  9. Natif, extension ou hébergeur
  10. Quiz

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éclencheurConnexion, échange de code, rafraîchissement, changement de mot de passe, liaison d’IdPToute modification par la console ou l’Admin REST API
ExemplesLOGIN, LOGIN_ERROR, LOGOUT, CODE_TO_TOKEN, UPDATE_CREDENTIAL, USER_DISABLED_BY_TEMPORARY_LOCKOUTCREATE sur USER, UPDATE sur CLIENT, CREATE sur REALM_ROLE_MAPPING
ContenuType, client, utilisateur, session, adresse IP, erreur, détailsOpération, type et chemin de la ressource, auteur, IP, et éventuellement le JSON envoyé
RéglageRealm settings, Events, User events settingsRealm 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 en WARN, les succès en DEBUG, 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

VoieNatif ou extensionTemps réelAvantagesLimites
Journaux serveur (jboss-logging, JSON, syslog ou collecte)NatifOuiRien à développer, couvre aussi les erreurs techniquesDépend de la collecte de l’hébergeur ; format à normaliser côté SIEM
Lecture périodique de l’API eventsNatif côté Keycloak, script côté SOCNon (intervalle)Simple, pas de code dans KeycloakExige le stockage en base ; risque de trous si l’expiration est trop courte
Event listener maisonExtensionOuiFormat et destination maîtrisésCode 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_ERROR rapporté à LOGIN) ;
  • adoption du second facteur (UPDATE_CREDENTIAL dont le type est otp ou webauthn) ;
  • 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
  1. 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.

  2. Créez un utilisateur carole avec un mot de passe non temporaire.

  3. En fenêtre privée, ouvrez http://localhost:8080/realms/approfondir/account et échouez deux fois la connexion de carole, puis réussissez-la.

  4. 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}'
  5. Vérifiez la présence de deux LOGIN_ERROR avec l’erreur invalid_user_credentials, puis d’un LOGIN.

  6. Modifiez le prénom de carole dans 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 commande TOKEN=… si l’API répond 401.

    curl -s -H "Authorization: Bearer $TOKEN" \
      "$KC/admin/realms/approfondir/admin-events?max=5" | jq '.[] | {operationType, resourcePath, representation}'
  7. Regardez le journal de votre conteneur Keycloak (docker logs ou docker compose logs) : les LOGIN_ERROR y figurent en WARN, les LOGIN ré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éVerdictPrécision
Enregistrement des événements utilisateur et d'administration en baseNatifDé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)NatifListener 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 utilisateurNatifDepuis 26.2, options event-metrics-user-* avec les métriques activées.
Envoi direct des événements vers un SIEM, un bus ou une APIExtensionEvent listener à écrire. SPI classée interne par Keycloak : peut changer sans préavis.
Collecte des journaux et transmission au SOCHébergeurDé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

  1. 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 ?

  2. Vous activez Include representation sur les événements d'administration. Quel risque devez-vous traiter ?

  3. Pourquoi ne pas faire de la base de Keycloak le stockage de référence des journaux de sécurité ?

  4. Le chef de projet veut suivre chaque semaine le nombre d'utilisateurs ayant enrôlé un second facteur. Quelle source est la plus simple ?