Files
ja4-platform/docs/database/migrations.md
toto 8f5e771096 docs: réécriture complète de la documentation base de données en français
Réécriture des 3 fichiers de documentation de la base de données ClickHouse :

- docs/database/schema.md : couverture complète des 2 bases, 14+ tables,
  7 dictionnaires, 8 MVs, 8 vues, TTL, partitions, moteurs et colonnes
- docs/database/migrations.md : 13 fichiers SQL (ajout 10-12), prérequis
  mis à jour (ClickHouse 24.8+, 5 CSV), deploy_schema.sh, init-stack.sh,
  vérification et rollback complets
- shared/clickhouse/README.md : référence rapide des 13 fichiers,
  deploy_schema.sh, patron double-base, prérequis

Suppression des références obsolètes : dict_anubis_ua, dict_anubis_country,
anubis_ua_rules, anubis_country_rules.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-09 22:03:37 +02:00

13 KiB

Migrations de base de données

Le schéma ClickHouse de ja4-platform est géré via 13 fichiers SQL numérotés dans shared/clickhouse/. Toutes les migrations sont idempotentes (utilisation de IF NOT EXISTS / IF EXISTS / CREATE OR REPLACE) et doivent être appliquées dans l'ordre numérique.

Le schéma utilise un patron double-base :

Base Variable d'environnement Défaut Contenu
Logs CLICKHOUSE_DB_LOGS ja4_logs http_logs_raw, http_logs, mv_http_logs
Processing CLICKHOUSE_DB_PROCESSING ja4_processing Agrégations, ML, vues, dictionnaires, audit

Ordre des migrations

Fichier Lignes Contenu
00_database.sql 5 Création des bases ja4_logs et ja4_processing
01_raw_tables.sql 16 Table d'ingestion http_logs_raw (MergeTree, TTL 2h)
02_dictionaries.sql 57 Dictionnaire dict_iplocate_asn (IP_TRIE, CSV), tables ref_bot_networks, bot_ip, bot_ja4
03_anubis_tables.sql 73 Tables de règles Anubis (anubis_ip_rules, anubis_asn_rules) et dictionnaires (dict_anubis_ip, dict_anubis_asn)
04_mv_http_logs.sql 197 Table http_logs (MergeTree, TTL 30j) + vue matérialisée mv_http_logs (parse JSON + enrichissement Anubis COALESCE IP→ASN)
05_aggregation_tables.sql 234 Dictionnaires de réputation (dict_bot_ip, dict_bot_ja4, dict_browser_ja4, dict_asn_reputation), 2 tables d'agrégation (agg_host_ip_ja4_1h, agg_header_fingerprint_1h) + 2 vues matérialisées
06_ml_tables.sql 144 Tables ML (ml_detected_anomalies, ml_all_scores) + vue view_ip_recurrence
07_ai_features_view.sql 156 Vue view_ai_features_1h (~65+ features ML depuis les agrégations + dictionnaires)
08_users.sql 22 Utilisateurs data_writer et analyst avec permissions
09_audit_table.sql 21 Table audit_logs pour le journal d'audit SOC
10_perf_indexes.sql 113 Index secondaires et projections de performance (migration idempotente pour instances existantes)
11_views.sql 216 Vues dashboard (view_dashboard_entities, view_dashboard_user_agents, view_form_bruteforce_detected, view_host_ip_ja4_rotation, view_resource_cascade_1h)
12_thesis_features.sql 580 4 tables d'agrégation thèse (agg_path_sequences_1h, agg_request_timing_1h, agg_ip_behavior_1h, agg_resource_cascade_1h) + 4 MVs + vue view_thesis_features_1h

Prérequis

1. Serveur ClickHouse

Un serveur ClickHouse en fonctionnement, version 24.8+ requise (support des projections AggregatingMergeTree avec deduplicate_merge_projection_mode).

2. Fichiers CSV de données

Placer les fichiers suivants dans /var/lib/clickhouse/user_files/ :

Fichier Source Description Entrées approx.
iplocate-ip-to-asn.csv IPLocate Correspondance IP→ASN avec pays, org, domaine ~714K
bot_ip.csv Personnalisé Préfixes IP de bots connus (format CIDR) ~3,5K
bot_ja4.csv Personnalisé Empreintes JA4 de bots connus ~31
browser_ja4.csv Personnalisé Empreintes JA4 de navigateurs légitimes ~1,2K
asn_reputation.csv Personnalisé Labels de réputation ASN (human, bot, unknown) ~82K

3. Mots de passe Anubis

Le fichier 03_anubis_tables.sql contient des mots de passe par défaut (CHANGE_ME) pour les dictionnaires Anubis basés sur ClickHouse. Les remplacer avant d'appliquer :

sed -i "s/CHANGE_ME/mot_de_passe_réel/g" 03_anubis_tables.sql

Comment appliquer

Méthode recommandée : deploy_schema.sh

Le script deploy_schema.sh applique les 13 fichiers dans l'ordre en substituant automatiquement les noms de base de données :

cd shared/clickhouse/

# Avec les noms de base par défaut (ja4_logs / ja4_processing)
./deploy_schema.sh

# Avec des noms personnalisés
CLICKHOUSE_DB_LOGS=my_logs \
CLICKHOUSE_DB_PROCESSING=my_proc \
CLICKHOUSE_HOST=clickhouse-server \
CLICKHOUSE_USER=admin \
CLICKHOUSE_PASSWORD='secret' \
  ./deploy_schema.sh

Variables d'environnement supportées :

Variable Défaut Description
CLICKHOUSE_DB_LOGS ja4_logs Nom de la base de logs
CLICKHOUSE_DB_PROCESSING ja4_processing Nom de la base de traitement
CLICKHOUSE_HOST localhost Hôte ClickHouse
CLICKHOUSE_PORT 9000 Port natif ClickHouse
CLICKHOUSE_USER default Utilisateur ClickHouse
CLICKHOUSE_PASSWORD (vide) Mot de passe ClickHouse

Méthode alternative : init-stack.sh

Le script scripts/init-stack.sh fournit une initialisation complète incluant le schéma, les migrations, la validation et le nettoyage :

./scripts/init-stack.sh

Application manuelle

cd shared/clickhouse/

for f in 0*.sql 1*.sql; do
    echo "Application de $f..."
    clickhouse-client --multiquery < "$f"
done

Avec authentification :

clickhouse-client --user admin --password 'secret' --multiquery < 00_database.sql
# ... répéter pour chaque fichier

Comment vérifier

Après l'application de toutes les migrations, exécuter ces requêtes pour valider chaque étape.

00 — Bases de données

SHOW DATABASES LIKE 'ja4%';
-- Attendu : ja4_logs, ja4_processing

01 — Table brute

EXISTS ja4_logs.http_logs_raw;
-- Attendu : 1

02 — Dictionnaire ASN + tables de référence

SELECT dictGetOrDefault('ja4_processing.dict_iplocate_asn', 'country_code',
       toIPv6(toIPv4('8.8.8.8')), 'MISSING');
-- Attendu : US (si CSV chargé) ou MISSING

EXISTS ja4_processing.ref_bot_networks;
-- Attendu : 1

03 — Tables Anubis

EXISTS ja4_processing.anubis_ip_rules;
EXISTS ja4_processing.anubis_asn_rules;
-- Attendu : 1 pour chacune

04 — http_logs + vue matérialisée

EXISTS ja4_logs.http_logs;
SELECT name FROM system.tables WHERE database = 'ja4_logs' AND name = 'mv_http_logs';
-- Attendu : mv_http_logs

05 — Tables d'agrégation + dictionnaires de réputation

EXISTS ja4_processing.agg_host_ip_ja4_1h;
EXISTS ja4_processing.agg_header_fingerprint_1h;
SELECT name FROM system.dictionaries
WHERE database = 'ja4_processing' AND name IN ('dict_bot_ip', 'dict_bot_ja4', 'dict_browser_ja4', 'dict_asn_reputation');
-- Attendu : 4 lignes

06 — Tables ML

EXISTS ja4_processing.ml_detected_anomalies;
EXISTS ja4_processing.ml_all_scores;
SELECT name FROM system.tables WHERE database = 'ja4_processing' AND name = 'view_ip_recurrence';
-- Attendu : view_ip_recurrence

07 — Vue de features AI

SELECT name FROM system.tables WHERE database = 'ja4_processing' AND name = 'view_ai_features_1h';
-- Attendu : view_ai_features_1h

08 — Utilisateurs

SHOW GRANTS FOR data_writer;
-- Attendu : GRANT INSERT, SELECT ON ja4_logs.http_logs_raw TO data_writer
SHOW GRANTS FOR analyst;
-- Attendu : GRANT SELECT sur 6 tables/vues

09 — Table d'audit

EXISTS ja4_processing.audit_logs;
-- Attendu : 1

10 — Index de performance

SELECT name FROM system.data_skipping_indices
WHERE table = 'ml_detected_anomalies' AND database = 'ja4_processing';
-- Attendu : idx_detected_at, idx_threat_level, idx_bot_name

11 — Vues dashboard

SELECT name FROM system.tables
WHERE database = 'ja4_processing'
  AND name LIKE 'view_%'
  AND engine = 'View';
-- Attendu : ≥ 7 vues (view_ip_recurrence, view_ai_features_1h,
--   view_form_bruteforce_detected, view_host_ip_ja4_rotation,
--   view_dashboard_user_agents, view_dashboard_entities, view_resource_cascade_1h)

12 — Tables et vue de thèse

EXISTS ja4_processing.agg_path_sequences_1h;
EXISTS ja4_processing.agg_request_timing_1h;
EXISTS ja4_processing.agg_ip_behavior_1h;
EXISTS ja4_processing.agg_resource_cascade_1h;
SELECT name FROM system.tables WHERE database = 'ja4_processing' AND name = 'view_thesis_features_1h';
-- Attendu : 1 pour chaque EXISTS, view_thesis_features_1h

Vérification complète

-- Tables dans ja4_logs
SELECT count() AS tables_logs
FROM system.tables
WHERE database = 'ja4_logs'
  AND name IN ('http_logs_raw', 'http_logs', 'mv_http_logs');
-- Attendu : 3

-- Tables dans ja4_processing
SELECT count() AS tables_processing
FROM system.tables
WHERE database = 'ja4_processing'
  AND name IN (
    'ref_bot_networks', 'bot_ip', 'bot_ja4',
    'anubis_ip_rules', 'anubis_asn_rules',
    'agg_host_ip_ja4_1h', 'agg_header_fingerprint_1h',
    'agg_path_sequences_1h', 'agg_request_timing_1h',
    'agg_ip_behavior_1h', 'agg_resource_cascade_1h',
    'ml_detected_anomalies', 'ml_all_scores', 'audit_logs'
  );
-- Attendu : 14

-- Dictionnaires
SELECT count() AS dicts
FROM system.dictionaries
WHERE database = 'ja4_processing';
-- Attendu : 7

-- Vues matérialisées dans ja4_logs
SELECT count() AS mvs_logs
FROM system.tables
WHERE database = 'ja4_logs' AND engine = 'MaterializedView';
-- Attendu : 1

-- Vues matérialisées dans ja4_processing
SELECT count() AS mvs_proc
FROM system.tables
WHERE database = 'ja4_processing' AND engine = 'MaterializedView';
-- Attendu : 6

Rollback

Approche générale

ClickHouse ne supporte pas les DDL transactionnels. Pour annuler une migration :

  1. Vues matérialisées : supprimer la MV avant sa table cible
  2. Dictionnaires : supprimer le dictionnaire avant les vues/MVs qui l'utilisent
  3. Tables : DROP TABLE IF EXISTS
  4. Vues : DROP VIEW IF EXISTS
  5. Utilisateurs : DROP USER IF EXISTS

Ordre de rollback (inverse de l'application)

-- 12 : Tables et vue de thèse
DROP VIEW IF EXISTS ja4_processing.view_thesis_features_1h;
DROP VIEW IF EXISTS ja4_processing.view_resource_cascade_1h;
DROP VIEW IF EXISTS ja4_processing.mv_agg_resource_cascade_1h;
DROP VIEW IF EXISTS ja4_processing.mv_agg_ip_behavior_1h;
DROP VIEW IF EXISTS ja4_processing.mv_agg_request_timing_1h;
DROP VIEW IF EXISTS ja4_processing.mv_agg_path_sequences_1h;
DROP TABLE IF EXISTS ja4_processing.agg_resource_cascade_1h;
DROP TABLE IF EXISTS ja4_processing.agg_ip_behavior_1h;
DROP TABLE IF EXISTS ja4_processing.agg_request_timing_1h;
DROP TABLE IF EXISTS ja4_processing.agg_path_sequences_1h;

-- 11 : Vues dashboard
DROP VIEW IF EXISTS ja4_processing.view_dashboard_entities;
DROP VIEW IF EXISTS ja4_processing.view_dashboard_user_agents;
DROP VIEW IF EXISTS ja4_processing.view_host_ip_ja4_rotation;
DROP VIEW IF EXISTS ja4_processing.view_form_bruteforce_detected;

-- 10 : Index de performance (pas de rollback nécessaire — idempotent)

-- 09 : Table d'audit
DROP TABLE IF EXISTS ja4_processing.audit_logs;

-- 08 : Utilisateurs
DROP USER IF EXISTS data_writer;
DROP USER IF EXISTS analyst;

-- 07 : Vue de features AI
DROP VIEW IF EXISTS ja4_processing.view_ai_features_1h;

-- 06 : Tables ML
DROP VIEW IF EXISTS ja4_processing.view_ip_recurrence;
DROP TABLE IF EXISTS ja4_processing.ml_all_scores;
DROP TABLE IF EXISTS ja4_processing.ml_detected_anomalies;

-- 05 : Agrégations + dictionnaires de réputation
DROP VIEW IF EXISTS ja4_processing.mv_agg_header_fingerprint_1h;
DROP VIEW IF EXISTS ja4_processing.mv_agg_host_ip_ja4_1h;
DROP TABLE IF EXISTS ja4_processing.agg_header_fingerprint_1h;
DROP TABLE IF EXISTS ja4_processing.agg_host_ip_ja4_1h;
DROP DICTIONARY IF EXISTS ja4_processing.dict_asn_reputation;
DROP DICTIONARY IF EXISTS ja4_processing.dict_browser_ja4;
DROP DICTIONARY IF EXISTS ja4_processing.dict_bot_ja4;
DROP DICTIONARY IF EXISTS ja4_processing.dict_bot_ip;

-- 04 : MV + http_logs
DROP VIEW IF EXISTS ja4_logs.mv_http_logs;
DROP TABLE IF EXISTS ja4_logs.http_logs;

-- 03 : Anubis
DROP DICTIONARY IF EXISTS ja4_processing.dict_anubis_asn;
DROP DICTIONARY IF EXISTS ja4_processing.dict_anubis_ip;
DROP TABLE IF EXISTS ja4_processing.anubis_asn_rules;
DROP TABLE IF EXISTS ja4_processing.anubis_ip_rules;

-- 02 : Dictionnaire ASN + tables de référence
DROP DICTIONARY IF EXISTS ja4_processing.dict_iplocate_asn;
DROP TABLE IF EXISTS ja4_processing.bot_ja4;
DROP TABLE IF EXISTS ja4_processing.bot_ip;
DROP TABLE IF EXISTS ja4_processing.ref_bot_networks;

-- 01 : Table brute
DROP TABLE IF EXISTS ja4_logs.http_logs_raw;

-- 00 : Bases de données
DROP DATABASE IF EXISTS ja4_processing;
DROP DATABASE IF EXISTS ja4_logs;

Notes importantes

  • Perte de données : la suppression d'une table détruit toutes ses données. Toujours sauvegarder avant un rollback.
  • Dépendance MV : les vues matérialisées doivent être supprimées avant leur table cible.
  • Dépendance dictionnaire : les vues/MVs utilisant dictGet() échoueront si le dictionnaire référencé est supprimé.
  • Ré-application idempotente : après un rollback, les migrations peuvent être ré-appliquées sans risque grâce aux clauses IF NOT EXISTS.
  • 04_mv_http_logs.sql est la version canonique de la vue matérialisée, remplaçant toute version antérieure dans services/correlator/sql/init.sql.

Migrations post-déploiement

Le répertoire services/correlator/sql/migrations/ contient des instructions ALTER TABLE pour les déploiements existants. Les appliquer manuellement :

clickhouse-client --multiquery < services/correlator/sql/migrations/<fichier>.sql

Ces migrations sont distinctes du schéma de base et ne sont nécessaires que pour mettre à jour des instances déjà en production.