Table des matières
MySQL et SSL
Vous avez rêvé … MySQL n'a rien de sécurisé.
On va installer SSL sur MySQL afin d'authentifier et chiffrer les échanges.
~~READMORE~~
Certificats
Auto-signé
Sur le serveur.
# cd /etc/mysql # mkdir certs # cd certs
Génération de clé privée:
# openssl genrsa 2048 > mysql-ca-key.pem
Certificat auto-signé:
# openssl req -new -x509 -nodes -days 3650 -key mysql-ca-key.pem -out mysql-ca-cert.pem ... Country Name (2 letter code) [AU]:FR State or Province Name (full name) [Some-State]: Locality Name (eg, city) []:Paris Organization Name (eg, company) [Internet Widgits Pty Ltd]:Eez.fr Corp. Organizational Unit Name (eg, section) []: Common Name (e.g. server FQDN or YOUR name) []:mail.local.eez.fr
Maintenant, on a 2 fichiers:
mysql-ca-key.pem mysql-ca-cert.pem
Le fichier “key” n'a pas être lisible par tous !
# chmod 0400 mysql-ca-key.pem
… qui va permettre de signer les autres certificats: serveur et clients.
Certificat du serveur
Créer les clefs pour le serveur:
# openssl req -newkey rsa:2048 -days 3650 -nodes -keyout mysql-server-key.pem -out mysql-server-req.pem
Transformer cette clé en RSA !? hein?
# openssl rsa -in mysql-server-key.pem -out mysql-server-key.pem writing RSA key
Signer:
# openssl x509 -req -in mysql-server-req.pem -days 3650 -CA mysql-ca-cert.pem -CAkey mysql-ca-key.pem -CAcreateserial -out mysql-server-cert.pem
“-CAcreateserial
” , la premiere fois, permet de créer un fichier (“mysql-ca-cert.srl”) qui va attribuer un “serial number
” a chaque certificat.
Le premier “serial” est créé aléatoirement , puis incrémenté avec chaque nouveau certificat.
Les droits:
Le fichier “key” n'a besoin d'être lisible que par “root” et “mysql”.
# chmod 0440 mysql-server-key.pem # chown :mysql mysql-server-key.pem
Certificat des clients
Créer les clefs pour les clients …
Client 1:
# openssl req -newkey rsa:2048 -days 3650 -nodes -keyout mysql-client_1-key.pem -out mysql-client_1-req.pem # openssl rsa -in mysql-client_1-key.pem -out mysql-client_1-key.pem
Client 2:
# openssl req -newkey rsa:2048 -days 3650 -nodes -keyout mysql-client_2-key.pem -out mysql-client_2-req.pem # openssl rsa -in mysql-client_2-key.pem -out mysql-client_2-key.pem
etc…
Signer les 2 clients:
# openssl x509 -req -in mysql-client_1-req.pem -days 3650 -CA mysql-ca-cert.pem -CAkey mysql-ca-key.pem -out mysql-client_1-cert.pem # openssl x509 -req -in mysql-client_2-req.pem -days 3650 -CA mysql-ca-cert.pem -CAkey mysql-ca-key.pem -out mysql-client_2-cert.pem
On peut toujours vérifier le contenu d'un certificat avec la commande:
# openssl x509 -in <CERTICAT> -noout -text
MySql serveur
conf
Dans /etc/mysql/conf.d/local.cnf
:
[mysqld] ssl-ca=/etc/mysql/certs/mysql-ca-cert.pem ssl-cert=/etc/mysql/certs/mysql-server-cert.pem ssl-key=/etc/mysql/certs/mysql-server-key.pem #ssl-crl=/etc/mysql/certs/mysql-server-revocation.pem
: Tester la revocation !
Tester vite
Si besoin, il faut redémarrer avec la nouvelle conf:
# /etc/init.d/mysql restart
Dans les logs, vérifier qu'on a pas :
Apr 11 02:07:09 mail mysqld: SSL error: Unable to get private key from '/etc/mysql/certs/mysql-server-key.pem'
… parce que MySQL est en train d'ignorer votre configuration SSL: votre fichier étant illisible.
Pour moi, c'était parce que j'avais oublié la ligne “magique”:
# openssl rsa -in <server-key>.pem -out <server-key>.pem
Sinon, vérifier comme cela:
$ mysql -u root -p mysql> show variables like '%ssl%'; +---------------+----------------------------------------+ | Variable_name | Value | +---------------+----------------------------------------+ | have_openssl | YES | | have_ssl | YES | | ssl_ca | /etc/mysql/certs/mysql-ca-cert.pem | | ssl_capath | | | ssl_cert | /etc/mysql/certs/mysql-server-cert.pem | | ssl_cipher | | | ssl_key | /etc/mysql/certs/mysql-server-key.pem | +---------------+----------------------------------------+ 7 rows in set (0.00 sec)
Si “have_openssl
” ou “have_ssl
” sont sur “DISABLED
”, alors le SSL n'est toujours pas activé ! Une erreur s'est glissé quelque part !
Client en SSL
Aprés avoir transmis les 3 fichiers qui vont bien, on peut déjà ce connecter en SSL.
$ mysql -h <HOST> -u <USER> -p <DATABASE> \ --ssl-ca=mysql-ca-cert.pem \ --ssl-cert=mysql-client_1-cert.pem \ --ssl-key=mysql-client_1-key.pem
… mais rien ne nous force, encore, a utiliser SSL.
mysql> status ... SSL: Cipher in use is DHE-RSA-AES256-SHA ...
SSL seulement
GRANT
mysql> GRANT SELECT ON <DATABASE>.* TO <USER>@'%' IDENTIFIED BY '<PASSWORD>' REQUIRE SSL;
<DATABASE> | le nom de la base de données |
<USER> | l'utilisateur |
<PASSWORD> | le mot de passe |
$ mysql -h <HOST> -u <USER> -p <DATABASE> Enter password: ERROR 1045 (28000): Access denied for user 'trouduc'@'mx0.local.eez.fr' (using password: YES)
Maintenant, on est obligé d'utiliser SSL pour ce connecter.
Les développeurs l'ont volontairement rendu peu parlante pour ne pas aider les vilains… Et effectivement, ça n'aide personne ! |
X509
Remplacer SSL
par X509
, mais ce n'est pas trés utile comme cela.
On va forcer une vérification du “Issuer
” ou du “Subject
” dans le certificat du client.
Pour extraire le “Issuer
” :
$ openssl x509 -issuer -noout -in <CLIENT_CERT>.pem
Pour extraire le “Subject
” :
$ openssl x509 -subject -noout -in <CLIENT_CERT>.pem
Exemple:
GRANT ALL PRIVILEGES ON <DATABASE>.* TO <USER>@'%' IDENTIFIED BY <PASSWORD> \ REQUIRE SUBJECT '/C=FR/ST=Some-State/L=Paris/O=xxx/OU=xxx/CN=xxx/emailAddress=xxx' \ AND ISSUER '/C=FR/ST=Some-State/L=Paris/O=xxx/OU=xxx/CN=xxx/emailAddress=xxx';