Aller au contenu principal

SIEM, audit des mutations, WORM et effacement

Envoi au SIEM (job siem_forward)​

Le worker (python -m eai.worker) lit la piste d'audit chaînée (eai.audit_events) de chaque tenant après un filigrane (eai.siem_cursors, migration V096) et transmet les événements de sécurité avec eai.domains.incidents.siem.forward : syslog RFC 5424 (UDP ou TCP) et webhook HTTP JSON.

  • Sélection : EAI_SIEM_FORWARD_ACTIONS, motifs séparés par des virgules (prefix.* ou nom exact, * pour tout l'audit). Valeur par défaut : security.* (échecs d'authentification, injections de prompt, refus de sortie, limitation de débit), policy.*, incident.*, approval.*, secret.*, api_key.*, audit.*, dlp.*, member.*, authz.write, authz.delete, et les coupe-circuits provider.disable, model.disable, agent.kill, agent.suspend. Les refus (decision.result = deny) et les échecs (outcome = failure ou error) sont toujours transmis.
  • Reprise : le filigrane n'avance qu'au-delà des événements acceptés par toutes les cibles. Un échec arrête le lot du tenant, l'erreur est enregistrée dans eai.siem_cursors.last_error et dans eai.worker_jobs, et le passage suivant reprend au premier événement non transmis. Avec plusieurs cibles, une cible déjà servie peut recevoir le même événement une seconde fois (au moins une fois par cible) ; event_id permet la déduplication.
  • Bornes : EAI_SIEM_FORWARD_BATCH (500) événements par tenant et par passage, EAI_WORKER_SIEM_FORWARD_SECONDS (30) entre deux passages.
  • Format : <pri>1 <horodatage> <hôte> eai-control-plane - audit - {json}, le JSON commence par "schema":"eai.audit.v1" puis porte l'Audit Event v1 (action, outcome, decision, actor, tenant_id, resource, evidence, hash). Sévérité syslog : erreur pour les échecs, refus et blocages, avertissement pour security.*, incident.*, secret.*, audit.*, notice sinon. Le webhook reçoit {"event": ..., "sourcetype": "eai:audit"}.

Wazuh​

Choix retenu : Wazuh n'est pas déployé par la plateforme (ni dans le chart, ni dans l'ApplicationSet). C'est le SIEM du client, joint en syslog TCP par EAI_SIEM_WAZUH_HOST / EAI_SIEM_WAZUH_PORT / EAI_SIEM_WAZUH_PROTO=tcp. Un SIEM n'a de valeur que hors du périmètre qu'il surveille ; l'exploiter dans le même cluster ferait perdre la trace d'une compromission de ce cluster. Les autres SIEM (Splunk HEC, Elastic) passent par EAI_SIEM_WEBHOOK_URL.

Fichiers fournis dans deploy/wazuh :

  • manager-ossec.conf : écoute syslog distante (<remote>) à fusionner dans /var/ossec/etc/ossec.conf, en restreignant allowed-ips à la plage de sortie du worker.
  • decoders/eai_audit_decoders.xml : préfiltre eai-control-plane - <msgid> - suivi de {"schema":"eai.audit.v1", puis JSON_Decoder à partir de la fin du préfiltre.
  • rules/eai_audit_rules.xml (100800 à 100814) : coupe-circuits, échecs et rafales d'échecs par tenant, injection de prompt, révocation ou rotation de clé, rupture de chaîne d'audit (audit.chain_verify_failed, émis par le job verify_chain), droits accordés, approbation rejetée, échecs d'authentification et force brute par adresse, refus de sortie, réponse à incident, changement de configuration de sécurité, limitation de débit.
  • agent-ossec.conf : agent des hôtes OpenBao uniquement (journal d'audit fichier d'OpenBao).

tests/test_siem_audit_worm.py vérifie que chaque règle vise une action réellement émise par le code et que les valeurs outcome attendues existent (success, failure, error).

Audit de chaque mutation​

tests/test_audit_mutation_coverage.py énumère toutes les routes POST, PUT, PATCH et DELETE et échoue si l'une d'elles n'atteint pas audit() (ou security_event()) dans son graphe d'appels. Les exemptions sont listées avec leur justification (routes en lecture seule : resolve, simulate, context/plan, render, validate ; webhook entrant journalisé dans eai.webhook_deliveries).

Routes à haute fréquence :

RouteÉvénementVolume
POST /v1/runs/{run_id}/heartbeatrun.heartbeatchangement d'état seulement : premier battement du run, ou réponse stop
POST /v1/sessions/{session_id}/messagessession.message.addun par message, rôle et longueur, jamais le contenu
POST /v1/finops/usagefinops.usage.ingestun par appel, sans la charge utile
POST /v1/finops/usage/batchfinops.usage.ingest_batchagrégé : un par lot avec sa taille
POST /v1/quotas/reserve, /commit, /releasefinops.quota.reserve, .commit, .releaseun par appel
POST /v1/finops/gpu/samplesfinops.gpu.samples_ingestagrégé : un par lot d'échantillons

Les producteurs d'usage à fort débit doivent utiliser la route batch. Les réservations internes de la passerelle LLM ne passent pas par ces routes et ne génèrent pas d'événement supplémentaire.

Export WORM périodique (job audit_worm)​

Chaque jour UTC complet de chaque chaîne de tenant non encore exporté donne un NDJSON et un manifeste signés, écrits avec verrouillage d'objet S3 (EAI_AUDIT_WORM_RETENTION_DAYS, 365) sous tenants/<tenant>/audit-worm/<export_id>. L'export est consigné dans eai.audit_exports et eai.audit_worm_days (un jour n'est jamais réexporté) et audité (audit.export). Au plus 200 exports par passage, l'arriéré continue au passage suivant. La logique est commune avec POST /v1/audit/export (eai.domains.observability.audit_api.write_export).

Signature (EAI_AUDIT_SIGNING) :

  • transit : OpenBao Transit sign sur l'empreinte SHA-256 avec la clé EAI_OPENBAO_AUDIT_SIGNING_KEY (eai-audit-export, type ed25519 ou ecdsa-p256), vérifiable par transit/verify. La clé privée ne quitte jamais OpenBao. Création : bao write transit/keys/eai-audit-export type=ed25519, politique du Control Plane limitée à transit/sign/eai-audit-export et transit/verify/eai-audit-export.
  • hmac : HMAC-SHA256 dérivé de la clé maître, réservé au développement et aux tests.
  • auto (défaut) : Transit si OpenBao est configuré, HMAC sinon.

En production, le contrôle de démarrage (eai/security/startup.py) refuse de démarrer sans EAI_OPENBAO_URL et EAI_OPENBAO_TOKEN, ou avec EAI_AUDIT_SIGNING=hmac.

Effacement d'une personne​

POST /v1/retention/erase couvre aussi les stockages externes, rapportés dans external :

  • Opik : traces dont la métadonnée eai.subject_hash est l'empreinte pseudonyme de la personne, listées par GET /v1/private/traces (filtre de métadonnée) puis supprimées par POST /v1/private/traces/delete (eai/integrations/opik.py, 10 000 traces par demande au plus, truncated sinon).
  • ClickHouse : DELETE léger des lignes d'usage (user_id) et des spans des sessions de la personne ; valeurs passées en paramètres typés. La ligne d'usage PostgreSQL reste conservée comme pièce financière.
  • Statut par stockage : not_configured, dry_run, completed ou error. Une erreur rend la demande incomplete et l'événement retention.erase est écrit avec outcome = failure : relancer la demande.
  • Un gel juridique sur la personne bloque toute la demande (blocked_legal_hold), stockages externes compris.

Réglages​

VariableDéfautRôle
EAI_SIEM_SYSLOG_HOST, _PORT, _PROTOcollecteur syslog
EAI_SIEM_WAZUH_HOST, _PORT, _PROTOécoute syslog du manager Wazuh
EAI_SIEM_WEBHOOK_URL, _TOKEN, _AUTH_SCHEMEwebhook HTTP JSON
EAI_SIEM_FORWARD_ACTIONSvoir plus hautsélection des événements
EAI_SIEM_FORWARD_BATCH500événements par tenant et par passage
EAI_WORKER_SIEM_FORWARD_SECONDS30intervalle du job siem_forward
EAI_WORKER_AUDIT_WORM_SECONDS3600intervalle du job audit_worm
EAI_AUDIT_WORM_RETENTION_DAYS365durée du verrouillage d'objet
EAI_AUDIT_SIGNINGautoauto, transit ou hmac
EAI_OPENBAO_AUDIT_SIGNING_KEYeai-audit-exportclé Transit de signature

Audit Gateway et Evidence Service (section 11 du kit)​

  • Jobs du worker : audit_gateway (boîte d'envoi vers EAI_AUDIT_GATEWAY_HTTP_URL et NATS JetStream), audit_seal (sceaux Ed25519), audit_integrity (recalcul et alertes), audit_retention (purge des charges chiffrées hors conservation légale). Réglages : configuration.md.
  • Récupérer les binaires de test : bash tools/audit/fetch.sh (nats-server 2.15.2, sha256 épinglé, dans /tmp/toolchains).
  • Vérifier hors ligne : GET /v1/evidence/bundle puis python -m eai.domains.evidence.verify bundle.json (code 0 : valide, 1 : altération).
  • Alerte d'intégrité : GET /v1/evidence/alerts?status=open ; ne jamais réparer la ligne, ouvrir un incident et conserver la preuve.
  • Modèle de sécurité : ../security/audit-evidence.md.