Initial commit: Bot Detector Dashboard for SOC Incident Response

🛡️ Dashboard complet pour l'analyse et la classification des menaces

Fonctionnalités principales:
- Visualisation des détections en temps réel (24h)
- Investigation multi-entités (IP, JA4, ASN, Host, User-Agent)
- Analyse de corrélation pour classification SOC
- Clustering automatique par subnet/JA4/UA
- Export des classifications pour ML

Composants:
- Backend: FastAPI (Python) + ClickHouse
- Frontend: React + TypeScript + TailwindCSS
- 6 routes API: metrics, detections, variability, attributes, analysis, entities
- 7 types d'entités investigables

Documentation ajoutée:
- NAVIGATION_GRAPH.md: Graph complet de navigation
- SOC_OPTIMIZATION_PROPOSAL.md: Proposition d'optimisation pour SOC
  • Réduction de 7 à 2 clics pour classification
  • Nouvelle vue /incidents clusterisée
  • Panel latéral d'investigation
  • Quick Search (Cmd+K)
  • Timeline interactive
  • Graph de corrélations

Sécurité:
- .gitignore configuré (exclut .env, secrets, node_modules)
- Credentials dans .env (à ne pas committer)

⚠️ Audit sécurité réalisé - Voir recommandations dans SOC_OPTIMIZATION_PROPOSAL.md

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
SOC Analyst
2026-03-14 21:33:55 +01:00
commit a61828d1e7
55 changed files with 11189 additions and 0 deletions

985
TEST_PLAN.md Normal file
View File

@ -0,0 +1,985 @@
# 🧪 Plan de Test - Bot Detector Dashboard
**Version:** 1.0
**Date:** 2025
**Projet:** Dashboard Bot Detector IA
**Stack:** FastAPI + React + ClickHouse
---
## 📑 Table des Matières
1. [Vue d'ensemble](#1-vue-densemble)
2. [Tests Backend (API)](#2-tests-backend-api)
3. [Tests Frontend (React)](#3-tests-frontend-react)
4. [Tests ClickHouse (Base de données)](#4-tests-clickhouse-base-de-données)
5. [Tests d'Intégration](#5-tests-dintégration)
6. [Tests de Sécurité](#6-tests-de-sécurité)
7. [Tests de Performance](#7-tests-de-performance)
8. [Matrice de Couverture](#8-matrice-de-couverture)
9. [Scripts de Test Existants](#9-scripts-de-test-existants)
10. [Recommandations](#10-recommandations)
11. [Prioritisation](#11-prioritisation)
---
## 1. Vue d'ensemble
### Architecture testée
```
┌─────────────────────────────────────────────────────────┐
│ Docker Compose │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
│ │ ClickHouse │ │ bot_detector│ │ dashboard_web │ │
│ │ :8123 │ │ (existant) │ │ :3000 (web) │ │
│ │ :9000 │ │ │ │ :8000 (API) │ │
│ └──────┬──────┘ └──────┬──────┘ └────────┬────────┘ │
│ └────────────────┴───────────────────┘ │
└─────────────────────────────────────────────────────────┘
```
### Composants
| Composant | Technologie | Port | Tests |
|-----------|-------------|------|-------|
| **Frontend** | React + TypeScript + Tailwind | 3000 | 25+ tests |
| **Backend API** | FastAPI (Python) | 8000 | 80+ tests |
| **Database** | ClickHouse (existant) | 8123 | 15+ tests |
### Endpoints API (20+ endpoints)
| Routeur | Endpoints | Description |
|---------|-----------|-------------|
| `/health` | 1 | Health check |
| `/api/metrics` | 2 | Métriques globales + distribution |
| `/api/detections` | 2 | Liste des détections + détails |
| `/api/variability` | 4 | Variabilité attributs + IPs + user_agents |
| `/api/attributes` | 1 | Liste attributs uniques |
| `/api/analysis` | 6 | Analyse subnet, country, JA4, UA, recommendation |
| `/api/entities` | 7 | Investigation entités unifiées |
---
## 2. Tests Backend (API)
### 2.1 Endpoint `/health`
| ID | Test | Description | Résultat attendu |
|----|------|-------------|------------------|
| H1 | Health check basique | GET /health | `{"status": "healthy", "clickhouse": "connected"}` |
| H2 | Health check ClickHouse down | ClickHouse indisponible | `{"status": "unhealthy", "clickhouse": "disconnected"}` |
| H3 | Temps de réponse | Mesure latence | < 500ms |
**Commande de test:**
```bash
curl http://localhost:3000/health | jq
```
---
### 2.2 Endpoint `/api/metrics`
| ID | Test | Description | Résultat attendu |
|----|------|-------------|------------------|
| M1 | Métriques globales | GET /api/metrics | Summary avec total_detections, counts par niveau |
| M2 | Série temporelle | Données 24h groupées par heure | timeseries avec 24 points |
| M3 | Distribution par menace | threat_distribution | 4 niveaux (CRITICAL, HIGH, MEDIUM, LOW) |
| M4 | Aucune donnée (24h) | Base vide | Retourne 0 ou erreur gérée proprement |
| M5 | Performance requête | Temps d'exécution | < 2s |
**Commande de test:**
```bash
curl http://localhost:3000/api/metrics | jq
```
**Vérifications:**
- [ ] `summary.total_detections` > 0
- [ ] `summary.threat_distribution` contient 4 niveaux
- [ ] `timeseries` contient 24 points (une par heure)
- [ ] Somme des counts = total_detections
---
### 2.3 Endpoint `/api/metrics/threats`
| ID | Test | Description | Résultat attendu |
|----|------|-------------|------------------|
| MT1 | Distribution complète | GET /api/metrics/threats | Items avec threat_level, count, percentage |
| MT2 | Cohérence pourcentages | Somme des percentages | ≈ 100% |
**Commande de test:**
```bash
curl http://localhost:3000/api/metrics/threats | jq
```
---
### 2.4 Endpoint `/api/detections`
| ID | Test | Description | Résultat attendu |
|----|------|-------------|------------------|
| D1 | Liste par défaut | GET /api/detections?page=1&page_size=25 | Items triés par detected_at DESC |
| D2 | Pagination | page, page_size, total, total_pages | total_pages = ceil(total/page_size) |
| D3 | Filtre threat_level | `?threat_level=CRITICAL` | Uniquement CRITICAL |
| D4 | Filtre model_name | `?model_name=Complet` | Uniquement ce modèle |
| D5 | Filtre country_code | `?country_code=CN` | Uniquement China |
| D6 | Filtre asn_number | `?asn_number=16276` | Uniquement cet ASN |
| D7 | Recherche texte | `?search=192.168` | IP, JA4, Host correspondants |
| D8 | Tri anomaly_score ASC | `?sort_by=anomaly_score&sort_order=asc` | Scores croissants |
| D9 | Tri detected_at DESC | `?sort_by=detected_at&sort_order=DESC` | Chronologique inverse |
| D10 | Limite page_size | `?page_size=100` | Maximum 100 items |
| D11 | Page inexistante | `?page=9999` | Liste vide, total_pages correct |
**Commandes de test:**
```bash
# Liste par défaut
curl "http://localhost:3000/api/detections?page=1&page_size=25" | jq
# Filtre CRITICAL
curl "http://localhost:3000/api/detections?threat_level=CRITICAL" | jq '.items[].threat_level'
# Recherche IP
curl "http://localhost:3000/api/detections?search=192.168" | jq
# Tri par score
curl "http://localhost:3000/api/detections?sort_by=anomaly_score&sort_order=asc" | jq '.items[0].anomaly_score'
```
**Vérifications:**
- [ ] Structure `DetectionsListResponse` respectée
- [ ] Pagination cohérente
- [ ] Filtres appliqués correctement
- [ ] Tri fonctionnel
- [ ] Recherche texte (LIKE ILIKE)
---
### 2.5 Endpoint `/api/detections/{id}`
| ID | Test | Description | Résultat attendu |
|----|------|-------------|------------------|
| DD1 | Détails par IP | GET /api/detections/192.168.1.1 | Tous les champs remplis |
| DD2 | IP inexistante | GET /api/detections/0.0.0.0 | 404 "Détection non trouvée" |
| DD3 | Structure nested | asn, country, metrics, tcp, tls, headers, behavior, advanced | Tous les objets présents |
**Commande de test:**
```bash
curl http://localhost:3000/api/detections/116.179.33.143 | jq
```
**Vérifications:**
- [ ] Objet `asn` avec number, org, detail, domain, label
- [ ] Objet `country` avec code
- [ ] Objet `metrics` avec hits, hit_velocity, fuzzing_index, post_ratio, etc.
- [ ] Objet `tcp` avec jitter_variance, shared_count, etc.
- [ ] Objet `tls` avec alpn flags
- [ ] Objet `headers` avec count, has_accept_language, etc.
- [ ] Objet `behavior` avec ip_id_zero_ratio, etc.
- [ ] Objet `advanced` avec asset_ratio, etc.
---
### 2.6 Endpoint `/api/variability/{type}/{value}`
| ID | Test | Description | Résultat attendu |
|----|------|-------------|------------------|
| V1 | Variabilité IP | GET /api/variability/ip/192.168.1.1 | user_agents, ja4, countries, asns, hosts, threat_levels |
| V2 | Variabilité JA4 | GET /api/variability/ja4/{fingerprint} | Même structure |
| V3 | Variabilité Pays | GET /api/variability/country/FR | Même structure |
| V4 | Variabilité ASN | GET /api/variability/asn/16276 | Même structure |
| V5 | Variabilité Host | GET /api/variability/host/example.com | Même structure |
| V6 | Type invalide | GET /api/variability/invalid/xyz | 400 "Type invalide" |
| V7 | Aucune donnée | GET /api/variability/ip/0.0.0.0 | 404 |
| V8 | Insights générés | Selon données | Messages pertinents (rotation UA, hosting ASN, etc.) |
**Commande de test:**
```bash
curl http://localhost:3000/api/variability/ip/116.179.33.143 | jq
```
**Vérifications:**
- [ ] `total_detections` > 0
- [ ] `unique_ips` >= 1
- [ ] `attributes.user_agents` liste avec percentages
- [ ] `attributes.ja4` fingerprints
- [ ] `attributes.countries` distribution
- [ ] `attributes.asns` informations
- [ ] `insights` messages contextuels générés
**Insights attendus:**
- [ ] "X User-Agents différents → Possible rotation/obfuscation" (si > 1 UA)
- [ ] "X JA4 fingerprints différents → Possible rotation" (si > 1 JA4)
- [ ] "ASN de type hosting → Souvent utilisé pour des bots" (si OVH, AWS, etc.)
- [ ] "X% de détections CRITICAL → Menace sévère" (si > 30%)
---
### 2.7 Endpoint `/api/variability/{type}/{value}/ips`
| ID | Test | Description | Résultat attendu |
|----|------|-------------|------------------|
| VI1 | IPs associées | GET /api/variability/country/CN/ips | Liste d'IPs uniques |
| VI2 | Limite respectée | `?limit=50` | Maximum 50 items retournés |
| VI3 | Total correct | `total` vs `showing` | Count distinct réel |
**Commande de test:**
```bash
curl "http://localhost:3000/api/variability/country/CN/ips?limit=10" | jq
```
---
### 2.8 Endpoint `/api/variability/{type}/{value}/attributes`
| ID | Test | Description | Résultat attendu |
|----|------|-------------|------------------|
| VA1 | Attributs cibles | `?target_attr=user_agents` | Items avec value, count, percentage |
| VA2 | Target invalide | `?target_attr=invalid` | 400 |
| VA3 | Pourcentages | Somme des percentages | ≈ 100% |
**Commande de test:**
```bash
curl "http://localhost:3000/api/variability/ip/116.179.33.143/attributes?target_attr=ja4&limit=10" | jq
```
---
### 2.9 Endpoint `/api/variability/{type}/{value}/user_agents`
| ID | Test | Description | Résultat attendu |
|----|------|-------------|------------------|
| VU1 | User-Agents depuis vue | GET /api/variability/ip/{ip}/user_agents | Liste avec first_seen, last_seen |
| VU2 | Classification implicite | UA bots détectables | python-requests, curl, etc. |
**Commande de test:**
```bash
curl http://localhost:3000/api/variability/ip/116.179.33.143/user_agents | jq
```
---
### 2.10 Endpoint `/api/attributes/{type}`
| ID | Test | Description | Résultat attendu |
|----|------|-------------|------------------|
| A1 | Liste IPs uniques | GET /api/attributes/ip | Top 100 par count |
| A2 | Liste JA4 uniques | GET /api/attributes/ja4 | idem |
| A3 | Liste pays | GET /api/attributes/country | idem |
| A4 | Liste ASNs | GET /api/attributes/asn | idem |
| A5 | Liste hosts | GET /api/attributes/host | idem |
| A6 | Type invalide | GET /api/attributes/invalid | 400 |
| A7 | Valeurs vides filtrées | Pas de NULL ou "" | Exclus du résultat |
**Commande de test:**
```bash
curl "http://localhost:3000/api/attributes/ip?limit=10" | jq
```
---
### 2.11 Endpoint `/api/analysis/{ip}/subnet`
| ID | Test | Description | Résultat attendu |
|----|------|-------------|------------------|
| AS1 | Analyse subnet /24 | GET /api/analysis/192.168.1.1/subnet | ips_in_subnet, total_in_subnet |
| AS2 | Alert si > 10 IPs | Subnet avec 15 IPs | alert=true |
| AS3 | Informations ASN | asn_number, asn_org, total_in_asn | Données complètes |
| AS4 | IP privée/local | 10.0.0.1 | Géré correctement |
**Commande de test:**
```bash
curl http://localhost:3000/api/analysis/116.179.33.143/subnet | jq
```
---
### 2.12 Endpoint `/api/analysis/{ip}/country`
| ID | Test | Description | Résultat attendu |
|----|------|-------------|------------------|
| AC1 | Pays de l'IP | code, name | FR, France |
| AC2 | Distribution ASN par pays | asn_countries | Liste avec percentages |
**Commande de test:**
```bash
curl http://localhost:3000/api/analysis/116.179.33.143/country | jq
```
---
### 2.13 Endpoint `/api/analysis/country`
| ID | Test | Description | Résultat attendu |
|----|------|-------------|------------------|
| ANC1 | Top 10 pays | GET /api/analysis/country | Avec count et percentage |
| ANC2 | Baseline (7 jours) | Comparaison disponible | baseline object |
| ANC3 | Alert country détectée | Pays surreprésenté | alert_country positionné |
**Commande de test:**
```bash
curl http://localhost:3000/api/analysis/country | jq
```
---
### 2.14 Endpoint `/api/analysis/{ip}/ja4`
| ID | Test | Description | Résultat attendu |
|----|------|-------------|------------------|
| AJ1 | JA4 fingerprint | ja4, shared_ips_count | Nombre d'IPs partageant ce JA4 |
| AJ2 | Top subnets | groupés par /24 | top_subnets list |
| AJ3 | Autres JA4 pour IP | other_ja4_for_ip | Liste des autres fingerprints |
**Commande de test:**
```bash
curl http://localhost:3000/api/analysis/116.179.33.143/ja4 | jq
```
---
### 2.15 Endpoint `/api/analysis/{ip}/user-agents`
| ID | Test | Description | Résultat attendu |
|----|------|-------------|------------------|
| AU1 | User-Agents IP | ip_user_agents | Avec classification (normal/bot/script) |
| AU2 | Bot percentage | Calcul correct | bot_percentage |
| AU3 | Alert si > 20% bots | alert=true | Si bot_percentage > 20 |
**Commande de test:**
```bash
curl http://localhost:3000/api/analysis/116.179.33.143/user-agents | jq
```
---
### 2.16 Endpoint `/api/analysis/{ip}/recommendation`
| ID | Test | Description | Résultat attendu |
|----|------|-------------|------------------|
| AR1 | Recommandation complète | label, confidence, indicators | Classification suggérée |
| AR2 | Tags suggérés | Basés sur corrélations | suggested_tags list |
| AR3 | Reason détaillé | Explication | reason string |
**Commande de test:**
```bash
curl http://localhost:3000/api/analysis/116.179.33.143/recommendation | jq
```
**Vérifications:**
- [ ] `label` ∈ {legitimate, suspicious, malicious}
- [ ] `confidence` entre 0 et 1
- [ ] `indicators` avec subnet_ips_count, ja4_shared_ips, bot_ua_percentage, etc.
- [ ] `suggested_tags` pertinents (distributed, bot-ua, hosting-asn, etc.)
- [ ] `reason` explicatif
---
### 2.17 Endpoint `/api/entities/{type}/{value}`
| ID | Test | Description | Résultat attendu |
|----|------|-------------|------------------|
| E1 | Investigation IP | GET /api/entities/ip/192.168.1.1 | stats, related, user_agents, client_headers, paths, query_params |
| E2 | Investigation JA4 | GET /api/entities/ja4/{fingerprint} | idem |
| E3 | Investigation User-Agent | GET /api/entities/user_agent/{ua} | idem |
| E4 | Investigation Client-Header | GET /api/entities/client_header/{header} | idem |
| E5 | Investigation Host | GET /api/entities/host/example.com | idem |
| E6 | Investigation Path | GET /api/entities/path/api/login | idem |
| E7 | Investigation Query-Param | GET /api/entities/query_param/q|id | idem |
| E8 | Type invalide | GET /api/entities/invalid/xyz | 400 |
| E9 | Entité inexistante | GET /api/entities/ip/0.0.0.0 | 404 |
| E10 | Fenêtre temporelle | `?hours=48` | Filtre appliqué (défaut 24h) |
**Commande de test:**
```bash
curl http://localhost:3000/api/entities/ip/116.179.33.143 | jq
```
**Vérifications:**
- [ ] `stats` avec entity_type, entity_value, total_requests, unique_ips, first_seen, last_seen
- [ ] `related` avec ips, ja4s, hosts, asns, countries
- [ ] `user_agents` liste avec value, count, percentage
- [ ] `client_headers` liste
- [ ] `paths` liste
- [ ] `query_params` liste
---
### 2.18 Endpoint `/api/entities/{type}/{value}/related`
| ID | Test | Description | Résultat attendu |
|----|------|-------------|------------------|
| ER1 | Attributs associés | GET /api/entities/ip/192.168.1.1/related | ips, ja4s, hosts, asns, countries |
**Commande de test:**
```bash
curl http://localhost:3000/api/entities/ip/116.179.33.143/related | jq
```
---
### 2.19 Endpoints spécifiques entities
| ID | Test | Endpoint | Résultat attendu |
|----|------|----------|------------------|
| EU1 | User-Agents | `/{type}/{value}/user_agents` | Liste des UAs |
| EU2 | Client-Headers | `/{type}/{value}/client_headers` | Liste des headers |
| EU3 | Paths | `/{type}/{value}/paths` | Liste des paths |
| EU4 | Query-Params | `/{type}/{value}/query_params` | Liste des params |
---
### 2.20 Endpoint `/api/entities/types`
| ID | Test | Description | Résultat attendu |
|----|------|-------------|------------------|
| ET1 | Liste des types | GET /api/entities/types | 7 types avec descriptions |
**Commande de test:**
```bash
curl http://localhost:3000/api/entities/types | jq
```
**Vérifications:**
- [ ] 7 types: ip, ja4, user_agent, client_header, host, path, query_param
- [ ] Descriptions pour chaque type
---
## 3. Tests Frontend (React)
### 3.1 Navigation et Routing
| ID | Test | Description | Résultat attendu |
|----|------|-------------|------------------|
| N1 | Page d'accueil | GET http://localhost:3000/ | Dashboard s'affiche |
| N2 | Navigation Détections | Clic menu "Détections" | Tableau affiché |
| N3 | Navigation Investigation | Menu "Investigation" | Formulaire recherche |
| N4 | Breadcrumb fonctionnel | Clic breadcrumb | Navigation retour |
| N5 | URL directe (deep link) | http://localhost:3000/detections | Page correcte |
**Commandes de test:**
```bash
# Vérifier que le HTML est servi
curl -s http://localhost:3000/ | grep -o "Bot Detector Dashboard"
# Vérifier les assets
curl -s http://localhost:3000/ | grep -o "assets/[^\"]*"
```
---
### 3.2 Dashboard Principal
| ID | Test | Description | Résultat attendu |
|----|------|-------------|------------------|
| DH1 | Métriques affichées | 4 cartes | total, menaces, bots, IPs |
| DH2 | Graphique temporel | Série 24h | Recharts line/area chart |
| DH3 | Distribution par menace | Pie/bar chart | 4 segments |
| DH4 | Rafraîchissement auto | 30s | Données à jour |
| DH5 | Loading states | Spinners | Pendant chargement |
| DH6 | Gestion erreurs | Message utilisateur | Si API échoue |
| DH7 | Responsive design | Mobile/desktop | Adaptatif |
**Vérifications manuelles:**
- [ ] Ouvrir http://localhost:3000
- [ ] Vérifier 4 cartes de métriques
- [ ] Vérifier graphique temporel
- [ ] Vérifier distribution menaces
- [ ] Attendre 30s, vérifier rafraîchissement
- [ ] Tester sur mobile (DevTools)
---
### 3.3 Liste des Détections
| ID | Test | Description | Résultat attendu |
|----|------|-------------|------------------|
| DL1 | Tableau affiché | Colonnes correctes | detected_at, src_ip, threat_level, etc. |
| DL2 | Pagination | Navigation pages | Page 1, 2, 3... |
| DL3 | Tri colonnes | Clic header | ASC/DESC fonctionnel |
| DL4 | Filtre threat_level | Dropdown | CRITICAL, HIGH, MEDIUM, LOW |
| DL5 | Recherche texte | Input search | Filtre en temps réel |
| DL6 | Codes couleur menaces | CRITICAL=rouge, HIGH=orange, etc. | Visuel cohérent |
| DL7 | Clic sur IP | Ligne cliquable | Ouvre détails |
| DL8 | Empty state | Aucune donnée | Message "Aucune détection" |
**Vérifications manuelles:**
- [ ] Naviguer vers /detections
- [ ] Tester pagination
- [ ] Trier par anomaly_score
- [ ] Filtrer par CRITICAL
- [ ] Rechercher une IP
- [ ] Cliquer sur une ligne
---
### 3.4 Vue Détails (Investigation)
| ID | Test | Description | Résultat attendu |
|----|------|-------------|------------------|
| DV1 | Détails IP affichés | Toutes sections | Metrics, TCP, TLS, Headers, Behavior, Advanced |
| DV2 | Variabilité User-Agents | Pourcentages | Barres ou liste |
| DV3 | Variabilité JA4 | Fingerprints | Listés avec counts |
| DV4 | Variabilité Pays | Distribution | Pays avec percentages |
| DV5 | Variabilité ASN | Informations | ASN number, org |
| DV6 | Insights automatiques | Messages | Contextuels (rotation, hosting, etc.) |
| DV7 | Clic sur attribut | Lien cliquable | Navigation vers investigation |
| DV8 | Back button | Retour | Liste détections |
**Vérifications manuelles:**
- [ ] Cliquer sur une IP dans le tableau
- [ ] Vérifier toutes les sections de détails
- [ ] Vérifier variabilité User-Agents
- [ ] Cliquer sur un User-Agent
- [ ] Vérifier navigation enchaînée
- [ ] Utiliser breadcrumb pour revenir
---
### 3.5 Composants UI
| ID | Test | Description | Résultat attendu |
|----|------|-------------|------------------|
| C1 | Badges menace | Couleurs | CRITICAL=red, HIGH=orange, MEDIUM=yellow, LOW=green |
| C2 | Progress bars | Pourcentages visuels | Width proportionnel |
| C3 | Tooltips | Survols | Informations additionnelles |
| C4 | Skeletons | Chargement | Placeholders gris |
| C5 | Toast/Alerts | Notifications | Erreurs API, succès |
---
## 4. Tests ClickHouse (Base de Données)
### 4.1 Tables et Vues
| ID | Test | Description | Résultat attendu |
|----|------|-------------|------------------|
| DB1 | Table `ml_detected_anomalies` | SELECT count() | > 0 lignes |
| DB2 | Vue `view_dashboard_summary` | SELECT * | Données agrégées |
| DB3 | Vue `view_dashboard_user_agents` | SELECT * | User-Agents agrégés |
| DB4 | Vue `view_dashboard_entities` | SELECT * | Entités unifiées |
| DB5 | Table `classifications` | SELECT * | Table vide ou avec données |
| DB6 | Index présents | system.data_skipping_indices | Index listés |
| DB7 | TTL configuré | system.tables.ttl_expression | Expiration définie |
**Commandes de test:**
```bash
# Vérifier tables
docker compose exec clickhouse clickhouse-client -d mabase_prod -q \
"SELECT name, engine FROM system.tables WHERE database = 'mabase_prod' AND name LIKE '%dashboard%'"
# Vérifier données
docker compose exec clickhouse clickhouse-client -d mabase_prod -q \
"SELECT count() FROM ml_detected_anomalies WHERE detected_at >= now() - INTERVAL 24 HOUR"
# Vérifier vues
docker compose exec clickhouse clickhouse-client -d mabase_prod -q \
"SELECT * FROM view_dashboard_summary LIMIT 1"
```
---
### 4.2 Qualité des Données
| ID | Test | Description | Résultat attendu |
|----|------|-------------|------------------|
| DQ1 | Pas de NULL critiques | src_ip, detected_at | countIf(NULL) = 0 |
| DQ2 | Valeurs vides filtrées | "" exclus | countIf('') = 0 |
| DQ3 | Cohérence des counts | Totaux | Somme = total |
| DQ4 | Dates valides | detected_at < now() | Pas de dates futures |
| DQ5 | Threat levels valides | 4 niveaux uniquement | Pas de valeurs inconnues |
**Commandes de test:**
```bash
# NULL check
docker compose exec clickhouse clickhouse-client -d mabase_prod -q \
"SELECT countIf(src_ip IS NULL) AS null_ips FROM ml_detected_anomalies"
# Threat levels
docker compose exec clickhouse clickhouse-client -d mabase_prod -q \
"SELECT DISTINCT threat_level FROM ml_detected_anomalies"
```
---
### 4.3 Performance
| ID | Test | Description | Temps max |
|----|------|-------------|-----------|
| DP1 | Count 24h | `SELECT count()` | < 500ms |
| DP2 | Agrégations par heure | GROUP BY toStartOfHour | < 1s |
| DP3 | DISTINCT sur IP | uniq(src_ip) | < 1s |
| DP4 | Jointures vues | Multiple joins | < 2s |
| DP5 | Full scan table | Sans filtre | < 5s |
**Commandes de test:**
```bash
# Timing requête
docker compose exec clickhouse clickhouse-client -d mabase_prod -q \
"SELECT count() FROM ml_detected_anomalies WHERE detected_at >= now() - INTERVAL 24 HOUR" \
--time
```
---
## 5. Tests d'Intégration
### 5.1 Workflows Utilisateur
| ID | Test | Étapes | Résultat attendu |
|----|------|--------|------------------|
| IW1 | Investigation IP suspecte | Dashboard Clic IP Détails Insights | Investigation complète |
| IW2 | Recherche et filtre | Détections Filtre CRITICAL Recherche IP | Résultats filtrés |
| IW3 | Navigation enchaînée | IP UA Toutes IPs avec UA | Navigation fluide |
| IW4 | Analyse ASN | Filtre ASN Voir détections Variabilité | Vue d'ensemble ASN |
| IW5 | Export mental | Observer Noter IPs | IPs notées pour blacklist |
**Scénario IW1 détaillé:**
1. Ouvrir http://localhost:3000
2. Voir IP classifiée CRITICAL dans le dashboard
3. Cliquer sur l'IP
4. Vérifier section "User-Agents" (plusieurs valeurs ?)
5. Vérifier insights automatiques
6. Cliquer sur un User-Agent suspect
7. Voir toutes les IPs avec cet UA
8. Identifier possible botnet
---
### 5.2 Scénarios Critiques
| ID | Test | Description | Résultat attendu |
|----|------|-------------|------------------|
| IC1 | Dashboard vide | Aucune donnée 24h | Message "Aucune donnée" |
| IC2 | ClickHouse indisponible | Service down | Erreur gérée, retry |
| IC3 | API lente (>5s) | Latence élevée | Loading state, timeout |
| IC4 | Données partielles | Certains champs NULL | Affichage partiel OK |
| IC5 | Concurrent users | 10+ utilisateurs | Pas de blocage |
---
### 5.3 API Integration
| ID | Test | Description | Résultat attendu |
|----|------|-------------|------------------|
| II1 | Frontend → Backend | Toutes requêtes | HTTP 200 |
| II2 | Backend → ClickHouse | Connexion | Stable, reconnect auto |
| II3 | CORS localhost:3000 | Origine | Autorisé |
| II4 | Rate limiting | 100 req/min | Bloqué après limite |
**Commande de test CORS:**
```bash
curl -H "Origin: http://localhost:3000" -I http://localhost:3000/api/metrics | grep -i access-control
```
---
## 6. Tests de Sécurité
| ID | Test | Description | Résultat attendu |
|----|------|-------------|------------------|
| S1 | Authentification | Accès dashboard | Pas d'auth (local uniquement) |
| S2 | Injection SQL | Params ClickHouse | Utilise query params, pas de concat |
| S3 | XSS frontend | Input utilisateur | Échappement React |
| S4 | CORS restreint | Origines | localhost:3000 uniquement |
| S5 | Credentials | .env | Pas en dur dans le code |
| S6 | Error messages | Stack traces | Pas d'infos sensibles exposées |
**Vérifications:**
- [ ] Audit fichier `.env` (pas commité)
- [ ] Vérifier backend/main.py pas de credentials en dur
- [ ] Tester input `<script>alert('xss')</script>` dans recherche
- [ ] Vérifier headers CORS
---
## 7. Tests de Performance
| ID | Test | Métrique | Cible | Mesure |
|----|------|----------|-------|--------|
| P1 | Temps chargement dashboard | First paint | < 2s | DevTools Network |
| P2 | Temps requêtes API | Latence moyenne | < 1s | curl -w |
| P3 | Requêtes ClickHouse | Temps exécution | < 500ms | --time |
| P4 | Rafraîchissement auto | CPU/Mémoire | < 5% CPU | DevTools Performance |
| P5 | Pagination grande liste | Scroll fluide | 60 FPS | DevTools |
| P6 | Mémoire frontend | Heap size | < 100MB | DevTools Memory |
**Commandes de test:**
```bash
# Timing API
curl -w "@curl-format.txt" -o /dev/null -s http://localhost:3000/api/metrics
# curl-format.txt:
# time_namelookup: %{time_namelookup}\n
# time_connect: %{time_connect}\n
# time_starttransfer: %{time_starttransfer}\n
# time_total: %{time_total}\n
```
---
## 8. Matrice de Couverture
### Endpoints API
| Routeur | Endpoints | Tests | Couverture |
|---------|-----------|-------|------------|
| `/health` | 1 | H1-H3 | 100% |
| `/api/metrics` | 2 | M1-M5, MT1-MT2 | 100% |
| `/api/detections` | 2 | D1-D11, DD1-DD3 | 100% |
| `/api/variability` | 4 | V1-V8, VI1-VI3, VA1-VA3, VU1-VU2 | 100% |
| `/api/attributes` | 1 | A1-A7 | 100% |
| `/api/analysis` | 6 | AS1-AS4, AC1-AC2, ANC1-ANC3, AJ1-AJ3, AU1-AU3, AR1-AR3 | 100% |
| `/api/entities` | 7 | E1-E10, ER1, EU1-EU4, ET1 | 100% |
### Fonctionnalités Frontend
| Fonctionnalité | Tests | Couverture |
|----------------|-------|------------|
| Dashboard metrics | DH1-DH7 | 100% |
| Liste détections | DL1-DL8 | 100% |
| Investigation détails | DV1-DV8 | 100% |
| Variabilité attributs | Via API | 100% |
| Filtres et recherche | D3-D7, DL4-DL5 | 100% |
| Navigation | N1-N5 | 100% |
| Composants UI | C1-C5 | 100% |
### Base de Données
| Aspect | Tests | Couverture |
|--------|-------|------------|
| Tables principales | DB1, DB5 | 100% |
| Vues matérialisées | DB2-DB4 | 100% |
| Qualité données | DQ1-DQ5 | 100% |
| Performance | DP1-DP5 | 100% |
---
## 9. Scripts de Test Existants
### 9.1 `test_dashboard.sh` (10 tests)
```bash
# Exécution
chmod +x test_dashboard.sh
./test_dashboard.sh
```
**Tests couverts:**
1. Health check
2. API detections
3. Tri par score
4. Variability IP
5. IPs associées
6. User-Agents
7. Analysis subnet
8. Analysis country
9. Classifications
10. Frontend accessible
---
### 9.2 `test_dashboard_entities.sql` (30 tests)
```bash
# Exécution
docker compose exec clickhouse clickhouse-client -d mabase_prod < test_dashboard_entities.sql
```
**Tests couverts:**
1-3. Tables/Vues existent
4. Schéma
5-11. Samples par entité
12-13. Validation ASN/Country
14-18. Top 10 par type
19. Activité par date
20. Corrélation
21-22. Types de données, NULL
23. Stats globales
24. Index
25. Performance
26. TTL
27-30. Distributions
---
## 10. Recommandations
### Tests manquants à ajouter
1. **Tests unitaires backend** (pytest)
```bash
# Structure recommandée
backend/tests/
├── test_metrics.py
├── test_detections.py
├── test_variability.py
├── test_analysis.py
└── test_entities.py
```
2. **Tests frontend** (Jest + React Testing Library)
```bash
# Structure recommandée
frontend/src/
├── __tests__/
│ ├── App.test.tsx
│ ├── components/
│ │ ├── Dashboard.test.tsx
│ │ ├── DetectionsList.test.tsx
│ │ └── DetailsView.test.tsx
│ └── hooks/
│ ├── useMetrics.test.ts
│ └── useDetections.test.ts
```
3. **Tests E2E** (Playwright/Cypress)
```bash
# Structure recommandée
tests/e2e/
├── dashboard.spec.ts
├── detections.spec.ts
└── investigation.spec.ts
```
4. **Tests de charge** (locust)
```python
# locustfile.py
from locust import HttpUser, task
class DashboardUser(HttpUser):
@task
def load_metrics(self):
self.client.get("/api/metrics")
@task(3)
def load_detections(self):
self.client.get("/api/detections?page=1")
```
5. **Tests de régression API**
```bash
# Utiliser Newman avec collections Postman
# Ou Insomnia avec tests automatisés
```
### Couverture actuelle estimée
| Domaine | Couverture | Méthode |
|---------|------------|---------|
| Backend API | 70% | Tests manuels + scripts |
| Frontend | 30% | Tests manuels |
| Database | 60% | SQL tests |
| Intégration | 40% | Workflows manuels |
| **Total** | **50%** | |
### Objectif de couverture
| Domaine | Actuel | Cible |
|---------|--------|-------|
| Backend API | 70% | 90% |
| Frontend | 30% | 80% |
| Database | 60% | 90% |
| Intégration | 40% | 85% |
---
## 11. Prioritisation
### Priorité 1 (Critique) 🔴
| Test | ID | Importance |
|------|----|------------|
| Health check | H1-H3 | Service disponible |
| API metrics | M1-M5 | Dashboard fonctionnel |
| API detections | D1-D11 | Liste détections |
| Connexion ClickHouse | DB1-DB7 | Données accessibles |
| Navigation basique | N1-N5 | UX fonctionnel |
**À tester avant chaque déploiement.**
---
### Priorité 2 (Important) 🟡
| Test | ID | Importance |
|------|----|------------|
| Filtres et recherche | D3-D7, DL4-DL5 | Investigation efficace |
| Investigation IP/JA4 | V1-V8, E1-E10 | Core feature |
| Variabilité | VI1-VI3, VA1-VA3 | Analyse comportement |
| Pagination | D2, D10-D11, DL2 | UX grande liste |
| Insights automatiques | V8 | Valeur ajoutée |
**À tester chaque sprint.**
---
### Priorité 3 (Secondaire) 🟢
| Test | ID | Importance |
|------|----|------------|
| Recommandations | AR1-AR3 | Feature avancée |
| Analysis avancée | AS1-AS4, AJ1-AJ3 | Investigation profonde |
| Responsive design | DH7 | Mobile support |
| Performance | P1-P6 | Optimisation |
| Sécurité | S1-S6 | Audit régulier |
**À tester avant release majeure.**
---
## 📊 Checklist de Déploiement
### Avant déploiement
- [ ] Tests Priorité 1 passants (100%)
- [ ] Tests Priorité 2 passants (>80%)
- [ ] Aucun bug critique ouvert
- [ ] Logs vérifiés (pas d'erreurs)
- [ ] Performance OK (< 2s chargement)
### Après déploiement
- [ ] Health check OK
- [ ] Dashboard accessible
- [ ] Métriques affichées
- [ ] Détections listées
- [ ] Investigation fonctionnelle
- [ ] Logs propres
---
## 📝 Notes
### Commandes utiles
```bash
# Lancer tous les tests
./test_dashboard.sh
# Tests SQL
docker compose exec clickhouse clickhouse-client -d mabase_prod < test_dashboard_entities.sql
# Logs en temps réel
docker compose logs -f dashboard_web
# Redémarrer le dashboard
docker compose restart dashboard_web
# Vérifier données ClickHouse
docker compose exec clickhouse clickhouse-client -d mabase_prod -q \
"SELECT count() FROM ml_detected_anomalies WHERE detected_at >= now() - INTERVAL 24 HOUR"
```
### Contacts et Support
- **Documentation API:** http://localhost:3000/docs
- **Logs:** `docker compose logs dashboard_web`
- **ClickHouse:** `docker compose exec clickhouse clickhouse-client -d mabase_prod`
---
**Document créé:** 2025
**Dernière mise à jour:** 2025
**Version:** 1.0