-- Script de création des tables pour le module Security & Monitoring -- Date : 2025-01-17 -- Version : 1.0 -- Préfixe : sec_ (security) -- ============================================ -- SUPPRESSION DES TABLES EXISTANTES (OPTIONNEL) -- ============================================ -- Décommenter si vous voulez recréer les tables -- DROP TABLE IF EXISTS `sec_blocked_ips`; -- DROP TABLE IF EXISTS `sec_failed_login_attempts`; -- DROP TABLE IF EXISTS `sec_performance_metrics`; -- DROP TABLE IF EXISTS `sec_alerts`; -- ============================================ -- CRÉATION DES TABLES DE SÉCURITÉ ET MONITORING -- ============================================ -- Table principale des alertes de sécurité CREATE TABLE IF NOT EXISTS `sec_alerts` ( `id` INT(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY, `alert_type` VARCHAR(50) NOT NULL COMMENT 'Type d\'alerte (BRUTE_FORCE, SQL_ERROR, etc.)', `alert_level` ENUM('INFO', 'WARNING', 'ERROR', 'CRITICAL', 'SECURITY') NOT NULL DEFAULT 'INFO', `ip_address` VARCHAR(45) DEFAULT NULL COMMENT 'Adresse IP source', `user_id` INT(11) UNSIGNED DEFAULT NULL COMMENT 'ID utilisateur si connecté', `username` VARCHAR(255) DEFAULT NULL COMMENT 'Username tenté ou utilisé', `endpoint` VARCHAR(255) DEFAULT NULL COMMENT 'Endpoint API concerné', `method` VARCHAR(10) DEFAULT NULL COMMENT 'Méthode HTTP', `details` JSON DEFAULT NULL COMMENT 'Détails additionnels en JSON', `occurrences` INT(11) DEFAULT 1 COMMENT 'Nombre d\'occurrences', `first_seen` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, `last_seen` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `email_sent` TINYINT(1) DEFAULT 0 COMMENT 'Email d\'alerte envoyé', `email_sent_at` TIMESTAMP NULL DEFAULT NULL, `resolved` TINYINT(1) DEFAULT 0 COMMENT 'Alerte résolue', `resolved_at` TIMESTAMP NULL DEFAULT NULL, `resolved_by` INT(11) UNSIGNED DEFAULT NULL COMMENT 'ID admin qui a résolu', `notes` TEXT DEFAULT NULL COMMENT 'Notes de résolution', KEY `idx_ip` (`ip_address`), KEY `idx_type_time` (`alert_type`, `last_seen`), KEY `idx_level` (`alert_level`), KEY `idx_resolved` (`resolved`), KEY `idx_user` (`user_id`), CONSTRAINT `fk_sec_alerts_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL, CONSTRAINT `fk_sec_alerts_resolver` FOREIGN KEY (`resolved_by`) REFERENCES `users` (`id`) ON DELETE SET NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Alertes de sécurité et monitoring'; -- Table des métriques de performance CREATE TABLE IF NOT EXISTS `sec_performance_metrics` ( `id` BIGINT(20) UNSIGNED AUTO_INCREMENT PRIMARY KEY, `endpoint` VARCHAR(255) NOT NULL COMMENT 'Endpoint API', `method` VARCHAR(10) NOT NULL COMMENT 'Méthode HTTP', `response_time_ms` INT(11) NOT NULL COMMENT 'Temps de réponse total en ms', `db_time_ms` INT(11) DEFAULT 0 COMMENT 'Temps cumulé des requêtes DB en ms', `db_queries_count` INT(11) DEFAULT 0 COMMENT 'Nombre de requêtes DB', `memory_peak_mb` FLOAT DEFAULT NULL COMMENT 'Pic mémoire en MB', `memory_start_mb` FLOAT DEFAULT NULL COMMENT 'Mémoire au début en MB', `http_status` INT(11) DEFAULT NULL COMMENT 'Code HTTP de réponse', `user_id` INT(11) UNSIGNED DEFAULT NULL COMMENT 'ID utilisateur si connecté', `ip_address` VARCHAR(45) DEFAULT NULL COMMENT 'Adresse IP', `user_agent` TEXT DEFAULT NULL COMMENT 'User Agent complet', `request_size` INT(11) DEFAULT NULL COMMENT 'Taille de la requête en octets', `response_size` INT(11) DEFAULT NULL COMMENT 'Taille de la réponse en octets', `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, KEY `idx_endpoint_time` (`endpoint`, `created_at`), KEY `idx_response_time` (`response_time_ms`), KEY `idx_created` (`created_at`), KEY `idx_status` (`http_status`), KEY `idx_user` (`user_id`), KEY `idx_date_endpoint` (`created_at`, `endpoint`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Métriques de performance des requêtes'; -- Table des tentatives de login échouées CREATE TABLE IF NOT EXISTS `sec_failed_login_attempts` ( `id` INT(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY, `username` VARCHAR(255) DEFAULT NULL COMMENT 'Username tenté', `encrypted_username` VARCHAR(255) DEFAULT NULL COMMENT 'Username chiffré si trouvé', `ip_address` VARCHAR(45) NOT NULL COMMENT 'Adresse IP', `user_agent` TEXT DEFAULT NULL COMMENT 'User Agent', `attempt_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, `error_type` VARCHAR(50) DEFAULT NULL COMMENT 'Type d\'erreur (invalid_password, user_not_found, etc.)', `country_code` VARCHAR(2) DEFAULT NULL COMMENT 'Code pays de l\'IP (si géoloc activée)', KEY `idx_ip_time` (`ip_address`, `attempt_time`), KEY `idx_username` (`username`), KEY `idx_encrypted_username` (`encrypted_username`), KEY `idx_time` (`attempt_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Tentatives de connexion échouées'; -- Table des IPs bloquées CREATE TABLE IF NOT EXISTS `sec_blocked_ips` ( `ip_address` VARCHAR(45) NOT NULL PRIMARY KEY COMMENT 'Adresse IP bloquée', `reason` VARCHAR(255) NOT NULL COMMENT 'Raison du blocage', `details` JSON DEFAULT NULL COMMENT 'Détails additionnels', `blocked_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, `blocked_until` TIMESTAMP NOT NULL COMMENT 'Bloqué jusqu\'à', `blocked_by` VARCHAR(50) DEFAULT 'system' COMMENT 'Qui a bloqué (system ou user ID)', `permanent` TINYINT(1) DEFAULT 0 COMMENT 'Blocage permanent', `unblocked_at` TIMESTAMP NULL DEFAULT NULL COMMENT 'Date de déblocage effectif', `unblocked_by` INT(11) UNSIGNED DEFAULT NULL COMMENT 'Qui a débloqué', `block_count` INT(11) DEFAULT 1 COMMENT 'Nombre de fois bloquée', KEY `idx_blocked_until` (`blocked_until`), KEY `idx_permanent` (`permanent`), CONSTRAINT `fk_sec_blocked_unblocked_by` FOREIGN KEY (`unblocked_by`) REFERENCES `users` (`id`) ON DELETE SET NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='IPs bloquées temporairement ou définitivement'; -- ============================================ -- INDEX ADDITIONNELS POUR PERFORMANCES -- ============================================ -- Index pour requêtes de monitoring fréquentes CREATE INDEX idx_sec_metrics_recent ON sec_performance_metrics(created_at DESC, endpoint); CREATE INDEX idx_sec_alerts_recent ON sec_alerts(last_seen DESC, alert_level); CREATE INDEX idx_sec_failed_recent ON sec_failed_login_attempts(attempt_time DESC, ip_address); -- ============================================ -- FIN DU SCRIPT -- ============================================ -- Note: La purge des données anciennes doit être gérée par: -- 1. Un cron qui appelle l'endpoint API /api/admin/cleanup -- 2. Ou directement via les méthodes cleanup des services PHP