Progettare una architettura sicura per i sistemi distribuiti

La sicurezza dei sistemi distribuiti rappresenta una sfida complessa a causa della diversità e della scala dei componenti coinvolti. Con molti servizi che interagiscono attraverso reti potenzialmente non sicure, il rischio di accessi non autorizzati e di violazioni dei dati aumenta significativamente. Questo articolo esplora un approcio pratico per la sicurezza di sistemi distribuiti utilizzando un progetto open-source. Il progetto dimostra come integrare diversi meccanismi di sicurezza e tecnologie per affrontare common challenge di sicurezza come l’autenticazione, l’autorizzazione e la comunicazione sicura.

Comprendere i Challenge di Sicurezza nei Sistemi Distribuiti

I sistemi distribuiti coinvolgono molti servizi o microservizi che devono comunicare in sicurezza attraverso una rete. I principali challenge di sicurezza in questi architetti includono:

  1. Comunicazione sicura: Assicurarsi che i dati trasmessi tra servizi siano crittografati e siano sicuri da ascolto o alterazione
  2. Autenticazione: Verificare l’identità degli utenti e dei servizi per prevenire l’accesso non autorizzato
  3. Autorizzazione: Controllare ciò che gli utenti e i servizi autenticati sono autorizzati a fare, in base ai loro ruoli e permessi
  4. Enforcement delle politiche: Implementare accessi controlli a livello granulare e politiche che governano le interazioni tra servizi e utenti.
  5. Gestione certificati: Gestione certificati digitali per crittare i dati e stabilire una fiducia tra i servizi

Questo progetto open-source affronta questi挑战 utilizzando diverse tecnologie integrate e soluzioni.

Configurazione e impostazione del progetto

Il progetto inizia impostando un ambiente sicuro utilizzando script shell e Docker. L’impostazione comprende la fornitura di certificati digitali e l’avvio dei servizi necessari per assicurarsi che tutti i componenti siano pronti per la comunicazione sicura.

Step per l’impostazione dell’ambiente

1. Fornitura di certificati

Il progetto utilizza un script shell (provisioning.sh) per simulare una Certificate Authority (CA) e generare i certificati necessari per i servizi.

   ./provisioning.sh

2. Avvio dei servizi

Docker Compose viene utilizzato per avviare tutti i servizi definiti nel progetto, assicurandosi che siano configurati correttamente per un’operazione sicura.

   docker-compose up

3. Testo della comunicazione service-to-service

Per validare le comunicazioni tra servizi utilizzando certificati e token JWT, viene fornito il script test_services.sh. Questo script dimostra come diversi servizi interagiscono in maniera sicura utilizzando i loro certificati assegnati.

Risoluzione dei Challenge di Sicurezza nei Sistemi Distribuiti

Il progetto integra diverse tecnologie chiave per affrontare i principali challenge di sicurezza menzionati prima. Ecco come ogni sfida è affrontata:

1. Comunicazione Sicura con Mutual TLS (mTLS)

Challenge

In un sistema distribuito, i servizi devono comunicare in maniera sicura per prevenire l’accesso non autorizzato e le violazioni di dati.

Soluzione

Il progetto utilizza Mutual TLS (mTLS) per la sicurezza delle comunicazioni tra i servizi. mTLS assicura che entrambi il cliente e il server autentichino l’altro utilizzando i loro certificati rispettivi. Questa autentificazione mutua impedisce ai servizi non autorizzati di comunicare con i servizi legittimi.

Implementazione

Nginx è configurato come un reverse proxy per gestire mTLS. Richiede sia certificati client che server per stabilire una connessione sicura, garantendo che i dati trasmessi tra i servizi rimangano confidenziali e immune da manomissioni.

2. Autenticazione con Keycloak

Sfida

L’autenticazione corretta degli utenti e dei servizi è cruciale per prevenire l’accesso non autorizzato.

Soluzione

Il progetto utilizza Keycloak, una soluzione open-source di gestione dell’identità e dell’accesso, per gestire l’autenticazione. Keycloak supporta molti metodi di autenticazione, incluso OpenID Connect e le credenziali del cliente, rendendolo adatto sia all’autenticazione utente che di servizi.

  • Autenticazione Utente:
    Gli utenti sono autenticati tramite OpenID Connect. Keycloak è configurato con un client (appTest-login-client) che gestisce i flussi di autenticazione utente, incluso il login, l’emissione del token e la gestione del callback.
  • Autenticazione Servizi:
    Per l’autenticazione servizio-a-servizio, il progetto utilizza un client Keycloak (client_credentials-test) configurato per il tipo di concessione delle credenziali del cliente. Questo metodo è ideale per l’autenticazione di servizi senza l’intervento dell’utente.

Esempio di Flusso di Autenticazione

  1. Gli utenti navigano alla pagina di login.
  2. Dopo il login riuscito, Keycloak reindirizza l’utente su una pagina di callback con un codice autorizzazione.
  3. Il codice autorizzazione viene quindi scambiato per un token JWT, utilizzato per le richieste successive. Il file authn.js nella directory nginx/njs fornisce una implementazione dettagliata di questo flusso.

Esempio di Autenticazione del Servizio Utilizzando Credenziali del Cliente

curl -X POST "http://localhost:9000/realms/tenantA/protocol/openid-connect/token" \
     -H "Content-Type: application/x-www-form-urlencoded" \
     -d "grant_type=client_credentials" \
     -d "client_id=client_credentials-test" \
     -d "client_secret=your-client-secret-here"

3. Autorizzazione utente con Open Policy Agent (OPA) e JWT

Sfida

Implementare controlli di accesso a livello granulare per assicurare che gli utenti autenticati e i servizi abbiano accesso solo ai risorse autorizzate

Soluzione

Il progetto utilizza una combinazione di Open Policy Agent (OPA) e token JWT per imporre le politiche di autorizzazione. Il progetto dimostra tre strategie differenti per la validazione JWT per garantire una sicurezza robusta:

  1. Recupero certificati da Keycloak: Recupera i certificati in modo dinamico da Keycloak per validare il token.
  2. Uso di x5t (Impronta): Utilizza l’impronta incorporata nel token per recuperare la chiave pubblica da un trust store locale.
  3. Validazione integrata del certificato: Valida il token utilizzando un certificato integrato, garantendo che il certificato sia validato rispetto ad una Autorità di Certificazione (CA) fidata.

Riferirsi al file nginx/njs/token.js per l’implementazione dettagliata di queste strategie.

4. Enforce della politica con Open Policy Agent (OPA)

Sfida

Implementare politiche di accesso dinamiche e flessibili sia per i servizi che per gli utenti

Soluzione

OPA è usato per enforcare politiche di accesso a granularità fine. Le politiche sono scritte in una lingua dichiarativa (Rego) e memorizzate nella directory opa/. Queste politiche definiscono le condizioni sotto le quali i servizi possono comunicare e gli utenti possono accedere ai risorse, garantendo che i controlli di accesso siano applicati consistentemente nel sistema.

5. Gestione del certificato

Sfida

Gestire i certificati digitali per i servizi per stabilire fiducia e garantire le comunicazioni sicure

Soluzione:
Il progetto include un sistema robusto di gestione certificati. Un script di shell (provisioning.sh) viene utilizzato per simulare una Autorità di Certificazione (CA) e generare certificati per ogni servizio. Questo approcio semplifica la gestione certificati e garantisce che tutti i servizi abbiano le credenziali necessarie per una comunicazione sicura.

Abbiamo anche aggiunto un endpoint per aggiornare il certificato del servizio senza aver bisogno di riavviare nginx.

curl --insecure  https://localhost/certs  --cert certificates/gen/serviceA/client.crt --key certificates/gen/serviceA/client.key -F cert=@certificates/gen/serviceA/client.crt -F key=@certificates/gen/serviceA/client.key

Conclusione

Costruire un sistema distribuito sicuro richiede una considerazione attenta di varie aspetti di sicurezza, inclusa la comunicazione sicura, l’autenticazione, l’autorizzazione, l’enforcement delle politiche e la gestione certificati. Questo progetto open-source fornisce un esempio completo di come integrare diversi meccanismi di sicurezza per affrontare questi挑战 efficacemente.

Seguendo le impostazioni e le configurazioni dimostrate in questo progetto, i developers possono sfruttare il TLS mutuo, Keycloak, Open Policy Agent e Nginx per costruire una robusta architettura di sicurezza. Queste tecnologie, quando combinate, forniscono una solida base per proteggere i sistemi distribuiti contro una vasta gamma di minacce, garantendo sia la protezione dati che l’accesso sicuro.

Source:
https://dzone.com/articles/designing-a-secure-architecture-for-distributed-systems