Files
ja4-platform/docs/services/dashboard.md
toto 51dd376f7a docs: mise à jour complète — 7/8 techniques, 85 features, 12 modules
Reflète l'état réel du système après les étapes 1-9 du roadmap :

- §5.2 (fleet_detector NetworkX/Louvain) et §5.8 (Jaccard cross-domain) : 
- MetaLearner (régression logistique, fallback poids fixes) : documenté
- ExIFFI (profondeur isolation EIF) + erreur AE par feature : documenté
- KL divergence en complément du KS, drift adversarial : documenté
- HTTP/2 fingerprinting (h2_fingerprint, dict_browser_h2, axis_h2_coherence) : documenté
- Métriques de cycle (metrics.py, ml_performance_metrics, alertes) : documenté
- Browser confidence : 5 axes → 6 axes (axis_h2_coherence)
- 85 features (73 FEATURES + 12 FEATURES_COMPLET), 12 modules, 53 routes dashboard
- Conformité thèse : 99.4% (était 97.9%), §5 : 87.5% (était 62.5%)
- Tables nouvelles : fleet_detections, ml_performance_metrics, soc_feedback
- Dictionnaires : 8 (dict_browser_h2 ajouté)
- Dashboard : 16 pages + 37 API routes (fleet, health ajoutés)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-10 01:31:20 +02:00

358 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Dashboard
Application web SOC (Security Operations Center) construite avec **FastAPI + Jinja2 + htmx**,
offrant la visualisation en temps réel, l'investigation et l'analyse des détections de bots
générées par le [bot-detector](bot-detector.md). Interroge ClickHouse sur deux bases de données
(`ja4_processing` et `ja4_logs`).
---
## Pile technologique
| Composant | Technologie |
|-----------|-------------|
| Backend | Python 3.11 + FastAPI |
| Templates | Jinja2 (rendu côté serveur) |
| Interactions dynamiques | htmx (mises à jour partielles via JSON API) |
| Graphiques | Chart.js + ECharts |
| Style | Tailwind CSS (CDN) |
| Base de données | ClickHouse via `clickhouse-connect` (client propre, **PAS** `ja4_common`) |
| Documentation API | Swagger UI (`/docs`) + OpenAPI JSON (`/openapi.json`) |
> **Note :** le dashboard n'utilise **pas** la bibliothèque partagée `ja4_common`. Il possède
> son propre client ClickHouse léger dans `backend/database.py`.
---
## Structure des fichiers
```
services/dashboard/
├── backend/
│ ├── __init__.py
│ ├── main.py Application FastAPI, montage templates + static, CORS, health
│ ├── config.py Variables d'environnement, safe_identifier()
│ ├── database.py Client clickhouse-connect singleton, query(), query_scalar(), execute()
│ └── routes/
│ ├── __init__.py
│ ├── api.py 37 routes JSON (1700+ lignes)
│ └── pages.py 16 routes de pages HTML (100+ lignes)
├── templates/
│ ├── base.html Template de base (layout, navigation, Tailwind CDN)
│ ├── overview.html Vue d'ensemble du dashboard
│ ├── detections.html Tableau paginé des détections d'anomalies
│ ├── scores.html Tableau paginé de tous les scores ML
│ ├── traffic.html Tableau paginé du trafic HTTP brut
│ ├── ip_detail.html Investigation détaillée d'une IP
│ ├── ja4_detail.html Investigation détaillée d'une empreinte JA4
│ ├── cluster_detail.html Investigation détaillée d'un cluster/campagne
│ ├── campaigns.html Vue des campagnes HDBSCAN
│ ├── features.html Analyse des features ML
│ ├── models.html Métadonnées et performances des modèles
│ ├── classify.html Interface de classification SOC
│ ├── tactics.html Tactiques de détection (brute-force, rotation, récurrence)
│ ├── reflists.html Listes de référence et dictionnaires ClickHouse
│ ├── network.html Graphe réseau des campagnes
│ ├── fleet.html Détections de flottes coordonnées (graphe bipartite)
│ └── health.html Santé du pipeline — métriques de performance par cycle
└── static/ Fichiers statiques (JS, CSS)
```
---
## Configuration
Toute la configuration est lue via `os.getenv()` dans `backend/config.py`.
| Variable | Type | Défaut | Description |
|----------|------|--------|-------------|
| `CLICKHOUSE_HOST` | str | `localhost` | Nom d'hôte du serveur ClickHouse |
| `CLICKHOUSE_PORT` | int | `8123` | Port HTTP ClickHouse |
| `CLICKHOUSE_USER` | str | `default` | Utilisateur ClickHouse |
| `CLICKHOUSE_PASSWORD` | str | `""` | Mot de passe ClickHouse |
| `CLICKHOUSE_DB_PROCESSING` | str | `ja4_processing` | Base de données ML/agrégations (fallback : `CLICKHOUSE_DB`) |
| `CLICKHOUSE_DB_LOGS` | str | `ja4_logs` | Base de données des logs HTTP |
| `API_HOST` | str | `0.0.0.0` | Adresse d'écoute du serveur |
| `API_PORT` | int | `8000` | Port d'écoute du serveur |
### Schéma dual-database
Le dashboard utilise deux bases de données ClickHouse :
- **`CLICKHOUSE_DB_PROCESSING`** (`ja4_processing`) : tables ML, agrégations, dictionnaires, feedback SOC
- **`CLICKHOUSE_DB_LOGS`** (`ja4_logs`) : `http_logs`, trafic brut
Les noms de bases sont validés par `safe_identifier()` (regex alphanumérique + underscore) avant injection dans les requêtes SQL.
### Dualité IPv4/IPv6
- `http_logs.src_ip` est de type `IPv4`
- Les tables ML (`ml_all_scores`, `ml_detected_anomalies`) stockent `IPv6` (mappé `::ffff:x.x.x.x`)
- Utiliser `toIPv6()` pour les requêtes sur les tables ML
- Utiliser `toIPv4OrZero()` pour les requêtes sur `http_logs`
- Retirer le préfixe `::ffff:` à l'affichage
---
## Couche base de données (`backend/database.py`)
Client `clickhouse-connect` avec singleton paresseux :
| Fonction | Signature | Description |
|----------|-----------|-------------|
| `get_client()` | `→ Client` | Singleton `clickhouse_connect.get_client()` |
| `query(sql, params)` | `→ list[dict]` | Exécute un SELECT, retourne une liste de dicts |
| `query_scalar(sql, params)` | `→ Any` | Exécute un SELECT, retourne une valeur scalaire |
| `execute(sql, params)` | `→ None` | Exécute un DDL/DML sans retour |
Conversion automatique des types : `IPv4Address`, `IPv6Address`, `bytes` → chaînes JSON-friendly.
### Patron de requêtes paramétrées
```python
from backend.config import DB_PROCESSING, DB_LOGS, safe_identifier
from backend.database import query, query_scalar
_DB = safe_identifier(DB_PROCESSING)
rows = query(
f"SELECT src_ip, anomaly_score FROM {_DB}.ml_detected_anomalies "
"WHERE src_ip = toIPv6({ip:String}) ORDER BY detected_at DESC LIMIT 10",
{"ip": ip_value},
)
```
---
## Routes de pages (16)
Toutes les pages sont rendues côté serveur via Jinja2 et utilisent htmx pour les mises à jour dynamiques.
| # | Chemin | Template | Description |
|---|--------|----------|-------------|
| 1 | `/` | `overview.html` | Vue d'ensemble : statistiques 24h, distribution des menaces, top IPs, timeline |
| 2 | `/detections` | `detections.html` | Tableau paginé des détections d'anomalies avec filtres |
| 3 | `/scores` | `scores.html` | Tableau paginé de tous les scores ML avec filtres |
| 4 | `/traffic` | `traffic.html` | Tableau paginé des logs HTTP bruts avec filtres |
| 5 | `/ip/{ip}` | `ip_detail.html` | Investigation détaillée d'une IP (détections, scores, logs, features, récurrence) |
| 6 | `/classify` | `classify.html` | Interface de classification SOC (feedback analyste) |
| 7 | `/features` | `features.html` | Analyse des features ML (profils humain/bot, importance) |
| 8 | `/models` | `models.html` | Métadonnées des modèles, statistiques de scoring |
| 9 | `/network` | `network.html` | Graphe réseau des campagnes (IP ↔ JA4 partagés) |
| 10 | `/campaigns` | `campaigns.html` | Campagnes HDBSCAN (clusters de bots agrégés) |
| 11 | `/ja4/{fingerprint:path}` | `ja4_detail.html` | Investigation détaillée d'une empreinte JA4 |
| 12 | `/cluster/{cid}` | `cluster_detail.html` | Investigation détaillée d'un cluster |
| 13 | `/tactics` | `tactics.html` | Tactiques de détection (brute-force, rotation JA4/UA, récurrence) |
| 14 | `/reflists` | `reflists.html` | Listes de référence et dictionnaires ClickHouse |
| 15 | `/fleet` | `fleet.html` | Détections de flottes coordonnées — graphe bipartite JA4×ASN, communautés, fleet_score |
| 16 | `/health` | `health.html` | Santé du pipeline — métriques de cycle, alertes calibration/drift/corrélation/latence |
---
## Routes API (37)
Toutes les routes sont préfixées par `/api` et retournent du JSON. Utilisées par htmx depuis les templates et consommables par des clients externes.
### Vue d'ensemble et statistiques
| # | Méthode | Chemin | Description |
|---|---------|--------|-------------|
| 1 | GET | `/api/overview` | Résumé du dashboard : détections/scores/trafic 24h, distribution des menaces, top IPs, timeline, modèles, statistiques navigateur |
| 2 | GET | `/api/heatmap` | Heatmap temporelle (heure × jour de semaine) depuis `http_logs` |
| 3 | GET | `/api/geo` | Répartition géographique et ASN des sessions |
| 4 | GET | `/api/alerts` | Flux d'alertes en direct (détections récentes HIGH/CRITICAL) |
| 5 | GET | `/api/timeline-detail` | Détail horaire de la timeline par niveau de menace |
### Détections et scores
| # | Méthode | Chemin | Description |
|---|---------|--------|-------------|
| 6 | GET | `/api/detections` | Liste paginée des détections d'anomalies avec filtres (threat_level, search, asn, country, ja4, bot, browser) et tri |
| 7 | GET | `/api/scores` | Liste paginée des scores ML avec filtres similaires |
| 8 | GET | `/api/traffic` | Liste paginée des logs HTTP bruts avec filtres |
### Investigation IP
| # | Méthode | Chemin | Description |
|---|---------|--------|-------------|
| 9 | GET | `/api/ip/{ip}` | Détail IP : détections, scores, logs HTTP, features AI, récurrence |
| 10 | GET | `/api/ip/{ip}/radar` | Données pour graphique radar : IP vs baseline ISP vs baseline bot |
### Features et modèles
| # | Méthode | Chemin | Description |
|---|---------|--------|-------------|
| 11 | GET | `/api/features` | Statistiques des features AI/thèse, profils humain/bot, importance (variance) |
| 12 | GET | `/api/models` | Métadonnées des modèles depuis fichiers JSON + statistiques de scoring ClickHouse |
| 13 | GET | `/api/models/timeline` | Volume horaire de scoring par modèle (7 jours) |
| 14 | GET | `/api/models/threats` | Répartition des niveaux de menace par modèle |
### Empreintes et navigateurs
| # | Méthode | Chemin | Description |
|---|---------|--------|-------------|
| 15 | GET | `/api/fingerprints` | Analyse des empreintes JA4 avec mapping de bots |
| 16 | GET | `/api/browsers` | Distribution des familles de navigateurs via JA4 |
| 17 | GET | `/api/behavior` | Données scatter des features comportementales + distributions |
### Classification SOC
| # | Méthode | Chemin | Description |
|---|---------|--------|-------------|
| 18 | GET | `/api/classify/stats` | Résumé statistique des classifications SOC |
| 19 | GET | `/api/classify/suggested` | Top des IPs non classifiées triées par sévérité |
| 20 | POST | `/api/classify` | Soumettre un feedback analyste SOC (bot/legitimate/suspicious) |
| 21 | GET | `/api/classifications` | Entrées de feedback SOC récentes |
### Campagnes et clusters
| # | Méthode | Chemin | Description |
|---|---------|--------|-------------|
| 22 | GET | `/api/campaigns` | Clusters de campagnes HDBSCAN (agrégés) |
| 23 | GET | `/api/campaigns/graph` | Données de graphe réseau (nœuds IP + arêtes JA4 partagés) |
| 24 | GET | `/api/campaigns/scatter` | Scatter plot : score d'anomalie vs vélocité par IP et campagne |
| 25 | GET | `/api/campaigns/{cid}` | Détail campagne : membres, profil, timeline |
### Investigation JA4 et cluster
| # | Méthode | Chemin | Description |
|---|---------|--------|-------------|
| 26 | GET | `/api/ja4/{fingerprint:path}` | Investigation d'empreinte JA4 (IPs, scores, logs, features) |
| 27 | GET | `/api/cluster/{cid}` | Investigation enrichie de cluster (profil, membres, graphe, répartitions) |
### Tactiques de détection
| # | Méthode | Chemin | Description |
|---|---------|--------|-------------|
| 28 | GET | `/api/brute-force` | Détection de brute-force / credential stuffing |
| 29 | GET | `/api/ja4-rotation` | Détection de rotation d'empreintes JA4 (évasion) |
| 30 | GET | `/api/recurrence` | IPs de menaces persistantes/récurrentes |
| 31 | GET | `/api/cascade/{ip}` | Cascade de ressources pour détection de navigateur headless |
| 32 | GET | `/api/ua-rotation` | Détection de rotation de User-Agent |
### Flottes et santé
| # | Méthode | Chemin | Description |
|---|---------|--------|-------------|
| 33 | GET | `/api/fleet` | Flottes de bots coordonnées — communautés JA4×ASN, fleet_score, IPs membres |
| 34 | GET | `/api/health` | Métriques de performance du pipeline — cycle, drift, corrélation, alertes |
### Dictionnaires et listes de référence
| # | Méthode | Chemin | Description |
|---|---------|--------|-------------|
| 35 | GET | `/api/dictionaries` | Métadonnées des 8 dictionnaires ClickHouse |
| 36 | GET | `/api/reflist/{name}` | Contenu paginé d'une liste de référence / dictionnaire |
| 37 | GET | `/api/reflist/{name}/stats` | Statistiques agrégées d'une liste de référence |
### Autres routes
| Méthode | Chemin | Description |
|---------|--------|-------------|
| GET | `/health` | Point de santé — retourne l'état de connexion ClickHouse |
| — | `/static` | Montage de fichiers statiques (`backend/static/`) |
| GET | `/docs` | Documentation Swagger UI (auto-généré par FastAPI) |
| GET | `/openapi.json` | Schéma OpenAPI (auto-généré par FastAPI) |
**Total : 16 pages + 37 API + 1 health check = 54 routes applicatives**
---
## Paramètres de requête courants
Les endpoints paginés (`/api/detections`, `/api/scores`, `/api/traffic`) acceptent :
| Paramètre | Type | Description |
|-----------|------|-------------|
| `page` | int | Numéro de page (défaut : 1) |
| `page_size` | int | Éléments par page (défaut : 20) |
| `threat_level` | str | Filtre par niveau de menace |
| `model_name` | str | Filtre par nom de modèle |
| `search` | str | Recherche plein texte (IP, JA4, host, bot_name) |
| `sort_by` | str | Champ de tri (validé contre une whitelist) |
| `sort_order` | str | `asc` ou `desc` |
---
## Workflow SOC
Le dashboard est conçu pour le workflow d'un analyste SOC :
1. **Vue d'ensemble** (`/`) — identifier les tendances de menaces 24h, les pics d'anomalies
2. **Détections** (`/detections`) — filtrer les anomalies par sévérité, rechercher des IPs spécifiques
3. **Investigation IP** (`/ip/{ip}`) — examiner les détections, scores, logs HTTP, features ML, radar de comparaison
4. **Analyse JA4** (`/ja4/{fp}`) — investiguer une empreinte TLS, voir toutes les IPs associées
5. **Campagnes** (`/campaigns`) — visualiser les clusters de bots, graphe réseau, scatter plot
6. **Cluster** (`/cluster/{cid}`) — plonger dans un cluster spécifique, examiner les membres et profils
7. **Flottes** (`/fleet`) — visualiser les communautés de botnets coordonnées (graphe bipartite JA4×ASN)
8. **Tactiques** (`/tactics`) — surveiller le brute-force, la rotation JA4/UA, les menaces récurrentes
9. **Classification** (`/classify`) — soumettre un feedback analyste (bot/légitime/suspect) pour alimenter XGBoost et le MetaLearner
10. **Features** (`/features`) — comparer les profils de features humain vs bot
11. **Modèles** (`/models`) — surveiller les performances des modèles ML
12. **Santé** (`/health`) — métriques de cycle, alertes de calibration, drift, corrélation et latence
---
## Architecture des templates
### Template de base (`base.html`)
Fournit le layout commun :
- Navigation latérale avec liens vers toutes les pages
- Chargement CDN de Tailwind CSS, htmx, Chart.js, ECharts
- Bloc `{% block content %}` pour le contenu de chaque page
### Rendu côté serveur + htmx
Chaque page est rendue côté serveur par Jinja2. Les interactions dynamiques utilisent htmx :
```html
<!-- Exemple : chargement dynamique des détections -->
<div hx-get="/api/detections?page=1&page_size=20"
hx-trigger="load"
hx-target="#detections-table">
</div>
```
Les graphiques sont rendus côté client par Chart.js et ECharts à partir des données JSON de l'API.
---
## CORS
Le middleware CORS est configuré de manière permissive dans `main.py` :
```python
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
```
L'application est principalement SSR mais l'API JSON est aussi consommable par des clients externes.
---
## Déploiement
```bash
# Construction de l'image Docker
make build-dashboard
# Tests
make test-dashboard
# Exécution locale (développement)
cd services/dashboard
uvicorn backend.main:app --reload --host 0.0.0.0 --port 8000
```
### Point de santé
```
GET /health → {"status": "healthy", "clickhouse": "connected"}
```