Guacamole sur un plateau épisode 4 sur 5

La recette est bientôt terminée !

Guacamole sur un plateau (4/5) : on sécurise la base de données

Guacamole sur un plateau épisode 4 sur 5

Abonnez-vous pour tout dévorer et ne rien manquer.

Déjà abonné ? Se connecter

Abonnez-vous

On avance sur l’installation de Guacamole et on touche au but. Maintenant que le serveur et le client sont installés, on passe à la sécurisation de la base de données. Dans le dernier épisode, on s’occupera de passer à deux facteurs pour l’authentification. Hé oui, la sécurité, c'est très important et pas à prendre à la légère.

Notre dossier sur Guacamole :

Sécurisons la connexion à la base de données

Si vous lancez tel quel, vous aurez un beau message d’erreur dans /var/log/tomcat9/catalina.out du genre :

[2023-10-19 20:38:32] [info] 20:38:32.407 [https-openssl-apr-8443-exec-8] ERROR o.a.g.rest.RESTExceptionMapper - Unexpected internal error:
[2023-10-19 20:38:32] [info] ### Error querying database.  Cause: java.sql.SQLNonTransientConnectionException: Could not connect to address=(host=localhost)(port=3306)(type=master) : (conn=31) Trying to connect with ssl, but ssl not enabled in the server
[2023-10-19 20:38:32] [info] ### The error may exist in org/apache/guacamole/auth/jdbc/user/UserMapper.xml
[2023-10-19 20:38:32] [info] ### The error may involve org.apache.guacamole.auth.jdbc.user.UserMapper.selectOne
[2023-10-19 20:38:32] [info] ### The error occurred while executing a query
[2023-10-19 20:38:32] [info] ### Cause: java.sql.SQLNonTransientConnectionException: Could not connect to address=(host=localhost)(port=3306)(type=master) : (conn=31) Trying to connect with ssl, but ssl not enabled in the server

Nous voulons une connexion TLS (SSL pour les nostalgiques) entre le serveur Tomcat et MariaDB. Or, par défaut, rien n’est chiffré. Si on va dans mysql, on voit :

MariaDB [(none)]> SHOW GLOBAL VARIABLES LIKE 'have_ssl';
+---------------+----------+
| Variable_name | Value |
+---------------+----------+
| have_ssl | DISABLED |
+---------------+----------+
1 row in set (0.002 sec)

Regardons la documentation Secure Connections Overview - MariaDB Knowledge Base.

Nous commençons par créer un certificat valide assez longtemps (on n’a pas besoin de changer tous les trois mois comme le certificat d’un site web exposé sur internet). Pas la peine de taper dans le grand luxe, un certificat autosigné conviendra très bien. Comme la communication va dans les deux sens, il en faut un pour le serveur, un pour le client.

On commence par se créer sa propre autorité de certification locale. La première étape est de créer une clé privée suffisamment robuste. Notez bien la passphrase pour cette clé privée, elle vous sera utile juste après.

root@r:~# cd /etc/mysql/certificates/ (à créer)
root@r:~# openssl genpkey -algorithm RSA -out ca-key.pem -aes256

On crée ensuite "l’autorité" à qui on fera les différentes demandes, en lui donnant une durée de vie de 2 ans (730 jours). Vous pouvez mettre ce que vous voulez dans les champs qui vous seront proposés à la saisie, cela n’a pas d’importance, à part pour le FQDN où je conseille de mettre le véritable hostname. Ça sera plus important pour les autres certificats servant à la sécurisation de la connexion SQL.

root@r:~# openssl req -x509 -new -nodes -key ca-key.pem -sha256 -out ca-cert.pem -days 730

On crée d’abord deux clés privées, une pour le serveur, une pour le client :

root@r:~# openssl ecparam -genkey -name secp384r1 -out client-key.pem
root@r:~# openssl ecparam -genkey -name secp384r1 -out server-key.pem

On fait deux demandes de certificats à notre autorité locale. Une précaution à prendre pour le paramètre hostname (ou FQDN) : mettez bien localhost, car sinon vous aurez une erreur lors de l’établissement de la connexion ! Évitez de mettre en mot de passe ici, il faudrait alors le renseigner à chaque lancement. Dans une infrastructure critique, on mettrait un secret stocké avec précaution (ailleurs, de préférence).

root@r:~# openssl req -new -key server-key.pem -out server-csr.pem
root@r:~# openssl req -new -key client-key.pem -out client-csr.pem

Et enfin on « émet » les certificats à l’aide de notre CA maison.

root@r:~# openssl x509 -req -in client-csr.pem -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out client-cert.pem -days 730 -extensions v3_ca
root@r:~# openssl x509 -req -in server-csr.pem -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -days 730 -extensions v3_ca

Et voilà !

On ajoute cela dans le fichier principal de configuration de la base de données, /etc/mysql/mariadb.cnf

[mariadb]
tls_version = TLSv1.2,TLSv1.3
ssl_cert = /etc/mysql/certificates/server-cert.pem
ssl_key = /etc/mysql/certificates/server-key.pem
ssl_ca = /etc/mysql/certificates/ca-cert.pem

[client-mariadb]
tls_version = TLSv1.2,TLSv1.3
ssl_cert = /etc/mysql/certificates/client-cert.pem
ssl_key = /etc/mysql/certificates/client-key.pem
ssl_ca = /etc/mysql/certificates/ca-cert.pem

Il faut ajuster les permissions pour le certificat serveur :

chmod og+x /etc/letsencrypt/live /etc/letsencrypt/archive
chown -R root:tomcat /etc/letsencrypt/live/[domaine] /etc/letsencrypt/archive/[domaine]
chmod +s /etc/letsencrypt/live/[domaine] /etc/letsencrypt/archive/[domaine]

Et comme Java fait bien les choses, il va vérifier que l’autorité de certification utilisée est connue par le système (ou plus précisément par le contexte Java qui est distinct de celui du système). Notre CA étant autosignée, elle ne figure donc pas dans la liste des autorités de confiance, et il faut que nous l’ajoutions.

Il faut l’ajouter dans le keystore (= fichier de certificats) utilisé pour ces autorités de certification.

root@r:~# keytool -cacerts -importcert -file ca-cert.pem

Un mot de passe vous sera demandé. Après de longues recherches sur internet, on trouve qu’il s’agit de changeit. Ça n’est pas une blague : il faut vraiment taper c-h-a-n-g-e-i-t (les 8 lettres) !

Arrivés à ce point, redémarrez mysql, et votre connexion sera chiffrée.

root@r:~# systemctl restart mysql
root@r:~# mysql
MariaDB [(none)]> SHOW GLOBAL VARIABLES LIKE 'have_ssl';
+---------------+----------+
| Variable_name | Value |
+---------------+----------+
| have_ssl | YES |
+---------------+----------+
1 row in set (0.002 sec)

Passons au client web

Vous aurez ensuite la chance de pouvoir admirer la mire d’authentification Guacamole, avec le numéro de version tout en bas. L’utilisateur par défaut est guacadmin:guacadmin, qu'il faut changer dès la première connexion.

Pour modifier le mot de passe par défaut, il faut aller dans “Préférences”. Attention : n’allez pas dans “Utilisateurs” (l’écran peut être trompeur).

Commentaires (9)


Pour une raison que j’ignore, il faut ajuster les permissions pour le certificat serveur.


La solution donnée (droits 755) me fait très mal aux yeux. Donner des droits d'exécution, et de lecture à tout le monde (et d'écriture pour le propriétaire), s'agissant d'une clé privée, ça fait mal d'un point de vue sécurité (et à plusieurs point de vue).

Je pense que le problème, c'est que le certificat est créé via l'utilisateur root. openssl, lors de la création des clés, génère un fichier avec des droits 600, c'est à dire que seul son propriétaire à les droits de lecture et d'écriture dessus (et encore heureux !).

Ici, les certificats sont générés en tant que root, mais les certificats serveurs sont utilisés par MariaDB. Et généralement (ça va dépendre des distributions) le serveur de base de données utilise un utilisateur / groupe qui lui est propre (mysql souvent).

Il faut donc soit changer le propriétaire du fichier, soit changer le groupe du fichier, et donner les droits appropriés. Ici, un truc comme ceci me parait beaucoup plus adapté :


chown root:mysql /etc/mysql/certificates/server-key.pem
chmod 640 /etc/mysql/certificates/server-key.pem


Le fichier server-key.pem reste la propriété de root, mais appartient au group mysql. On donne ensuite des droits en lecture / écriture pour le propriétaire, et de lecture pour le groupe.
Gros +1. Il y aura aussi vraisemblablement les droits sur le répertoires /etc/mysql/certificates à corriger, qui lui devrait être en root:mysql rwxr-x--- . Chiffrer la communication entre guacamole et mysql, alors qu’elle est locale, ne sert plus à grand chose si n’importe quel utilisateur local a accès à la clé privée (ça a toujours du sens si on est sur deux machines différentes).

Il y a le même soucis dans l’article précédent sur le certificat généré pour guacamole lui-même, qui devrait être en lecture pour l’utilisateur tomcat uniquement.

white_tentacle

Gros +1. Il y aura aussi vraisemblablement les droits sur le répertoires /etc/mysql/certificates à corriger, qui lui devrait être en root:mysql rwxr-x--- . Chiffrer la communication entre guacamole et mysql, alors qu’elle est locale, ne sert plus à grand chose si n’importe quel utilisateur local a accès à la clé privée (ça a toujours du sens si on est sur deux machines différentes).

Il y a le même soucis dans l’article précédent sur le certificat généré pour guacamole lui-même, qui devrait être en lecture pour l’utilisateur tomcat uniquement.
Arf, j'ai pas lu l'article précédent. J'avoue ^^

Mais oui, en tout cas, c'est important de bien sécuriser les clés. C'est d'autant plus important que l'idée des articles est de monter un bastion sécurisé !

Une clé privée (ou une clé de chiffrement symétrique) se doit de n'être accessible que par le minimum de monde. Et surtout pas exécutable :aie:
Modifié le 15/12/2023 à 13h29

fdorin

Arf, j'ai pas lu l'article précédent. J'avoue ^^

Mais oui, en tout cas, c'est important de bien sécuriser les clés. C'est d'autant plus important que l'idée des articles est de monter un bastion sécurisé !

Une clé privée (ou une clé de chiffrement symétrique) se doit de n'être accessible que par le minimum de monde. Et surtout pas exécutable :aie:
Egalement OK pour les certificats, par contre c'est un peu plus sioux d'après ce que j'ai vu, il faudrait faire :
root@r:/etc# chown -R tomcat /etc/letsencrypt/archive /etc/letsencrypt/live
Pour le droit exécutable, certbot himself les laisse... Je ne sais pas pourquoi, d'ailleurs.

Jean_G

Egalement OK pour les certificats, par contre c'est un peu plus sioux d'après ce que j'ai vu, il faudrait faire :
root@r:/etc# chown -R tomcat /etc/letsencrypt/archive /etc/letsencrypt/live
Pour le droit exécutable, certbot himself les laisse... Je ne sais pas pourquoi, d'ailleurs.
C’est encore un peu trop.

À priori, ceci devrait être suffisant:
chmod og+x /etc/letsencrypt/live /etc/letsencrypt/archive
chown -R root:tomcat /etc/letsencrypt/live/[domaine] /etc/letsencrypt/archive/[domaine]
chmod +s /etc/letsencrypt/live/[domaine] /etc/letsencrypt/archive/[domaine]

Le soucis est que contrairement à un apache en configuration standard, tomcat ne doit pas avoir les droits root au lancement et ensuite changer d’utilisateur, mais être directement lancé sous l’utilisateur tomcat. Du coup, impossible pour lui d’accéder au dossier de clés letsencrypt sans qu’on lui en donne explicitement la permission. Ici, on s’assure de ne le faire que pour le domaine qu’il gère.
Modifié le 15/12/2023 à 15h55
Le 755 est un mauvais réflexe de serveur web. Tout à fait d'accord avec la solution pour mysql. Je l'intègre dans l'article... dès que je peux. Seb, si tu nous écoutes ?

Jean_G

Le 755 est un mauvais réflexe de serveur web. Tout à fait d'accord avec la solution pour mysql. Je l'intègre dans l'article... dès que je peux. Seb, si tu nous écoutes ?
J’arriveeeeeeeee !

Sébastien Gavois

J’arriveeeeeeeee !
Et le droit à la déconnexion !?!
C'est pas une heure pour répondre ça !! 😂😂
Mais gg à tous.
Proposition pratique : il faudrait mettre à jour la liste des articles du dossier au début de chaque article de la série, parce que là c'est plus simple de revenir en arrière que d'avancer... On pourra commencer par le 1 et finir par le 5 \o/
Fermer