Guida completa all'utilizzo di HashiCorp Vault in un ambiente Spring Boot


Comprehensive Guide to Using HashiCorp Vault in a Spring Boot Environment



Indice

  • Cos'è HashiCorp Vault?
  • Il Ruolo di Vault in Produzione con Spring Boot
  • Panoramica dell'Architettura di Sistema
  • Autenticazione e Rischi di Sicurezza
  • Vault Agent e Integrazione Sicura
  • Configurazione di Vault per la Memorizzazione dei Segreti e l'Impostazione di HTTPS
  • Configurazione di Vault per il Motore di Transito (Crittografia e Decrittografia)
  • Gestione del Token di Vault in Spring Boot
  • Conclusione

Cos'è HashiCorp Vault?

HashiCorp Vault è uno strumento open-source progettato per gestire i segreti e proteggere i dati sensibili. Fornisce uno storage centralizzato per i segreti, controllo degli accessi e registrazione degli audit. Vault si integra facilmente con varie piattaforme cloud, consentendo di proteggere i dati sensibili sia in ambienti cloud-native che on-premise.

Il Ruolo di Vault in Produzione con Spring Boot

In produzione, Vault assicura che i segreti, come le credenziali del database, siano gestiti dinamicamente, eliminando la necessità di informazioni sensibili hardcoded nell'applicazione.

Vantaggi di HashiCorp Vault per la Gestione dei Segreti

  • Storage Centralizzato per i Segreti: Previene la presenza di segreti hardcoded nel codice, riducendo la superficie di attacco.
  • Credenziali Dinamiche: Genera credenziali temporanee, minimizzando i rischi di sicurezza.
  • Audit e Conformità: I log di audit integrati aiutano a monitorare gli accessi e a soddisfare i requisiti normativi.

Panoramica dell'Architettura di Sistema

Componenti dell'Architettura Un tipico setup di Vault in produzione con Spring Boot comprende:

  • Applicazione Spring Boot: Il framework microservizi principale basato su Java.
  • Vault Agent: Intermediario sul server di produzione dove gira Spring Boot, che recupera i segreti dal server Vault.
  • Server Vault: Gestisce e memorizza i segreti in modo sicuro.
  • Database SQL: Backend che contiene i dati dell'applicazione e richiede accesso sicuro tramite credenziali dinamiche.

Diagramma del Flusso dei Segreti I seguenti passaggi illustrano come i segreti vengono recuperati e utilizzati:

  1. Spring Boot richiede credenziali dal Vault Agent.
  2. Il Vault Agent si autentica al server Vault e recupera i segreti necessari.
  3. Le credenziali vengono iniettate in modo sicuro nell'applicazione, che poi si connette al database SQL.

Autenticazione e Rischi di Sicurezza

Rischi nella Memorizzazione delle Credenziali Memorizzare nomi utente e password in chiaro o in file di configurazione può esporli agli attacchi, creando un rischio significativo per la sicurezza.

Strategie di Mitigazione

  • Evitare Credenziali Statiche: Utilizzare credenziali dinamiche anziché nomi utente e password hardcoded.
  • Autenticazione AppRole: Il metodo AppRole di Vault consente l'autenticazione non interattiva con token dinamici, migliorando la sicurezza.
  • Secret Wrapping: Vault può incapsulare i segreti in un token a tempo limitato per passare in modo sicuro le credenziali tra i sistemi.

Vault Agent e Integrazione Sicura

Configurare il Vault Agent in un Ambiente di Produzione In un ambiente di produzione, il Vault Agent è distribuito sullo stesso server dell'applicazione Spring Boot, mentre il server Vault si trova su una macchina separata. Tutte le comunicazioni tra il Vault Agent, il server Vault e il database SQL sono sicure tramite crittografia TLS.

Environments Setup Overview
Environment overview

Panoramica del Setup dell'Ambiente:

  • Server Vault (IP: 192.168.101.1): Gestisce i segreti e li fornisce in modo sicuro alle applicazioni autorizzate.
  • Vault Agent (IP: 192.168.101.2): Intermediario sul server di produzione dove gira Spring Boot, che recupera i segreti dal server Vault.
  • Database SQL (IP: 192.168.101.3): Memorizza i dati dell'applicazione, accessibili tramite credenziali gestite da Vault.
  • Crittografia TLS: Garantisce la privacy e l'integrità dei dati nelle comunicazioni tra i componenti di Vault.

Esempio di Configurazione del Vault Agent: Ecco come configurare il Vault Agent sul server di produzione (192.168.101.2) per recuperare in modo sicuro i segreti dal server Vault (192.168.101.1) tramite TLS.


auto_auth { method "approle" { mount_path = "auth/approle" config = { role_id_file_path = "/etc/vault/role_id" secret_id_file_path = "/etc/vault/secret_id" } } } cache { use_auto_auth_token = true } listener "tcp" { address = "0.0.0.0:8200" tls_cert_file = "/etc/vault-agent/certs/vault-agent.crt" tls_key_file = "/etc/vault-agent/certs/vault-agent.key" tls_client_ca_file = "/etc/vault-agent/certs/ca.crt" } vault { address = "https://192.168.101.1:8200" }

Integrazione di Spring Boot in Produzione

L'applicazione Spring Boot in esecuzione su 192.168.101.2 comunica con il Vault Agent per recuperare in modo sicuro le credenziali dinamiche.

Esempio: Proprietà dell'Applicazione per l'Integrazione con Vault:


spring: cloud: vault: uri: https://127.0.0.1:8200 # Vault Agent local communication authentication: APPROLE token: ${VAULT_TOKEN}

Configurazione di Vault per la Memorizzazione dei Segreti e l’Impostazione di HTTPS





Memorizzazione dei Segreti per Spring Boot

Per memorizzare segreti, come le credenziali del database, in Vault e recuperarli in modo sicuro in un'applicazione Spring Boot, segui questi passaggi:

Step 1: Abilitare il Motore dei Segreti KV

vault secrets enable kv
 

Step 2: Memorizzare i Segreti

vault kv put secret/myapp/db username="myuser" password="mypassword"

Step 3: Configurare Spring Boot per Recuperare i Segreti

spring: cloud: vault: kv: enabled: true uri: https://192.168.101.1:8200 authentication: APPROLE token: ${VAULT_TOKEN} kv: backend: secret

Abilitare HTTPS su Vault

Per abilitare HTTPS e garantire comunicazioni sicure tra Vault, Vault Agent e Spring Boot, è necessario configurare Vault con certificati SSL.

Step 1: Generare Certificati SSL

openssl req -x509 -newkey rsa:4096 -keyout vault.key -out vault.crt -days 365 -nodes
 

Step 2: Configurare Vault per HTTPS


listener "tcp" { address = "0.0.0.0:8200" tls_cert_file = "/etc/vault/vault.crt" tls_key_file = "/etc/vault/vault.key" } storage "file" { path = "/vault/data" }

Step 3: Avviare Vault con HTTPS


vault server -config=/etc/vault/config.hcl
 

Configurazione di Vault per il Motore di Transito (Crittografia e Decrittografia)



Il motore Transit di Vault è progettato per operazioni crittografiche come la crittografia e la decrittografia dei dati. Di seguito sono riportati i passaggi per configurare Vault per gestire la crittografia e la decrittografia utilizzando la chiave di crittografia my-encryption-key.

Step 1: Abilitare il Motore dei Segreti Transit


Per abilitare il motore dei segreti Transit, usa il CLI di Vault. Questo motore è responsabile della gestione delle chiavi di crittografia e dell’esecuzione delle operazioni crittografiche come la crittografia e la decrittografia dei dati.
vault secrets enable transit
 

This command enables the Transit Secrets Engine at the default path, transit/. If you want to enable it at a custom path, you can specify that with the -path flag, but for simplicity, we’ll stick with the default.

Step 2: Creare una Chiave di Crittografia 

Dopo aver abilitato il motore Transit, il passaggio successivo è creare una chiave di crittografia chiamata my-encryption-key. Questa chiave verrà utilizzata dall'applicazione Spring Boot per crittografare e decrittografare i dati.

vault write -f transit/keys/my-encryption-key
 

This command creates a named encryption key (my-encryption-key) under the Transit engine. By default, the key is generated with 256-bit AES-GCM encryption. You can customize the key type by specifying additional parameters if needed.

Step 3: Configurare le Autorizzazioni della Chiave 

Per assicurarti che la chiave sia utilizzabile sia per la crittografia che per la decrittografia, devi configurare le autorizzazioni appropriate. Vault gestisce automaticamente la chiave e traccia il suo utilizzo.Abilitare la Crittografia: La chiave è pronta per crittografare i dati una volta creata.
Abilitare la Decrittografia: Per impostazione predefinita, Vault abilita sia la crittografia che la decrittografia.

Puoi verificare lo stato e la configurazione della chiave con:

vault read transit/keys/my-encryption-key

 

Step 4: Utilizzare la Chiave per Crittografia e Decrittografia

Crittografare i Dati

To encrypt data using the my-encryption-key:

curl --header "X-Vault-Token: $VAULT_TOKEN" \ --request POST \ --data '{"plaintext": "VGhpcyBpcyBhIHNlY3JldCBtZXNzYWdl"}' \ https://192.168.101.1:8200/v1/transit/encrypt/my-encryption-key
 

Nella richiesta precedente:

  • Il campo plaintext contiene i dati codificati in base64 da crittografare (VGhpcyBpcyBhIHNlY3JldCBtZXNzYWdl è "This is a secret message" in Base64).

  • Il server Vault risponde con una stringa di ciphertext.

Decrittografare i Dati

To decrypt the data using the same key:


curl --header "X-Vault-Token: $VAULT_TOKEN" \ --request POST \ --data '{"ciphertext": "vault:v1:i8NjUu..."}' \ https://192.168.101.1:8200/v1/transit/decrypt/my-encryption-key
 

Nella richiesta precedente:

  • Il campo ciphertext contiene la stringa criptata restituita da Vault durante il processo di crittografia.

Implementare Crittografia e Decrittografia in Spring Boot

Una volta configurato il server Vault, puoi integrare la crittografia e la decrittografia nella tua applicazione Spring Boot. Ecco il codice Java per crittografare e decrittografare i dati:



import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import org.springframework.http.ResponseEntity; import org.springframework.web.client.HttpClientErrorException; import java.util.Base64; import java.util.HashMap; import java.util.Map; @Service public class VaultEncryptionService { @Autowired private RestTemplate restTemplate; private static final String VAULT_TRANSIT_ENCRYPT_URL = "https://192.168.101.1:8200/v1/transit/encrypt/my-encryption-key"; private static final String VAULT_TRANSIT_DECRYPT_URL = "https://192.168.101.1:8200/v1/transit/decrypt/my-encryption-key"; // Encrypt Data public String encryptData(String plaintext) { Map<String, String> requestBody = new HashMap<>(); requestBody.put("plaintext", Base64.getEncoder().encodeToString(plaintext.getBytes())); try { ResponseEntity<Map<String, Object>> response = restTemplate.postForEntity( VAULT_TRANSIT_ENCRYPT_URL, requestBody, Map.class); if (response.getBody() != null && response.getBody().containsKey("ciphertext")) { return (String) response.getBody().get("ciphertext"); } else { throw new RuntimeException("Encryption failed: no ciphertext returned"); } } catch (HttpClientErrorException e) { throw new RuntimeException("Error during encryption request: " + e.getResponseBodyAsString(), e); } } // Decrypt Data public String decryptData(String ciphertext) { Map<String, String> requestBody = new HashMap<>(); requestBody.put("ciphertext", ciphertext); try { ResponseEntity<Map<String, Object>> response = restTemplate.postForEntity( VAULT_TRANSIT_DECRYPT_URL, requestBody, Map.class); if (response.getBody() != null && response.getBody().containsKey("plaintext")) { String base64Decrypted = (String) response.getBody().get("plaintext"); return new String(Base64.getDecoder().decode(base64Decrypted)); } else { throw new RuntimeException("Decryption failed: no plaintext returned"); } } catch (HttpClientErrorException e) { throw new RuntimeException("Error during decryption request: " + e.getResponseBodyAsString(), e); } } }


Gestione del Token di Vault in Spring Boot

Il VAULT_TOKEN è una parte fondamentale del processo di autenticazione tra la tua applicazione Spring Boot e HashiCorp Vault. I token di Vault possono essere iniettati nella tua applicazione Spring Boot tramite variabili d'ambiente, rendendo il token disponibile a runtime senza hardcodificarlo nei file di configurazione, migliorando così la sicurezza.

Step 1: Configurare la Gestione del Token di Vault 

Esistono due metodi principali per gestire il VAULT_TOKEN in modo sicuro:

  1. Usare Vault Agent con Auto-Auth: Il Vault Agent si autentica con Vault e inietta automaticamente il token nell'ambiente.

  2. Impostare Manualmente la Variabile d'Ambiente: Il token può essere esportato come variabile d'ambiente durante il deployment.

Utilizzare Vault Agent per la Gestione del Token 

Il Vault Agent può essere configurato per autenticarsi automaticamente utilizzando AppRole (o un altro metodo) e gestire il ciclo di vita del token, inclusi il rinnovo automatico e la cache. Il Vault Agent recupererà un token da Vault e lo inietterà nell'ambiente, rendendolo disponibile per l'applicazione Spring Boot.
Ecco come configurare il Vault Agent per l'iniezione automatica del token:
auto_auth { method "approle" { mount_path = "auth/approle" config = { role_id_file_path = "/etc/vault/role_id" secret_id_file_path = "/etc/vault/secret_id" } } } cache { use_auto_auth_token = true } listener "tcp" { address = "127.0.0.1:8200" tls_disable = true } vault { address = "https://192.168.101.1:8200" token_file = "/etc/vault/token" }

In questa configurazione:

  • Il Vault Agent si autentica utilizzando AppRole con i file role_id e secret_id.
  • Il parametro token_file indica dove verrà memorizzato il token dopo un’autenticazione riuscita (/etc/vault/token).
  • Il token viene memorizzato nella cache e rinnovato automaticamente, garantendo che sia sempre disponibile senza intervento manuale.

Iniettare il Token in Spring Boot 

Una volta che il Vault Agent ha recuperato il token e lo ha scritto nel file token_file, puoi configurare Spring Boot per leggere il token da questo file o direttamente dall'ambiente:

export VAULT_TOKEN=$(cat /etc/vault/token)

Questo rende il VAULT_TOKEN disponibile come variabile d'ambiente.

2. Manually Setting the Vault Token as an Environment Variable

You can also export the Vault token directly as an environment variable when deploying your application. For example, in your CI/CD pipeline or server deployment script:

export VAULT_TOKEN="s.YOUR_VAULT_TOKEN"

In questo modo, il token viene passato in modo sicuro all'applicazione Spring Boot durante l'avvio.

Step 2: Iniettare il VAULT_TOKEN nelle Proprietà di Spring Boot

Nella tua applicazione Spring Boot, puoi fare riferimento alla variabile d'ambiente VAULT_TOKEN all'interno del file application.yml o application.properties:

spring: cloud: vault: uri: https://192.168.101.1:8200 authentication: APPROLE token: ${VAULT_TOKEN}

Spring Boot risolverà automaticamente il segnaposto ${VAULT_TOKEN} leggendo il valore dalla variabile d'ambiente esportata durante il deployment o gestita dal Vault Agent.

Step 3: Testare la Configurazione

Per verificare che il VAULT_TOKEN sia correttamente iniettato nell'applicazione, puoi eseguire il seguente comando:

echo $VAULT_TOKEN

Se il token è impostato correttamente, verrà stampato il token, e Spring Boot lo utilizzerà per autenticarsi con Vault.

Gestione del Rinnovo e della Scadenza del Token

Se utilizzi il Vault Agent, il token viene automaticamente rinnovato prima della scadenza, grazie ai meccanismi di auto-autenticazione e cache. Se gestisci manualmente il token, assicurati che venga rinnovato regolarmente tramite il tuo processo di CI/CD o deployment, poiché i token di Vault hanno una durata limitata (TTL).

Sfide e Considerazioni in Produzione:

  1. Latenza: Potrebbe esserci un leggero aumento della latenza se l'applicazione recupera frequentemente segreti da Vault. Per mitigare questo problema, puoi memorizzare i segreti in cache localmente nell'applicazione o utilizzare i meccanismi di cache integrati di Vault.
  2. Disponibilità di Vault: In ambienti di produzione, è fondamentale garantire un'elevata disponibilità di Vault. Puoi distribuire Vault in modalità altamente disponibile con Consul o utilizzare l'archiviazione Raft di Vault per garantire la disponibilità continua.
  3. Configurazioni di Sicurezza: TLS deve essere configurato per la comunicazione tra l'applicazione Spring Boot e Vault, soprattutto in produzione. Inoltre, l'utilizzo di metodi di autenticazione come AppRole o Kubernetes può fornire modi più sicuri per autenticare le applicazioni senza incorporare token statici nell'applicazione.

Conclusione

L'integrazione di HashiCorp Vault con Spring Boot garantisce una gestione sicura e centralizzata dei segreti in ambienti di produzione. Utilizzando le capacità di generazione dinamica delle credenziali e crittografia di Vault, gli sviluppatori possono ridurre il rischio di esposizione di dati sensibili, migliorando la sicurezza delle loro applicazioni.

Riferimenti:

Su di me

Sono appassionato di tecnologie IT. Se sei interessato a saperne di più o a rimanere aggiornato sui miei ultimi articoli, sentiti libero di connetterti con me su:


LinkedIn
Instagram
Personal Website

Non esitare a contattarmi attraverso queste piattaforme se hai domande!

Non vedo l'ora di conoscere i tuoi pensieri! 👇

Commenti

Post popolari in questo blog

Monitoraggio e Logging con Prometheus: Una Guida Pratica

Nozioni fondamentali sul monitoraggio di Grafana e Prometheus: configurazione, visualizzazione e avvisi con PromQL