Files
ja4-platform/docs/development.md
Jacquin Antoine f88b739992 feat(e2e): add distributed E2E test framework with parametric traffic generation
Add run-e2e-test.sh with CLI parameters (--hits, --http-ratio, --dns, --tls,
--src-ips, --keep-analysis, --up) for configurable traffic generation. Traffic
runs from VM endpoints with multiple source IPs (alias IPs on eth0) to produce
distinct sessions for the ML pipeline. Fix curl TLS flags (--tlsv1.2 instead
of --tls-v1-2), skip redundant local verification in distributed mode, and
fix dashboard is_available() cache that never retried after ClickHouse recovery.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-15 00:09:32 +02:00

219 lines
7.8 KiB
Markdown

# Guide de développement
Ce guide couvre la compilation, les tests, le packaging et l'extension du monorepo ja4-platform. Toutes les opérations de build et de test s'exécutent dans Docker — aucune toolchain Go, Python, C ou eBPF n'est requise sur la machine hôte.
## Prérequis
| Outil | Version minimale | Notes |
|-------|-----------------|-------|
| Docker | 20.10+ | BuildKit activé (`DOCKER_BUILDKIT=1`) |
| Docker Compose | 2.x | Pour bot-detector et dashboard |
| make | 3.81+ | GNU Make |
| git | 2.x | Pour le versioning |
## Compilation de tous les services
```bash
make build-all
```
Cela construit les images Docker pour :
- `ja4-platform/ja4ebpf:latest`
- `ja4-platform/bot-detector:latest`
- `ja4-platform/dashboard:latest`
### Compilation individuelle
```bash
make build-ja4ebpf # Bytecode eBPF (clang) + binaire Go dans Docker Rocky Linux
make build-bot-detector # Image Python
make build-dashboard # Image FastAPI + Jinja2
```
## Exécution des tests
```bash
make test-all
```
### Tests E2E distribués (full stack : capture + ML + dashboard)
```bash
make e2e-up # Créer les 4 VMs (centos8/rocky9/rocky10/analysis)
make e2e-down # Détruire les VMs E2E
make test-e2e # Test E2E complet (capture + ML + dashboard)
make test-e2e-quick # Test E2E rapide (trafic réduit, 1 cycle bot-detector)
```
### Tests par service
| Service | Commande | Détails |
|---------|----------|---------|
| ja4ebpf | `make test-ja4ebpf` | Tests Go avec `-race`, nécessite `NET_RAW`/`NET_ADMIN`/`BPF` |
| bot-detector | `make test-bot-detector` | Suite pytest Python |
| dashboard | `make test-dashboard` | pytest pour les routes FastAPI |
| ja4_common (Python) | `make test-ja4common-python` | Tests de la librairie Python partagée |
## Tests d'intégration
Les tests d'intégration full-stack s'exécutent contre Docker Compose avec une instance ClickHouse réelle :
```bash
make test-integration # 8 phases : build -> start -> schema -> traffic -> pipeline -> dashboard -> bot-detector -> ja4ebpf
make test-integration-keep # idem mais laisse la stack en fonctionnement
make test-integration-down # démontage de la stack d'intégration
make test-nginx # stack nginx + ja4ebpf
make test-nginx-varnish # nginx + Varnish + ja4ebpf
make test-hitch-varnish # hitch (TLS) + Varnish + ja4ebpf
make test-all-stacks # les 3 stacks serveur en séquence
```
La suite de tests se trouve dans `tests/integration/` et réinitialise la base entre chaque exécution.
## Construction des paquets RPM
```bash
make rpm-ja4ebpf
# RPMs dans services/ja4ebpf/dist/rpm/el{8,9,10}/
```
Le build RPM utilise un pipeline Docker multi-étapes Rocky Linux :
1. L'étape `go-builder` compile le bytecode eBPF (clang/llvm) puis le binaire Go statique
2. Les étapes `rpm-el8`, `rpm-el9`, `rpm-el10` exécutent `rpmbuild` pour chaque distro cible
3. L'étape de sortie `alpine` collecte tous les RPMs via `--output type=local`
## Développement local
### Service Go/eBPF (ja4ebpf)
Le fichier `go.work` relie les modules Go :
```
go 1.24.6
use (
./shared/go/ja4common
./services/ja4ebpf
)
```
La compilation locale du bytecode eBPF nécessite `clang`, `llvm` et `bpftool`. En pratique, on passe toujours par Docker :
```bash
# Rebuild du bytecode eBPF + binaire Go (Docker Rocky Linux)
make build-ja4ebpf
# Tests unitaires ja4ebpf (Docker avec cap NET_RAW + BPF)
make test-ja4ebpf
# Test single dans Docker
docker run --rm --cap-add=NET_RAW --cap-add=NET_ADMIN --cap-add=BPF \
ja4ebpf:tests go test -v -run TestDispatcher ./internal/dispatcher/
```
### Services Python (bot-detector, dashboard)
```bash
# Installer la librairie partagée en mode développement
cd shared/python/ja4_common && pip install -e .
# Lancer le bot-detector localement
cd services/bot-detector && pip install -r bot_detector/requirements.txt
python -m bot_detector
# Lancer le dashboard localement
cd services/dashboard && pip install -r backend/requirements.txt
uvicorn backend.main:app --reload --host 0.0.0.0 --port 8000
```
#### Dépendances Python pour le développement local du bot-detector
| Librairie | Usage |
|-----------|-------|
| `isotree` | Extended Isolation Forest (scoreur principal non supervisé) |
| `torch` | NFEnsemble / TrafficNormalizingFlow (PyTorch, Deep Ensemble M=5) |
| `xgboost` | Modèle supervisé (entraîné sur les labels SOC) |
| `hdbscan` | Clustering de campagnes d'attaque |
| `shap` | Explicabilité des scores d'anomalie |
| `scikit-learn` | Fallback pour Isolation Forest si isotree indisponible |
| `clickhouse-connect` | Client ClickHouse (via ja4_common) |
#### Structure modulaire du bot-detector (16 modules)
```
services/bot-detector/bot_detector/
├── __init__.py # Package init
├── __main__.py # Point d'entrée (python -m bot_detector)
├── config.py # Configuration (os.getenv, PAS pydantic-settings)
├── log.py # Configuration du logging
├── infra.py # Connexion ClickHouse, health check
├── preprocessing.py # Feature engineering, filtrage, normalisation
├── models.py # EIF, NFEnsemble/TrafficNormalizingFlow, XGBoost (entraînement + scoring)
├── scoring.py # Ensemble triple voix, seuils adaptatifs, ADWIN drift
├── browser.py # Détection de navigateur 5 axes multifactoriels
├── pipeline.py # Orchestration du cycle de détection
├── cycle.py # Boucle principale (cycle de 5 minutes)
└── tests/ # Tests pytest (self-contained, pas d'import lourd)
```
## Scripts utilitaires
| Script | Commande Make | Description |
|--------|--------------|-------------|
| `init-stack.sh` | `make init-stack` | Initialisation complète de la stack ClickHouse (schéma + données CSV) |
| `import-prod-data.sh` | `make import-prod-data` | Import de données de prod avec décalage temporel |
| `reload-prod-logs.sh` | `make reload-prod-logs` | Export prod -> réimport dev avec décalage |
| `update-csv-data.sh` | -- | Téléchargement et génération de toutes les données CSV de référence |
```bash
make init-and-import # Initialisation complète (schéma + CSV + import prod)
make init-stack # Initialisation seule (schéma + CSV)
make import-prod-data # Import des données prod pré-exportées
make reload-prod-logs # Rechargement depuis la prod
```
## Ajout d'un nouveau service
### Service Go
1. Créer le répertoire et initialiser le module :
```bash
mkdir -p services/my-service/cmd/my-service services/my-service/internal
cd services/my-service && go mod init github.com/antitbone/ja4/my-service
```
2. Ajouter au `go.work` :
```
use (
./shared/go/ja4common
./services/ja4ebpf
./services/my-service # <- add this
)
```
3. Ajouter les cibles Makefile.
### Service Python
1. Créer le répertoire avec `requirements.txt`.
2. Ajouter `ja4-common` comme dépendance locale.
3. Utiliser `from ja4_common.clickhouse import get_client` pour l'accès ClickHouse.
## Package Python ja4_common
Le package Python partagé (`shared/python/ja4_common`) fournit :
- `ClickHouseSettings` — modèle pydantic-settings lisant depuis `.env`
- `ClickHouseClient` — client singleton avec reconnexion automatique
- `get_client()` — accesseur singleton au niveau du module
> **Note :** le dashboard n'utilise PAS ja4_common — il possède son propre client léger `clickhouse-connect` dans `backend/database.py`.
## Variables d'environnement
Consultez la documentation de chaque service pour la référence complète :
- [Configuration de ja4ebpf](services/ja4ebpf.md#configuration)
- [Configuration du Bot Detector](services/bot-detector.md#environment-variables)
- [Configuration du Dashboard](services/dashboard.md#configuration)