Internal APIs & X-Internal-Key
Documentazione sul sistema di protezione delle API interne tra microservizi.
Panoramicaβ
Gli endpoint /internal/* sono progettati per la comunicazione service-to-service e non devono essere accessibili pubblicamente. Per proteggere questi endpoint, Γ¨ stato implementato un sistema di autenticazione basato su header.
Come funzionaβ
Header X-Internal-Keyβ
Tutte le richieste agli endpoint /internal/* devono includere l'header:
X-Internal-Key: <chiave-segreta>
Risposteβ
| Scenario | HTTP Status | Risposta |
|---|---|---|
| Header mancante | 403 | {"error": "forbidden", "message": "Invalid or missing X-Internal-Key header"} |
| Chiave sbagliata | 403 | {"error": "forbidden", "message": "Invalid or missing X-Internal-Key header"} |
| Chiave corretta | 200 | Dati richiesti |
Configurazioneβ
Variabile d'ambienteβ
Imposta in ogni microservizio:
INTERNAL_API_KEY=tua-chiave-segreta-qui
[!WARNING] Se non imposti la variabile, viene usata una chiave di default. All'avvio vedrai il warning:
β οΈ ATTENZIONE: Stai usando la chiave INTERNAL_API_KEY di default!
Imposta INTERNAL_API_KEY nel file .env per la produzione!
Generare una chiave sicuraβ
openssl rand -hex 32
Servizi protettiβ
I seguenti servizi espongono endpoint /internal/* protetti:
| Servizio | Prefisso | Endpoint Esempio |
|---|---|---|
| auth | /internal/ | /internal/users/{id}, /internal/verify-token |
| devices | /internal/ | /internal/devices/{id}, /internal/users/{user_id}/devices |
Servizi che chiamano API interneβ
| Servizio | Chiama | Client |
|---|---|---|
| notifications | auth, devices | auth_client.py, devices_client.py |
| sharing | auth, devices | auth_client.py, devices_client.py |
| websocket | auth, devices | auth_client.py, devices_client.py |
| commands | auth, devices | auth_client.py, devices_client.py |
| positions | auth, devices | auth_client.py, devices_client.py |
| events | auth, devices | auth_client.py, devices_client.py |
| geofences | auth, devices | auth_client.py, devices_client.py |
| billing | auth | auth_client.py |
Esempio di chiamataβ
Python (client interno)β
import os
import httpx
INTERNAL_API_KEY = os.getenv("INTERNAL_API_KEY", "chiave-default")
def _headers():
return {"X-Internal-Key": INTERNAL_API_KEY}
def get_user(user_id: int):
with httpx.Client() as client:
resp = client.get(
f"http://auth:8081/internal/users/{user_id}",
headers=_headers()
)
return resp.json()
cURL (testing)β
# β Senza header - 403 Forbidden
curl http://localhost:8081/internal/users/1
# β
Con header - 200 OK
curl -H "X-Internal-Key: tua-chiave" http://localhost:8081/internal/users/1
Protezione Traefikβ
Oltre alla verifica header, Traefik blocca le richieste esterne a /internal/*:
# traefik/dynamic.yml
middlewares:
block-internal:
replacePath:
path: "/blocked"
# docker-compose.yml (auth)
labels:
- "traefik.http.routers.auth-internal-block.rule=PathPrefix(`/api/auth/internal`)"
- "traefik.http.routers.auth-internal-block.priority=200"
- "traefik.http.routers.auth-internal-block.middlewares=block-internal@file"
Best Practicesβ
- Non esporre /internal/ dall'esterno* - Usa Traefik per bloccare
- Usa chiavi diverse per ambiente - Dev, staging, produzione
- Ruota le chiavi periodicamente - Specialmente dopo data breach
- Non loggare la chiave - Evita di stamparla nei log
- Usa Docker secrets in produzione - PiΓΉ sicuro delle variabili ambiente