Add validation in ValidateForEnvironment() to fail startup when CLAMAV_REQUIRED=false in production. Virus scanning is mandatory for all file uploads in production. Phase 1 audit - P1.4
7 KiB
ClamAV Configuration — Veza Backend API
Vue d'ensemble
Le backend Veza API intègre ClamAV pour scanner tous les fichiers uploadés avant toute persistance (base de données, système de fichiers, ou stockage S3). Cette fonctionnalité garantit qu'aucun malware ne peut être stocké sur le serveur.
MOD-P1-001: Le scan ClamAV est maintenant obligatoire et se fait AVANT toute persistance. Si ClamAV est indisponible, tous les uploads sont rejetés (fail-secure).
Implémentation (clamdscan exec)
Le scan utilise clamdscan (exécutable système) au lieu de la bibliothèque go-clamd abandonnée. Aucune dépendance Go externe pour ClamAV. Le daemon clamd doit être démarré ; clamdscan s'y connecte via socket Unix ou TCP selon la configuration système.
Variables d'environnement
Configuration ClamAV
# Activer/désactiver ClamAV (par défaut: true)
CLAMAV_ENABLED=true
# Chemin vers clamdscan (par défaut: clamdscan)
# Ex: clamdscan, /usr/bin/clamdscan
CLAMAV_CLAMD_PATH=clamdscan
Exemples de configuration
Développement local
CLAMAV_ENABLED=true
CLAMAV_CLAMD_PATH=clamdscan
Production (clamd sur machine distante)
Configurer clamd.conf pour pointer vers le daemon distant, ou utiliser un wrapper. Par défaut clamdscan utilise le socket Unix local.
Désactiver ClamAV (non recommandé en production)
ENABLE_CLAMAV=false
Production : CLAMAV_REQUIRED obligatoire
En production (APP_ENV=production), CLAMAV_REQUIRED=true est obligatoire. Le démarrage de l'API échouera avec une erreur explicite si CLAMAV_REQUIRED=false. Le scan antivirus des uploads est une exigence de sécurité en production.
Installation et démarrage de ClamAV
Linux (Ubuntu/Debian)
# Installer ClamAV
sudo apt-get update
sudo apt-get install clamav clamav-daemon
# Démarrer le daemon
sudo systemctl start clamav-daemon
sudo systemctl enable clamav-daemon
# Mettre à jour les signatures de virus
sudo freshclam
Docker
# Lancer ClamAV dans un conteneur Docker
docker run -d --name clamav \
-p 3310:3310 \
-v /var/lib/clamav:/var/lib/clamav \
clamav/clamav:latest
macOS (Homebrew)
# Installer ClamAV
brew install clamav
# Démarrer le daemon
brew services start clamav
Comportement fail-secure
Si ClamAV est activé mais indisponible
- ✅ Le serveur démarre (pas de blocage au démarrage)
- ❌ Tous les uploads sont rejetés avec HTTP 503 (Service Unavailable)
- 📝 Message d'erreur clair : "Virus scanning service is temporarily unavailable"
Si un virus est détecté
- ❌ L'upload est rejeté avec HTTP 422 (Unprocessable Entity)
- 📝 Message d'erreur : "File rejected: virus detected"
- 🔒 Le fichier n'est JAMAIS persistant (ni DB, ni FS, ni S3)
Si le scan échoue (timeout, erreur de connexion)
- ❌ L'upload est rejeté avec HTTP 503 (Service Unavailable)
- 📝 Message d'erreur : "Virus scan failed"
- 🔒 Fail-secure : en cas de doute, on rejette
Tests
Tests unitaires (sans ClamAV requis)
# Exécuter tous les tests unitaires
go test ./internal/services -run TestUploadValidator -v
# Tests spécifiques
go test ./internal/services -run TestUploadValidator_ClamAVDown_RejectsUploads -v
go test ./internal/services -run TestUploadValidator_ClamAVDisabled_AllowsUploads -v
Tests d'intégration (ClamAV requis)
Les tests d'intégration nécessitent ClamAV en cours d'exécution et utilisent un build tag.
# 1. Démarrer ClamAV (voir section Installation)
# 2. Exécuter les tests d'intégration avec le tag 'clamav'
go test -tags=clamav ./internal/services -run TestUploadValidator_ClamAV -v
# 3. Test spécifique avec fichier EICAR (test virus standard)
go test -tags=clamav ./internal/services -run TestUploadValidator_ClamAV_EICAR_Rejected -v
# 4. Test avec fichier propre
go test -tags=clamav ./internal/services -run TestUploadValidator_ClamAV_CleanFile_Accepted -v
Configuration pour les tests d'intégration
Par défaut, les tests utilisent clamdscan. Pour un chemin personnalisé :
export CLAMAV_CLAMD_PATH=/usr/bin/clamdscan
go test -tags=clamav ./internal/services -run TestUploadValidator_ClamAV -v
Vérification que le scan se fait AVANT la persistance
Preuve dans le code
-
Handler (
internal/core/track/handler.go:117-160):- Le scan ClamAV est appelé AVANT
trackService.UploadTrack() - Si le scan échoue, la fonction retourne immédiatement (pas d'appel au service)
- Le scan ClamAV est appelé AVANT
-
Service (
internal/core/track/service.go:145-216):UploadTrack()sauvegarde le fichier (ligne 182) et crée l'enregistrement DB (ligne 213)- Ces opérations ne sont jamais appelées si le scan échoue dans le handler
-
Validateur (
internal/services/upload_validator.go:124-222):ValidateFile()fait le scan ClamAV avant de retournerresult.Valid = true- Si le scan détecte un virus,
result.Valid = falseet une erreur est retournée
Ordre d'exécution garanti
1. Handler reçoit le fichier uploadé
2. Handler appelle ValidateFile() avec context
3. ValidateFile() fait le scan ClamAV (timeout 30s)
4. Si scan OK → ValidateFile() retourne result.Valid = true
5. Si scan OK → Handler appelle trackService.UploadTrack()
6. UploadTrack() sauvegarde le fichier et crée l'enregistrement DB
Si le scan échoue à l'étape 3, les étapes 5-6 ne sont JAMAIS exécutées.
Timeouts et limites
- Timeout de scan : 30 secondes maximum
- Gestion du contexte : Utilise
context.WithTimeout()pour éviter les blocages - Logs structurés : Tous les scans sont loggés avec
zap.Logger
Codes HTTP retournés
| Situation | Code HTTP | Message |
|---|---|---|
| ClamAV indisponible (enabled mais down) | 503 | "Virus scanning service is temporarily unavailable" |
| Virus détecté | 422 | "File rejected: virus detected" |
| Erreur de scan (timeout, connexion) | 503 | "Virus scan failed" |
| Fichier propre | 201 | Upload réussi |
Dépannage
Le serveur démarre mais les uploads sont rejetés
Symptôme : HTTP 503 avec message "Virus scanning service is temporarily unavailable"
Causes possibles :
- ClamAV n'est pas démarré :
sudo systemctl status clamav-daemon - clamdscan introuvable : Vérifier
CLAMAV_CLAMD_PATHet que clamd est installé - Firewall bloque le port 3310
Solution :
# Vérifier que ClamAV écoute
sudo netstat -tlnp | grep 3310
# Tester la connexion
telnet localhost 3310
# Redémarrer ClamAV
sudo systemctl restart clamav-daemon
Les tests d'intégration échouent
Symptôme : go test -tags=clamav échoue avec erreur de connexion
Solution :
- Vérifier que ClamAV est démarré
- Vérifier que clamd est démarré et que clamdscan peut s'y connecter
- Vérifier les logs :
sudo journalctl -u clamav-daemon -f