Skip to main content

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:

  1. Catturare: Intercettare le richieste dirette a un servizio specifico (es. /api/devices).
  2. Pulire: Rimuovere il prefisso di routing prima di inoltrare la richiesta.
  3. 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 configurare root_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-auth per protezione perimetrale) che internamente dal servizio (via jwt_auth.py per 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).

AttoreAzionePath Visto
ClientChiama l'URL pubblico con JWT/api/devices/health
TraefikIntercetta la regola PathPrefix(/api/devices)/api/devices/health
TraefikVerifica Auth (perimetro) tramite auth-service-
TraefikApplica devices-strip: toglie /api/devices/health
TraefikInoltra al microservizio/health
MicroservizioValida JWT internamente e processa richiesta/health
MicroservizioRisponde200 OK

Vantaggi

  1. Portabilità: Il container può essere spostato o rinominato senza cambiare una riga di codice Python.
  2. Sicurezza Massima: Doppia barriera. Se il microservizio sbaglia qualcosa, Traefik protegge comunque.
  3. Gestione Ibrida: Routing centralizzato in Traefik, ma logica applicativa (incluso CORS) locale al servizio per massima robustezza.
  4. 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:

  1. Mondo Esterno (Client/Browser): Passa OBBLIGATORIAMENTE attraverso Traefik. Se prova a chiamare /api/auth/internal/logs, Traefik intercetta il pattern e lo blocca.
  2. 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:

  1. Forward Auth (Double Auth): Tutti i servizi business (non auth) sono protetti da un controllo preventivo del token.
  2. Rate Limiting: Limite di 100 req/s (burst 50) per prevenire abusi sui servizi critici.
  3. Dashboard Security: La dashboard di Traefik è protetta da Basic Auth (admin) ed esposta solo su port 80 (path /dashboard/).
  4. Compression: Risposte GZip attive per risparmiare banda.

Di seguito la mappa aggiornata delle regole Traefik per i microservizi.

MicroservizioTraefik Rule (PathPrefix)Middleware (StripPrefix)App RootStato
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@file attivo (senza header X-User-Id).
  • RateLimit: rate-limit@file attivo.
  • Block Internal: block-internal@file attivo sempre.