PostgreSQL sejak lama telah mendukung koneksi SSL dan juga mekanisme otentikasi berbasis sertifikat. Meskipun tidak ada hal baru dalam hal ini bagi dunia PostgreSQL. Namun, masalah kecil yang mengganggu untuk koneksi klien (otentikasi berbasis sertifikat klien) adalah prompt "Masukkan frasa sandi PEM:" untuk kunci klien terenkripsi.
Fitur baru di PostgreSQL 13 melengkapi parameter server 'ssl_passphrase_command'. Sementara parameter ssl_passphrase_command memungkinkan admin server untuk menentukan frasa sandi untuk kunci server terenkripsi yang digunakan untuk sertifikat server; parameter koneksi yang baru diperkenalkan 'sslpassword' memberikan kontrol yang agak mirip untuk koneksi klien.
Melihat Infrastruktur
Untuk melakukan latihan langsung untuk analisis fitur ini, saya telah membuat sistem yang cukup mendasar:
- Dua mesin virtual
- pgServer ( 172.25.130.189 )
- pgClient ( 172.25.130.178 )
- Sertifikat yang ditandatangani sendiri di pgServer
- PostgreSQL 13 diinstal di kedua mesin
- gcc untuk mengkompilasi contoh program libpq
Menyiapkan Server
Untuk menganalisis fitur ini, pertama-tama siapkan instance server PostgreSQL 13 dengan sertifikat yang relevan dan konfigurasi masing-masing pada mesin virtual pgServer.
[example@sqldat.com]$ echo ${HOME}
/var/lib/pgsql/
[example@sqldat.com]$ mkdir ~/server_certs/
[example@sqldat.com]$ openssl genrsa -des3 -passout pass:secretserverpass -out ~/server_certs/server.key
[example@sqldat.com]$ 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:
[example@sqldat.com]$ chmod 0600 /var/lib/pgsql/server_certs/server.key
[example@sqldat.com]$ cp ~/server_certs/server.crt ~/server_certs/root.crt Perintah di atas menghasilkan sertifikat yang ditandatangani sendiri menggunakan kunci yang dilindungi oleh frasa sandi. Izin server.key dibatasi seperti yang dipersyaratkan oleh PostgreSQL. Mengonfigurasi instance PostgreSQL untuk menggunakan sertifikat ini bukanlah hal yang ajaib sekarang. Pertama buat folder DATA dasar menggunakan:
[example@sqldat.com]$ initdb dan rekatkan parameter konfigurasi berikut di postgresql.conf yang dihasilkan:
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' Dan juga memastikan bahwa koneksi SSL dari node pgClient diterima dan dapat menggunakan mekanisme otentikasi sertifikat dengan menempelkan baris berikut di pg_hba.conf yang dihasilkan:
hostssl all all 172.25.130.178/32 cert clientcert=1 Yang diperlukan sekarang adalah menjalankan server dengan konfigurasi di atas menggunakan perintah pg_ctl:
[example@sqldat.com]$ pg_ctl start Menyiapkan Klien
Langkah selanjutnya adalah membuat sertifikat klien yang ditandatangani oleh sertifikat server yang disebutkan di atas:
[example@sqldat.com]$ mkdir ~/client_certs/
[example@sqldat.com]$ openssl genrsa -des3 -passout pass:secretclientpass -out ~/client_certs/postgresql.key
[example@sqldat.com]$ 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: Pada langkah di atas, kunci klien terenkripsi dan CSR untuk sertifikat klien dibuat. Langkah-langkah berikut menyelesaikan sertifikat klien dengan menandatanganinya menggunakan sertifikat akar Server dan Kunci Server.
[example@sqldat.com]$ 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: Satu aspek penting untuk diingat adalah nama CN dalam sertifikat. Anggap itu lebih merupakan identifikasi atau Nama entitas. Dalam sertifikat klien di atas, jika CN diatur ke 'postgres', itu dimaksudkan untuk peran bernama postgres. Juga saat menyiapkan sertifikat server, kami menggunakan CN=pgServer; mungkin penting ketika kami menggunakan mode verifikasi penuh dari Koneksi SSL.
Saatnya menyalin sertifikat ke mesin klien untuk mencoba Koneksi SSL:
[example@sqldat.com]$ scp -r client_certs/* example@sqldat.com:~/.postgresql Secara default di lingkungan Linux/Unix, ketika psql digunakan untuk membuat koneksi SSL, psql akan mencari sertifikat/kunci di '${HOME}/.postgresql' dari pengguna saat ini. Semua file ini juga dapat ditentukan dalam parameter koneksi - Namun, hal itu akan mengaburkan hal yang ingin kami uji.
Pada mesin pgClient, ubah izin postgresql.key untuk memastikan PostgreSQL menerima hal yang sama.
[example@sqldat.com]$ chmod 0600 ~/.postgresql/postgresql.key Menguji Fitur
Parameter Koneksi PSQL
Kami cukup banyak selesai dengan pengaturan lingkungan. Mari kita coba membuat Koneksi SSL:
[example@sqldat.com]$ psql "host=172.25.130.189 port=5432 user=postgres dbname=postgres sslmode=prefer"
Enter PEM pass phrase: Baiklah! Semuanya dimulai dengan prompt di atas saja. Jika kita memiliki program batch atau skrip otomatisasi, perintahnya sedikit rumit untuk ditangani. Dengan tambahan baru parameter 'sslpassword' di string koneksi, sekarang mudah untuk menentukannya seperti di bawah ini:
[example@sqldat.com]$ psql "host=172.25.130.189 port=5432 user=postgres dbname=postgres sslmode=prefer sslpassword=secretclientpass" Koneksi akan berhasil setelah ini, tanpa prompt apapun.
Libpq Hook untuk Kata Sandi SSL
Cerita berlanjut - ada penambahan fungsi kait 'PQsetSSLKeyPassHook_OpenSSL' di antarmuka Libpq. Ini dapat digunakan oleh aplikasi klien yang mungkin tidak memiliki akses ke frasa sandi kunci dan perlu dibuat/diambil dari antarmuka eksternal menggunakan beberapa logika kompleks.
void PQsetSSLKeyPassHook_OpenSSL(PQsslKeyPassHook_OpenSSL_type hook); Fungsi panggilan balik tipe PQsslKeyPassHook_OpenSSL_type dapat didaftarkan menggunakan kait ini. Panggilan balik akan dipanggil oleh Libpq saat membutuhkan frasa sandi. Tanda tangan dari fungsi panggilan balik tersebut harus:
int my_callback_function(char *buf, int size, PGconn *conn); Di bawah ini adalah salah satu contoh program 'client_conn.c' - yang mendemonstrasikan integrasi kait semacam itu:
#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;
} Kompilasi dan jalankan yang sama untuk memeriksa apakah itu benar-benar berfungsi:
[example@sqldat.com]$ gcc -DUSE_OPENSSL -I/usr/pgsql-13/include/ -lpq -L/usr/pgsql-13/lib/ client_conn.c -o client_conn
[example@sqldat.com]$ client_conn
[example@sqldat.com]$ ./client_conn
Server version: 130000 Perhatian Terakhir
Blog di atas menunjukkan perubahan kecil namun berguna dalam parameter koneksi Libpq/psql untuk otentikasi berbasis Sertifikat di PostgreSQL. Namun, sebuah kata peringatan - dalam latihan langsung di atas kami telah menggunakan sertifikat yang ditandatangani sendiri; itu mungkin tidak cocok dengan baik di organisasi / lingkungan produksi Anda. Anda mungkin mencari beberapa sertifikat pihak ketiga untuk menggunakan penyiapan SSL tersebut.