Aller au contenu

Connexions TCP/IP sécurisées avec SSL - PostgreSQL

Objet

Un prérequis à cette installation est la présence d’openssl à la fois sur le système client et sur le système serveur. PostgreSQL doit aussi avoir été compilé avec le support SSL (--with-openssl). C’est généralement le cas pour tous les paquets binaires des différents OS et distributions supportés.

Il est possible de vérifier si cette option de compilation est activée sur des binaires déjà installés à l’aide de la commande suivante (chercher “ssl”) :

# chemin pour RedHat & dérivés
/usr/pgsql-14/bin/pg_config --configure

Configuration avec certificat auto-signé

Cette partie présente la mise en œuvre rapide de connexions SSL sur un serveur PostgreSQL sur la base d’un certificat auto-signé.

Préparation de l’installation

Génération d’un certificat auto signé

Les fichiers nécessaires doivent être créés dans le répertoire PGDATA, aussi une partie du travail sera exécuté dans ce répertoire.

[postgres@pgsql1 ]# cd /var/lib/pgsql/data

Les noms des fichiers seront ceux par défaut. Adapter au besoin les paramètres ssl_cert_file, ssl_key_file

On commence par générer une clé privée avec une “passphrase”.

[postgres@pgsql1 data]# openssl genrsa -out server.key 2048
Generating RSA private key, 2048 bit long modulus
...............................................................+++
........................................................................+++
e is 65537 (0x10001)

Il faut ensuite s’assurer que seul l’utilisateur postgres pourra accéder à cette clé, sinon PostgreSQL remontera une erreur :

[postgres@pgsql1 data]# chmod 400 server.key

Le certificat du serveur peut maintenant être généré :

[postgres@pgsql1 data]# openssl req -new -key server.key -days 3650 -out server.crt -x509 -subj '/C=FR/ST=Isere/L=Grenoble/O=Gilles'

Cette ligne de commande crée un certificat auto-signé (-x509) sauvegardé dans le fichier server.crt et valide pendant 10 ans (-days 3650).

L’option -subj permet de définir en ligne de commande les informations du certificat qui sont normalement demandées au prompt de l’utilisateur.

Comme le certificat est auto-signé, on utilise ce même certificat comme sa propre autorité de certification.

[postgres@pgsql1 data]# cp server.crt root.crt

Vous devez donc disposer de trois fichiers dans le PGDATA : server.key, server.crt, root.crt

Maintenant que le certificat serveur est généré, il ne reste qu’à configurer les accès SSL à PostgreSQL.

Activation du SSL

Pour que PostgreSQL active les connexions SSL, il faut modifier le fichier postgresql.conf :

ssl = true

A ce stade, comme nous avons déjà généré le certificat, il faut redémarrer le serveur PostgreSQL pour que l’activation de la directive ssl soit suivie d’effet (la commande de redémarrage peut varier selon la méthode d’installation) :

[root@pgsql1 ~]# systemctl restart postgresql-17

Si vous décidez de modifier le certificat, il faudra redémarrer à nouveau PostgreSQL car le certificat est lu et chargé uniquement au démarrage de PostgreSQL.

Pour plus d’information, reportez vous à la documentation : http://docs.postgresql.fr/current/ssl-tcp.html

Configuration des accès SSL

Le serveur écoutera les deux connexions, standard et SSL sur le même port TCP (5432 par défaut), et négociera avec tout client l’utilisation de SSL. Par défaut, le client peut choisir cette option ou pas.

Au niveau serveur, les autorisations de connexions SSL se font dans le fichier pg_hba.conf. Vous trouverez tous les détails et significations des paramétrages de ce fichier dans la documentation PostgreSQL (http://docs.postgresql.fr/current/client-authentication.html) et notamment sur hostnossl et hostssl.

Ce sont ces deux enregistrements qui sont utilisés dans notre exemple :

hostnossl  dbtestssl    all                     0.0.0.0/0             reject
hostssl    dbtestssl    my_ssl_user             192.168.1.138/32      md5

  • l’enregistrement hostnossl est utilisé pour intercepter toutes les tentatives de connexion à la base dbtestssl qui n’utilisent pas SSL et les rejeter ;
  • l’enregistrement hostssl est lui utilisé pour intercepter les seules tentatives de connexion par TCP/IP qui utilisent le chiffrement SSL, afin d’autoriser l’utilisateur my_ssl_user à se connecter à la base dbtestssl depuis la machine 192.168.1.138. Il s’agit là d’une connexion traditionnelle avec mot de passe mais encryptée.

À ce stade, la connexion est sécurisée pour tous les clients se connectant à l’instance PostgreSQL, mais il est possible d’aller plus loin en n’autorisant que les connexions munies d’un certificat de confiance (option d’authentification clientcert). L’exemple suivant modifie la seconde ligne pour autoriser sans saisie de mot de passe les connexions entrantes disposant d’un certificat SSL de confiance :

hostssl    dbtestssl    my_ssl_user             192.168.1.138/32      trust     clientcert=1

Les chapitres suivants décrivent comment mettre en œuvre cette connexion sans mot de passe.

Une fois la modification réalisée, la configuration PostgreSQL peut être rechargée (la commande de rechargement peut varier selon la méthode d’installation) :

/etc/init.d/postgresql reload

Génération des certificats clients

Pour que l’utilisateur my_ssl_user puisse établir une connexion SSL avec notre serveur PostgreSQL il va falloir lui créer un certificat de confiance que l’application cliente (psql, pgadmin, libpq…) pourra renvoyer à la demande du serveur. Toutes les opérations suivantes sont à réaliser sur le serveur PostgreSQL sur lequel le certificat serveur est installé.

On commence par créer la clé privée du certificat pour la machine cliente dans un fichier nommé postgresql.key :

[postgres@pgsql1 ~]# mkdir cert_my_ssl_user
[postgres@pgsql1 ~]# cd cert_my_ssl_user/
[postgres@pgsql1 cert_my_ssl_user]# openssl genrsa -out /tmp/postgresql.key 2048
Generating RSA private key, 2048 bit long modulus
......+++
.......+++
e is 65537 (0x10001)

Génération du certificat client pour 5 ans, soit 1825 jours (ce nombre de jours est indiqué par l’option -days) :

[postgres@pgsql1 cert_my_ssl_user]# openssl req -days 1825 -new -key /tmp/postgresql.key -out /tmp/postgresql.csr -subj '/C=FR/ST=Isere/L=Grenoble/O=Gilles/CN=my_ssl_user'

Signature du certificat avec notre autorité de confiance (root.crt) :

[postgres@pgsql1 cert_my_ssl_user]# openssl x509 -days 1825 -req -in /tmp/postgresql.csr -CA /var/lib/pgsql/data/root.crt -CAkey /var/lib/pgsql/data/server.key -out /tmp/postgresql.crt -CAcreateserial

On peut vérifier les informations du certificat de cette façon :

[postgres@pgsql1 cert_my_ssl_user]# openssl x509 -in /tmp/postgresql.crt -text

Copie des fichiers temporaires générés dans le répertoire courant :

[postgres@pgsql1 cert_my_ssl_user]# mv /tmp/postgresql.* .
[postgres@pgsql1 cert_my_ssl_user]# chmod 600 postgresql.key
[postgres@pgsql1 cert_my_ssl_user]# cp /var/lib/pgsql/data/root.crt .
[postgres@pgsql1 cert_my_ssl_user]# cd ..
[postgres@pgsql1 ~]# tar czf cert_myssluser.tar.gz cert_my_ssl_user/

Voilà, il ne reste plus qu’à envoyer l’archive générée avec le certificat du client pour qu’il puisse se connecter.

Installation sur le poste client

La section « Certificats des clients » de la documentation PostgreSQL décrit très bien le processus d’échange des certificats entre le client et le serveur.

Vous devez donc copier les fichiers de l’archive cert_myssluser.tar.gz dans le répertoire correspondant à votre OS et l’utilisateur de l’application. Par exemple pour faire un test depuis le répertoire HOME d’un utilisateur Unix :

tar xzf cert_myssluser.tar.gz
mv cert_my_ssl_user/ .postgresql/
chmod 600 .postgresql/postgresql.key

Et enfin connexion au serveur PostgreSQL :

psql "host=192.168.1.100 user=my_ssl_user port=5432 dbname=dbtestssl sslmode=verify-ca"

Sous Windows, il suffit de placer les fichiers dans le dossier : %APPDATA%\postgresql\, puis dans pgAdmin III créer une nouvelle connexion.

Configuration avec une autorité de certification

Configuration côté serveur

Sur le serveur PostgreSQL, générer une clé serveur et un certificat request avec la commande :

openssl req -nodes -newkey rsa:2048 -sha256 -keyout server.key -out server.csr

Deux fichiers sont produits : server.key et server.csr.

Il faut fournir le fichier server.csr généré à l’autorité de certification. Cette autorité donnera en retour un certificat serveur signé, nommé server.crt, ainsi que le certificat public de l’autorité signataire sous la forme du fichier root.crt.

Placer les trois fichiers server.crt, server.key et root.crt dans le répertoire de données du serveur ($PGDATA).

Modifier les droits sur le fichier server.key :

chmod 400 server.key

Activation du SSL

L’activation du SSL se déroule de la même façon que pour un certificat auto-signé, se référer à la section correspondante : Activation du SSL

Configuration des accès SSL

La configuration des accès SSL se déroule de la même façon que pour un certificat auto-signé, se référer à la section correspondante : Configuration des accès SSL

Génération des certificats clients

Générer une clé postgresql.key pour le client :

openssl genrsa -out /tmp/postgresql.key 2048

Générer un certificate request postgresql.csr pour le client, en complétant correctement le requestDN (option -subj) :

openssl req -days 730 -new -key /tmp/postgresql.key -out /tmp/postgresql.csr -subj '/C=FR/XXXXXX'

Envoyer le fichier postgresql.csr généré à l’autorité de certification. Elle réalise alors la signature et retourne un certificat client signé, nommé postgresql.crt.

Rassemblez les fichiers postgresql.key, postgresql.crt, ainsi que le certificat root.crt obtenu au moment de la configuration du serveur. Ils sont à placer sur le client.

Installation sur le client

La section “Certificats des clients” de la documentation PostgreSQL (https://docs.postgresql.fr/current/libpq-ssl.html#libpq-ssl-clientcert) décrit les emplacements par défaut à utiliser sur le client.

S’il s’agit d’un client sous Linux, on placera les trois fichiers dans le répertoire .postgresql dans le home de l’utilisateur sur la machine cliente.

S’il s’agit d’un client sous Windows il suffit de placer les fichiers dans le dossier : %APPDATA%\postgresql\, puis dans pg_admin III créer une nouvelle connexion pour valider la connexion.