PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Présentation des paramètres de connexion libpq sslpassword de PostgreSQL 13

PostgreSQL supporte depuis longtemps les connexions SSL ainsi que les mécanismes d'authentification basés sur des certificats. Bien que rien à cet égard ne semble être nouveau pour le monde PostgreSQL. Cependant, un petit problème persistant pour la connexion client (authentification basée sur les certificats client) était une invite "Entrez la phrase de passe PEM :" pour la clé client chiffrée.

Une nouvelle fonctionnalité dans PostgreSQL 13 complète le paramètre de serveur 'ssl_passphrase_command'. Alors que le paramètre ssl_passphrase_command permet aux administrateurs de serveur de spécifier une phrase de passe pour les clés de serveur chiffrées utilisées pour les certificats de serveur ; le nouveau paramètre de connexion 'sslpassword' donne un contrôle quelque peu similaire pour les connexions client.

Un regard sur l'infrastructure 

Pour faire un exercice pratique pour cette analyse des fonctionnalités, j'ai établi un système assez basique :

  • Deux machines virtuelles
    • pgServer ( 172.25.130.189 ) 
    • pgClient  ( 172.25.130.178 )
  • Certificats auto-signés sur pgServer
  • PostgreSQL 13 installé sur les deux machines 
  • gcc pour compiler un exemple de programme libpq

Configuration du serveur 

Pour analyser la fonctionnalité, configurons d'abord une instance de serveur PostgreSQL 13 avec les certificats pertinents et la configuration respective sur la machine virtuelle 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

Les commandes ci-dessus génèrent un certificat auto-signé à l'aide d'une clé protégée par une phrase secrète. Les autorisations de server.key sont restreintes comme requis par PostgreSQL. Configurer l'instance PostgreSQL pour utiliser ces certificats n'est plus une magie maintenant. Créez d'abord un dossier DATA de base en utilisant :

[[email protected]]$ initdb 

et collez les paramètres de configuration suivants dans le postgresql.conf généré :

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'

Et assurez-vous également qu'une connexion SSL du nœud pgClient est acceptée et peut utiliser le mécanisme d'authentification par certificat en collant la ligne suivante dans le pg_hba.conf généré :

hostssl    all     all             172.25.130.178/32       cert clientcert=1

Il ne reste plus qu'à démarrer le serveur avec la configuration ci-dessus à l'aide de la commande pg_ctl :

[[email protected]]$ pg_ctl start

Configuration du client 

La prochaine étape serait de générer des certificats client qui sont signés par les certificats serveur susmentionnés :

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

Dans l'étape ci-dessus, une clé client chiffrée et un CSR pour le certificat client sont générés. Les étapes suivantes complètent un certificat client en le signant à l'aide du certificat racine du serveur et de la clé du serveur.

[[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 aspect important à retenir est le nom CN dans les certificats. Considérez-le comme une identification ou un nom de l'entité. Dans le certificat client ci-dessus, si le CN est défini sur "postgres", il est destiné à un rôle nommé postgres. Lors de la configuration du certificat du serveur, nous avons également utilisé CN=pgServer ; cela peut avoir de l'importance lorsque nous utilisons un mode de vérification complète de la connexion SSL.

Il est temps de copier les certificats sur la machine cliente pour essayer la connexion SSL :

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

Par défaut sur les environnements Linux/Unix, lorsque psql est utilisé pour établir des connexions SSL, il recherche les certificats/clés dans '${HOME}/.postgresql' de l'utilisateur actuel. Tous ces fichiers peuvent également être spécifiés dans les paramètres de connexion - Cependant, cela aurait brouillé la chose que nous voulons tester.

Sur la machine pgClient, modifiez l'autorisation de postgresql.key pour vous assurer que PostgreSQL accepte la même chose.

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

Tester la fonctionnalité 

Paramètre de connexion PSQL 

Nous avons pratiquement terminé la configuration de l'environnement. Essayons d'établir une connexion SSL :

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

Enter PEM pass phrase:

Eh bien ! Tout a commencé avec l'invite ci-dessus uniquement. Si nous avons un programme batch ou un script d'automatisation, l'invite est légèrement délicate à gérer. Avec le nouvel ajout du paramètre 'sslpassword' dans la chaîne de connexion, il est maintenant facile de spécifier cela comme ci-dessous :

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

La connexion devrait réussir après cela, sans aucune invite.

Hook Libpq pour le mot de passe SSL

L'histoire continue - il y a l'ajout d'une fonction de crochet 'PQsetSSLKeyPassHook_OpenSSL' dans l'interface Libpq. Cela peut être utilisé par les applications clientes qui n'ont peut-être pas accès à la phrase secrète de la clé et doivent générer/récupérer à partir d'une interface externe à l'aide d'une logique complexe.

void PQsetSSLKeyPassHook_OpenSSL(PQsslKeyPassHook_OpenSSL_type hook);

Une fonction de rappel de type PQsslKeyPassHook_OpenSSL_type peut être enregistrée à l'aide de ce crochet. Le rappel sera invoqué par Libpq lorsqu'il aura besoin d'obtenir une phrase de passe. La signature d'une telle fonction de rappel doit être :

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

Vous trouverez ci-dessous un exemple de programme "client_conn.c" - qui illustre l'intégration d'un tel hook :

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

}

Compilez et exécutez la même chose pour vérifier si cela fonctionne vraiment :

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

Un dernier mot d'avertissement

Le blog ci-dessus montre un petit mais utile changement dans les paramètres de connexion Libpq/psql pour l'authentification basée sur les certificats dans PostgreSQL. Mais, un mot d'avertissement - dans l'exercice pratique ci-dessus, nous avons utilisé des certificats auto-signés ; il se peut qu'il ne s'intègre pas très bien dans votre organisation/environnement de production. Vous pouvez chercher à obtenir des certificats tiers pour utiliser une telle configuration SSL.