PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Una panoramica dei parametri di connessione di PostgreSQL 13 libpq sslpassword

PostgreSQL da tempo supporta le connessioni SSL e anche i meccanismi di autenticazione basati su certificati. Anche se nulla al riguardo sembra essere nuovo per il mondo PostgreSQL. Tuttavia, un piccolo problema fastidioso per la connessione client (autenticazione basata su certificati client) era la richiesta "Inserisci passphrase PEM:" per la chiave client crittografata.

Una nuova funzionalità in PostgreSQL 13 completa il parametro del server 'ssl_passphrase_command'. Mentre il parametro ssl_passphrase_command consente agli amministratori del server di specificare una passphrase per le chiavi del server crittografate utilizzate per i certificati del server; il parametro di connessione appena introdotto 'sslpassword' offre un controllo in qualche modo simile per le connessioni client.

Uno sguardo all'infrastruttura 

Per eseguire un esercizio pratico per questa analisi delle caratteristiche, ho stabilito un sistema piuttosto semplice:

  • Due macchine virtuali
    • pgServer ( 172.25.130.189 ) 
    • pgClient  ( 172.25.130.178 )
  • Certificati autofirmati su pgServer
  • PostgreSQL 13 installato su entrambe le macchine 
  • gcc per compilare un programma libpq di esempio

Configurazione del server 

Per analizzare la funzionalità, configuriamo prima un'istanza del server PostgreSQL 13 con i relativi certificati e la rispettiva configurazione sulla macchina virtuale pgServer.

[[email protected]]$ echo ${HOME}

/var/lib/pgsql/

[[email protected]]$ mkdir ~/server_certs/ 

[[email protected]]$ openssl genrsa -des3 -passout pass:secretserverpass -out ~/server_certs/server.key

[[email protected]]$ openssl req -new -key ~/server_certs/server.key -days 365 -out ~/server_certs/server.crt -x509 -subj "/C=AU/ST=NSW/L=DY/O=MyOrg/OU=Dev/CN=pgServer"

Enter pass phrase for /var/lib/pgsql/server_certs/server.key:

[[email protected]]$ chmod 0600 /var/lib/pgsql/server_certs/server.key

[[email protected]]$ cp ~/server_certs/server.crt ~/server_certs/root.crt

I comandi precedenti generano un certificato autofirmato utilizzando una chiave protetta da una passphrase. Le autorizzazioni di server.key sono limitate come richiesto da PostgreSQL. Configurare l'istanza PostgreSQL per utilizzare questi certificati non è una magia ora. Per prima cosa crea una cartella DATA di base usando:

[[email protected]]$ initdb 

e incolla i seguenti parametri di configurazione nel postgresql.conf generato:

ssl=on

ssl_cert_file='/var/lib/pgsql/server_certs/server.crt'

ssl_key_file='/var/lib/pgsql/server_certs/server.key'

ssl_ca_file='/var/lib/pgsql/server_certs/root.crt'

ssl_passphrase_command = 'echo secretserverpass'

listen_addresses = '172.25.130.189'

E assicurati anche che una connessione SSL dal nodo pgClient sia accettata e possa utilizzare il meccanismo di autenticazione del certificato incollando la seguente riga nel pg_hba.conf generato:

hostssl    all     all             172.25.130.178/32       cert clientcert=1

Tutto ciò che serve ora è avviare il server con la configurazione precedente usando il comando pg_ctl:

[[email protected]]$ pg_ctl start

Configurazione del client 

Il passaggio successivo sarebbe generare certificati client che sono firmati dai suddetti certificati server:

[[email protected]]$ mkdir ~/client_certs/

[[email protected]]$ openssl genrsa -des3 -passout pass:secretclientpass -out ~/client_certs/postgresql.key

[[email protected]]$ openssl req -new -key ~/client_certs/postgresql.key -out ~/client_certs/postgresql.csr -subj "/C=AU/ST=NSW/L=DY/O=MyOrg/OU=Dev/CN=postgres"

Enter pass phrase for ~/client_certs/postgresql.key:

Nel passaggio precedente, vengono generate una chiave client crittografata e una CSR per il certificato client. I passaggi seguenti completano un certificato client firmandolo utilizzando il certificato radice del server e la chiave del server.

[[email protected]]$ openssl x509 -req -in ~/client_certs/postgresql.csr -CA ~/server_certs/root.crt -CAkey ~/server_certs/server.key -out ~/client_certs/postgresql.crt -CAcreateserial

Signature ok

subject=/C=AU/ST=NSW/L=DY/O=MyOrg/OU=Dev/CN=postgres

Getting CA Private Key

Enter pass phrase for /var/lib/pgsql/server_certs/server.key:

Un aspetto importante da ricordare è il nome CN nei certificati. Consideralo più un'identificazione o un nome dell'entità. Nel certificato client di cui sopra, se il CN è impostato su "postgres", è inteso per un ruolo denominato postgres. Inoltre, durante la configurazione del certificato del server, abbiamo utilizzato CN=pgServer; potrebbe essere importante quando utilizziamo una modalità di verifica completa della connessione SSL.

È ora di copiare i certificati sulla macchina client per provare la connessione SSL:

[[email protected]]$ scp -r client_certs/* [email protected]:~/.postgresql

Per impostazione predefinita su ambienti Linux/Unix, quando psql viene utilizzato per effettuare connessioni SSL, cerca certificato/chiavi in ​​'${HOME}/.postgresql' dell'utente corrente. Tutti questi file possono essere specificati anche nei parametri di connessione, tuttavia, ciò avrebbe offuscato la cosa che vogliamo testare.

Sulla macchina pgClient, cambia l'autorizzazione di postgresql.key per assicurarti che PostgreSQL accetti lo stesso.

[[email protected]]$ chmod 0600 ~/.postgresql/postgresql.key

Test della funzionalità 

Parametro di connessione PSQL 

Abbiamo praticamente finito con l'impostazione dell'ambiente. Proviamo a creare una connessione SSL:

[[email protected]]$ psql "host=172.25.130.189 port=5432 user=postgres dbname=postgres sslmode=prefer"

Enter PEM pass phrase:

Bene! Tutto è iniziato solo con il prompt di cui sopra. Se abbiamo un programma batch o uno script di automazione, il prompt è leggermente complicato da gestire. Con la nuova aggiunta del parametro 'sslpassword' nella stringa di connessione, ora è facile specificarlo come di seguito:

[[email protected]]$ psql "host=172.25.130.189 port=5432 user=postgres dbname=postgres sslmode=prefer sslpassword=secretclientpass"

Dopo questo, la connessione dovrebbe essere riuscita, senza alcun messaggio.

Libpq Hook per password SSL

La storia continua:è stata aggiunta una funzione di hook "PQsetSSLKeyPassHook_OpenSSL" nell'interfaccia di Libpq. Può essere utilizzato dalle applicazioni client che potrebbero non avere accesso alla passphrase della chiave e devono essere generate/prelevate da un'interfaccia esterna utilizzando una logica complessa.

void PQsetSSLKeyPassHook_OpenSSL(PQsslKeyPassHook_OpenSSL_type hook);

Una funzione di richiamata di tipo PQsslKeyPassHook_OpenSSL_type può essere registrata utilizzando questo hook. La richiamata verrà invocata da Libpq quando sarà necessario ottenere una passphrase. La firma di tale funzione di richiamata dovrebbe essere:

int my_callback_function(char *buf, int size, PGconn *conn);

Di seguito è riportato un programma di esempio 'client_conn.c' - che dimostra l'integrazione di tale hook:

#include <stdlib.h>

#include <string.h>

#include "libpq-fe.h"

void do_exit(PGconn *conn) {

    PQfinish(conn);

    exit(1);

}

/**

 * For PQsetSSLKeyPassHook_OpenSSL to provide password for SSL Key

 **/

int ssl_password_provider(char *buf, int size, PGconn *conn)

{    

    const char * default_key_password = "secretclientpass";

    strcpy(buf, default_key_password);

    return strlen(default_key_password);

}

/**

 * Sample program to make a connection and check server version

 */

int main() 

{

    PQsetSSLKeyPassHook_OpenSSL( ssl_password_provider );

    PGconn *conn = PQconnectdb("host=172.25.130.189 port=5413 user=postgres dbname=postgres sslmode=prefer");

    if (PQstatus(conn) == CONNECTION_BAD) 

    {

        fprintf(stderr, "Connection to DB failed: %s\n", PQerrorMessage(conn));

        do_exit(conn);

    }

    printf("Server version: %d\n", PQserverVersion(conn));

    PQfinish(conn);

    return 0;

}

Compila ed esegui lo stesso per verificare se funziona davvero:

[[email protected]]$ gcc -DUSE_OPENSSL  -I/usr/pgsql-13/include/ -lpq -L/usr/pgsql-13/lib/ client_conn.c -o client_conn

[[email protected]]$ client_conn

[[email protected]]$ ./client_conn

Server version: 130000

Un'ultima parola di cautela

Il blog sopra mostra una piccola ma utile modifica nei parametri di connessione Libpq/psql per l'autenticazione basata su certificati in PostgreSQL. Ma, una parola di cautela:nell'esercizio pratico di cui sopra abbiamo utilizzato certificati autofirmati; potrebbe non adattarsi molto bene alla tua organizzazione/ambiente di produzione. Potresti cercare di ottenere alcuni certificati di terze parti per utilizzare tale configurazione SSL.