PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Eine Übersicht über PostgreSQL 13 libpq sslpassword-Verbindungsparameter

PostgreSQL unterstützt seit langem SSL-Verbindungen und auch zertifikatsbasierte Authentifizierungsmechanismen. Obwohl nichts in dieser Hinsicht neu für die PostgreSQL-Welt zu sein scheint. Ein kleines Problem für die Client-Verbindung (auf Client-Zertifikaten basierende Authentifizierung) war jedoch eine Aufforderung „Enter PEM pass phrase:“ für den verschlüsselten Client-Schlüssel.

Eine neue Funktion in PostgreSQL 13 ergänzt den Serverparameter „ssl_passphrase_command“. Während der Parameter ssl_passphrase_command es Serveradministratoren ermöglicht, eine Passphrase für verschlüsselte Serverschlüssel anzugeben, die für Serverzertifikate verwendet werden; der neu eingeführte Verbindungsparameter „sslpassword“ bietet eine ähnliche Kontrolle für Client-Verbindungen.

Ein Blick auf die Infrastruktur 

Um eine praktische Übung für diese Merkmalsanalyse durchzuführen, habe ich ein ziemlich einfaches System entwickelt:

  • Zwei virtuelle Maschinen
    • pgServer ( 172.25.130.189 ) 
    • pgClient  ( 172.25.130.178 )
  • Selbstsignierte Zertifikate auf pgServer
  • PostgreSQL 13 auf beiden Computern installiert 
  • gcc zum Kompilieren eines libpq-Beispielprogramms

Server einrichten 

Um die Funktion zu analysieren, richten wir zunächst eine PostgreSQL 13-Serverinstanz mit relevanten Zertifikaten und der entsprechenden Konfiguration auf der virtuellen pgServer-Maschine ein.

[[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

Die obigen Befehle generieren ein selbstsigniertes Zertifikat mit einem Schlüssel, der durch eine Passphrase geschützt ist. Die Berechtigungen von server.key sind wie von PostgreSQL gefordert eingeschränkt. Das Konfigurieren der PostgreSQL-Instanz für die Verwendung dieser Zertifikate ist jetzt keine Hexerei mehr. Erstellen Sie zuerst einen Basis-DATEN-Ordner mit:

[[email protected]]$ initdb 

und fügen Sie die folgenden Konfigurationsparameter in die generierte postgresql.conf ein:

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'

Stellen Sie außerdem sicher, dass eine SSL-Verbindung vom pgClient-Knoten akzeptiert wird und den Zertifikatauthentifizierungsmechanismus verwenden kann, indem Sie die folgende Zeile in die generierte pg_hba.conf einfügen:

hostssl    all     all             172.25.130.178/32       cert clientcert=1

Jetzt muss nur noch der Server mit der obigen Konfiguration mit dem pg_ctl-Befehl gestartet werden:

[[email protected]]$ pg_ctl start

Einrichten des Clients 

Der nächste Schritt wäre, Client-Zertifikate zu generieren, die von oben genannten Server-Zertifikaten signiert sind:

[[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:

Im obigen Schritt werden ein verschlüsselter Client-Schlüssel und ein CSR für das Client-Zertifikat generiert. Die folgenden Schritte vervollständigen ein Clientzertifikat, indem sie es mit dem Serverstammzertifikat und dem Serverschlüssel signieren.

[[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:

Ein wichtiger Aspekt ist der CN-Name in Zertifikaten. Betrachten Sie es eher als Identifikation oder Namen der Entität. Wenn im obigen Client-Zertifikat der CN auf „postgres“ gesetzt ist, ist er für eine Rolle mit dem Namen „postgres“ bestimmt. Auch beim Einrichten des Serverzertifikats haben wir CN=pgServer verwendet; es kann eine Rolle spielen, wenn wir einen Verifizierungsmodus der SSL-Verbindung verwenden.

Zeit zum Kopieren der Zertifikate auf den Client-Rechner, um die SSL-Verbindung auszuprobieren:

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

Wenn psql in Linux/Unix-Umgebungen zum Herstellen von SSL-Verbindungen verwendet wird, sucht es standardmäßig nach Zertifikaten/Schlüsseln in „${HOME}/.postgresql“ des aktuellen Benutzers. All diese Dateien können auch in Verbindungsparametern angegeben werden - Das hätte jedoch das, was wir testen möchten, getrübt.

Ändern Sie auf dem pgClient-Rechner die Berechtigung von postgresql.key, um sicherzustellen, dass PostgreSQL dasselbe akzeptiert.

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

Funktion testen 

PSQL-Verbindungsparameter 

Wir sind mit der Einrichtung der Umgebung ziemlich fertig. Versuchen wir, eine SSL-Verbindung herzustellen:

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

Enter PEM pass phrase:

Nun! Alles begann nur mit der obigen Aufforderung. Wenn wir ein Batch-Programm oder ein Automatisierungsskript haben, ist die Eingabeaufforderung etwas schwierig zu handhaben. Mit der neuen Hinzufügung des Parameters „sslpassword“ in der Verbindungszeichenfolge ist es jetzt einfach, dies wie folgt anzugeben:

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

Die Verbindung sollte danach ohne Nachfrage erfolgreich sein.

Libpq-Hook für SSL-Passwort

Die Geschichte geht weiter - in der Libpq-Schnittstelle wurde eine Hook-Funktion ‚PQsetSSLKeyPassHook_OpenSSL‘ hinzugefügt. Dies kann von Client-Anwendungen verwendet werden, die möglicherweise keinen Zugriff auf die Schlüssel-Passphrase haben und diese mithilfe einer komplexen Logik von einer externen Schnittstelle generieren/abrufen müssen.

void PQsetSSLKeyPassHook_OpenSSL(PQsslKeyPassHook_OpenSSL_type hook);

Mit diesem Hook kann eine Callback-Funktion vom Typ PQsslKeyPassHook_OpenSSL_type registriert werden. Der Rückruf wird von Libpq aufgerufen, wenn eine Passphrase benötigt wird. Die Signatur einer solchen Rückruffunktion sollte sein:

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

Unten ist ein Beispielprogramm ‚client_conn.c‘ - das die Integration eines solchen Hooks demonstriert:

#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;

}

Kompiliere dasselbe und führe es aus, um zu prüfen, ob es wirklich funktioniert:

[[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

Ein letztes Wort der Vorsicht

Der obige Blog zeigt eine kleine, aber nützliche Änderung der Libpq/psql-Verbindungsparameter für die zertifikatbasierte Authentifizierung in PostgreSQL. Aber ein Wort der Vorsicht – in der obigen praktischen Übung haben wir selbstsignierte Zertifikate verwendet; Es passt möglicherweise nicht sehr gut in Ihre Organisation / Produktionsumgebung. Sie können versuchen, Zertifikate von Drittanbietern zu erhalten, um eine solche SSL-Einrichtung zu verwenden.