Dans les deux précédentes parties (
pg_hba part1 et
pg_hba part2) nous avons vu comment accepter les connections à un serveur Postgresql en local sans mot de passe, puis avec mot de passe, puis via le réseau. Le point faible de l’accès via le réseau est qu’il n’était pas obligatoirement crypté. Pourtant dans les environnements où le serveur n’est pas dans un réseau totalement sous contrôle (comme dans les hébergements cloud) le cryptage s’impose. C’est donc ce que nous allons faire maintenant : configurer et activer l’authentification et le cryptage (via SSL) de notre
serveur Postgresql ET de notre
client pgAdmin.
1) pg_hba.conf
Il n’y a qu'un seul mot à changer dans le fichier pg_hba.conf !
Il suffit de remplacer «
host » par «
hostssl » et on obtient une ligne du type :
hostssl all all xx.xx.xx.xx/nn md5
NOTES:
- On parle ici de SSL, pas du SSH. Un tunnel SSH est une autre technique utilisée quand le serveur et/ou le client ne supportent pas le cryptage de manière native.
- Une ligne avec « host » accepte à la fois les connexions cryptées et non cryptées. Notre but étant de forcer le cryptage on ne doit pas garder de ligne « host » (sauf si elle est associée à des ip dont le chemin entre les clients et le serveur est totalement sous contrôle)
2) postgresql.conf
Là aussi pas grand-chose à faire. Il faut juste avoir la ligne «
ssl = on » (et pas de ligne ssl =off !)
NB: Quand tout sera finit il faudra redémarrer le service postgresql.
3) Clés SSL coté serveur
Postgresql a besoin d’au moins 2 fichiers (server.crt et server.key) dans son répertoire data (PGDATA) pour pouvoir accepter les connexions SSL. Comme le certificat du serveur sera signé par nous-même il n’y a pas besoin d’autres fichiers.
Le fichier
server.key contient la clé privée du serveur. Ce fichier est secret et doit appartenir au daemon postgres et n’être lisible que par lui. Sinon ça ne marche pas !
Le fichier
server.crt n’est pas secret, il contient le certificat du serveur. Il sera envoyé au client pour prouver l’identité du serveur. Il contient le nom du host où s’exécute Postgresql.
(voir plus bas le script bash
genSrvKeyCrt qui génère automatiquement ces deux fichiers)
4) Clés SLL coté client
pgAdmin (ou autre client de Postgresql acceptant SSL) a besoin d’au moins 3 fichiers (root.crt, user-name.key user-name.crt).
Là aussi, le fichier
user-name.key est une clé privée qui doit rester secrète et n’être lisible que par le client.
Le fichier
user-name.crt est le certificat de l’utilisateur coté Postgresql. Il sera envoyé au serveur pour prouver l’identité de l’utilisateur. Il contient le nom de l’utilisateur coté Postgresql qui n’est pas forcément le même que l’utilisateur Unix ou Windows)
Le fichier
root.crt est en fait exactement le même fichier que
server.crt que l’on a déjà vu coté serveur.
(voir plus bas le script bash
genCliKeyCrt qui génère automatiquement ces deux fichiers)
5) scripts + openssl
(ce qui suit est moins long qu'il ne parait ...)
Les deux fichiers coté serveur (server.crt et server.key) sont à générer en premier, et une fois pour toute. Le fichier server.crt coté serveur servant de root.crt coté client pour tous les utilisateurs, si on régénère les fichiers coté serveur il faut régénérer tous les certificats des utilisateurs.
Les deux fichiers coté client (user-name.key et user-name.crt) sont générés à la demande pour chaque utilisateur accepté par le serveur Postgresql. Ces fichiers étant associés à l’utilisateur de Postgresql ils peuvent être partagés par plusieurs utilisateurs Unix accédant à Postgresql de la même manière.
Pour simplifier la création de ces clés et certificats on va utiliser deux scripts shell qui enchaineront les commandes
openssl nécessaires pour générer tous ces fichiers.
On suppose que les deux scripts sont quelque part dans le PATH et que l'on travaille dans cette arborescence :
...
|
+--> server/
| +--> server.key
| +--> server.crt
|
+-- clients/
+--> user-name.key
+--> user-name.crt
+--> root.crt
En copiant les deux scripts ci-dessous attention à ne pas insérer d'espaces après les \ en fin de ligne.
======================
==== genSrvKeyCrt ====
======================
#!/bin/bash
HOST=$(hostname)
# Coté serveur on a besoin de deux fichiers.
# 1) server.key (clé privée du serveur)
# 2) server.crt (certificat/identité du serveur)
# 1.1) Création de la clé privé du serveur
openssl genrsa \
-des3 \
-out server.key \
-passout pass:1234 \
1024
# 1.2) Supprime la passphrase (1234) de la clé privé
openssl rsa \
-in server.key \
-out server.key \
-passin pass:1234
# 1.3) Vérification
openssl rsa -in server.key -check -noout
# 2.1) Création d'un certificat auto certifié d'une validité de 10 ans
openssl req \
-new \
-x509 \
-days 3650 \
-key server.key \
-out server.crt \
-subj "/OU=pgserver/CN=$HOST"
# 2.2) Vérification
openssl verify -CAfile server.crt server.crt
# Afficher le certificat (facultatif)
# openssl x509 -in server.crt -text -noout
### end ###
L’exécution donne ceci :
> cd /path/to/server
> GenSrvKeyCrt.sh
Generating RSA private key, 1024 bit long modulus
..................++++++
...++++++
e is 65537 (0x10001)
writing RSA key
RSA key ok
server.crt: OK
Copier
server.crt et
server.key dans le répertoire PGDATA du serveur Postgresql.
Veiller à ce qu'ils appartiennent à 'postgres' et qu'ils ne soit lisibles que par 'postgres'.
> ls -l /path/to/postgres/data/server.*
-rw------- 1 postgres postgres 769 Oct 24 19:56 /home/postgres/data/server.crt
-rw------- 1 postgres postgres 887 Oct 24 19:56 /home/postgres/data/server.key
REDEMARRER le service postgresql avec :
systemctl reload postgresql
======================
==== GenCliKeyCrt ====
======================
#!/bin/bash
if [ "$1" == "" ]; then
echo
echo " Usage: $0 pgUserName"
echo "Exemples: $0 jean"
echo " $0 postgres"
echo
exit
fi
PGUSER=$1
echo
echo "Création de la clé et du certificat pour $PGUSER"
echo
# Coté client on a besoin de 3 fichiers
# 1) root.crt (l’autorité de certification (nous!))
# 2) .key (clé privée de l'utilisateur)
# 3) .crt (certificat/identité de l'utilisateur)
# 1) importer root.crt du répertoire frère 'server'
cp ../server/server.crt root.crt
# 2.1) Création de la clé privée user-name.key pour le client
openssl genrsa \
-des3 \
-out $PGUSER.key \
-passout pass:1234 \
1024
# 2.2) Supprime la passphrase (1234) de la clé privée
openssl rsa \
-in $PGUSER.key \
-out $PGUSER.key \
-passin pass:1234
# 2.3) Vérification
openssl rsa -in $PGUSER.key -check -noout
# 3.1) Création du certificat user-name.crt pour le client
openssl req \
-new \
-key $PGUSER.key \
-out $PGUSER.csr \
-subj "/OU=pgclient/CN=$PGUSER"
# 3.2) Signature par le serveur du certificat du client
openssl x509 \
-req \
-CAcreateserial \
-in $PGUSER.csr \
-out $PGUSER.crt \
-CA root.crt \
-CAkey ../server/server.key
#fichier maintenant inutile
rm $PGUSER.csr
# 3.3) Vérifications
openssl verify -CAfile root.crt $PGUSER.crt
openssl verify -CAfile root.crt ../server/server.crt
# Affiche le certificat (facultatif)
# openssl x509 -in $PGUSER.crt -text -noout
### end ###
L’exécution donne ceci :
> cd /path/to/client
> GenCliKeyCrt.sh bidule
Création de la clé et du certificat pour bidule
Generating RSA private key, 1024 bit long modulus
...........................................++++++
..++++++
e is 65537 (0x10001)
writing RSA key
RSA key ok
Signature ok
subject=/OU=client/CN=bidule
Getting CA Private Key
bidule.crt: OK
../server/server.crt: OK
Copier les trois fichiers (
bidule.csr,
bidule.key,
root.crt) sur la machine client.
Puis configurer la partie SSL de pgAdmin comme indiqué ci-dessous.
La partie "Properties" est configurée comme d’habitude avec le nom du user (
bidule) et son password. Mais maintenant tout sera crypté et le serveur comme le client se seront authentifié car partageant le même
root.crt.
Le premier utilisateur pour le quel on fait tout cela est en général 'postgres' et non 'bidule' ;-)