Connessione SSL a PostgreSQL

PostgreSQL e' un potente DBMS relazionale Open Source noto per la robustezza e la ricchezza di funzionalita'. PostgreSQL supporta in modo nativo il protocollo SSL: e' quindi possibile accedere ai dati presenti sul DB con una connessione cifrata. Questo documento descrive i dettagli del funzionamento e della configurazione della base dati PostgreSQL utilizzando il protocollo SSL per la trasmissione dei dati.
Questa pagina ha un taglio pratico e presenta esempi di diverse configurazioni tuttavia non e' un documento introduttivo ed e' consigliato ad un pubblico informaticamente adulto...

Un documento introduttivo su PostgreSQL e' Introduzione a PostgreSQL, mentre un documento piu' completo e' Qualcosa in piu' su PostgreSQL. Per una documentazione completa della teoria e dettagli specifici si rimanda alla documentazione PostgreSQL ufficiale.

Architettura PostgreSQL

Un breve accenno all'architettura di PostgreSQL puo' essere utile...
Architettura PostgreSQL Il processo postmaster e' il processo principale che si occupa della gestione delle connessioni ed e' il "padre" di tutti i processi, sia di sistema (eg. wal writer) sia quelli relativi alle connessione utente. Tutti i processi girano come utente postgres ed eseguono un attach al segmento di shared memory su cui vengono mantenuti buffer e lock.

I processi utente sono facilmente individuabili (eg. con il comando ps -efa) poiche' nella command line riportano il database utilizzato, l'IP(porta) del client e lo stato:

postgres 1692 1 0 Apr01 ? 00:01:03 /usr/pgsql-9.3/bin/postmaster -p 5432 -D /data postgres 1694 1692 0 Apr01 ? 00:00:04 postgres: logger process postgres 1696 1692 0 Apr01 ? 00:00:51 postgres: checkpointer process postgres 1697 1692 0 Apr01 ? 00:01:38 postgres: writer process postgres 1698 1692 0 Apr01 ? 00:01:45 postgres: wal writer process postgres 1699 1692 0 Apr01 ? 00:00:42 postgres: autovacuum launcher process postgres 1700 1692 0 Apr01 ? 00:08:19 postgres: stats collector process postgres 1874 1692 0 07:52 ? 00:00:00 postgres: test demo 10.0.1.69(35884) SELECT postgres 2566 1692 0 07:57 ? 00:00:00 postgres: test demo 10.0.1.70(35934) COMMIT postgres 3203 1692 0 08:05 ? 00:00:00 postgres: test demo [local] idle postgres 6969 1692 0 08:13 ? 00:00:00 postgres: test demo 10.0.1.77(35934) idle postgres 7296 1692 0 08:17 ? 00:00:00 postgres: test demo 10.0.1.73(35934) idle in transaction

La configurazione dei parametri di PostgreSQL si effettua modificando il file postgresql.conf mentre la configurazione degli accessi si effettua nel file pg_hba.conf e quindi a livello di database con i comandi SQL di GRANT.

Il processo postmaster e' in LISTEN sulla porta socket 5432 (per default ma puo' essere cambiata) e per ogni connessione utente attiva un processo.
Nella fase iniziale della connessione di un client vengono scambiati gli hash delle password (in modo crittografato se indicato nel file pg_hba) ma tutta la successiva trasmissione dati avviene in chiaro con il protocollo TCP.

La trasmissione in chiaro dei dati puo' essere accettabile quando si utilizzano reti dedicate e protette, come generalmente avviene tra application server e DB server, ma fornisce un livello molto basso di sicurezza. Nel caso in cui sia necessario un livello di sicurezza maggiore e' necessario effettuare la crittografazione dell'intera trasmissione dati con il protocollo SSL che PostgreSQL supporta in modo nativo. Ecco la ragione di questo documento!

SSL (TL;DR)

Abbiamo utilizzato fino ad ora il termine SSL ma e' sbagliato!
Un'avvertenza: ho inserito questo paragrafo per completezza, ma e' piuttosto criptico (ovviamente... dato l'argomento ;-): potete tranquillamente saltarlo!

Per essere precisi l'SSL (Secure Sockets Layer) e' il predecessore dell'attuale TLS (Transport Layer Security) e sono entrambe protocolli crittografici utilizzati per le comunicazioni sopra il livello di trasporto TCP (Transmission Control Protocol). L'utilizzo piu' comune e noto del TLS/SSL e' su web per garantire la sicurezza delle comunicazioni verso i siti (con il protocollo HTTPS), altrettanto importante e significativo e' l'uso del TLS/SSL nelle connessioni VPN, ... Per l'accesso alle basi dati e' molto meno utilizzato poiche' solitamente queste vengono poste su reti interne non raggiungibili da Internet.

TLS/SSL forniscono meccanismi per l'autenticazione, l'integrita' dei dati e la cifratura operando al di sopra del livello di trasporto [NdE il livello di trasporto e' il TCP]. Nella fase di avvio della comunicazione tra due nodi viene prima negoziato l'algoritmo da utilizzare, quindi vengono scambiate le chiavi di cifratura ed eseguita l'autenticazione. La fase di autenticazione avviene con lo scambio di chiavi asimmetriche (ovviamente viene inviata solo la chiave pubblica) e la verifica di certificati emessi da certificate authority (CA). Una volta instaurata la comunicazione i messaggi vengono cifrati con chiavi simmetriche ed verificati singolarmente con un checksum.

Per ogni fase vengono utilizzati protocolli diversi ed in ogni versione vengono aggiornati gli algoritmi (eliminando quelli che sono stati ricosciuti meno sicuri). Attualmente vengono utilizzati per lo scambio di chiavi: RSA, Diffie-Hellman, ECDH, ... per l'autenticazione: RSA, DSA, ECDSA, ... per la cifratura simmetrica: RC4, DES, Triple DES, AES, ... per la verifica d'integrita': in TLS sono utilizzati HMAC-MD5 o HMAC-SHA. Ad esempio con l'SSL per la verifica di integrita' venivano utilizzati anche: MD2, MD4, MD5 e SHA, ora ritenuti non sufficientemente sicuri.

Tutto chiaro? Probabilmente no... ma non importa! E' piu' semplice di quanto sembri: con il corretto utilizzo di TLS/SSL si e' certi dell'identita' del chiamato/chiamante, ogni messaggio viene verificato (e quindi non puo' essere modificato), ogni messaggio viene cifrato (e quindi non puo' essere letto da altri).

Configurazione

PostgreSQL supporta in modo nativo l'SSL quindi non e' necessario ricompilare programmi, installare componenti aggiuntivi o, naturalmente trattandosi di un database Open Source, acquistare licenze. E' solo necessario effettuare una corretta configurazione...

Poiche' vi sono diverse possibilita' di configurazione vediamo una prima configurazione di base e nei capitoli successivi vediamo come cambiarla!
Ecco i passi per configurare il protocollo SSL con un certificato self-signed:

# Tutti i file debbono essere nella data directory di PostgreSQL
cd $PGDATA

# Creamo una richiesta di un certificato
# Bisogna rispondere alle varie domande: e' importante che il Common Name sia l'FQDN del server
openssl req -new -text -out server.req

# Ora e' necessario rimuovere la passphrase
openssl rsa -in privkey.pem -out server.key
rm privkey.pem

# Generiamo il certificato self-signed
openssl req -x509 -in server.req -text -key server.key -out server.crt

# Le permission del file debbono essere molto ristrette altrimenti non vengono accettate
chmod og-rwx server.key

# Impostiamo l'SSL e riavviamo PostgreSQL (e' necessario un riavvio)
ssl = on

Con i passi eseguiti abbiamo generato un certificato server (file server.crt) ed una chiave privata (file server.key). Ora PostgreSQL accetta connessioni sia in chiaro che con SSL sulla porta 5432. E' il client che decide quale tipo di modalita' utilizzare... Tutti coloro che potevano collegarsi al DB ora possono farlo con un protocollo cifrato.

Client

Con le impostazioni effettuate fino ad ora e' il client che decide se utilizzare una connessione cifrata oppure in chiaro.
Il client imposta la sua scelta con il parametro sslmode che ha valori crescenti in termini di sicurezza e di peso computazionale: disable, allow, prefer, require, verify-ca, verify-full. Il significato dovrebbe essere chiaro!

Ecco come si configura la connessione SSL con classico tool di amministrazione pgAdmin: Opzioni SSL su pgAdmin

E' possibile effettuare una connessione SSL a PostgreSQL dalla maggior parte dei client... anche da psql:

$ psql "service=myservice sslmode=require" $ psql "postgresql://localhost:5432/test?sslmode=require"

pg_hba

E' venuto il momento per i DBA di decidere quando una connessione deve essere cifrata!

La configurazione si effettua nel file pg_hba.conf. Una riga di configurazione ha la forma:

host       database  user  address  auth-method  [auth-options]
host       database  user  IP-address  IP-mask  auth-method  [auth-options]

hostssl    database  user  address  auth-method  [auth-options]
hostssl    database  user  IP-address  IP-mask  auth-method  [auth-options]

Con la keyword host PostgreSQL accetta connessioni sia in chiaro che in SSL. Ma se si sostituisce la keyword con hostssl allora PostgreSQL consente solo una connessione cifrata con SSL al database/utente indicato.

In questo modo e' possibile proteggere database specifici, utenze particolari oppure, ed e' il caso piu' frequente, connessioni che provengono da reti esterne meno protette. E' disponibile anche la keyword hostnossl per indicare che PostgreSQL accetta connessioni solo in chiaro e hostgssenc per le connessioni GSSAPI [NdA GSSAPI (Generic Security Services Application Program Interface) e' un protocollo di autenticazione Kerberos].
Tra i metodi di autentificazione e' possibile indicare cert e nelle auth-options e' possibile indicare clientcert=verify-ca o clientcert=verify-full come vederemo nel prossimo capitolo!

Strong Authentication

Quando il gioco si fa duro...

Il certificato utilizzato nell'esempio precedente e' Self-Signed e non garantisce la massima sicurezza. Per essere garantiti che nessuno si sostituisca al DB server e' necessario un certificato emesso da una CA ufficiale, e' necessario che sul client venga caricato il certificato della root CA, e' necessario che venga utilizzato il parametro sslmode=verify-full.

E' possibile autorizzare i client con un livello di sicurezza maggiore rispetto a quello fornito dalla semplice coppia username/password. In questo caso ogni client deve avere un certificato, vanno inserte nel file root.crt le certificate authorities (CAs) ritenute valide, possono essere configurate le Certificate Revocation List (CRL) e va impostata l'opzione clientcert nel file pg_hba.conf [NdE tecnicamente questa e' la strong authentication cui si riferisce il titolo di questo paragrafo].

Il protocollo SSL e' disponibile da diversi anni e supportato da sempre in PostgreSQL, tuttavia e' comunque importante utilizzare le versioni piu' aggiornate. Sono molto recenti e gravi le scoperte di problemi su alcuni protocolli di cifratura e su alcune versioni SSL!

Chi?

E' importante per il DBA sapere quali connessioni sono cifrate e quali avvengono in chiaro. Dalla versione 9.5 in poi e' disponibile la vista pg_stat_ssl che riporta per ogni sessione (pid) se la connessione e' cifrata o meno (ssl), quale versione di SSL (version) e quale algoritmo di cifratura (cipher) sono utilizzati.
Naturalmente la colonna pid puo' essere utilizzata per eseguire un join con la pg_stat_activity ed ottenere ulteriori informazioni sulle sessioni utente.

Dalla versione 9.4 sul log delle connessioni vengono riportate informazioni sull'SSL:

LOG:  connection authorized: user=test database=test SSL enabled (protocol=TLSv1.1, cipher=DHE-RSA-AES256-SHA)

In tutte le versioni di PostgreSQL l'utente puo' conoscere se la propria sessione utilizza l'SSL o meno; per ottenere questa informazione e' disponibile l'estensione sslinfo. Una volta attivata [NdE e' banale: basta il comando create extension sslinfo; ] fornisce informazioni sulla connessione corrente e sull'eventuale certificato utilizzato per la connessione:

select ssl_is_used(), ssl_version(), ssl_cipher(), ssl_client_cert_present(); ssl_is_used()|ssl_version()| ssl_cipher() |ssl_client_cert_present -------------+-------------+------------------+----------------------- t| TLSv1|DHE-RSA-AES256-SHA| f

L'estensione sslinfo fornisce informazioni solo sulla sessione corrente e non su tutte le sessioni attive sul DB.

Su GitHub e' disponibile un'extension che rende l'informazione accessibile con una semplice query sulla vista pg_sslstatus (non essendo distribuita con PostgreSQL questa estensione va compilata ed installata nel proprio ambiente) [NdA non piu' utile dalla versione 9.5 di PostgreSQL].

Varie ed eventuali

L'utilizzo del protocollo SSL presenta notevoli vantaggi in termini di sicurezza ma ha i suoi costi.
La crittografazione ha un peso computazionale (con gli HW attuali difficimente e' un problema per lo scambio dei dati che utilizza chiavi simmetriche ma la fase di autenticazione e' notevolmente piu' lenta), la configurazione e' piu' complessa e richiede tempo, i certificati tipicamente hanno un costo ed una scadenza.

La scadenza dei certificati in particolare richiede una gestione attenta: quante volte e' successo di dover sostituire velocemente il certificato su un web server? Lo stesso puo' avvenire anche con i certificati per l'SSL di PostgreSQL!

Conclusioni

L'utilizzo di protocolli cifrati per la connessione a PostgreSQL aumenta in modo significativo la sicurezza dei dati ed e' quindi una soluzione quando si hanno dati sensibili da proteggere.
Le configurazioni in Cloud sono sempre piu' diffuse e questo presenta nuove sfide perche' tipicamente le basi dati venivano accedute solo da reti interne e protette, mentre con le configurazioni in Cloud gli accessi possono provenire da ambienti non controllati. In PostgreSQL con l'SSL si puo' proteggere in modo efficace la trasmissione dei dati anche se ospitati in Cloud.

Riassumendo la connessione SSL a PostgreSQL e' utile e questo documento ha cercato di dimostrare anche che e' facile da configurare!


Titolo: Connessione SSL a PostgreSQL
Livello: Esperto (4/5)
Data: 14 Febbraio 2016
Versione: 1.0.2 - 14 Febbraio 2021
Autore: mail [AT] meo.bogliolo.name