fix(ja4ebpf): split bpf2go generate into Ja4Tc + Ja4Ssl, fix RPM systemd-rpm-macros
- Use two separate //go:generate directives (Ja4Tc for tc_capture.c, Ja4Ssl
for uprobe_ssl.c) to avoid duplicate LICENSE symbol and multi-file clang issue
- Update loader.go to hold tcObjs/sslObjs separately with correct field names:
UprobeSslSetFd, UprobeSslReadEntry, UretprobeSslReadExit,
KprobeAccept4Entry, KretprobeAccept4Exit
- Add systemd-rpm-macros to all three RPM build stages (el8/el9/el10)
so that %{_unitdir} macro resolves correctly
- RPMs now build successfully for el8, el9, el10
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
# 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 ou C n'est requise sur la machine hôte.
|
||||
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
|
||||
|
||||
@ -11,8 +11,6 @@ Ce guide couvre la compilation, les tests, le packaging et l'extension du monore
|
||||
| make | 3.81+ | GNU Make |
|
||||
| git | 2.x | Pour le versioning |
|
||||
|
||||
Aucun compilateur Go, Python ou C n'est nécessaire sur la machine hôte.
|
||||
|
||||
## Compilation de tous les services
|
||||
|
||||
```bash
|
||||
@ -20,18 +18,14 @@ make build-all
|
||||
```
|
||||
|
||||
Cela construit les images Docker pour :
|
||||
- `ja4-platform/sentinel:latest`
|
||||
- `ja4-platform/correlator:latest`
|
||||
- `ja4-platform/ja4ebpf:latest`
|
||||
- `ja4-platform/bot-detector:latest`
|
||||
- `ja4-platform/dashboard:latest`
|
||||
|
||||
mod-reqin-log est un module Apache et n'est construit que dans le cadre du processus RPM.
|
||||
|
||||
### Compilation individuelle
|
||||
|
||||
```bash
|
||||
make build-sentinel # Binaire Go dans Docker
|
||||
make build-correlator # Binaire Go dans Docker
|
||||
make build-ja4ebpf # Bytecode eBPF (clang) + binaire Go dans Docker Rocky Linux
|
||||
make build-bot-detector # Image Python
|
||||
make build-dashboard # Image FastAPI + Jinja2
|
||||
```
|
||||
@ -46,9 +40,7 @@ make test-all
|
||||
|
||||
| Service | Commande | Détails |
|
||||
|---------|----------|---------|
|
||||
| sentinel | `make test-sentinel` | Tests Go avec `-race`, nécessite `NET_RAW`/`NET_ADMIN` |
|
||||
| correlator | `make test-correlator` | Tests Go avec seuil de couverture 80% |
|
||||
| mod-reqin-log | `make test-mod-reqin-log` | Tests unitaires C (sérialisation JSON, config, headers) |
|
||||
| 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 |
|
||||
@ -58,42 +50,32 @@ make test-all
|
||||
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 → sentinel
|
||||
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 de données entre chaque exécution.
|
||||
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-all
|
||||
make rpm-ja4ebpf
|
||||
# RPMs dans services/ja4ebpf/dist/rpm/el{8,9,10}/
|
||||
```
|
||||
|
||||
Construit les RPMs pour sentinel, correlator et mod-reqin-log ciblant Rocky Linux 8/9/10 :
|
||||
|
||||
```bash
|
||||
make rpm-sentinel # → services/sentinel/dist/rpm/
|
||||
make rpm-correlator # → services/correlator/dist/rpm/
|
||||
make rpm-mod-reqin-log # → services/mod-reqin-log/dist/rpm/
|
||||
```
|
||||
|
||||
Chaque build RPM utilise un pipeline Docker multi-étapes :
|
||||
1. L'étape builder compile le binaire (Go) ou l'objet partagé (C)
|
||||
2. L'étape rpmbuild exécute `rpmbuild` pour chaque distro cible (el8, el9, el10)
|
||||
3. L'étape de sortie copie les RPMs sur l'hôte via `--output type=local`
|
||||
|
||||
### Paquets de distribution
|
||||
|
||||
```bash
|
||||
make dist # Alias for rpm-all
|
||||
# RPMs in services/<service>/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
|
||||
|
||||
### Services Go (sentinel, correlator)
|
||||
### Service Go/eBPF (ja4ebpf)
|
||||
|
||||
Le fichier `go.work` relie les modules Go :
|
||||
|
||||
@ -101,23 +83,23 @@ Le fichier `go.work` relie les modules Go :
|
||||
go 1.24.6
|
||||
|
||||
use (
|
||||
./services/sentinel
|
||||
./services/correlator
|
||||
./shared/go/ja4common
|
||||
./services/ja4ebpf
|
||||
)
|
||||
```
|
||||
|
||||
Si Go 1.24+ est installé localement, le développement sans Docker est possible :
|
||||
La compilation locale du bytecode eBPF nécessite `clang`, `llvm` et `bpftool`. En pratique, on passe toujours par Docker :
|
||||
|
||||
```bash
|
||||
# Tests sentinel en local
|
||||
cd services/sentinel && go test ./... -race -v
|
||||
# Rebuild du bytecode eBPF + binaire Go (Docker Rocky Linux)
|
||||
make build-ja4ebpf
|
||||
|
||||
# Tests correlator en local
|
||||
cd services/correlator && go test ./... -race -cover -v
|
||||
# Tests unitaires ja4ebpf (Docker avec cap NET_RAW + BPF)
|
||||
make test-ja4ebpf
|
||||
|
||||
# Compilation du binaire sentinel (nécessite libpcap-dev)
|
||||
cd services/sentinel && go build -o ja4sentinel ./cmd/ja4sentinel/
|
||||
# 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)
|
||||
@ -137,12 +119,10 @@ uvicorn backend.main:app --reload --host 0.0.0.0 --port 8000
|
||||
|
||||
#### Dépendances Python pour le développement local du bot-detector
|
||||
|
||||
Les dépendances principales sont listées dans `services/bot-detector/bot_detector/requirements.txt`. Les librairies ML clés sont :
|
||||
|
||||
| Librairie | Usage |
|
||||
|-----------|-------|
|
||||
| `isotree` | Extended Isolation Forest (scoreur principal non supervisé) |
|
||||
| `torch` | Autoencoder (PyTorch, architecture n→64→32→16→32→64→n) |
|
||||
| `torch` | Autoencoder (PyTorch, architecture n->64->32->16->32->64->n) |
|
||||
| `xgboost` | Modèle supervisé (entraîné sur les labels SOC) |
|
||||
| `hdbscan` | Clustering de campagnes d'attaque |
|
||||
| `shap` | Explicabilité des scores d'anomalie |
|
||||
@ -167,117 +147,48 @@ services/bot-detector/bot_detector/
|
||||
└── tests/ # Tests pytest (self-contained, pas d'import lourd)
|
||||
```
|
||||
|
||||
### Module C (mod-reqin-log)
|
||||
|
||||
Nécessite `apxs` (outil d'extension Apache) et les headers de développement :
|
||||
|
||||
```bash
|
||||
cd services/mod-reqin-log
|
||||
make build # Compile mod_reqin_log.so
|
||||
make test # Exécute les tests unitaires
|
||||
make rpm # Construit les paquets RPM
|
||||
```
|
||||
|
||||
## Scripts utilitaires
|
||||
|
||||
Les scripts dans `scripts/` facilitent l'initialisation et la gestion de l'environnement de développement :
|
||||
|
||||
| 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 |
|
||||
| `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
|
||||
# Initialisation complète (schéma + données CSV + import prod)
|
||||
make init-and-import
|
||||
|
||||
# Initialisation seule (schéma + CSV)
|
||||
make init-stack
|
||||
|
||||
# Import des données prod pré-exportées
|
||||
make import-prod-data
|
||||
|
||||
# Rechargement depuis la prod
|
||||
make reload-prod-logs
|
||||
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 du service :
|
||||
1. Créer le répertoire et initialiser le module :
|
||||
```bash
|
||||
mkdir -p services/my-service/cmd/my-service
|
||||
mkdir -p services/my-service/internal
|
||||
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. Initialiser le module Go :
|
||||
```bash
|
||||
cd services/my-service
|
||||
go mod init github.com/antitbone/ja4/my-service
|
||||
```
|
||||
|
||||
3. Ajouter au `go.work` :
|
||||
2. Ajouter au `go.work` :
|
||||
```
|
||||
use (
|
||||
./services/sentinel
|
||||
./services/correlator
|
||||
./services/my-service # ← add this
|
||||
./shared/go/ja4common
|
||||
./services/ja4ebpf
|
||||
./services/my-service # <- add this
|
||||
)
|
||||
```
|
||||
|
||||
4. Importer la librairie partagée :
|
||||
```go
|
||||
import (
|
||||
"github.com/antitbone/ja4/ja4common/logger"
|
||||
"github.com/antitbone/ja4/ja4common/config"
|
||||
"github.com/antitbone/ja4/ja4common/shutdown"
|
||||
)
|
||||
```
|
||||
|
||||
5. Ajouter les cibles Makefile :
|
||||
```makefile
|
||||
build-my-service:
|
||||
docker build -f services/my-service/Dockerfile -t ja4-platform/my-service:latest .
|
||||
|
||||
test-my-service:
|
||||
docker build -f services/my-service/Dockerfile.dev -t ja4-platform/my-service-tests:latest .
|
||||
docker run --rm ja4-platform/my-service-tests:latest
|
||||
```
|
||||
|
||||
6. Mettre à jour les dépendances `build-all` et `test-all`.
|
||||
3. Ajouter les cibles Makefile.
|
||||
|
||||
### Service Python
|
||||
|
||||
1. Créer le répertoire du service avec un `requirements.txt` ou `pyproject.toml`.
|
||||
2. Ajouter `ja4-common` comme dépendance (installée depuis `shared/python/ja4_common`).
|
||||
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.
|
||||
4. Ajouter les cibles Makefile en suivant le modèle bot-detector/dashboard.
|
||||
|
||||
## Workspace go.work
|
||||
|
||||
Le fichier `go.work` à la racine du dépôt relie tous les modules Go, permettant le développement cross-module sans publication :
|
||||
|
||||
```
|
||||
go 1.24.6
|
||||
|
||||
use (
|
||||
./services/sentinel
|
||||
./services/correlator
|
||||
./shared/go/ja4common
|
||||
)
|
||||
```
|
||||
|
||||
Lors de l'ajout d'un nouveau module Go :
|
||||
1. `go mod init` dans le répertoire du service
|
||||
2. Ajouter le chemin dans `go.work`
|
||||
3. Référencer les packages partagés via leur chemin de module : `github.com/antitbone/ja4/ja4common/...`
|
||||
4. Exécuter `go work sync` pour mettre à jour le workspace
|
||||
|
||||
Les deux services Go ont une directive `replace` dans leur `go.mod` pointant vers `../../shared/go/ja4common`. Le workspace prend priorité en développement local ; la directive `replace` est nécessaire pour les builds Docker où `go.work` n'est pas disponible.
|
||||
|
||||
## Package Python ja4_common
|
||||
|
||||
@ -289,31 +200,10 @@ Le package Python partagé (`shared/python/ja4_common`) fournit :
|
||||
|
||||
> **Note :** le dashboard n'utilise PAS ja4_common — il possède son propre client léger `clickhouse-connect` dans `backend/database.py`.
|
||||
|
||||
### Extension de ja4_common
|
||||
|
||||
1. Ajouter de nouveaux modules sous `shared/python/ja4_common/ja4_common/`
|
||||
2. Les exporter dans `__init__.py`
|
||||
3. Ajouter les dépendances dans `pyproject.toml`
|
||||
4. Lancer les tests : `make test-ja4common-python`
|
||||
|
||||
### Utilisation dans un nouveau service
|
||||
|
||||
Ajouter dans `requirements.txt` :
|
||||
```
|
||||
ja4-common @ file:///app/shared/python/ja4_common
|
||||
```
|
||||
|
||||
Or in Docker, copy the shared library and install:
|
||||
```dockerfile
|
||||
COPY shared/python/ja4_common /app/shared/python/ja4_common
|
||||
RUN pip install /app/shared/python/ja4_common
|
||||
```
|
||||
|
||||
## Variables d'environnement
|
||||
|
||||
Chaque service lit sa configuration depuis des variables d'environnement et/ou des fichiers YAML. Consultez la documentation de chaque service pour la référence complète :
|
||||
Consultez la documentation de chaque service pour la référence complète :
|
||||
|
||||
- [Configuration du Sentinel](services/sentinel.md#configuration-reference)
|
||||
- [Configuration du Correlator](services/correlator.md#configuration-reference)
|
||||
- [Configuration de ja4ebpf](services/ja4ebpf.md#configuration)
|
||||
- [Configuration du Bot Detector](services/bot-detector.md#environment-variables)
|
||||
- [Configuration du Dashboard](services/dashboard.md#configuration)
|
||||
|
||||
Reference in New Issue
Block a user