sql >> Base de Datos >  >> RDS >> PostgreSQL

Una descripción general de los parámetros de conexión libpq sslpassword de PostgreSQL 13

PostgreSQL desde hace mucho tiempo admite conexiones SSL y también mecanismos de autenticación basados ​​en certificados. Aunque nada en este sentido parece nuevo para el mundo de PostgreSQL. Sin embargo, un pequeño problema persistente para la conexión del cliente (autenticación basada en certificados de cliente) fue un mensaje "Ingrese la frase de contraseña PEM:" para la clave de cliente cifrada.

Una nueva función en PostgreSQL 13 complementa el parámetro de servidor 'ssl_passphrase_command'. Mientras que el parámetro ssl_passphrase_command permite a los administradores del servidor especificar una frase de contraseña para las claves de servidor cifradas utilizadas para los certificados de servidor; el parámetro de conexión recientemente introducido 'sslpassword' brinda un control algo similar para las conexiones de los clientes.

Una mirada a la infraestructura 

Para realizar un ejercicio práctico para este análisis de funciones, he establecido un sistema bastante básico:

  • Dos máquinas virtuales
    • pgServer ( 172.25.130.189 ) 
    • pgCliente  ( 172.25.130.178 )
  • Certificados autofirmados en pgServer
  • PostgreSQL 13 instalado en ambas máquinas 
  • gcc para compilar un programa libpq de muestra

Configuración del servidor 

Para analizar la característica, primero configuremos una instancia de servidor PostgreSQL 13 con certificados relevantes y la configuración respectiva en la máquina 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

Los comandos anteriores generan un certificado autofirmado utilizando una clave que está protegida por una frase de contraseña. Los permisos de server.key están restringidos según lo requiera PostgreSQL. Configurar la instancia de PostgreSQL para usar estos certificados no es mágico ahora. Primero cree una carpeta de DATOS base usando:

[[email protected]]$ initdb 

y pegue los siguientes parámetros de configuración en el postgresql.conf generado:

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'

Y también asegúrese de que se acepte una conexión SSL desde el nodo pgClient y pueda usar el mecanismo de autenticación de certificado pegando la siguiente línea en el pg_hba.conf generado:

hostssl    all     all             172.25.130.178/32       cert clientcert=1

Todo lo que se necesita ahora es iniciar el servidor con la configuración anterior usando el comando pg_ctl:

[[email protected]]$ pg_ctl start

Configuración del cliente 

El siguiente paso sería generar certificados de cliente que estén firmados por los certificados de servidor antes mencionados:

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

En el paso anterior, se generan una clave de cliente cifrada y una CSR para el certificado de cliente. Los siguientes pasos completan un certificado de cliente al firmarlo con el certificado raíz del servidor y la clave del servidor.

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

Un aspecto importante a recordar es el nombre CN en los certificados. Considérelo más como una identificación o Nombre de la entidad. En el certificado de cliente anterior, si el CN ​​se establece en 'postgres', está destinado a un rol llamado postgres. Además, al configurar el certificado del servidor, usamos CN=pgServer; puede importar cuando usamos un modo de verificación completa de conexión SSL.

Es hora de copiar los certificados en la máquina cliente para probar la conexión SSL:

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

De forma predeterminada en entornos Linux/Unix, cuando se utiliza psql para realizar conexiones SSL, busca certificados/claves en ‘${HOME}/.postgresql’ del usuario actual. Todos estos archivos también se pueden especificar en los parámetros de conexión; sin embargo, eso habría nublado lo que queremos probar.

En la máquina pgClient, cambie el permiso de postgresql.key para asegurarse de que PostgreSQL acepte lo mismo.

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

Prueba de la función 

Parámetro de conexión PSQL 

Ya casi hemos terminado con la configuración del entorno. Intentemos hacer una conexión SSL:

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

Enter PEM pass phrase:

¡Bien! Todo comenzó solo con el aviso anterior. Si tenemos un programa por lotes o un script de automatización, el indicador es un poco complicado de manejar. Con la nueva adición del parámetro 'contraseña ssl' en la cadena de conexión, ahora es fácil especificarlo como se muestra a continuación:

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

La conexión debería ser exitosa después de esto, sin ningún aviso.

Libpq Hook para contraseña SSL

La historia continúa:se agregó una función de enlace 'PQsetSSLKeyPassHook_OpenSSL' en la interfaz de Libpq. Esto puede ser utilizado por aplicaciones cliente que pueden no tener acceso a la frase de contraseña clave y necesitan generar/recuperar desde una interfaz externa usando alguna lógica compleja.

void PQsetSSLKeyPassHook_OpenSSL(PQsslKeyPassHook_OpenSSL_type hook);

Se puede registrar una función de devolución de llamada de tipo PQsslKeyPassHook_OpenSSL_type utilizando este enlace. Libpq invocará la devolución de llamada cuando necesite obtener una frase de contraseña. La firma de dicha función de devolución de llamada debe ser:

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

A continuación se muestra un programa de muestra 'client_conn.c', que demuestra la integración de dicho gancho:

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

}

Compila y ejecuta lo mismo para verificar si realmente funciona:

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

Una palabra final de precaución

El blog anterior muestra un cambio pequeño pero útil en los parámetros de conexión de Libpq/psql para la autenticación basada en certificados en PostgreSQL. Pero, una palabra de precaución:en el ejercicio práctico anterior hemos estado usando certificados autofirmados; puede que no encaje muy bien en su organización/entorno de producción. Puede buscar obtener algunos certificados de terceros para usar dicha configuración SSL.