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~~
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.
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
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
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 !
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 !
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 ...
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.
Cette erreur “ERROR 1045 (28000)…” revient systématiquement en cas de problème SSL. Les développeurs l'ont volontairement rendu peu parlante pour ne pas aider les vilains… Et effectivement, ça n'aide personne ! |
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';