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.