Configuration

Chaque système d'audit a des exigences différentes. Une startup qui suit les modifications de pages a besoin de paramètres différents d'une banque qui enregistre des transactions financières. Le fichier de configuration vous permet d'adapter AuditChain à votre cas d'usage exact — du choix d'une connexion de base de données dédiée à la mise en place d'alertes Slack lorsque l'intégrité de la chaîne échoue.

Après l'installation, publiez le fichier de configuration si ce n'est pas déjà fait :

php artisan vendor:publish --tag="audit-chain-config"

Cela crée le fichier config/audit-chain.php dans votre application.

Référence rapide

Clé Valeur par défaut Description
connection null Connexion DB pour les logs d'audit (séparée recommandée)
table audit_logs Nom de la table
state_table null Table sentinelle pour l'état de la chaîne (par défaut _state)
chain_seed env('AUDIT_CHAIN_SEED', 'genesis') Seed secret pour le hash de genèse
queue.enabled true Envoyer l'enregistrement de l'audit en file d'attente
queue.connection null Connexion de la file d'attente
queue.queue default Nom de la file d'attente
events.log_reads false Capturer les événements retrieved
anonymization.replacement [ANONYMIZED] Chaîne de remplacement pour l'anonymisation RGPD
retention.days 90 Nombre de jours de conservation des logs (audit:prune)
notifications.channels ['mail'] Canaux de notification : mail, webhook
notifications.mail_to [] Adresses e-mail pour les alertes mail
notifications.webhooks [] URLs de webhook (Slack, Teams, Discord, personnalisé)

Connexion à la base de données

'connection' => null,

Par défaut, AuditChain utilise la connexion de base de données par défaut de votre application. Pour les systèmes en production, une connexion de base de données séparée est fortement recommandée. Cela isole les données d'audit des données de l'application, rendant plus difficile pour une application compromise de falsifier le journal d'audit.

Pour utiliser une connexion séparée, définissez-la dans config/database.php et référencez-la ici :

// config/database.php
'connections' => [
    'audit' => [
        'driver' => 'mysql',
        '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', ''),
        // ...
    ],
],

// config/audit-chain.php
'connection' => 'audit',

Astuce : Pour une immutabilité maximale, configurez l'utilisateur de la base de données d'audit avec des permissions INSERT et SELECT uniquement — pas de UPDATE ni de DELETE. AuditChain impose l'immutabilité au niveau Eloquent, mais les restrictions au niveau de la base de données protègent contre les modifications SQL directes.

Nom de la table

'table' => 'audit_logs',

La table de base de données utilisée pour stocker les entrées du journal d'audit. Modifiez ce paramètre si audit_logs entre en conflit avec une table existante dans votre application.

Table d'état

'state_table' => null, // defaults to '{table}_state'

La table sentinelle utilisée pour stocker l'état de la chaîne (last_hash, checkpoint_hash). Cette table à une seule ligne est utilisée par HasAuditTrail pour suivre le dernier hash de la chaîne via SELECT last_hash FOR UPDATE, évitant le besoin de parcourir la table audit_logs. Si la valeur est null, elle prend par défaut le nom de votre table d'audit suffixé par _state (par ex. audit_logs_state).

Seed de la chaîne

'chain_seed' => env('AUDIT_CHAIN_SEED', 'genesis'),

Le seed de la chaîne est utilisé pour calculer le hash de genèse — le premier maillon de la chaîne de hash cryptographique. Définissez-le avec une valeur aléatoire et secrète en production via votre fichier .env :

AUDIT_CHAIN_SEED=your-random-secret-value-here

Vous pouvez générer une valeur appropriée avec :

php artisan tinker --execute="echo Str::random(64);"

Important : Un seed de chaîne prévisible affaiblit les garanties de détection de falsification de la chaîne de hash. Si un attaquant connaît le seed, il pourrait reconstruire un hash de genèse valide. Définissez toujours une valeur secrète en production.

Note : Le seed de la chaîne n'est pertinent que lors de l'utilisation de HasAuditTrail (mode complet). Si vous utilisez uniquement HasActivityLog (mode léger), aucune chaîne de hash n'est calculée et le seed n'est pas utilisé.

Configuration de la file d'attente

'queue' => [
    'enabled' => true,
    'connection' => null,
    'queue' => 'default',
],

Par défaut, l'enregistrement des logs d'audit est envoyé en file d'attente pour éviter de ralentir les requêtes HTTP. C'est le paramètre recommandé pour la production.

Clé Valeur par défaut Description
queue.enabled true Lorsque true, les logs d'audit sont enregistrés via un job en file d'attente. Passez à false pour un enregistrement synchrone.
queue.connection null La connexion de file d'attente à utiliser. null utilise la connexion par défaut de votre application.
queue.queue default Le nom de la file d'attente sur laquelle dispatcher les jobs d'audit.

Si vous souhaitez que les logs d'audit soient enregistrés sur une file d'attente dédiée (pour éviter les retards causés par d'autres jobs), spécifiez un nom de file d'attente :

'queue' => [
    'enabled' => true,
    'connection' => 'redis',
    'queue' => 'auditing',
],

Note : Lorsque la file d'attente est activée et que vous utilisez HasAuditTrail, la chaîne de hash est tout de même calculée de manière synchrone au moment du dispatch pour maintenir l'ordre de la chaîne. Le job en file d'attente gère l'écriture en base de données.

Événements

'events' => [
    'log_reads' => false,
],

Contrôle les événements Eloquent capturés.

Clé Valeur par défaut Description
events.log_reads false Lorsque true, capture les événements retrieved (lectures de model).

Attention : L'activation de log_reads est très verbeuse. Chaque requête Eloquent qui charge un model auditable génère une entrée dans le journal d'audit. Cela peut produire un volume massif d'enregistrements. N'activez cette option que si vous avez une exigence de conformité spécifique pour suivre l'accès aux données, comme l'article 15 du RGPD (droit d'accès) ou l'article 33 (notification de violation — savoir qui a accédé à quelles données).

Anonymisation

'anonymization' => [
    'replacement' => '[ANONYMIZED]',
],

Paramètres pour l'anonymisation RGPD. Lorsque vous appelez $model->anonymize(), les champs de données personnelles de type chaîne sont remplacés par cette chaîne suivie d'un suffixe aléatoire (via Str::random(8)) pour éviter les violations de contrainte UNIQUE. Les champs de type non-chaîne reçoivent null.

Par exemple, avec le remplacement par défaut :

$user->anonymize();
// email => '[ANONYMIZED]-a1b2c3d4'
// name  => '[ANONYMIZED]-e5f6g7h8'
// age   => null  (les champs non-chaîne deviennent null)

Vous pouvez personnaliser la chaîne de remplacement si nécessaire :

'anonymization' => [
    'replacement' => '[REDACTED]',
],

Rétention

'retention' => [
    'days' => 90,
],

Contrôle la purge automatique des anciens logs d'audit via la commande Artisan audit:prune.

Clé Valeur par défaut Description
retention.days 90 Nombre de jours de conservation des logs d'audit. Les logs plus anciens sont supprimés par audit:prune.

Pour purger les logs, exécutez la commande manuellement ou planifiez-la :

# Delete logs older than the configured retention period
php artisan audit:prune

# Override with a custom retention period
php artisan audit:prune --days=365

# Prune only a specific model type
php artisan audit:prune --type="App\Models\User"

Planifiez-la dans routes/console.php :

Schedule::command('audit:prune')->daily();

Note : Vérifiez vos exigences réglementaires avant de définir une période de rétention. Le RGPD exige généralement la minimisation des données (rétention courte), tandis que les réglementations financières peuvent exiger une rétention plus longue (par ex. 7 ans). Définissez retention.days à une valeur qui satisfait votre obligation de conformité la plus exigeante.

Notifications

'notifications' => [
    'channels' => ['mail'],
    'mail_to' => [env('AUDIT_ALERT_EMAIL', '')],
    'webhooks' => [],
],

Configure la manière dont vous êtes alerté lorsque audit:verify --notify détecte des défaillances d'intégrité de la chaîne.

Clé Valeur par défaut Description
notifications.channels ['mail'] Canaux à utiliser : mail, webhook, ou les deux.
notifications.mail_to [] Tableau d'adresses e-mail pour recevoir les alertes mail.
notifications.webhooks [] Tableau d'URLs de webhook (Slack, Teams, Discord ou endpoints personnalisés).

Alertes par e-mail

Ajoutez la variable AUDIT_ALERT_EMAIL à votre fichier .env :

AUDIT_ALERT_EMAIL=security@yourcompany.com

Ou spécifiez plusieurs destinataires directement dans la configuration :

'notifications' => [
    'channels' => ['mail'],
    'mail_to' => [
        'security@yourcompany.com',
        'cto@yourcompany.com',
    ],
],

Alertes par webhook

Les payloads des webhooks sont compatibles avec Slack, Microsoft Teams, Discord et les endpoints personnalisés. Les clés text et content sont incluses pour la compatibilité multiplateforme.

'notifications' => [
    'channels' => ['mail', 'webhook'],
    'mail_to' => [env('AUDIT_ALERT_EMAIL', '')],
    'webhooks' => [
        env('AUDIT_ALERT_SLACK_WEBHOOK'),
        env('AUDIT_ALERT_TEAMS_WEBHOOK'),
    ],
],

Planification de la vérification

Pour une surveillance continue, planifiez la commande de vérification dans routes/console.php :

Schedule::command('audit:verify --notify')->hourly();

Cela exécute la vérification de la chaîne toutes les heures et envoie des notifications via vos canaux configurés si des défaillances d'intégrité sont détectées.

Fichier de configuration complet

Pour référence, voici la configuration complète par défaut :

// config/audit-chain.php

return [
    'connection' => null,
    'table' => 'audit_logs',
    'state_table' => null, // defaults to '{table}_state'
    'chain_seed' => env('AUDIT_CHAIN_SEED', 'genesis'),
    'queue' => [
        'enabled' => true,
        'connection' => null,
        'queue' => 'default',
    ],
    'events' => [
        'log_reads' => false,
    ],
    'anonymization' => [
        'replacement' => '[ANONYMIZED]',
    ],
    'retention' => [
        'days' => 90,
    ],
    'notifications' => [
        'channels' => ['mail'],
        'mail_to' => [env('AUDIT_ALERT_EMAIL', '')],
        'webhooks' => [],
    ],
];

Et ensuite ?