Project

General

Profile

Actions

Feature #24

closed
CD

Implémenter un hook pour la création automatique de tickets Redmine depuis les scans Trivy et Semgrep

Feature #24: Implémenter un hook pour la création automatique de tickets Redmine depuis les scans Trivy et Semgrep

Added by Client Dashboard about 2 months ago. Updated about 2 months ago.

Status:
Shipped
Priority:
Normal
Assignee:
-
Start date:
06/11/2026
Due date:
% Done:

100%

Estimated time:
(Total: 0:00 h)
spec_ref:

## Spec — Hook création auto de tickets Redmine depuis Trivy & Semgrep

### Approche (hexagonal api/)
Endpoint webhook `POST /scan-results` → normalise chaque vuln en `SecurityFinding` → cas d'usage crée un ticket via le `RedmineClient` existant (modèle create_ticket_from_draft). Dédup par clé stockée dans un champ custom `security_key` : Trivy `CVE-{id}`/`{paquet}@{version}_CVE-{id}` ; Semgrep `{fichier}:{ligne}_{rule-id}`. Ticket ouvert avec la clé → pas de doublon ; seulement résolu/fermé → régression (nouveau ticket).

### Découpage (3 couches)
1. Domaine & application : SecurityFinding, normaliseurs Trivy/Semgrep, calcul clé, format ticket, use case via port abstrait.
2. Infrastructure Redmine : adaptateur (recherche par security_key, création, anti-doublon/régression).
3. Présentation & sécurité : endpoint, validation Pydantic stricte + anti-injection, permissions (secret webhook + project_key), doc.

### AC : endpoint Trivy+Semgrep ; format (tag Sécurité + Submitted) ; anti-doublon + régression ; sécurité (validation + permissions) ; tests respx + RUN_REDMINE_LIVE ; doc.

Validé PO (approuvé). Découpé : #46 → #47 → #48.

build_status:
build_number:
ci_run_url:
scan_status:
scan_report_url:
deploy_status:
preprod_url:
deployed_at:
branch:
pr_url:
security_key:
severity:
paused:

Description

### Problème
Actuellement, lorsqu’un scan de sécurité (Trivy ou Semgrep) détecte une vulnérabilité dans un projet, aucun processus automatisé n’existe pour créer un ticket Redmine. Cela entraîne une perte de temps pour les équipes qui doivent manuellement suivre et reporter ces vulnérabilités, avec un risque d’oubli ou de doublons.

### Contexte
Le client utilise **Trivy** (pour les vulnérabilités de dépendances et conteneurs) et **Semgrep** (pour les vulnérabilités de code statique). Les résultats de ces scans doivent être automatiquement transformés en tickets Redmine avec les caractéristiques suivantes :
- **Déclencheur** : Webhook écoutant les rapports des scans.
- **Format des tickets** : Titre et description standardisés, tag `Sécurité`, statut `Soumis`.
- **Anti-doublons** : Logique pour éviter la création de tickets en double pour la même vulnérabilité.
- **Régressions** : Création d’un nouveau ticket si la vulnérabilité réapparaît après correction.

### Comportement proposé
1. **Réception des scans** : L’app écoute un endpoint dédié (`POST /scan-results`) pour recevoir les rapports de Trivy et Semgrep.
2. **Création du ticket** : Pour chaque vulnérabilité détectée, un ticket Redmine est créé avec :
- Un **titre** formaté selon l’outil (ex. `[Sécurité] Dépendance vulnérable : (CVE-2021-23337)` pour Trivy).
- Une **description** incluant toutes les informations disponibles dans le rapport du scan (description, sévérité, extrait de code, lien vers la CVE, recommandations, etc.).
- Un **tag** `Sécurité`.
- Un **statut** `Soumis`.
3. **Anti-doublons** : Utilisation d’une clé unique pour éviter les doublons (ex. `CVE-{id}` pour Trivy, `{fichier}:{ligne}_{rule-id}` pour Semgrep).
4. **Régressions** : Création d’un nouveau ticket si la vulnérabilité réapparaît après correction.

### Exemple de payload attendu
```json
{
"tool": "trivy", // ou "semgrep"
"project_key": "mon-projet", // clé du projet dans l'app
"vulnerability": {
"id": "CVE-2021-23337", // pour Trivy
"package": "lodash",
"version": "4.17.20",
"severity": "High",
"description": "Vulnérabilité permettant une exécution de code arbitraire...",
"report_url": "https://lien-vers-le-rapport.com"
}
}
```

## Acceptance criteria
- [ ] **Intégration du webhook** : L’app expose un endpoint `POST /scan-results` qui accepte les rapports de Trivy et Semgrep et déclenche la création d’un ticket.
- [ ] **Format des tickets** :
- Le **titre** est généré selon le format spécifié pour Trivy et Semgrep.
- La **description** inclut toutes les informations disponibles dans le rapport du scan.
- Le **tag** `Sécurité` est ajouté.
- Le **statut** est `Soumis`.
- [ ] **Anti-doublons** :
- Pour Trivy, la clé unique est `CVE-{id}` (ou `{nom_paquet}@{version}_CVE-{id}` si la CVE n’est pas disponible).
- Pour Semgrep, la clé unique est `{fichier}:{ligne}_{rule-id}`.
- Si un ticket existe déjà avec la même clé, aucun nouveau ticket n’est créé.
- [ ] **Régressions** : Un nouveau ticket est créé si la vulnérabilité réapparaît après correction.
- [ ] **Tests contractuels** :
- Mock des requêtes HTTP vers Redmine pour valider le format des tickets créés.
- Mock des payloads de Trivy et Semgrep pour tester la logique de création et d’anti-doublons.
- [ ] **Tests d’intégration (optionnels)** :
- Test en environnement réel avec `REDMINE_BASE_URL` et `REDMINE_API_KEY` configurés (si `RUN_REDMINE_LIVE=1`).
- Création d’un projet temporaire, d’un ticket, vérification des champs, puis suppression du projet.
- [ ] **Sécurité** :
- Validation des payloads reçus via le webhook pour éviter les injections ou abus.
- Vérification des permissions pour s’assurer que seul le projet concerné peut créer des tickets.
- [ ] **Documentation** :
- Documentation du format attendu pour les payloads du webhook.
- Documentation de la logique d’anti-doublons et de gestion des régressions.


Subtasks 3 (0 open3 closed)

Feature #46: Domaine & application : SecurityFinding, normalisation Trivy/Semgrep, clé de dédup et format de ticketShipped06/11/2026

Actions
Feature #47: Infrastructure Redmine : recherche par clé (champ custom), création + anti-doublons/régressionShipped06/11/2026

Actions
Feature #48: Présentation & sécurité : endpoint POST /scan-results, validation, permissions + docShipped06/11/2026

Actions

RA Updated by Redmine Admin about 2 months ago Actions #1

  • Status changed from Submitted to Spec

RA Updated by Redmine Admin about 2 months ago Actions #2

  • Subtask #46 added

RA Updated by Redmine Admin about 2 months ago Actions #3

  • Subtask #47 added

RA Updated by Redmine Admin about 2 months ago Actions #4

  • Subtask #48 added

RA Updated by Redmine Admin about 2 months ago Actions #5

  • spec_ref updated (diff)

**Spec rédigée + validée PO (approuvé).** Découpé en 3 sous-tâches hexagonales (chaîne linéaire) :
- #46 — Domaine & application (SecurityFinding, normalisation, clé, format, use case) [M]
- #47 — Infrastructure Redmine (recherche par `security_key`, création, anti-doublon/régression) [M] (dép. #46)
- #48 — Présentation & sécurité (endpoint, validation, permissions, doc) [M] (dép. #46, #47)

Spec dans `spec_ref`. Épopée découpée ⇒ `done_ratio` dérivé des enfants. Ticket en `Spec`. (Cibles dev : `backend-dev` sur les 3.)

RA Updated by Redmine Admin about 2 months ago Actions #6

  • Status changed from Spec to In development

RA Updated by Redmine Admin about 2 months ago Actions #7

  • Status changed from In development to QA

Rollup épopée : tous les enfants sont désormais au moins en QA (#46 Shipped, #47 QA, #48 QA). Passage de l'épopée #24 en QA (enfant le moins avancé = QA).

RA Updated by Redmine Admin about 2 months ago Actions #8

  • Status changed from QA to Shipped

Épopée livrée en production (rollup : tous les enfants Shipped). Hook création auto de tickets Redmine depuis Trivy/Semgrep : #46 (domaine/application) + #47 (infrastructure Redmine) + #48 (présentation `POST /scan-results` + sécurité) tous en prod (master #65). Note : le champ custom `security_key` (id 12) n'est pas encore provisionné sur le Redmine live — l'adaptateur retombe sur le repli titre/description ; poser `REDMINE_SECURITY_KEY_FIELD_ID=12` après provisioning du champ pour activer le chemin exact (sans changement de code).

Actions

Also available in: PDF Atom