veza/veza-backend-api/docs/CLAMAV_SETUP.md

236 lines
6.5 KiB
Markdown
Raw Normal View History

2025-12-13 02:34:34 +00:00
# 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).
---
## Variables d'environnement
### Configuration ClamAV
```bash
# Activer/désactiver ClamAV (par défaut: true)
CLAMAV_ENABLED=true
# Adresse du daemon ClamAV (par défaut: localhost:3310)
# Format: host:port (ex: localhost:3310, 192.168.1.100:3310)
CLAMAV_ADDRESS=localhost:3310
```
### Exemples de configuration
#### Développement local
```bash
CLAMAV_ENABLED=true
CLAMAV_ADDRESS=localhost:3310
```
#### Production avec ClamAV distant
```bash
CLAMAV_ENABLED=true
CLAMAV_ADDRESS=clamav.internal:3310
```
#### Désactiver ClamAV (non recommandé en production)
```bash
CLAMAV_ENABLED=false
```
---
## 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 `localhost:3310`. Pour utiliser une autre adresse :
```bash
export CLAMAV_ADDRESS=192.168.1.100:3310
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. Mauvaise adresse : Vérifier `CLAMAV_ADDRESS`
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 la variable `CLAMAV_ADDRESS` si ClamAV est sur une autre machine
3. Vérifier les logs : `sudo journalctl -u clamav-daemon -f`
---
## Références
- [ClamAV Documentation](https://docs.clamav.net/)
- [go-clamd Library](https://github.com/dutchcoders/go-clamd)
- [EICAR Test File](https://en.wikipedia.org/wiki/EICAR_test_file)