Exporter le System Log Okta (API, CSV, SIEM)
Exporter le System Log Okta pour une enquête : CSV de l'Admin Console, /api/v1/logs avec la bonne pagination, Log Streaming, exports SIEM et pièges à éviter.
TL;DR. Pour une enquête, récupérez toute l'organisation sur les 90 jours de rétention avec GET /api/v1/logs, une fenêtre bornée since/until, limit=1000, et suivez l'en-tête Link: rel="next" jusqu'à ce qu'il disparaisse. Ne paginez jamais en déplaçant since vous-même. Réservez le CSV de l'Admin Console à un coup d'œil rapide, et les données SIEM ou Log Streaming aux besoins au-delà de 90 jours. Gardez le JSON brut : tous les autres formats perdent des champs.
C'est à l'export que la plupart des enquêtes Okta dérapent sans bruit. Pas parce que c'est difficile, mais parce que le raccourci évident (chercher l'utilisateur suspect, cliquer sur télécharger) produit un fichier qui a l'air complet et ne l'est pas. Cet article est la version longue de la checklist de la page d'accueil de l'outil.
Ce que vous exportez
Le System Log Okta est un flux d'objets LogEvent. Chacun porte un eventType, un actor, un tableau target, un client (IP, user agent, géolocalisation), un securityContext (ASN, organisation de l'AS, FAI, indicateur de proxy), un authenticationContext (dont l'identifiant de session), un outcome, un debugContext.debugData et un uuid unique. Le schéma est documenté dans la référence de l'API System Log.
Deux propriétés des données dictent tout ce qui suit :
- La rétention est de 90 jours. Okta indique que les données de plus de 90 jours ne sont pas renvoyées (guide de requêtage du System Log). Si l'incident peut être plus ancien, il ne reste que ce qui a été streamé ou collecté avant.
- Les corrélations ont besoin des événements des autres. Une réinitialisation par le support est journalisée avec l'agent comme acteur et votre victime comme cible. Un octroi de rôle l'est avec l'attaquant comme acteur et le nouvel admin comme cible. Filtrez sur un utilisateur et vous perdez la moitié de l'histoire.
Option 1 : l'API System Log (recommandée)
Elle donne le JSON d'origine, tous les champs, et une procédure reproductible.
Identifiants
Passez par un accès en lecture seule : un jeton d'API créé par un administrateur en lecture seule, ou une application de service OAuth 2.0 disposant du scope okta.logs.read. Un jeton d'API Okta porte les permissions de l'admin qui l'a créé (Okta Help Center : jetons d'API) : ne le créez donc pas depuis un Super Administrator pour cette tâche, et révoquez-le une fois l'export terminé. Pendant un incident actif, assurez-vous aussi que le compte utilisé n'est pas l'un de ceux que l'attaquant pourrait contrôler.
Requêtes bornées et pagination
Le guide de requêtage distingue deux types de requêtes :
| Requête bornée | Requête de polling | |
|---|---|---|
| Paramètres | since et until renseignés | pas de until, sortOrder=ASCENDING |
| Usage | exporter une période fixe | suivre les nouveaux événements en continu |
| Fin | la dernière page n'a pas de lien next | renvoie toujours un lien next |
| Ordre | par published | peut être désordonné |
En forensique, c'est la requête bornée qu'il vous faut. Le guide est explicite sur deux points importants : suivez les liens next plutôt que de paginer à la main avec since et until (cela peut sauter ou dupliquer des événements), et certains événements d'une période récente peuvent arriver en retard. Exportez jusqu'à « maintenant moins quelques minutes », et relancez les dernières heures plus tard si l'incident est en cours.
Une boucle shell minimale :
url="https://${OKTA_DOMAIN}/api/v1/logs?since=2026-06-15T00:00:00Z&until=2026-09-13T00:00:00Z&limit=1000"
n=0
while [ -n "$url" ]; do
n=$((n+1))
curl -sS -D headers.txt \
-H "Authorization: SSWS ${OKTA_API_TOKEN}" \
-H "Accept: application/json" \
"$url" > "okta-system-log-$(printf %04d $n).json"
url=$(tr -d '\r' < headers.txt | grep -i '^link:.*rel="next"' \
| sed -E 's/^[Ll]ink: <([^>]+)>.*/\1/')
sleep 1 # rester largement sous la limite de débit
done
gzip okta-system-log-*.json
Chaque page est un tableau JSON. Inutile de les fusionner : l'analyseur accepte de nombreux fichiers à la fois, ainsi que des tableaux écrits bout à bout dans un même fichier. Les événements sont dédupliqués par uuid, donc des pages qui se chevauchent ou une relance ne posent aucun problème.
limit va jusqu'à 1 000 événements par page. Les requêtes sont soumises à des limites de débit et à un délai d'expiration de 30 secondes par requête : une organisation très active sur 90 jours représente beaucoup de pages, laissez tourner.
Filtrer côté serveur : seulement pour le tri
L'API accepte une expression filter telle que eventType eq "user.mfa.factor.reset_all" et un paramètre de mot-clé q (guide de requêtage). C'est utile pour répondre à une question rapide. Pour l'export de preuves, laissez-les de côté.
Option 2 : CSV de l'Admin Console
Dans l'Admin Console, Reports › System Log, choisissez la période, laissez la recherche vide et utilisez Download CSV (Okta Help Center : System Log). Aucun jeton n'est nécessaire et c'est rapide pour une courte période.
La contrepartie, c'est la fidélité : un CSV aplatit les objets imbriqués, et je n'ai pas pu vérifier dans la documentation publique la liste exacte des colonnes du téléchargement de la console. L'analyseur lit les CSV dont les en-têtes sont des chemins LogEvent (actor.alternateId, client.ipAddress, target[0].displayName, securityContext.asNumber, etc.) ou une colonne _raw contenant le JSON d'origine. Si un CSV de la console donne moins de constats que prévu, refaites l'export via l'API avant de conclure quoi que ce soit.
Option 3 : Log Streaming (EventBridge, Splunk Cloud)
Okta peut streamer les événements du System Log quasiment en temps réel vers Amazon EventBridge ou Splunk Cloud ; un super admin le configure dans Reports › Log Streaming (Okta Help Center : log streaming). Un flux ne transmet que les événements à venir : c'est une stratégie de rétention, pas un outil de récupération.
Si un flux existe déjà, exportez la période depuis sa destination :
- Les archives EventBridge (S3, CloudWatch Logs) conservent chaque LogEvent dans le champ
detailde l'enveloppe EventBridge. Le JSON ou le JSON Lines, compressé en gzip ou non, se dépose tel quel. - Splunk : cherchez le source type Okta et exportez les résultats en JSON ou CSV. Le champ
_rawcontient l'événement d'origine et est utilisé quand il est présent ; les enveloppesresultsont dépliées.
Option 4 : autres SIEM
La règle est partout la même : exportez les événements bruts avec les noms de champs d'origine.
- Elastic : les documents sont extraits de
_sourceautomatiquement. - Le JSON Lines générique avec un LogEvent par ligne fonctionne directement, tout comme les lignes préfixées syslog qui se terminent par l'événement JSON.
- Microsoft Sentinel : la table personnalisée classique
Okta_CLaplatit les champs en colonnes suffixées commeactor_alternateId_s; l'analyseur ne les mappe pas encore. Si le JSON d'origine est disponible, exportez-le plutôt.
Checklist avant analyse
Avant de confier l'export à qui que ce soit, ou à l'analyseur :
- La période couvre au moins plusieurs jours avant le premier événement suspect (les références comportementales ont besoin d'historique).
- Aucun filtre ni recherche n'a été appliqué.
- Les premier et dernier horodatages
publishedcorrespondent à la fenêtre demandée. - Les fichiers sont conservés sans modification, avec leurs empreintes, là où l'attaquant ne peut pas les atteindre.
- Le jeton ou l'application de service utilisé pour l'export est révoqué ou désactivé.
L'étape suivante est l'analyse de l'export. Si vous ne savez pas encore quoi chercher, commencez par le guide d'investigation d'une compromission Okta.
Pour aller plus loin
- Okta Developer : guide de requêtage du System Log (requêtes bornées et de polling, filtres, rétention)
- Okta Developer : référence de l'API System Log
- Okta Help Center : log streaming
- Okta Help Center : gestion des jetons d'API