Base de données séparée
Par défaut, AuditChain stocke les journaux d'audit dans la base de données par défaut de votre application. Pour les systèmes en production — en particulier ceux soumis à des exigences de conformité — une connexion de base de données séparée est fortement recommandée. Isoler les données d'audit rend considérablement plus difficile pour une application compromise de falsifier le journal d'audit.
Pourquoi utiliser une connexion séparée ?
Isolation de sécurité — Si un attaquant obtient l'accès à la base de données de votre application, le journal d'audit se trouve sur un serveur ou une base de données différent(e) avec des identifiants différents. Les journaux d'audit survivent à la compromission et fournissent des preuves pour la réponse aux incidents.
Contrôle d'accès — L'utilisateur de la base de données d'audit peut être restreint aux opérations INSERT et SELECT uniquement. Pas de UPDATE, pas de DELETE. Même si quelqu'un obtient les identifiants, il ne peut ni modifier ni effacer les enregistrements d'audit au niveau de la base de données.
Rétention indépendante — Votre base de données applicative peut avoir ses propres politiques de sauvegarde et de rétention. Une base de données d'audit séparée vous permet d'appliquer des politiques différentes — des sauvegardes plus longues, des snapshots plus fréquents, un accès plus strict aux exports.
Isolation des performances — La journalisation d'audit à haut volume ne rivalise pas avec les requêtes de votre application pour le même pool de connexions, les verrous ou les E/S.
Configuration
1. Définir la connexion de base de données
Ajoutez une connexion audit dans config/database.php :
// config/database.php 'connections' => [ // Votre base de données applicative 'mysql' => [ 'driver' => 'mysql', 'host' => env('DB_HOST', '127.0.0.1'), 'database' => env('DB_DATABASE', 'forge'), 'username' => env('DB_USERNAME', 'forge'), 'password' => env('DB_PASSWORD', ''), // ... ], // Base de données d'audit dédiée 'audit' => [ 'driver' => 'mysql', 'host' => env('AUDIT_DB_HOST', '127.0.0.1'), 'port' => env('AUDIT_DB_PORT', '3306'), 'database' => env('AUDIT_DB_DATABASE', 'audit'), 'username' => env('AUDIT_DB_USERNAME', 'audit_user'), 'password' => env('AUDIT_DB_PASSWORD', ''), 'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci', 'prefix' => '', 'strict' => true, 'engine' => 'InnoDB', ], ],
2. Définir les variables d'environnement
Ajoutez les identifiants de la base de données d'audit dans votre .env :
AUDIT_DB_HOST=127.0.0.1 AUDIT_DB_PORT=3306 AUDIT_DB_DATABASE=audit_trail AUDIT_DB_USERNAME=audit_user AUDIT_DB_PASSWORD=secret
3. Configurer AuditChain pour utiliser la connexion
Définissez la valeur connection dans config/audit-chain.php :
'connection' => 'audit',
4. Exécuter la migration
Lors de l'exécution des migrations, spécifiez la connexion :
php artisan migrate --database=audit
Ou, si vous avez déjà publié la migration, le fichier de migration respectera automatiquement la connexion configurée.
Permissions de l'utilisateur de base de données
Pour une immutabilité maximale, créez un utilisateur de base de données avec des permissions minimales :
-- MySQL CREATE USER 'audit_user'@'%' IDENTIFIED BY 'strong-password'; GRANT SELECT, INSERT ON audit_trail.* TO 'audit_user'@'%'; FLUSH PRIVILEGES;
-- PostgreSQL CREATE USER audit_user WITH PASSWORD 'strong-password'; GRANT SELECT, INSERT ON ALL TABLES IN SCHEMA public TO audit_user;
Avec ces permissions :
- AuditChain peut écrire de nouvelles entrées de journal d'audit
- AuditChain peut lire les entrées pour la vérification et les requêtes
- Personne ne peut modifier ou supprimer des entrées via cette connexion, même avec un accès SQL direct
AuditChain applique déjà l'immutabilité au niveau Eloquent en lançant une RuntimeException lors d'une mise à jour ou d'une suppression. Les restrictions au niveau de la base de données ajoutent une seconde couche de défense qui survit aux compromissions au niveau applicatif.
Nettoyage avec une base de données séparée
La commande audit:prune respecte automatiquement la connexion configurée. Cependant, si votre utilisateur de base de données d'audit ne dispose que des permissions INSERT et SELECT, le nettoyage échouera.
Deux approches :
Option A : Utilisez un utilisateur de base de données séparé avec la permission DELETE pour le nettoyage. Exécutez la commande de nettoyage avec une connexion ou des identifiants différents.
Option B : Accordez la permission DELETE à l'utilisateur d'audit mais restreignez-la à une tâche planifiée qui ne s'exécute que via le scheduler Laravel. C'est plus simple mais offre moins d'isolation.
En pratique, la plupart des équipes optent pour l'option B — la commande de nettoyage ne supprime que les enregistrements plus anciens que la période de rétention, et le scheduler fournit un contexte d'exécution contrôlé.
Même serveur, base de données différente
Vous n'avez pas besoin d'un serveur de base de données séparé. Une base de données séparée sur le même serveur offre déjà une isolation significative :
AUDIT_DB_HOST=127.0.0.1 AUDIT_DB_DATABASE=myapp_audit AUDIT_DB_USERNAME=audit_user AUDIT_DB_PASSWORD=different-password
Le principal avantage est l'utilisateur séparé avec des permissions restreintes. Un serveur différent ajoute une isolation au niveau réseau mais n'est pas obligatoire.
Moteur de base de données différent
La connexion d'audit peut utiliser un moteur de base de données différent de celui de votre application. Par exemple, votre application peut utiliser MySQL tandis que la base de données d'audit utilise PostgreSQL :
'audit' => [ 'driver' => 'pgsql', 'host' => env('AUDIT_DB_HOST', '127.0.0.1'), 'database' => env('AUDIT_DB_DATABASE', 'audit'), 'username' => env('AUDIT_DB_USERNAME', 'audit_user'), 'password' => env('AUDIT_DB_PASSWORD', ''), 'schema' => 'public', ],
AuditChain utilise du SQL standard (aucune fonctionnalité spécifique à un moteur), donc toute base de données supportée par Laravel fonctionne.
Attention : L'utilisation de SQLite comme base de données d'audit n'est pas recommandée en production. SQLite ne supporte pas le verrouillage
FOR UPDATEutilisé par la chaîne de hash, ce qui peut entraîner des conditions de concurrence sous charge. SQLite convient pour le développement et les tests, mais utilisez MySQL ou PostgreSQL en production.