đĄïž SENTRY â Bilan d'Ă©tape : TAXII 2.1 rĂ©el, phases 4, 5 et 6¶
Date : 03/10/2026 · Branche : feature/phases-4-6 (empilée sur feature/phase3-cve-v2,
elle-mĂȘme sur feature/taxii-v2) · Base : 9402bb1
Verdict : code des six modules livrĂ© et testĂ© ; aucun jalon M2âM6 n'est constatĂ© tant
que la branche n'est pas fusionnée et que le worker n'a pas tourné sur données réelles.
1. RĂ©sumĂ©¶
| Volet | Livré | Statut |
|---|---|---|
Backend TAXII 2.1 (taxii2-client 2.3.0) |
T1âT11 du cahier de la tĂąche | â
codĂ©, testĂ© hors ligne ; test rĂ©el prĂȘt (-m live) |
| VĂ©rification des sources TAXII | 6 sources examinĂ©es, 1 retenue (RedEye), DigitalSide dĂ©sactivĂ©e | â |
| Phase 4 â Incidents | API, CLI, liaisons IOC/CVE, chronologie immuable par trigger PostgreSQL, alerte â incident | â (3.6 faux positifs â) |
| Phase 5 â Dashboard SOC | synthĂšse, activitĂ© 24 h, exports JSON/CSV en flux, console Rich | â (sĂ©ries 7 j â) |
| Phase 6 â Threat Hunting | 6 rĂšgles, sessions enregistrĂ©es, API, CLI, chasse planifiĂ©e dans le worker | â |
| SĂ©curitĂ© | limitation des connexions (429 + Retry-After), anti-injection CSV, SSRF TAXII | â (HTTPS/en-tĂȘtes â) |
2. TAXII 2.1 â rĂ©sultats par sous-tĂąche¶
| # | Exigence | Réalisation | Preuve |
|---|---|---|---|
| T1 | Dépendance | taxii2-client==2.3.0 épinglée, types-requests en dev, override mypy |
pyproject.toml |
| T2 | Inspection de l'API | Collection(url, conn=âŠ, collection_info=âŠ) Ă©vite la dĂ©couverte ; _HTTPConnection.get valide le Content-Type |
ADR-010 |
| T3 | Backend | Collection.get_objects dans asyncio.to_thread |
taxii.py::_fetch_with_library |
| T4 | Authentification par hĂŽte | TAXII_AUTH : hote=user:pass, bearer:, header:NOM:VALEUR ; correspondance exacte de l'hĂŽte |
6 tests |
| T5 | Pagination | more/next, plafond TAXII_MAX_PAGES, avertissement de troncature |
4 tests |
| T6 | added_after |
dernier succĂšs â 15 min | test dĂ©diĂ© |
| T7 | Fetch injectable | fetch: HeaderFetcher | None = None |
tests |
| T8 | Branchement du collecteur | use_library = fetch is fetch_feed_content and settings.taxii_client == "library" |
collector.py |
| T9 | Test réel | tests/test_live_sources.py, marqueur live, SENTRY_LIVE_TESTS=1 |
à exécuter sur Kali |
| T10 | Validation | pagination, added_after, plafond de pages |
27 tests test_taxii_client.py |
| T11 | Sécurité | voir § 3 | tests |
Ăcart Ă votre suggestion T8. La ligne proposĂ©e
taxii_fetch = None if fetch is fetch_feed_content else fetch a été enrichie d'un interrupteur
TAXII_CLIENT=library|builtin : il permet de revenir au client interne sans redéploiement si la
bibliothÚque se comporte mal sur un serveur réel. Comportement par défaut identique au vÎtre.
3. SĂ©curitĂ© du client TAXII (T11)¶
taxii2-client s'appuie sur requests, qui suit les redirections et n'a aucun délai par
dĂ©faut. Brancher la bibliothĂšque telle quelle aurait fait rĂ©gresser trois protections dĂ©jĂ
acquises par le client interne. _GuardedConnection les rétablit :
| Risque | Parade | Test |
|---|---|---|
| Redirection vers une IP interne (contournement SSRF) | max_redirects = 0 ; contrĂŽle assert_public_destination avant chaque requĂȘte |
â |
| Serveur lent qui bloque le worker | dĂ©lai imposĂ© via functools.partial(session.request, timeout=âŠ) |
â |
| Réponse géante (épuisement mémoire) | stream=True + lecture plafonnée dans un hook de réponse |
â |
| Fuite d'identifiants | secret attaché à l'hÎte exact, jamais relayé ; masqué dans les journaux (mask_secrets) |
â |
| Collection publique | aucun en-tĂȘte d'authentification si l'hĂŽte n'est pas dans TAXII_AUTH |
â |
| Erreurs hĂ©tĂ©rogĂšnes | requests/TAXIIServiceException â FetchError typĂ©e ; 429/5xx rĂ©essayĂ©s avec backoff |
â |
| Connexion orpheline | collection.close() dans finally |
â |
| API root sur un autre hĂŽte (dĂ©couverte) | refusĂ©e | â |
4. VĂ©rification prĂ©alable des sources¶
RÚgle appliquée : aucune source n'entre dans le seed sans avoir été vérifiée existante et
accessible. Outils livrés : sentry taxii discover <url> et sentry feeds probe <url> (collecte
d'essai d'une page, sans écriture en base).
| Source | Constat | Décision |
|---|---|---|
| DigitalSide (invité) | délai de connexion dépassé depuis deux réseaux | semée inactive |
| RedEye Threat Indicators | jeton gratuit sur e-mail, 100 req/h | semée, nécessite TAXII_AUTH |
| MITRE ATT&CK | public, mais techniques et groupes, aucun IOC | non semée |
| CrowdSec CTI | TAXII rĂ©servĂ© aux offres payantes | non semĂ©e (format d'auth prĂȘt) |
| Zedmos | inscription validée par un administrateur | non semée |
| CISA AIS 2.0 | certificat PKI + accord d'adhésion | non semée |
| IPsum niveau 5 (texte) | accessible, sans clé, ~volume suffisant pour M2 | ajoutée |
Confiance : élevée pour DigitalSide, MITRE, CISA (constats directs ou documentation officielle) ; moyenne pour RedEye (documentation lue, jeton non obtenu, donc format réel non éprouvé).
5. Phases 4 Ă 6 â contenu¶
Incidents (ADR-008). Machine d'Ă©tat NIST SP 800-61 Ă 6 Ă©tapes ; transition interdite â 409 ;
clÎture exigeant un post-mortem ; chronologie immuable doublement verrouillée (écouteurs ORM
before_update/before_delete + trigger plpgsql trg_incident_events_immutable) ; tables de
liaison IOC et CVE ; ouverture d'incident depuis une alerte CVE, idempotente par
source_alert_id unique ; contraintes CHECK nommées.
Dashboard. /dashboard/summary (IOC actifs, CVE P0/P1, incidents ouverts, santé des flux),
/dashboard/recent (24 h), exports en flux (pas de chargement en mémoire), CSV conforme RFC 4180
avec neutralisation des formules (CWE-1236).
Threat Hunting (ADR-009). Deux modes : chasse sur observables soumis (journaux pare-feu,
proxy, EDR) ou sur la base d'IOC. Six rĂšgles : relais Tor (liste officielle), DNS dynamique, DGA
par entropie de Shannon, IP ransomware, CVE exploitable Ă inventaire d'actifs, IOC connu. Une
rÚgle en échec rend la session PARTIELLE sans bloquer les autres. Chasse planifiée dans le
worker (HUNT_INTERVAL_SECONDS, 24 h par défaut).
6. MĂ©triques¶
| Indicateur | 29/09 | 03/10 |
|---|---|---|
| Tests (PostgreSQL 16) | 326 | 388 (+4 ignorés : tests réels) |
| Couverture | â 95 % | 94 % |
| Python | 3.12, 3.14 | 3.12, 3.14 â |
Routes /api/v1 |
14 | 28 |
| Commandes CLI | 19 | 34 |
| Tables | 10 | 14 |
| Migrations | 4 | 6 |
| ADR | 7 | 10 |
| Lignes de code applicatif / de tests | â | â 10 100 / â 5 800 |
ruff check, ruff format --check, mypy --strict : propres.
7. DĂ©fauts trouvĂ©s et corrigĂ©s pendant l'Ă©tape¶
| Défaut | Gravité | Correctif |
|---|---|---|
requests suit les redirections et n'a pas de délai (régression SSRF/DoS en adoptant la bibliothÚque) |
Haute | _GuardedConnection |
if exc.response: faux pour une réponse 4xx/5xx (Response.bool) |
Moyenne | is not None |
Chasse : hunt.matches.append déclenchait un chargement paresseux hors greenlet |
Moyenne | insertion directe HuntingMatch(session_id=âŠ) |
| RÚgle inconnue détectée aprÚs l'indexation du catalogue (KeyError) | Faible | contrÎle déplacé avant |
| Test du trigger laissant le moteur lié à une boucle fermée | Faible (tests) | dispose() en finally + remise à zéro du schéma |
Override mypy ayant absorbé exclude dans pyproject.toml |
Faible | restauré |
8. DĂ©fauts connus, non bloquants¶
- Construction de l'image Docker non vérifiée ici (proxy Docker Hub bloqué dans le bac à sable).
- Test réel TAXII non exécuté : DigitalSide injoignable, jeton RedEye non obtenu.
- Heuristique DGA non calibrée sur un corpus réel : taux de faux positifs inconnu.
- RULE-05 rapproche actifs et CVE par mot dans la description : rappel limité sans CPE.
9. SWOT de l'Ă©tape¶
| Forces | Faiblesses |
|---|---|
| Six modules testés, sécurité traitée dÚs la conception | Aucun constat sur données réelles |
| Sources vérifiées avant intégration | Une seule source STIX exploitable, et sous jeton |
| Opportunités | Menaces |
| Démonstration complÚte possible dÚs la fusion | Pile de trois branches à fusionner dans l'ordre |
| RedEye + OTX suffisent à M2 complet | Dépendance à des flux gratuits instables |
10. Prochaines Ă©tapes (dans l'ordre)¶
- Récupérer le bundle et fusionner
feature/taxii-v2âphase3-cve-v2âphases-4-6(ETAPES_POUSSER_SUR_MAIN.md). VĂ©rification : pipeline GitLab vert Ă chaque MR. sentry db upgrade && sentry seed. VĂ©rification :sentry db current= rĂ©vision cible.- Demander le jeton RedEye et la clĂ© OTX ; les mettre dans
.env. - Sur Kali :
SENTRY_LIVE_TESTS=1 pytest tests/test_live_sources.py --no-cov, puissentry feeds probesur RedEye. VĂ©rification :usable: true. sentry feeds workerpendant 24 h. VĂ©rification :sentry statusâ M2 et M3 â .- Ouvrir 3.6 (faux positifs), 4.2 (sĂ©ries 7 j), 4.5 (HTTPS + en-tĂȘtes), 5.6 (audit).