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.
[[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
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:
[[email protected]]$ 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:
[[email protected]]$ pg_ctl start
Menyiapkan Klien
Langkah selanjutnya adalah membuat sertifikat klien yang ditandatangani oleh sertifikat server yang disebutkan di atas:
[[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:
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.
[[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:
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:
[[email protected]]$ scp -r client_certs/* [email protected]:~/.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.
[[email protected]]$ chmod 0600 ~/.postgresql/postgresql.key
Menguji Fitur
Parameter Koneksi PSQL
Kami cukup banyak selesai dengan pengaturan lingkungan. Mari kita coba membuat Koneksi SSL:
[[email protected]]$ 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:
[[email protected]]$ 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:
[[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
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.