# 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 ```bash # 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 ```bash 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) ```bash 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) ```bash # 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 ```bash # 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) ```bash # 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) ```bash # 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. ```bash # 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é : ```bash 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 1. **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) 2. **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 3. **Validateur** (`internal/services/upload_validator.go:124-222`): - `ValidateFile()` fait le scan ClamAV **avant** de retourner `result.Valid = true` - Si le scan détecte un virus, `result.Valid = false` et 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** : 1. ClamAV n'est pas démarré : `sudo systemctl status clamav-daemon` 2. clamdscan introuvable : Vérifier `CLAMAV_CLAMD_PATH` et que clamd est installé 3. Firewall bloque le port 3310 **Solution** : ```bash # 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** : 1. Vérifier que ClamAV est démarré 2. Vérifier que clamd est démarré et que clamdscan peut s'y connecter 3. Vérifier les logs : `sudo journalctl -u clamav-daemon -f` --- ## Références - [ClamAV Documentation](https://docs.clamav.net/) - [EICAR Test File](https://en.wikipedia.org/wiki/EICAR_test_file)