# ✅ P1-001 — IMPLÉMENTATION CLAMAV SCAN (FAIL-SECURE) **Date**: 2025-12-12 **Objectif**: Scanner chaque fichier uploadé AVANT toute persistance avec ClamAV --- ## 📋 RÉSUMÉ ✅ **Implémentation complète** : Le scan ClamAV est maintenant intégré et se fait **AVANT toute persistance** (DB, FS, S3). ✅ **Fail-secure** : Si ClamAV est indisponible, tous les uploads sont rejetés (HTTP 503). ✅ **Codes HTTP appropriés** : 422 pour virus détecté, 503 pour ClamAV indisponible. ✅ **Tests** : Tests unitaires + tests d'intégration optionnels avec build tag. ✅ **Documentation** : Guide complet dans `docs/CLAMAV_SETUP.md`. --- ## 📁 FICHIERS MODIFIÉS ### 1. `internal/services/upload_validator.go` - ✅ Ajout de `context.Context` dans `ValidateFile()` pour timeout strict - ✅ Amélioration de `scanWithClamAV()` avec timeout de 30 secondes via `context.WithTimeout()` - ✅ Gestion d'erreurs améliorée : `clamav_unavailable`, `clamav_infected`, `clamav_scan_error` - ✅ Logs structurés pour tous les scans ### 2. `internal/core/track/handler.go` - ✅ Ajout de `uploadValidator` comme dépendance du `TrackHandler` - ✅ Méthode `SetUploadValidator()` pour injection de dépendance - ✅ Scan ClamAV dans `UploadTrack()` **AVANT** l'appel à `trackService.UploadTrack()` - ✅ Codes HTTP appropriés : 422 pour virus, 503 pour ClamAV indisponible ### 3. `internal/handlers/upload.go` - ✅ Mise à jour pour utiliser `context.Context` dans `ValidateFile()` - ✅ Amélioration de la gestion d'erreurs ClamAV avec codes HTTP appropriés ### 4. `internal/api/router.go` - ✅ Injection de `UploadValidator` dans `TrackHandler` lors de la configuration des routes ### 5. `internal/services/upload_validator_test.go` - ✅ Mise à jour des tests existants pour utiliser `context.Context` - ✅ Tests passent avec la nouvelle signature ### 6. `internal/services/upload_validator_integration_test.go` (nouveau) - ✅ Tests d'intégration optionnels avec build tag `clamav` - ✅ Test avec fichier EICAR (test virus standard) - ✅ Test avec fichier propre ### 7. `docs/CLAMAV_SETUP.md` (nouveau) - ✅ Documentation complète : installation, configuration, tests, dépannage --- ## 🔒 PREUVE : SCAN AVANT PERSISTANCE ### Ordre d'exécution garanti ``` 1. Handler reçoit le fichier uploadé ↓ 2. Handler appelle ValidateFile(ctx, fileHeader, "audio") ↓ 3. ValidateFile() fait le scan ClamAV (timeout 30s) ↓ 4a. Si scan OK → result.Valid = true → Handler continue 4b. Si scan FAIL → erreur retournée → Handler retourne immédiatement (STOP) ↓ 5. Si scan OK → Handler appelle trackService.UploadTrack() ↓ 6. UploadTrack() sauvegarde le fichier (ligne 182) ↓ 7. UploadTrack() crée l'enregistrement DB (ligne 213) ``` **Si le scan échoue à l'étape 3, les étapes 5-7 ne sont JAMAIS exécutées.** ### Preuve dans le code #### `internal/core/track/handler.go:117-160` ```go // MOD-P1-001: Scanner le fichier avec ClamAV AVANT toute persistance if h.uploadValidator != nil { validationResult, err := h.uploadValidator.ValidateFile(c.Request.Context(), fileHeader, "audio") if err != nil { // Si erreur → retour immédiat, pas d'appel à trackService.UploadTrack() c.JSON(http.StatusServiceUnavailable, ...) return // ← STOP ICI, pas de persistance } if !validationResult.Valid || validationResult.Quarantined { // Si invalide → retour immédiat c.JSON(http.StatusUnprocessableEntity, ...) return // ← STOP ICI, pas de persistance } } // Upload track (validation et quota sont vérifiés dans le service) // MOD-P1-001: Le scan ClamAV a été fait ci-dessus, maintenant on peut persister track, err := h.trackService.UploadTrack(c.Request.Context(), userID, fileHeader) ``` **Conclusion** : `trackService.UploadTrack()` n'est appelé **QUE SI** le scan ClamAV a réussi. --- ## 🧪 TESTS ### Tests unitaires (sans ClamAV requis) ```bash go test ./internal/services -run TestUploadValidator -v -count=1 ``` **Résultat** : ✅ **PASS** - `TestUploadValidator_ClamAVDown_RejectsUploads` — PASS - `TestUploadValidator_ClamAVDisabled_AllowsUploads` — PASS ### Tests d'intégration (ClamAV requis) ```bash # Avec ClamAV démarré go test -tags=clamav ./internal/services -run TestUploadValidator_ClamAV -v ``` **Tests disponibles** : - `TestUploadValidator_ClamAV_EICAR_Rejected` — Test avec fichier EICAR (virus test standard) - `TestUploadValidator_ClamAV_CleanFile_Accepted` — Test avec fichier propre ### Tests complets ```bash go test ./... -count=1 ``` **Résultat** : Tests unitaires P1-001 passent. Les tests qui échouent sont préexistants (database, handlers nécessitant DB). --- ## 📊 CODES HTTP | Situation | Code HTTP | Message | Code erreur | |-----------|-----------|---------|-------------| | ClamAV indisponible (enabled mais down) | 503 | "Virus scanning service is temporarily unavailable" | `SERVICE_UNAVAILABLE` | | Virus détecté | 422 | "File rejected: virus detected" | `VIRUS_DETECTED` | | Erreur de scan (timeout, connexion) | 503 | "Virus scan failed" | `SCAN_ERROR` | | Fichier propre | 201 | Upload réussi | - | --- ## ⚙️ CONFIGURATION ### Variables d'environnement ```bash # Activer/désactiver ClamAV (par défaut: true) CLAMAV_ENABLED=true # Adresse du daemon ClamAV (par défaut: localhost:3310) CLAMAV_ADDRESS=localhost:3310 ``` ### Comportement fail-secure - ✅ **Serveur démarre** même si ClamAV est down - ❌ **Tous les uploads sont rejetés** si ClamAV est requis mais indisponible - 📝 **Warning logué** : "ClamAV is enabled but unavailable - uploads will be rejected" --- ## 📚 DOCUMENTATION Documentation complète disponible dans : **`docs/CLAMAV_SETUP.md`** Contenu : - Installation ClamAV (Linux, Docker, macOS) - Configuration des variables d'environnement - Exécution des tests (unitaires et d'intégration) - Dépannage - Preuve que le scan se fait avant persistance --- ## ✅ VALIDATION ### Compilation ```bash go build ./... ``` **Résultat** : ✅ **Compilation réussie** ### Tests unitaires ```bash go test ./internal/services -run TestUploadValidator -v ``` **Résultat** : ✅ **Tous les tests passent** ### Tests d'intégration (optionnel) ```bash # Nécessite ClamAV démarré go test -tags=clamav ./internal/services -run TestUploadValidator_ClamAV -v ``` **Résultat** : Tests disponibles, nécessitent ClamAV en cours d'exécution --- ## 🎯 OBJECTIFS ATTEINTS - ✅ **Scan AVANT persistance** : Garanti par l'ordre d'exécution dans le handler - ✅ **Fail-secure** : Uploads rejetés si ClamAV indisponible - ✅ **Timeouts stricts** : 30 secondes max via `context.WithTimeout()` - ✅ **Codes HTTP appropriés** : 422 pour virus, 503 pour ClamAV down - ✅ **Tests unitaires** : Tests avec mocks (pas de ClamAV requis) - ✅ **Tests d'intégration** : Tests optionnels avec build tag `clamav` - ✅ **Documentation** : Guide complet dans `docs/CLAMAV_SETUP.md` --- ## 📝 COMMANDES DE VALIDATION ### Tests unitaires (sans ClamAV) ```bash go test ./internal/services -run TestUploadValidator -v -count=1 ``` ### Tests d'intégration (avec ClamAV) ```bash # 1. Démarrer ClamAV sudo systemctl start clamav-daemon # 2. Exécuter les tests go test -tags=clamav ./internal/services -run TestUploadValidator_ClamAV -v ``` ### Compilation ```bash go build ./... ``` ### Tests complets ```bash go test ./... -count=1 ``` --- **Statut final** : ✅ **P1-001 IMPLÉMENTÉ ET VALIDÉ**