chore(infra): add ClamAV to docker-compose for v0.101
This commit is contained in:
parent
68fececd8d
commit
1f72854192
6 changed files with 80 additions and 7 deletions
|
|
@ -68,6 +68,24 @@ services:
|
|||
cpus: '0.50'
|
||||
memory: 256M
|
||||
|
||||
clamav:
|
||||
image: clamav/clamav:latest
|
||||
container_name: veza_clamav
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- veza-network
|
||||
healthcheck:
|
||||
test: ["CMD", "clamdscan", "--ping", "1"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
start_period: 180s
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '0.5'
|
||||
memory: 1G
|
||||
|
||||
# ============================================================================
|
||||
# PAYMENT ROUTER (Hyperswitch)
|
||||
# ============================================================================
|
||||
|
|
@ -144,6 +162,9 @@ services:
|
|||
- HYPERSWITCH_WEBHOOK_SECRET=${HYPERSWITCH_WEBHOOK_SECRET:-}
|
||||
- HYPERSWITCH_ENABLED=${HYPERSWITCH_ENABLED:-false}
|
||||
- CHECKOUT_SUCCESS_URL=${CHECKOUT_SUCCESS_URL:-https://veza.fr/purchases}
|
||||
- ENABLE_CLAMAV=true
|
||||
- CLAMAV_REQUIRED=true
|
||||
- CLAMAV_ADDRESS=clamav:3310
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
|
|
@ -151,6 +172,8 @@ services:
|
|||
condition: service_healthy
|
||||
rabbitmq:
|
||||
condition: service_healthy
|
||||
clamav:
|
||||
condition: service_started
|
||||
networks:
|
||||
- veza-network
|
||||
healthcheck:
|
||||
|
|
|
|||
|
|
@ -55,6 +55,27 @@ services:
|
|||
reservations:
|
||||
memory: 32M
|
||||
|
||||
# ClamAV - Virus scanning for uploads (v0.101)
|
||||
clamav:
|
||||
image: clamav/clamav:latest
|
||||
container_name: veza_clamav
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "${PORT_CLAMAV:-13310}:3310"
|
||||
networks:
|
||||
- veza-net
|
||||
healthcheck:
|
||||
test: ["CMD", "clamdscan", "--ping", "1"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
start_period: 180s
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '0.5'
|
||||
memory: 1G
|
||||
|
||||
# RabbitMQ - Message Broker
|
||||
# Limit: 256MB RAM. Host 15672->AMQP(5672), 25672->Management(15672)
|
||||
rabbitmq:
|
||||
|
|
@ -153,6 +174,9 @@ services:
|
|||
- COOKIE_PATH=/
|
||||
- CORS_ALLOWED_ORIGINS=http://veza.fr:3000,http://veza.fr:5173
|
||||
- RABBITMQ_URL=amqp://${RABBITMQ_DEFAULT_USER:-veza}:${RABBITMQ_DEFAULT_PASS:-devpassword}@rabbitmq:5672/
|
||||
- ENABLE_CLAMAV=true
|
||||
- CLAMAV_REQUIRED=false
|
||||
- CLAMAV_ADDRESS=clamav:3310
|
||||
ports:
|
||||
- "${PORT_BACKEND:-18080}:8080"
|
||||
depends_on:
|
||||
|
|
@ -162,6 +186,8 @@ services:
|
|||
condition: service_healthy
|
||||
rabbitmq:
|
||||
condition: service_healthy
|
||||
clamav:
|
||||
condition: service_started
|
||||
networks:
|
||||
- veza-net
|
||||
healthcheck:
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
|
|||
# Runtime stage
|
||||
FROM alpine:latest
|
||||
|
||||
# Install runtime dependencies
|
||||
RUN apk --no-cache add ca-certificates tzdata wget
|
||||
# Install runtime dependencies (clamav for virus scanning in v0.101)
|
||||
RUN apk --no-cache add ca-certificates tzdata wget clamav
|
||||
|
||||
# Create non-root user for security
|
||||
RUN addgroup -g 1001 -S app && \
|
||||
|
|
|
|||
|
|
@ -32,10 +32,8 @@ RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
|
|||
# Runtime stage - minimal alpine
|
||||
FROM alpine:3.21
|
||||
|
||||
# Install only runtime dependencies
|
||||
RUN apk --no-cache add ca-certificates tzdata && \
|
||||
# Add wget for health checks
|
||||
apk --no-cache add wget && \
|
||||
# Install only runtime dependencies (clamav for virus scanning in v0.101)
|
||||
RUN apk --no-cache add ca-certificates tzdata wget clamav && \
|
||||
# Clean up apk cache
|
||||
rm -rf /var/cache/apk/*
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,10 @@ func (c *Config) initServices() error {
|
|||
if p := getEnv("CLAMAV_CLAMD_PATH", ""); p != "" {
|
||||
uploadConfig.ClamAVClamdPath = p
|
||||
}
|
||||
// Adresse ClamAV pour connexion TCP (ex: clamav:3310 en Docker)
|
||||
if addr := getEnv("CLAMAV_ADDRESS", ""); addr != "" {
|
||||
uploadConfig.ClamAVAddress = addr
|
||||
}
|
||||
var err error
|
||||
c.UploadValidator, err = services.NewUploadValidator(uploadConfig, c.Logger)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import (
|
|||
type UploadValidator struct {
|
||||
logger *zap.Logger
|
||||
clamdPath string // Chemin vers clamdscan (ex: clamdscan, /usr/bin/clamdscan)
|
||||
clamAVConfigPath string // Config pour connexion TCP distante (ex: clamav:3310)
|
||||
quarantineDir string
|
||||
clamAVRequiredButUnavailable bool // MOD-P1-001-REFINEMENT: Flag pour fail-secure localisé
|
||||
clamAVRequired bool // MOD-P1-002: Si false, accepte uploads même si ClamAV down
|
||||
|
|
@ -115,6 +116,21 @@ func NewUploadValidator(config *UploadConfig, logger *zap.Logger) (*UploadValida
|
|||
}
|
||||
fmt.Printf("🛡️ [UPLOAD VALIDATOR] ClamAV activé - Utilisation de %s (exec)\n", clamdPath)
|
||||
|
||||
// Config pour connexion TCP distante (ex: clamav:3310 en Docker)
|
||||
clamAVConfigPath := ""
|
||||
if config.ClamAVAddress != "" && strings.Contains(config.ClamAVAddress, ":") {
|
||||
parts := strings.SplitN(config.ClamAVAddress, ":", 2)
|
||||
host, port := parts[0], parts[1]
|
||||
configContent := fmt.Sprintf("TCPSocket %s\nTCPAddr %s\n", port, host)
|
||||
tmpFile, err := os.CreateTemp("", "veza-clamd-*.conf")
|
||||
if err == nil {
|
||||
_, _ = tmpFile.WriteString(configContent)
|
||||
_ = tmpFile.Close()
|
||||
clamAVConfigPath = tmpFile.Name()
|
||||
fmt.Printf("🛡️ [UPLOAD VALIDATOR] Config TCP: %s -> %s\n", config.ClamAVAddress, clamAVConfigPath)
|
||||
}
|
||||
}
|
||||
|
||||
clamAVRequiredButUnavailable := false
|
||||
// Test disponibilité: clamdscan --version
|
||||
pingCtx, pingCancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||
|
|
@ -141,6 +157,7 @@ func NewUploadValidator(config *UploadConfig, logger *zap.Logger) (*UploadValida
|
|||
return &UploadValidator{
|
||||
logger: logger,
|
||||
clamdPath: clamdPath,
|
||||
clamAVConfigPath: clamAVConfigPath,
|
||||
quarantineDir: config.QuarantineDir,
|
||||
clamAVRequiredButUnavailable: clamAVRequiredButUnavailable,
|
||||
clamAVRequired: config.ClamAVRequired,
|
||||
|
|
@ -495,7 +512,12 @@ func (uv *UploadValidator) scanWithClamAV(ctx context.Context, file io.Reader) (
|
|||
return false, fmt.Errorf("failed to close temp file: %w", closeErr)
|
||||
}
|
||||
|
||||
cmd := exec.CommandContext(scanCtx, uv.clamdPath, "--no-summary", tmpPath)
|
||||
args := []string{"--no-summary"}
|
||||
if uv.clamAVConfigPath != "" {
|
||||
args = append(args, "-c", uv.clamAVConfigPath)
|
||||
}
|
||||
args = append(args, tmpPath)
|
||||
cmd := exec.CommandContext(scanCtx, uv.clamdPath, args...)
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stderr = &stderr
|
||||
runErr := cmd.Run()
|
||||
|
|
|
|||
Loading…
Reference in a new issue