Intégrer la CI et Dependency-Track

Ce document explique comment activer et configurer les deux fonctionnalités de qualité/sécurité de gitrust :

  1. La CI intégrée (Dagger) qui exécute les builds/tests/lints à chaque push.
  2. Le dependency tracker (Syft + Dependency-Track) qui scanne les composants du code à chaque push et détecte les vulnérabilités connues.

Ces deux systèmes sont indépendants : on peut activer l'un sans l'autre.


1. Architecture générale

flowchart TB
  subgraph Client
    Dev[Développeur]
  end
  subgraph Gitrust[Instance Gitrust]
    HTTP[:4000 HTTP/Git]
    SSH[:2222 SSH/Git]
    Worker[CiWorker
tokio task] Sbom[SbomService
tokio spawn] DB[(PostgreSQL)] end subgraph Builder[Serveur de build] Docker[Docker/Podman] Dagger[Dagger CLI] CiEngine[/opt/gitrust-ci/ci-engine/] end subgraph Security[Stack sécurité optionnelle] Syft[syft] Dtrack[Dependency-Track] end Dev -->|git push| HTTP Dev -->|git push| SSH HTTP --> Worker SSH --> Worker HTTP --> Sbom SSH --> Sbom Worker -->|SSH + rsync| Builder Builder -->|logs streamés| Worker Worker --> DB Sbom -->|scan workspace| Syft Sbom -->|PUT BOM| Dtrack Dtrack -->|findings| Sbom Sbom --> DB

Trois composants fonctionnent en parallèle :

  • CiWorker : tâche Tokio qui consomme des CiTask depuis un channel mpsc, limitée par un Semaphore à CI_MAX_CONCURRENT pipelines simultanés.
  • SbomService : exécuté dans un tokio::spawn après chaque push, totalement découplé du CI.
  • Serveur de build : machine distante (ou localhost) qui exécute Docker + Dagger. Gitrust y envoie le workspace par rsync et lance Dagger par SSH.

2. Mettre en place la CI

2.1 Pré-requis serveur de build

Le serveur de build peut être la même machine que Gitrust (CI_REMOTE_HOST=localhost) ou une machine dédiée. Il doit disposer de :

Outil Rôle
Docker ou Podman Containers Dagger
Dagger CLI Moteur d'exécution
SSH (accès sortant depuis Gitrust) Transport
rsync Copie du workspace
git, tar Extraction du tree du commit

Installation automatique recommandée :

# Depuis la machine Gitrust (l'utilisateur doit pouvoir SSH vers le builder)
./deployment/setup-remote-ci.sh .env

Le script exécute :

  1. Vérification de la connectivité SSH
  2. Installation de Docker si absent
  3. Installation de Dagger CLI si absent
  4. Création du répertoire de travail distant
  5. Synchronisation du ci-engine
  6. Smoke test (versions)

2.2 Configuration Gitrust (fichier .env)

Ajouter au .env de Gitrust :

# Activer globalement le CI
CI_ENABLED=true

# Chemin du ci-engine sur le serveur de build
CI_ENGINE_PATH=/opt/gitrust-ci/ci-engine

# Limite de parallélisme
CI_MAX_CONCURRENT=4
CI_DEFAULT_TIMEOUT=3600
CI_WORKSPACE_PATH=/tmp/gitrust-ci

# Serveur de build (mettre localhost pour "même machine")
CI_REMOTE_HOST=builder.example.com
CI_REMOTE_USER=ci-runner
CI_REMOTE_PATH=/opt/gitrust-ci
CI_REMOTE_SSH_PORT=22
# CI_REMOTE_SSH_KEY=/home/gitrust/.ssh/id_ed25519   # si pas ssh-agent

Redémarrer Gitrust : systemctl restart gitrust (ou cargo run --release).

2.3 Activer la CI sur un dépôt

Dans l'interface web : aller sur le dépôt → SettingsCI.

  • Cocher CI enabled (requis — par défaut false)
  • Cocher Trigger on push (active l'exécution à chaque push)
  • Optionnel : Auto-cancel (annule les pipelines en cours quand un nouveau démarre)
  • Optionnel : Allowed branches (ex. main,develop — vide = toutes)

2.4 Choisir le mode : Easy ou Power

flowchart LR
  Push[Commit
poussé] --> Tree{Arbre du
commit contient ?} Tree -->|.dagger/| Power[Mode Power
dagger call -m .dagger/ ci] Tree -->|.gitrust-ci.yml| Easy[Mode Easy
dagger call -m ci-engine test-pr] Tree -->|rien| None[Pas de pipeline] Power --> Run[Exécution
distante SSH] Easy --> Run

Mode Easy (recommandé pour commencer)

Créer .gitrust-ci.yml à la racine du dépôt :

# Raccourci : charge un profil pré-configuré (rust | python | node)
language: rust

build:
  command: "cargo build --release"

checks:
  lint: "cargo clippy -- -D warnings"
  format: "cargo fmt -- --check"

tests:
  command: "cargo test --release"

Les profils disponibles se trouvent dans deployment/ci-engine/profiles/ (rust.yaml, python.yaml, node.yaml) dans le dépôt source.

Mode Power

Pour les utilisateurs avancés, créer un module Dagger complet dans .dagger/ :

.dagger/
├── dagger.json
├── src/
│   └── main.py         # ou Go/TypeScript

La fonction ci du module est appelée directement :

dagger call -m .dagger/ ci

Avantage : accès au Daggerverse, composition, tests de pipeline. Voir la documentation Dagger.

2.5 Suivi d'un pipeline

Après un git push, une entrée apparaît dans l'onglet CI du dépôt :

stateDiagram-v2
  [*] --> Pending: create_pipeline
  Pending --> Running: worker picks CiTask
  Running --> Success: exit 0
  Running --> Failure: exit != 0
  Running --> Cancelled: timeout / auto_cancel / manuel
  Success --> [*]
  Failure --> [*]
  Cancelled --> [*]

Les logs stdout/stderr sont streamés ligne par ligne dans la table ci_logs et visibles en direct dans l'UI. En cas d'échec, une notification est envoyée au propriétaire du dépôt.


3. Mettre en place le Dependency Tracker

Cette partie est totalement indépendante de la CI. Elle scanne le code poussé et produit un SBOM CycloneDX, puis (optionnellement) l'envoie à Dependency-Track pour une analyse de vulnérabilités.

3.1 Installer Syft

Sur la machine Gitrust (le scan se fait localement, pas sur le builder) :

# Installation officielle
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh \
  | sh -s -- -b /usr/local/bin

# Vérification
syft --version

Dans .env :

CI_SBOM_ENABLED=true
CI_SYFT_BIN=/usr/local/bin/syft   # optionnel, défaut: syft dans PATH

À ce stade : à chaque push, un SBOM CycloneDX est généré et stocké (sans upload externe). Visible dans l'onglet Security du dépôt : nombre de composants, sha256 du BOM.

3.2 Déployer Dependency-Track

Dependency-Track est une application Java qui stocke les SBOM et corrèle avec les bases CVE/OSV/NVD. Déploiement Docker recommandé :

mkdir -p /opt/dtrack && cd /opt/dtrack
curl -L -o docker-compose.yml \
  https://dependencytrack.org/docker-compose.yml
docker compose up -d

L'API est disponible sur http://localhost:8081 et l'UI sur http://localhost:8080. Login initial : admin / admin (à changer immédiatement).

3.3 Créer une clé API

Dans Dependency-Track → AdministrationAccess ManagementTeams :

  1. Créer (ou réutiliser) une équipe gitrust.
  2. Lui attribuer les permissions :
  3. BOM_UPLOAD
  4. PROJECT_CREATION_UPLOAD
  5. VIEW_PORTFOLIO
  6. VIEW_VULNERABILITY
  7. Générer une API key et la copier.

3.4 Configurer Gitrust

Ajouter au .env :

CI_DTRACK_ENABLED=true
CI_DTRACK_URL=http://localhost:8081
CI_DTRACK_API_KEY=odt_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Redémarrer Gitrust. À chaque push :

sequenceDiagram
  participant Push as post-receive
  participant Sbom as SbomService
  participant Git as git archive
  participant Syft
  participant Dtrack as Dependency-Track
  participant DB as sbom_reports

  Push->>Sbom: process_push(sha, ref)
  Sbom->>DB: upsert status=pending
  Sbom->>Git: archive sha | tar -x tmpdir
  Sbom->>Syft: scan dir:tmpdir -o cyclonedx-json
  Syft-->>Sbom: BOM bytes
  Sbom->>DB: update sha256
  Sbom->>Dtrack: PUT /api/v1/bom (base64)
  Dtrack-->>Sbom: token
  loop max 30s
    Sbom->>Dtrack: GET /api/v1/bom/token/{token}
    Dtrack-->>Sbom: processing ?
  end
  Sbom->>Dtrack: GET /api/v1/finding/project/{uuid}
  Dtrack-->>Sbom: findings[]
  Sbom->>DB: update status=success
+ critical/high/medium/low

3.5 Lire les résultats

Onglet Security du dépôt → encart SBOM :

  • Nombre de composants détectés
  • Compteurs par sévérité : Critical / High / Medium / Low
  • Lien direct vers le projet dans Dependency-Track (si l'UUID est résolu)
  • Hash sha256 du BOM (traçabilité)

Si Dependency-Track met plus de 30s à analyser, le status reste processing — un sweeper ultérieur ira rechercher les findings.


4. Débogage

Problèmes CI courants

Symptôme Cause probable Vérifier
Pipeline reste pending Worker non démarré, ou channel saturé Logs CI worker started, CI_MAX_CONCURRENT
Échec rsync vers le serveur de build SSH bloqué, clé absente ssh -p ${CI_REMOTE_SSH_PORT} ${CI_REMOTE_USER}@${CI_REMOTE_HOST} manuel
dagger: command not found Dagger non installé sur le builder Relancer setup-remote-ci.sh
Status Cancelled inattendu Timeout (CI_DEFAULT_TIMEOUT) ou auto-cancel Augmenter le timeout, vérifier pipelines concurrents

Problèmes SBOM courants

Symptôme Cause probable Vérifier
SBOM generation disabled CI_SBOM_ENABLED=false .env
syft spawn failed Binaire introuvable which syft, CI_SYFT_BIN
invalid commit sha SHA non hex 40 chars Rare, signale un bug
Dtrack upload 401 API key invalide ou permissions manquantes Régénérer, vérifier les 4 permissions
Status processing indéfiniment Dtrack surchargé, analyse lente Attendre, ou relancer un push

Logs utiles

# Logs Gitrust (systemd)
journalctl -u gitrust -f | grep -E "CI|SBOM|sbom|pipeline"

# Vérifier un pipeline en DB
psql $DATABASE_URL -c "SELECT id, status, commit_sha, created_at FROM ci_pipelines ORDER BY created_at DESC LIMIT 10;"

# Vérifier un SBOM
psql $DATABASE_URL -c "SELECT commit_sha, status, components_count, critical_count, high_count FROM sbom_reports ORDER BY created_at DESC LIMIT 10;"

5. Checklist récapitulative

CI : - [ ] Docker + Dagger installés sur le serveur de build (setup-remote-ci.sh) - [ ] CI_ENABLED=true et CI_REMOTE_* dans .env - [ ] Gitrust redémarré - [ ] CI activée dans Settings → CI pour chaque dépôt - [ ] Fichier .gitrust-ci.yml (Easy) ou .dagger/ (Power) commité - [ ] Push → pipeline visible dans l'onglet CI

Dependency Tracker : - [ ] Syft installé sur la machine Gitrust - [ ] CI_SBOM_ENABLED=true dans .env - [ ] (Optionnel) Dependency-Track déployé + API key créée avec les 4 permissions - [ ] (Optionnel) CI_DTRACK_ENABLED=true, CI_DTRACK_URL, CI_DTRACK_API_KEY dans .env - [ ] Gitrust redémarré - [ ] Push → SBOM visible dans l'onglet Security