L'implementazione di un'infrastruttura a microservizi di livello enterprise richiede l'adozione di pattern architetturali rigorosi e policy di sicurezza by-design. Il sistema analizzato adotta un modello architetturale orientato al Domain-Driven Design (DDD), sviluppato su uno stack moderno con Java 25 e Spring Boot.
L'intero paradigma di sicurezza si fonda sulla protezione delle comunicazioni e dei dati sensibili, impiegando un API Gateway per centralizzare la gestione del traffico e delle policy.
L'intero paradigma di sicurezza si fonda sulla protezione delle comunicazioni e dei dati sensibili, impiegando un API Gateway per centralizzare la gestione del traffico e delle policy.
Source Code: https://github.com/marcoberri/spring-security-api/
Schema Architetturale e Microservizi nel Docker Compose
L'infrastruttura è progettata per segregare le responsabilità orchestrando diversi container tramite Docker Compose, comprensivo dell'Identity Provider (Keycloak).
[ Client / Browser ]
│
├── (1) POST /realms/spring-security-realm/protocol/openid-connect/token ──► [ Keycloak IDP (port 8080) ]
│ │
│ ◄── RSA Signed JWT Token (Lifespan: 1 minute, aud: sensitive-data-service) ───────┘
│
▼ (2) Protected API requests over TLS (Port 443)
┌────────────────────────────────────────────────────────────────────────────────────────┐
│ Spring Cloud Gateway (api-gateway) │
│ • PKCS12 TLS Termination (External port 443) │
│ • OIDC JWT validation and token expiration check (60-second lifespan) │
│ • Request payload size enforcement (Max 1MB) & JSON Content-Type validation │
│ • Spring Cloud LoadBalancer (Round Robin) with Actuator Health Checks │
│ • Zero-Trust internal TLS connection to backend nodes │
└────────────────────────────────────┬───────────────────────────────────────────────────┘
│ (3) Internal TLS Zero-Trust Connection (Port 8443)
┌────────────────┴────────────────┐
▼ ▼
┌─────────────────────────────────┐ ┌─────────────────────────────────┐
│ Sensitive Data Service (Clone 1)│ │ Sensitive Data Service (Clone 2)│
│ • Internal port 8443 (TLS) │ │ • Internal port 8443 (TLS) │
│ • No exposed host ports │ │ • No exposed host ports │
│ • JPA Encryption: AES-256-GCM │ │ • JPA Encryption: AES-256-GCM │
│ • Security Audit Tracking Log │ │ • Security Audit Tracking Log │
│ • Docker Secret: db_aes_key │ │ • Docker Secret: db_aes_key │
└────────────────┬────────────────┘ └────────────────┬────────────────┘
│ │
└─────────────────┬─────────────────┘
▼
┌───────────────────────────┐
│ Database in RAM │
│ Dati crittografati │
└───────────────────────────┘
Keycloak come Identity Provider (IdP) e Authorization Server
Il ruolo di Identity Provider (IDP) è delegato a Keycloak, che gestisce l'emissione dei JSON Web Token (JWT) necessari per l'autenticazione.
- I token presentano una durata estremamente breve, con una vita massima pari a 1 minuto.
- Sono firmati tramite algoritmo RSA utilizzando chiavi di minimo 3072 bit.
- La struttura del Realm è precaricata tramite il file
realm-export.json. - Viene configurato il client
spring-api-gatewayin modalità confidential. - Include un mapper dedicato per iniettare i claim
aud(audience) esub(ID utente), indispensabili per il tracciamento delle operazioni all'interno del dominio.
Sicurezza Perimetrale, Bilanciamento e Content Protection
L'API Gateway basato su Spring Cloud agisce come unico punto di ingresso per la gestione dei JWT e del traffico. Le sue responsabilità includono:
- Validazione JWT e OIDC: Il gateway verifica la firma dei JWT recuperando dinamicamente le chiavi pubbliche di Keycloak tramite l'endpoint OIDC standard
/.well-known/openid-configuration. - Content Protection: Impone un limite massimo di 1MB per le dimensioni del payload delle richieste POST ed esegue la validazione dei parametri e del formato JSON in ingresso, respingendo le richieste malformate.
- Load Balancing e Health Monitoring: Il gateway agisce direttamente come Load Balancer integrato, distribuendo nativamente le richieste valide con logica Round Robin verso i cloni del microservizio di backend. Inoltre, monitora costantemente la salute dei backend interrogando periodicamente il loro endpoint Spring Boot Actuator (
/actuator/health). I nodi non sani vengono automaticamente rimossi dalla rotazione e il traffico instradato su nodi operativi.
Persistenza Crittografata e Backend Replicati
Le richieste processate dal gateway vengono inoltrate ai nodi di backend tramite un canale TLS che assicura una connessione crittografata punto-a-punto tramite certificato autogenerato. Il microservizio responsabile dei dati sensibili non è mai esposto direttamente, ma è protetto all'interno della rete virtuale privata ed è replicato.
A livello di dominio, il sistema include una tabella per il tracciamento delle operazioni. Per l'archiviazione, il progetto utilizza un database in RAM che contiene dati di test e dati di produzione rigorosamente crittografati. La sicurezza dei dati a riposo è garantita dall'algoritmo di crittografia AES-256-GCM (Advanced Encryption Standard in Galois/Counter Mode). Oltre a cifrare il dato, la modalità GCM fornisce un Authentication Tag che garantisce integrità e confidenzialità, permettendo al sistema di accorgersi immediatamente di eventuali manomissioni a livello di storage.
A livello di dominio, il sistema include una tabella per il tracciamento delle operazioni. Per l'archiviazione, il progetto utilizza un database in RAM che contiene dati di test e dati di produzione rigorosamente crittografati. La sicurezza dei dati a riposo è garantita dall'algoritmo di crittografia AES-256-GCM (Advanced Encryption Standard in Galois/Counter Mode). Oltre a cifrare il dato, la modalità GCM fornisce un Authentication Tag che garantisce integrità e confidenzialità, permettendo al sistema di accorgersi immediatamente di eventuali manomissioni a livello di storage.
Gestione dei Segreti (Docker Secrets)
La chiave simmetrica per l'algoritmo AES non è mai passata in chiaro né inserita nel codice sorgente. Viene invece gestita in modo sicuro tramite i Docker Secrets, venendo iniettata temporaneamente nella memoria del container (montata in
/run/secrets/). In Spring Boot, questa chiave viene recuperata agilmente configurando l'importazione dell'albero di configurazione tramite la direttiva spring.config.import=configtree:/run/secrets/.
Riferimenti e Fonti: