PostgreSQL již dlouho podporuje připojení SSL a také autentizační mechanismy založené na certifikátech. I když se v tomto ohledu zdá, že pro svět PostgreSQL není nic nového. Malým nepříjemným problémem pro připojení klienta (autentizace na základě klientských certifikátů) však byla výzva „Zadejte heslo PEM:“ pro šifrovaný klíč klienta.
Nová funkce v PostgreSQL 13 doplňuje parametr serveru 'ssl_passphrase_command'. Zatímco parametr ssl_passphrase_command umožňuje správcům serveru zadat přístupové heslo pro šifrované klíče serveru používané pro certifikáty serveru; nově zavedený parametr připojení „sslpassword“ poskytuje poněkud podobnou kontrolu pro klientská připojení.
Podívejte se na infrastrukturu
Abychom si prošli praktickým cvičením pro analýzu této funkce, vytvořil jsem docela základní systém:
- Dva virtuální stroje
- pgServer ( 172.25.130.189 )
- pgClient ( 172.25.130.178 )
- Certifikáty s vlastním podpisem na serveru pgServer
- PostgreSQL 13 nainstalovaný na obou počítačích
- gcc pro sestavení ukázkového programu libpq
Nastavení serveru
Abychom tuto funkci analyzovali, nastavme nejprve instanci serveru PostgreSQL 13 s příslušnými certifikáty a příslušnou konfigurací na virtuálním počítači 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
Výše uvedené příkazy generují certifikát s vlastním podpisem pomocí klíče, který je chráněn přístupovou frází. Oprávnění serveru.key jsou omezena tak, jak to vyžaduje PostgreSQL. Konfigurace instance PostgreSQL pro použití těchto certifikátů není nyní žádná magie. Nejprve vytvořte základní složku DATA pomocí:
[[email protected]]$ initdb
a vložte následující konfigurační parametry do vygenerovaného postgresql.conf:
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'
A také se ujistěte, že je akceptováno připojení SSL z uzlu pgClient a může používat mechanismus ověřování certifikátů vložením následujícího řádku do vygenerovaného souboru pg_hba.conf:
hostssl all all 172.25.130.178/32 cert clientcert=1
Nyní je potřeba pouze spustit server s výše uvedenou konfigurací pomocí příkazu pg_ctl:
[[email protected]]$ pg_ctl start
Nastavení klienta
Dalším krokem by bylo vygenerování klientských certifikátů, které jsou podepsány výše uvedenými serverovými certifikáty:
[[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:
Ve výše uvedeném kroku se vygeneruje zašifrovaný klientský klíč a CSR pro klientský certifikát. Následující kroky dokončí klientský certifikát jeho podepsáním pomocí kořenového certifikátu serveru a klíče serveru.
[[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:
Jeden důležitý aspekt, který je třeba si zapamatovat, je název CN v certifikátech. Považujte to spíše za identifikaci nebo název entity. Pokud je ve výše uvedeném klientském certifikátu CN nastaveno na „postgres“, je to určeno pro roli s názvem postgres. Při nastavování certifikátu serveru jsme také použili CN=pgServer; může záležet, když použijeme režim ověření plného připojení SSL.
Čas zkopírovat certifikáty do klientského počítače a vyzkoušet připojení SSL:
[[email protected]]$ scp -r client_certs/* [email protected]:~/.postgresql
Ve výchozím nastavení v prostředích Linux/Unix, když se psql používá k vytváření připojení SSL, hledá certifikát/klíče v „${HOME}/.postgresql“ aktuálního uživatele. Všechny tyto soubory lze také specifikovat v parametrech připojení - To by však zatemnilo věc, kterou chceme testovat.
Na počítači pgClient změňte oprávnění postgresql.key, abyste se ujistili, že PostgreSQL akceptuje totéž.
[[email protected]]$ chmod 0600 ~/.postgresql/postgresql.key
Testování funkce
Parametr připojení PSQL
S nastavením prostředí jsme téměř hotovi. Zkusme vytvořit připojení SSL:
[[email protected]]$ psql "host=172.25.130.189 port=5432 user=postgres dbname=postgres sslmode=prefer"
Enter PEM pass phrase:
No! Všechno to začalo pouze výše uvedenou výzvou. Pokud máme dávkový program nebo automatizační skript, je manipulace s výzvou trochu složitější. S novým přidáním parametru 'sslpassword' do připojovacího řetězce je nyní snadné jej specifikovat, jak je uvedeno níže:
[[email protected]]$ psql "host=172.25.130.189 port=5432 user=postgres dbname=postgres sslmode=prefer sslpassword=secretclientpass"
Po tomto by mělo být připojení úspěšné, bez jakékoli výzvy.
Libpq Hook pro heslo SSL
Příběh pokračuje – v rozhraní Libpq je přidána funkce zavěšení ‘PQsetSSLKeyPassHook_OpenSSL’. Toho mohou využívat klientské aplikace, které nemusí mít přístup ke klíčovému přístupovému slovu a potřebují generovat/načítat z externího rozhraní pomocí nějaké složité logiky.
void PQsetSSLKeyPassHook_OpenSSL(PQsslKeyPassHook_OpenSSL_type hook);
Funkci zpětného volání typu PQsslKeyPassHook_OpenSSL_type lze zaregistrovat pomocí tohoto háku. Zpětné volání zavolá Libpq, když potřebuje získat přístupovou frázi. Podpis takové funkce zpětného volání by měl být:
int my_callback_function(char *buf, int size, PGconn *conn);
Níže je jeden ukázkový program ‘client_conn.c’ – který demonstruje integraci takového háku:
#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;
}
Zkompilujte a spusťte totéž, abyste ověřili, zda to opravdu funguje:
[[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
Poslední upozornění
Výše uvedený blog ukazuje malou, ale užitečnou změnu v parametrech připojení Libpq/psql pro ověřování založené na certifikátech v PostgreSQL. Ale pozor - ve výše uvedeném praktickém cvičení jsme používali certifikáty s vlastním podpisem; nemusí se příliš hodit do vaší organizace/produkčního prostředí. Chcete-li používat takové nastavení SSL, můžete se pokusit získat nějaké certifikáty třetích stran.