Dans cette série de blogs, nous allons vous expliquer comment configurer un serveur MariaDB entièrement chiffré pour le chiffrement au repos et en transit, afin d'assurer une protection maximale des données contre volé physiquement ou lors du transfert et de la communication avec d'autres hôtes. L'idée de base est que nous allons transformer notre déploiement "simple" en une réplication MariaDB entièrement chiffrée, comme simplifié dans le schéma suivant :
Nous allons configurer un certain nombre de composants de chiffrement :
- Chiffrement en transit, qui consiste en :
- Cryptage client-serveur
- Chiffrement de la réplication
- Chiffrement au repos, qui consiste en :
- Cryptage des fichiers de données
- Chiffrement du journal binaire/de relais.
Notez que cet article de blog ne couvre que le chiffrement en transit. Nous allons couvrir le chiffrement au repos dans la deuxième partie de cette série de blogs.
Cette procédure de déploiement supposait que nous disposions déjà d'un serveur de réplication MariaDB déjà en cours d'exécution. Si vous n'en avez pas, vous pouvez utiliser ClusterControl pour déployer une nouvelle réplication MariaDB en quelques minutes, en moins de 5 clics. Tous les serveurs fonctionnent sur MariaDB 10.4.11 sur le système CentOS 7.
Cryptage en transit
Les données peuvent être exposées à des risques à la fois en transit et au repos et nécessitent une protection dans les deux états. Le chiffrement en transit protège vos données si les communications sont interceptées pendant que les données se déplacent entre les hôtes via le réseau, soit depuis votre site et le fournisseur de cloud, entre les services ou entre les clients et le serveur.
Pour MySQL/MariaDB, les données sont en mouvement lorsqu'un client se connecte à un serveur de base de données ou lorsqu'un nœud esclave réplique les données d'un nœud maître. MariaDB prend en charge les connexions cryptées entre les clients et le serveur à l'aide du protocole TLS (Transport Layer Security). TLS est parfois appelé SSL (Secure Sockets Layer) mais MariaDB n'utilise pas réellement le protocole SSL pour les connexions cryptées car son cryptage est faible. Plus de détails à ce sujet sur la page de documentation de MariaDB.
Chiffrement client-serveur
Dans cette configuration, nous allons utiliser des certificats auto-signés, ce qui signifie que nous n'utilisons pas de parties externes telles que Google, Comodo ou tout autre fournisseur d'autorité de certification populaire pour vérifier notre identité. Dans SSL/TLS, la vérification de l'identité est la première étape qui doit être franchie avant que le serveur et le client n'échangent leurs certificats et leurs clés.
MySQL fournit un outil très pratique appelé mysql_ssl_rsa_setup qui s'occupe automatiquement de la génération de la clé et du certificat. Malheureusement, il n'existe pas encore d'outil de ce type pour le serveur MariaDB. Par conséquent, nous devons préparer et générer manuellement les fichiers liés à SSL pour nos besoins MariaDB TLS.
Ce qui suit est une liste des fichiers que nous allons générer à l'aide de l'outil OpenSSL :
- Clé CA - Clé privée RSA au format PEM. Doit être gardé secret.
- Certificat CA - Certificat X.509 au format PEM. Contient les métadonnées de la clé publique et du certificat.
- RSE du serveur - Demande de signature de certificat. Le Nom Commun (CN) lors du remplissage du formulaire est important, par exemple CN=mariadb-server
- Clé du serveur - Clé privée RSA. Doit être gardé secret.
- Certificat du serveur - Certificat X.509 signé par clé CA. Contient les métadonnées de la clé publique et du certificat.
- RSE client - Demande de signature de certificat. Doit utiliser un nom commun (CN) différent du CSR du serveur, par exemple CN=client1
- Clé client - Clé privée RSA. Doit être gardé secret.
- Certificat client - Certificat X.509 signé par clé CA. Contient les métadonnées de la clé publique et du certificat.
Tout d'abord, créez un répertoire pour stocker nos certificats et clés pour le chiffrement en transit :
$ mkdir -p /etc/mysql/transit/
$ cd /etc/mysql/transit/
Juste pour vous donner une idée de la raison pour laquelle nous nommons le répertoire comme mentionné, c'est parce que dans la prochaine partie de cette série de blogs, nous allons créer un autre répertoire pour le chiffrement au repos dans /etc/mysql/rest.
Autorité de certification
Générer un fichier clé pour notre propre autorité de certification (CA) :
$ openssl genrsa 2048 > ca-key.pem
Generating RSA private key, 2048 bit long modulus
.......................+++
...............................................................................................................................................................................................................................................+++
e is 65537 (0x10001)
Générer un certificat pour notre propre Autorité de Certification (CA) basé sur le ca-key.pem généré auparavant avec une expiration de 3650 jours :
$ openssl req -new -x509 -nodes -days 3650 -key ca-key.pem -out ca.pem
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:SE
State or Province Name (full name) []:Stockholm
Locality Name (eg, city) [Default City]:Stockholm
Organization Name (eg, company) [Default Company Ltd]:Severalnines
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:CA
Email Address []:[email protected]
Nous devrions maintenant avoir ca-key.pem et ca.pem sous ce répertoire de travail.
Clé et certificat pour le serveur
Ensuite, générez la clé privée pour le serveur MariaDB :
$ openssl genrsa 2048 > server-key.pem
Generating RSA private key, 2048 bit long modulus
.............................................................................................................+++
..................................................................................................................+++
e is 65537 (0x10001)
Un certificat de confiance doit être un certificat signé par une autorité de certification. Ici, nous allons utiliser notre propre autorité de certification car nous faisons confiance aux hôtes du réseau. Avant de pouvoir créer un certificat signé, nous devons générer un certificat de demande appelé Certificate Signing Request (CSR).
Créez un CSR pour le serveur MariaDB. Nous allons appeler le certificat en tant que server-req.pem. Ce n'est pas le certificat que nous allons utiliser pour le serveur MariaDB. Le certificat final est celui qui sera signé par notre propre clé privée CA (comme indiqué à l'étape suivante) :
$ openssl req -new -key server-key.pem -out server-req.pem
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:SE
State or Province Name (full name) []:Stockholm
Locality Name (eg, city) [Default City]:Stockholm
Organization Name (eg, company) [Default Company Ltd]:Severalnines
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:MariaDBServer
Email Address []:[email protected]
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Prenez note du nom commun où nous avons spécifié "MariaDBServer". Il peut s'agir de n'importe quel nom, mais la valeur ne doit pas être identique à celle du certificat client. Généralement, si les applications se connectent au serveur MariaDB via un FQDN ou un nom d'hôte (skip-name-resolve=OFF), vous souhaiterez probablement spécifier le FQDN du serveur MariaDB comme nom commun.
Nous pouvons ensuite générer le certificat X.509 final (server-cert.pem) et signer le CSR (server-req.pem) avec le certificat de l'AC (ca.pem) et la clé privée de l'AC (ca -key.pem):
$ openssl x509 -req -in server-req.pem -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -days 3650 -sha256
Signature ok
subject=/C=SE/ST=Stockholm/L=Stockholm/O=Severalnines/CN=MariaDBServer/[email protected]
Getting CA Private Key
À ce stade, voici ce que nous avons :
$ ls -1 /etc/mysql/transite
ca-key.pem
ca.pem
server-cert.pem
server-key.pem
server-req.pem
Nous n'avons besoin que du certificat CA (ca.pem), du certificat signé du serveur (server-cert.pem) et de la clé privée du serveur (server-key.pem) pour le serveur MariaDB. Le CSR (server-req.pem) n'est plus requis.
Clé et certificat pour le client
Ensuite, nous devons générer des fichiers de clé et de certificat pour le client MariaDB. Le serveur MariaDB n'acceptera que la connexion à distance du client qui possède ces fichiers de certificat.
Commencez par générer une clé de 2048 bits pour le client :
$ openssl genrsa 2048 > client-key.pem
Generating RSA private key, 2048 bit long modulus
.............................................................................................................+++
..................................................................................................................+++
e is 65537 (0x10001)
Créez un CSR pour le client appelé client-req.pem :
$ openssl req -new -key client-key.pem -out client-req.pem
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:SE
State or Province Name (full name) []:Stockholm
Locality Name (eg, city) [Default City]:Stockholm
Organization Name (eg, company) [Default Company Ltd]:Severalnines
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:Client1
Email Address []:[email protected]
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Faites attention au nom commun où nous spécifions "Client1". Spécifiez n'importe quel nom qui représente le client. Cette valeur doit être différente du nom commun du serveur. Pour une utilisation avancée, vous pouvez utiliser ce nom commun pour autoriser certains utilisateurs avec un certificat correspondant à cette valeur, par exemple :
MariaDB> GRANT SELECT ON schema1.* TO 'client1'@'192.168.0.93' IDENTIFIED BY 's' REQUIRE SUBJECT '/CN=Client2';
Nous pouvons ensuite générer le certificat X.509 final (client-cert.pem) et signer le CSR (client-req.pem) avec le certificat de l'AC (ca.pem) et la clé privée de l'AC (ca -key.pem):
$ openssl x509 -req -in client-req.pem -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out client-cert.pem -days 3650 -sha256
Signature ok
subject=/C=SE/ST=Stockholm/L=Stockholm/O=Severalnines/CN=Client1/[email protected]
Getting CA Private Key
Tous les certificats dont nous avons besoin pour la configuration du chiffrement en transit sont générés. Vérifiez que les deux certificats sont correctement signés par l'autorité de certification :
$ openssl verify -CAfile ca.pem server-cert.pem client-cert.pem
server-cert.pem: OK
client-cert.pem: OK
Configurer SSL pour MariaDB
Créez un nouveau répertoire sur chaque esclave :
(slave1)$ mkdir -p /etc/mysql/transit/
(slave2)$ mkdir -p /etc/mysql/transit/
Copiez les fichiers de chiffrement sur tous les esclaves :
$ scp -r /etc/mysql/transit/* [email protected]:/etc/mysql/transit/
$ scp -r /etc/mysql/transit/* [email protected]:/etc/mysql/transit/
Assurez-vous que le propriétaire du répertoire certs correspond à l'utilisateur "mysql" et modifiez les autorisations de tous les fichiers clés afin qu'il ne soit pas lisible globalement :
$ cd /etc/mysql/transit
$ chown -R mysql:mysql *
$ chmod 600 client-key.pem server-key.pem ca-key.pem
Voici ce que vous devriez voir lorsque vous répertoriez les fichiers sous le répertoire "transit" :
$ ls -al /etc/mysql/transit
total 32
drwxr-xr-x. 2 root root 172 Dec 14 04:42 .
drwxr-xr-x. 3 root root 24 Dec 14 04:18 ..
-rw-------. 1 mysql mysql 1675 Dec 14 04:19 ca-key.pem
-rw-r--r--. 1 mysql mysql 1383 Dec 14 04:22 ca.pem
-rw-r--r--. 1 mysql mysql 1383 Dec 14 04:42 client-cert.pem
-rw-------. 1 mysql mysql 1675 Dec 14 04:42 client-key.pem
-rw-r--r--. 1 mysql mysql 1399 Dec 14 04:42 client-req.pem
-rw-r--r--. 1 mysql mysql 1391 Dec 14 04:34 server-cert.pem
-rw-------. 1 mysql mysql 1679 Dec 14 04:28 server-key.pem
-rw-r--r--. 1 mysql mysql 1415 Dec 14 04:31 server-req.pem
Ensuite, nous allons activer la connexion SSL pour MariaDB. Sur chaque hôte MariaDB (maître et esclaves), modifiez le fichier de configuration et ajoutez les lignes suivantes dans la section [mysqld] :
ssl-ca=/etc/mysql/transit/ca.pem
ssl-cert=/etc/mysql/transit/server-cert.pem
ssl-key=/etc/mysql/transit/server-key.pem
Redémarrez le serveur MariaDB un nœud à la fois, en commençant par les esclaves et enfin sur le maître :
(slave1)$ systemctl restart mariadb
(slave2)$ systemctl restart mariadb
(master)$ systemctl restart mariadb
Après le redémarrage, MariaDB est désormais capable d'accepter des connexions simples en s'y connectant sans aucun paramètre lié à SSL ou avec des connexions cryptées, lorsque vous spécifiez un paramètre lié à SSL dans la chaîne de connexion.
Pour les utilisateurs de ClusterControl, vous pouvez activer le chiffrement client-serveur en quelques clics. Allez simplement dans ClusterControl -> Sécurité -> Cryptage SSL -> Activer -> Créer un certificat -> Expiration du certificat -> Activer SSL :
ClusterControl générera les clés requises, le certificat X.509 et le certificat CA et configurer le cryptage SSL pour les connexions client-serveur pour tous les nœuds du cluster. Pour la réplication MySQL/MariaDB, les fichiers SSL seront situés sous /etc/ssl/replication/cluster_X, où X est l'ID de cluster sur chaque nœud de base de données. Les mêmes certificats seront utilisés sur tous les nœuds et ceux existants pourraient être écrasés. Les nœuds doivent être redémarrés individuellement une fois cette tâche terminée. Nous vous recommandons de redémarrer d'abord un esclave de réplication et de vérifier que les paramètres SSL fonctionnent.
Pour redémarrer chaque nœud, accédez à ClusterControl -> Nodes -> Node Actions -> Restart Node. Redémarrez un nœud à la fois, en commençant par les esclaves. Le dernier nœud doit être le nœud maître avec l'indicateur d'arrêt forcé activé :
Vous pouvez savoir si un nœud est capable de gérer le chiffrement client-serveur en en regardant l'icône de cadenas vert juste à côté du nœud de la base de données dans la grille Vue d'ensemble :
À ce stade, notre cluster est maintenant prêt à accepter la connexion SSL de MySQL utilisateurs.
Connexion via une connexion chiffrée
Le client MariaDB nécessite tous les fichiers SSL liés au client que nous avons générés à l'intérieur du serveur. Copiez le certificat client généré, le certificat CA et la clé client sur l'hôte client :
$ cd /etc/mysql/transit
$ scp client-cert.pem client-key.pem ca.pem [email protected]:~
**ClusterControl génère les fichiers SSL client sous /etc/ssl/replication/cluster_X/sur chaque nœud de base de données, où X est l'ID du cluster.
Créez un utilisateur de base de données qui nécessite SSL sur le maître :
MariaDB> CREATE SCHEMA sbtest;
MariaDB> CREATE USER [email protected]'%' IDENTIFIED BY 'mysecr3t' REQUIRE SSL;
MariaDB> GRANT ALL PRIVILEGES ON sbtest.* to [email protected]'%';
Depuis l'hôte client, connectez-vous au serveur MariaDB avec les paramètres liés à SSL. Nous pouvons vérifier l'état de la connexion en utilisant l'instruction "STATUS":
(client)$ mysql -usbtest -p -h192.168.0.91 -P3306 --ssl-cert client-cert.pem --ssl-key client-key.pem --ssl-ca ca.pem -e 'status'
...
Current user: [email protected]
SSL: Cipher in use is DHE-RSA-AES256-GCM-SHA384
...
Faites attention à la ligne SSL où le chiffrement est utilisé pour le cryptage. Cela signifie que le client est correctement connecté au serveur MariaDB via une connexion cryptée.
À ce stade, nous avons chiffré la connexion client-serveur au serveur MariaDB, comme représenté par la flèche verte à deux pointes dans le schéma suivant :
Dans la partie suivante, nous allons chiffrer les connexions de réplication entre les nœuds.
Chiffrement de la réplication
La configuration des connexions chiffrées pour la réplication est similaire à celle des connexions client/serveur. Nous pouvons utiliser les mêmes certificats client, clé et certificat CA pour permettre à l'utilisateur de réplication d'accéder au serveur du maître via le canal de chiffrement. Cela activera indirectement le chiffrement entre les nœuds lorsque le thread d'E/S esclave extrait les événements de réplication du maître.
Configurons ceci sur un esclave à la fois. Pour le premier esclave, 192.168.0.92, ajoutez la ligne suivante sous la section [client] dans le fichier de configuration MariaDB :
[client]
ssl-ca=/etc/mysql/transit/ca.pem
ssl-cert=/etc/mysql/transit/client-cert.pem
ssl-key=/etc/mysql/transit/client-key.pem
Arrêtez le thread de réplication sur l'esclave :
(slave)MariaDB> STOP SLAVE;
Sur le maître, modifiez l'utilisateur de réplication existant pour le forcer à se connecter via SSL :
(master)MariaDB> ALTER USER [email protected] REQUIRE SSL;
Sur l'esclave, testez la connectivité au maître, 192.168.0.91 via la ligne de commande mysql avec l'indicateur --ssl :
(slave)MariaDB> mysql -urpl_user -p -h192.168.0.91 -P 3306 --ssl -e 'status'
...
Current user: [email protected]
SSL: Cipher in use is DHE-RSA-AES256-GCM-SHA384
...
Assurez-vous que vous pouvez vous connecter à l'hôte maître sans erreur. Ensuite, sur l'esclave, spécifiez l'instruction CHANGE MASTER avec les paramètres SSL comme ci-dessous :
(slave)MariaDB> CHANGE MASTER TO MASTER_SSL = 1, MASTER_SSL_CA = '/etc/mysql/transit/ca.pem', MASTER_SSL_CERT = '/etc/mysql/transit/client-cert.pem', MASTER_SSL_KEY = '/etc/mysql/transit/client-key.pem';
Démarrer l'esclave de réplication :
(slave)MariaDB> START SLAVE;
Vérifiez que la réplication fonctionne correctement avec les paramètres SSL associés :
MariaDB> SHOW SLAVE STATUS\G
...
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Master_SSL_Allowed: Yes
Master_SSL_CA_File: /etc/mysql/transit/ca.pem
Master_SSL_Cert: /etc/mysql/transit/client-cert.pem
Master_SSL_Key: /etc/mysql/transit/client-key.pem
...
L'esclave se réplique maintenant à partir du maître en toute sécurité via le cryptage TLS.
Répétez toutes les étapes ci-dessus sur l'esclave restant, 192.168.0.93. La seule différence est l'instruction alter user à exécuter sur le maître où nous devons passer à son hôte respectif :
(master)MariaDB> ALTER USER [email protected] REQUIRE SSL;
À ce stade, nous avons terminé le chiffrement en transit, comme illustré par les lignes vertes du maître aux esclaves dans le schéma suivant :
Vous pouvez vérifier la connexion de chiffrement en regardant la sortie tcpdump pour l'interface eth1 sur l'esclave. Voici un exemple de réplication standard sans chiffrement :
(plain-slave)$ tcpdump -i eth1 -s 0 -l -w - 'src port 3306 or dst port 3306' | strings
tcpdump: listening on eth1, link-type EN10MB (Ethernet), capture size 262144 bytes
H"-'
binlog.000008Ulw
binlog.000008Ulw
sbtest
sbtest
create table t1 (id INT AUTO_INCREMENT PRIMARY KEY, data VARCHAR(255))
binlog.000008
sbtest
BEGIN3
sbtest
test data3
Ok*Z
binlog.000008*Z
^C11 packets captured
11 packets received by filter
0 packets dropped by kernel
Nous pouvons clairement voir le texte lu par l'esclave depuis le maître. Lors d'une connexion chiffrée, vous devriez voir des caractères charabia comme ci-dessous :
(encrypted-slave)$ tcpdump -i eth1 -s 0 -l -w - 'src port 3306 or dst port 3306' | strings
tcpdump: listening on eth1, link-type EN10MB (Ethernet), capture size 262144 bytes
:|f^yb#
O5~_
@#PFh
k)]O
jtk3c
@NjN9_a
!\[email protected]
NrF
?7&Y
^C6 packets captured
6 packets received by filter
0 packets dropped by kernel
Conclusion
Dans la prochaine partie de cette série de blogs, nous allons chercher à terminer notre configuration entièrement chiffrée avec le chiffrement MariaDB au repos. Restez à l'écoute !