Traefik Standardization Philosophy
Questo documento descrive lo standard "Clean" adottato per la configurazione di Traefik e dei microservizi nella piattaforma Visla.
Obiettivo
L'obiettivo è disaccoppiare completamente la logica di routing (gestita dal Gateway/Traefik) dalla logica applicativa (gestita dai microservizi FastAPI).
Il microservizio non deve "sapere" di essere esposto su un path specifico (es. /api/devices) o di trovarsi dietro un proxy. Deve comportarsi come se fosse l'unico servizio al mondo, rispondendo alla root /.
La Regola d'Oro
Traefik si occupa del "dove" (routing) e del "pulire" (stripprefix). Il microservizio si occupa solo del "cosa" (logica).
Configurazione Standard
1. Traefik (Gateway)
Traefik è responsabile di:
- Catturare: Intercettare le richieste dirette a un servizio specifico (es.
/api/devices). - Pulire: Rimuovere il prefisso di routing prima di inoltrare la richiesta.
- Proteggere: Aggiungere header di sicurezza, gestire i CORS e garantire la Double-Security.
Standard per Docker Labels (docker-compose.yml / Nomad):
labels:
# 1. Attiva Traefik per questo servizio
- "traefik.enable=true"
# 2. Regola di Routing: Cattura tutto ciò che inizia con il prefisso del servizio
- "traefik.http.routers.{SERVICE_NAME}.rule=PathPrefix(`/api/{SERVICE_NAME}`)"
# 3. Middleware di Pulizia: Definisce la rimozione del prefisso
- "traefik.http.middlewares.{SERVICE_NAME}-strip.stripprefix.prefixes=/api/{SERVICE_NAME}"
# 4. Applicazione: Applica routing + strip + CORS + Security + ForwardAuth
- "traefik.http.routers.{SERVICE_NAME}.middlewares={SERVICE_NAME}-strip,cors-headers@file,security-headers@file,block-internal@file,forward-auth@file,rate-limit@file,compress@file"
2. Microservizio (FastAPI)
Il codice applicativo deve essere "ignaro" dell'infrastruttura di routing.
Standard per app.py:
- ❌ NO
root_path: Non configurareroot_path="/api/...". L'applicazione deve ascoltare su/. - ❌ NO
CORSMiddleware(in test): gestire CORS centralmente nel Gateway (Traefik). I CORS nel codice sono stati commentati per evitare conflitti. - ✅ Double Security: L'autenticazione JWT viene validata SIA da Traefik (via
forward-authper protezione perimetrale) che internamente dal servizio (viajwt_auth.pyper logica applicativa). Non vengono usati header X-User-Id intermedi.
Esempio app.py pulito:
app = FastAPI(
title="Service Name",
version="1.0.0",
# Nessun root_path qui!
openapi_url="/openapi.json"
)
# ❌ Middleware CORS commentato (gestito da Traefik)
# app.add_middleware(
# CORSMiddleware,
# ...
# )
@app.get("/health")
def health():
return {"status": "ok"}
Flusso della Richiesta
Esempio: Chiamata a Devices (/api/devices/health).
| Attore | Azione | Path Visto |
|---|---|---|
| Client | Chiama l'URL pubblico con JWT | /api/devices/health |
| Traefik | Intercetta la regola PathPrefix(/api/devices) | /api/devices/health |
| Traefik | Verifica Auth (perimetro) tramite auth-service | - |
| Traefik | Applica devices-strip: toglie /api/devices | /health |
| Traefik | Inoltra al microservizio | /health |
| Microservizio | Valida JWT internamente e processa richiesta | /health |
| Microservizio | Risponde | 200 OK |
Vantaggi
- Portabilità: Il container può essere spostato o rinominato senza cambiare una riga di codice Python.
- Sicurezza Massima: Doppia barriera. Se il microservizio sbaglia qualcosa, Traefik protegge comunque.
- Gestione Ibrida: Routing centralizzato in Traefik, ma logica applicativa (incluso CORS) locale al servizio per massima robustezza.
- Uniformità: Tutti i servizi si comportano allo stesso modo, semplificando il debug.
Sicurezza "Intelligente" (block-internal)
Per proteggere i microservizi, abbiamo implementato un meccanismo di difesa perimetrale che blocca l'accesso dall'esterno agli endpoint sensibili.
Funzionamento
Il middleware block-internal@file (definito in dynamic.yml) analizza ogni richiesta in entrata dal Gateway.
- Regola Regex: Utilizza l'espressione regolare
^.*/internal/.*$per identificare qualsiasi URL che contenga la parola/internal/. - Azione: Se viene trovata una corrispondenza, il path della richiesta viene istantaneamente deviato su
/blocked-internal-access. Poiché questo path non esiste nel microservizio, la richiesta fallisce con un 404 o 403.
Perché "Intelligente"?
L'architettura separa nettamente due mondi:
- Mondo Esterno (Client/Browser): Passa OBBLIGATORIAMENTE attraverso Traefik. Se prova a chiamare
/api/auth/internal/logs, Traefik intercetta il pattern e lo blocca. - Mondo Interno (Docker Network): I microservizi si parlano direttamente tra loro utilizzando i nomi dei container (es.
http://auth:8081/internal/validate). Questa comunicazione non passa per Traefik, quindi non viene influenzata dal middleware e rimane perfettamente funzionante.
Ottimizzazioni di Sicurezza (Gennaio 2026)
Oltre al routing standard, sono state attivate le seguenti protezioni globali:
- Forward Auth (Double Auth): Tutti i servizi business (non
auth) sono protetti da un controllo preventivo del token. - Rate Limiting: Limite di 100 req/s (burst 50) per prevenire abusi sui servizi critici.
- Dashboard Security: La dashboard di Traefik è protetta da Basic Auth (
admin) ed esposta solo su port 80 (path/dashboard/). - Compression: Risposte GZip attive per risparmiare banda.
Di seguito la mappa aggiornata delle regole Traefik per i microservizi.
| Microservizio | Traefik Rule (PathPrefix) | Middleware (StripPrefix) | App Root | Stato |
|---|---|---|---|---|
| auth | /api/auth | ✅ /api/auth | / | STANDARD + RateLimit |
| billing | /api/billing | ✅ /api/billing | / | Double Security + RateLimit |
| client-logs | /api/client-logs | ✅ /api/client-logs | / | Double Security |
| commands | /api/commands | ✅ /api/commands | / | Double Security |
| devices | /api/devices | ✅ /api/devices | / | Double Security |
| device-simulator | /api/simulator, /api/test-devices | ✅ /api/simulator, /api/test-devices | / | Double Security |
| events | /api/events | ✅ /api/events | / | Double Security |
| geofences | /api/geofences | ✅ /api/geofences | / | Double Security |
| notifications | /api/notifications | ✅ /api/notifications | / | Double Security |
| positions | /api/positions | ✅ /api/positions | / | Double Security |
| sharing | /api/sharing | ✅ /api/sharing | / | Double Security |
| websocket | /api/websocket | ✅ /api/websocket | / | Double Security |
Legenda:
- Double Security:
forward-auth@fileattivo (senza headerX-User-Id).- RateLimit:
rate-limit@fileattivo.- Block Internal:
block-internal@fileattivo sempre.