Un MySQL avec les paramètres par défaut après mysql_secure_installation est mieux qu’au premier démarrage, mais reste insuffisant pour la production : le compte root est un super-utilisateur omnipotent, aucun chiffrement TLS n’est forcé, les rôles ne sont pas séparés, et il n’y a pas d’audit des connexions. Chaque point est un vecteur d’attaque exploitable.
Ce guide suit une démarche couche par couche : d’abord comprendre l’authentification (caching_sha2_password), puis créer des utilisateurs restreints (host + privilèges), ensuite chiffrer le transport (TLS), et enfin restreindre le réseau et tracer les actions. Chaque commande est testée sur un lab réel (MySQL 8.4 LTS, Debian 12).
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Comprendre l’authentification
caching_sha2_passwordet la fin demysql_native_password - Créer des utilisateurs avec restriction par host et mots de passe forts
- Séparer les rôles avec le pattern admin / applicatif / monitoring / backup
- Activer le chiffrement TLS et forcer les connexions chiffrées
- Restreindre l’exposition réseau (bind_address, skip_name_resolve)
- Configurer l’audit des connexions, le slow query log et le connection_control
Dans quel contexte ?
Section intitulée « Dans quel contexte ? »Vous devez sécuriser MySQL dans ces situations :
- Vous passez d’un lab de développement (localhost, root sans mot de passe réseau) à une mise en production
- Votre équipe partage le compte root pour toutes les opérations — vous voulez séparer les responsabilités
- Vous devez ouvrir MySQL au réseau pour une application distante et garantir que les connexions sont chiffrées
- Un client ancien (PHP 5.x, connecteur Python mysqlclient < 2.0) refuse de se connecter après la migration vers MySQL 8.4 (problème d’authentification)
- Vous préparez un audit de sécurité et devez prouver la politique d’accès, le chiffrement et la traçabilité
Ce guide ne couvre pas…
Section intitulée « Ce guide ne couvre pas… »Prérequis
Section intitulée « Prérequis »- MySQL installé et le service actif (voir le guide Installation)
- Accès au compte
rootviamysql -u root -p - Connaître les bases du client mysql (voir le guide Prise en main du client mysql)
- Accès root ou sudo sur le serveur (pour modifier
mysqld.cnfet gérer les certificats)
Authentification MySQL
Section intitulée « Authentification MySQL »caching_sha2_password : le défaut depuis MySQL 8.0
Section intitulée « caching_sha2_password : le défaut depuis MySQL 8.0 »MySQL utilise un système de plugins d’authentification — chaque compte utilisateur est associé à un plugin qui gère la vérification du mot de passe. Depuis MySQL 8.0, le plugin par défaut est caching_sha2_password.
Pour vérifier quel plugin chaque compte utilise réellement :
SELECT user, host, pluginFROM mysql.userWHERE user NOT IN ('mysql.sys','mysql.session','mysql.infoschema')ORDER BY user, host;+-------------+-----------+-----------------------+| user | host | plugin |+-------------+-----------+-----------------------+| admin_app | localhost | caching_sha2_password || app_writer | 10.0.1.% | caching_sha2_password || root | localhost | caching_sha2_password |+-------------+-----------+-----------------------+Comment ça fonctionne : le mot de passe est hashé avec SHA-256 puis mis en cache côté serveur. La première authentification d’un utilisateur nécessite un échange sécurisé (connexion TLS, ou échange de clé RSA). Les authentifications suivantes utilisent le cache — d’où le nom “caching”.
| Plugin | Algorithme | Sécurité | Défaut depuis |
|---|---|---|---|
caching_sha2_password | SHA-256 + cache | Forte | MySQL 8.0 |
mysql_native_password | SHA-1 double | Faible (vulnérable aux attaques par rejeu) | MySQL 4.1 à 5.7 |
sha256_password | SHA-256 sans cache | Correcte mais lente | — |
auth_socket | Identité Unix (comme peer dans PostgreSQL) | Forte | — |
mysql_native_password : désactivé par défaut en 8.4
Section intitulée « mysql_native_password : désactivé par défaut en 8.4 »MySQL 8.4 a désactivé mysql_native_password par défaut. Le plugin n’est plus chargé au démarrage :
SELECT PLUGIN_NAME, PLUGIN_STATUSFROM information_schema.PLUGINSWHERE PLUGIN_NAME = 'mysql_native_password';+-----------------------+---------------+| PLUGIN_NAME | PLUGIN_STATUS |+-----------------------+---------------+| mysql_native_password | DISABLED |+-----------------------+---------------+Impact : les anciens clients ou connecteurs qui ne supportent pas caching_sha2_password ne pourront plus se connecter. C’est le cas de :
- PHP avec
mysqli+ libmysqlclient ancien (PHP < 7.4 sans mysqlnd) - Python avec
mysqlclient< 2.0 - Certains outils legacy (anciens clients MySQL 5.x)
Si vous devez temporairement réactiver mysql_native_password pour une migration :
[mysqld]mysql_native_password = ONauthentication_policy : le contrôle multiniveau
Section intitulée « authentication_policy : le contrôle multiniveau »MySQL 8.4 supporte l’authentification multifacteur (MFA). Le paramètre authentication_policy définit les exigences pour chaque facteur :
SHOW VARIABLES LIKE 'authentication_policy';+-----------------------+-------+| Variable_name | Value |+-----------------------+-------+| authentication_policy | *,, |+-----------------------+-------+La valeur *,, signifie : premier facteur obligatoire (n’importe quel plugin), deuxième et troisième optionnels. Pour forcer l’utilisation de caching_sha2_password comme premier facteur :
SET PERSIST authentication_policy = 'caching_sha2_password,,';Gestion des utilisateurs
Section intitulée « Gestion des utilisateurs »CREATE USER avec restriction par host
Section intitulée « CREATE USER avec restriction par host »Contrairement à PostgreSQL qui contrôle l’accès par IP dans pg_hba.conf, MySQL intègre la restriction réseau directement dans le compte utilisateur via la partie @host :
-- Connexion locale uniquementCREATE USER 'admin_app'@'localhost' IDENTIFIED BY 'AdminApp2026!Secure';
-- Connexion depuis un réseau applicatifCREATE USER 'app_writer'@'10.0.1.%' IDENTIFIED BY 'AppWriter2026!Prod';
-- Connexion depuis une IP préciseCREATE USER 'monitoring'@'10.0.1.50' IDENTIFIED BY 'Monitor2026!Read';Pattern @host | Signification | Usage |
|---|---|---|
'localhost' | Socket Unix + 127.0.0.1 | Admin, CLI local |
'10.0.1.%' | Tout le sous-réseau 10.0.1.x | Réseau applicatif |
'10.0.1.50' | Une seule IP | Monitoring, service spécifique |
'%' | N’importe quelle IP | Dangereux — à éviter |
MySQL évalue user@host comme un couple unique — 'alice'@'localhost' et 'alice'@'10.0.1.%' sont deux comptes distincts avec des mots de passe et des privilèges potentiellement différents.
ALTER USER : modifier mot de passe et plugin
Section intitulée « ALTER USER : modifier mot de passe et plugin »-- Changer le mot de passeALTER USER 'app_writer'@'10.0.1.%' IDENTIFIED BY 'NouveauMDP2026!Fort';
-- Migrer un compte de mysql_native_password vers caching_sha2_passwordALTER USER 'ancien_compte'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'NouveauMDP2026!';Pour lister les comptes et leur plugin d’authentification :
SELECT user, host, plugin, password_expired, account_lockedFROM mysql.userWHERE user NOT IN ('mysql.sys','mysql.session','mysql.infoschema')ORDER BY user, host;+-------------+-----------+-----------------------+------------------+----------------+| user | host | plugin | password_expired | account_locked |+-------------+-----------+-----------------------+------------------+----------------+| admin_app | localhost | caching_sha2_password | N | N || app_writer | 10.0.1.% | caching_sha2_password | N | N || labadmin | localhost | caching_sha2_password | N | N || monitoring | 10.0.1.50| caching_sha2_password | N | N || root | localhost | caching_sha2_password | N | N |+-------------+-----------+-----------------------+------------------+----------------+Verrouillage de compte et expiration du mot de passe
Section intitulée « Verrouillage de compte et expiration du mot de passe »MySQL offre des contrôles supplémentaires sur les comptes :
-- Verrouiller un compte (la connexion est refusée)ALTER USER 'alice'@'localhost' ACCOUNT LOCK;
-- DéverrouillerALTER USER 'alice'@'localhost' ACCOUNT UNLOCK;
-- Forcer le changement de mot de passe à la prochaine connexionALTER USER 'alice'@'localhost' PASSWORD EXPIRE;
-- Expiration automatique tous les 90 joursALTER USER 'alice'@'localhost' PASSWORD EXPIRE INTERVAL 90 DAY;
-- Historique des mots de passe (empêche la réutilisation)ALTER USER 'alice'@'localhost' PASSWORD HISTORY 5;
-- Nombre maximum de tentatives échouées avant verrouillageCREATE USER 'bob'@'localhost' IDENTIFIED BY 'Bob2026!Secure' FAILED_LOGIN_ATTEMPTS 3 PASSWORD_LOCK_TIME 1; -- déverrouillage automatique après 1 jourvalidate_password : imposer la complexité
Section intitulée « validate_password : imposer la complexité »Le composant validate_password est généralement installé par mysql_secure_installation. Vérifiez :
SHOW VARIABLES LIKE 'validate_password%';+--------------------------------------+--------+| Variable_name | Value |+--------------------------------------+--------+| validate_password.check_user_name | ON || validate_password.dictionary_file | || validate_password.length | 8 || validate_password.mixed_case_count | 1 || validate_password.number_count | 1 || validate_password.policy | MEDIUM || validate_password.special_char_count | 1 |+--------------------------------------+--------+| Politique | Exigences |
|---|---|
LOW | Longueur minimale uniquement |
MEDIUM | Longueur + majuscule + minuscule + chiffre + caractère spécial |
STRONG | MEDIUM + pas dans un dictionnaire de mots de passe courants |
Pour passer en STRONG :
SET PERSIST validate_password.policy = STRONG;SET PERSIST validate_password.length = 12;Système de rôles
Section intitulée « Système de rôles »CREATE ROLE et GRANT rôle TO utilisateur
Section intitulée « CREATE ROLE et GRANT rôle TO utilisateur »MySQL supporte les rôles depuis la version 8.0 — un rôle est un ensemble nommé de privilèges que vous pouvez attribuer à plusieurs utilisateurs :
-- Créer les rôles (pas de LOGIN — ce sont des groupes de privilèges)CREATE ROLE 'role_reader', 'role_writer', 'role_admin';
-- Accorder des privilèges aux rôlesGRANT SELECT ON lab_mysql.* TO 'role_reader';GRANT SELECT, INSERT, UPDATE, DELETE ON lab_mysql.* TO 'role_writer';GRANT ALL PRIVILEGES ON lab_mysql.* TO 'role_admin';
-- Attribuer les rôles aux utilisateursGRANT 'role_reader' TO 'monitoring'@'10.0.1.50';GRANT 'role_writer' TO 'app_writer'@'10.0.1.%';GRANT 'role_admin' TO 'admin_app'@'localhost';SET DEFAULT ROLE et activation des rôles
Section intitulée « SET DEFAULT ROLE et activation des rôles »Par défaut, les rôles ne sont pas activés automatiquement à la connexion. L’utilisateur doit soit les activer manuellement (SET ROLE), soit configurer un rôle par défaut :
-- Activer tous les rôles par défaut pour un utilisateurSET DEFAULT ROLE ALL TO 'app_writer'@'10.0.1.%';SET DEFAULT ROLE ALL TO 'monitoring'@'10.0.1.50';SET DEFAULT ROLE ALL TO 'admin_app'@'localhost';Ou activer l’activation automatique globale pour tous les utilisateurs :
SET PERSIST activate_all_roles_on_login = ON;Privilèges granulaires de MySQL 8.4
Section intitulée « Privilèges granulaires de MySQL 8.4 »MySQL 8.4 a décomposé l’ancien privilège SUPER en privilèges plus fins :
| Privilège granulaire | Remplace (ancien SUPER) | Usage |
|---|---|---|
FLUSH_PRIVILEGES | FLUSH PRIVILEGES | Recharger les tables de privilèges |
FLUSH_TABLES | FLUSH TABLES | Vider les caches de tables |
OPTIMIZE_LOCAL_TABLE | OPTIMIZE TABLE | Optimiser les tables |
SYSTEM_VARIABLES_ADMIN | SET GLOBAL/PERSIST | Configuration runtime |
CONNECTION_ADMIN | Gérer les connexions des autres | DBA uniquement |
ROLE_ADMIN | GRANT role TO user | Gestion des rôles |
Règle : n’accordez jamais SUPER — utilisez les privilèges granulaires correspondant au besoin exact.
Moindre privilège : architecture recommandée
Section intitulée « Moindre privilège : architecture recommandée »Séparer les comptes
Section intitulée « Séparer les comptes »| Rôle | Privilèges | Compte type | Host |
|---|---|---|---|
| DBA | ALL PRIVILEGES + administration | admin_app@localhost | Socket local uniquement |
| Applicatif (écriture) | SELECT, INSERT, UPDATE, DELETE sur le schéma | app_writer@10.0.1.% | Réseau applicatif |
| Applicatif (lecture) | SELECT sur le schéma | app_reader@10.0.1.% | Réseau applicatif |
| Monitoring | PROCESS, REPLICATION CLIENT, SELECT sur performance_schema | monitoring@10.0.1.50 | IP du serveur de monitoring |
| Backup | SELECT, RELOAD, LOCK TABLES, SHOW VIEW, EVENT, TRIGGER | backup@localhost | Local uniquement |
-
Créer le compte monitoring (lecture performance + processus) :
CREATE USER 'monitoring'@'10.0.1.50'IDENTIFIED BY 'Monitor2026!Readonly';GRANT PROCESS, REPLICATION CLIENT ON *.* TO 'monitoring'@'10.0.1.50';GRANT SELECT ON performance_schema.* TO 'monitoring'@'10.0.1.50';GRANT SELECT ON sys.* TO 'monitoring'@'10.0.1.50'; -
Créer le compte backup (mysqldump, xtrabackup) :
CREATE USER 'backup'@'localhost'IDENTIFIED BY 'Backup2026!Secure';GRANT SELECT, RELOAD, LOCK TABLES, SHOW VIEW, EVENT, TRIGGERON *.* TO 'backup'@'localhost';GRANT BACKUP_ADMIN ON *.* TO 'backup'@'localhost'; -
Vérifier les privilèges :
SHOW GRANTS FOR 'monitoring'@'10.0.1.50';+-------------------------------------------------------------------+| Grants for monitoring@10.0.1.50 |+-------------------------------------------------------------------+| GRANT PROCESS, REPLICATION CLIENT ON *.* TO `monitoring`@`10.0.1.50` || GRANT SELECT ON `performance_schema`.* TO `monitoring`@`10.0.1.50` || GRANT SELECT ON `sys`.* TO `monitoring`@`10.0.1.50` |+-------------------------------------------------------------------+
Partial revokes : révoquer sur un schéma spécifique
Section intitulée « Partial revokes : révoquer sur un schéma spécifique »MySQL 8.0.16+ supporte les partial revokes — la possibilité de révoquer un privilège global pour un schéma spécifique. Activez d’abord la fonctionnalité :
SET PERSIST partial_revokes = ON;Exemple : donner SELECT global sauf sur le schéma mysql (qui contient les mots de passe) :
GRANT SELECT ON *.* TO 'app_reader'@'10.0.1.%';REVOKE SELECT ON mysql.* FROM 'app_reader'@'10.0.1.%';Éviter GRANT ALL et SUPER
Section intitulée « Éviter GRANT ALL et SUPER »| À éviter | Pourquoi | Alternative |
|---|---|---|
GRANT ALL PRIVILEGES ON *.* | Donne tous les droits sur toutes les bases | Accorder par schéma + privilège exact |
GRANT SUPER | Privilège monolithique en voie de dépréciation | Utiliser les privilèges granulaires 8.4 |
GRANT ALL ON db.* | Inclut DROP, ALTER, GRANT | Lister SELECT, INSERT, UPDATE, DELETE |
Chiffrement TLS
Section intitulée « Chiffrement TLS »Vérifier l’état TLS actuel
Section intitulée « Vérifier l’état TLS actuel »SHOW VARIABLES WHERE Variable_name IN ('ssl_ca','ssl_cert','ssl_key','tls_version');+---------------+-----------------+| Variable_name | Value |+---------------+-----------------+| ssl_ca | ca.pem || ssl_cert | server-cert.pem || ssl_key | server-key.pem || tls_version | TLSv1.2,TLSv1.3|+---------------+-----------------+Vérifier si la connexion courante est chiffrée :
SHOW SESSION STATUS LIKE 'Ssl_cipher';+---------------+------------------------+| Variable_name | Value |+---------------+------------------------+| Ssl_cipher | TLS_AES_256_GCM_SHA384 |+---------------+------------------------+Si Ssl_cipher est vide, la connexion n’est pas chiffrée.
Certificats auto-générés par MySQL
Section intitulée « Certificats auto-générés par MySQL »Lors de la première initialisation (mysqld --initialize), MySQL génère automatiquement des certificats auto-signés dans le datadir :
ls -la /var/lib/mysql/*.pem-rw------- 1 mysql mysql 1704 Apr 13 08:30 /var/lib/mysql/ca-key.pem-rw-r--r-- 1 mysql mysql 1131 Apr 13 08:30 /var/lib/mysql/ca.pem-rw-r--r-- 1 mysql mysql 1131 Apr 13 08:30 /var/lib/mysql/server-cert.pem-rw------- 1 mysql mysql 1704 Apr 13 08:30 /var/lib/mysql/server-key.pem-rw-r--r-- 1 mysql mysql 1131 Apr 13 08:30 /var/lib/mysql/client-cert.pem-rw------- 1 mysql mysql 1704 Apr 13 08:30 /var/lib/mysql/client-key.pemCes certificats auto-signés suffisent pour le chiffrement du transport mais ne permettent pas de vérifier l’identité du serveur côté client. En production, utilisez des certificats signés par une PKI interne.
Configurer TLS avec des certificats personnalisés
Section intitulée « Configurer TLS avec des certificats personnalisés »[mysqld]ssl_ca = /etc/mysql/ssl/ca.pemssl_cert = /etc/mysql/ssl/server-cert.pemssl_key = /etc/mysql/ssl/server-key.pemtls_version = TLSv1.2,TLSv1.3# Permissions sur la clé privéechown mysql:mysql /etc/mysql/ssl/server-key.pemchmod 600 /etc/mysql/ssl/server-key.pem
sudo systemctl restart mysqlForcer TLS dans CREATE USER (REQUIRE SSL / X509)
Section intitulée « Forcer TLS dans CREATE USER (REQUIRE SSL / X509) »MySQL permet de forcer le TLS au niveau du compte utilisateur — contrairement à PostgreSQL qui le contrôle dans pg_hba.conf :
-- Forcer TLS (chiffrement uniquement)CREATE USER 'app_secure'@'10.0.1.%' IDENTIFIED BY 'Secure2026!TLS' REQUIRE SSL;
-- Forcer TLS avec certificat client (authentification mutuelle)CREATE USER 'app_mutual'@'10.0.1.%' IDENTIFIED BY 'Mutual2026!Cert' REQUIRE X509;
-- Sur un compte existantALTER USER 'app_writer'@'10.0.1.%' REQUIRE SSL;REQUIRE | Chiffrement | Vérifie certificat client | Usage |
|---|---|---|---|
NONE | Non requis | Non | Défaut — dangereux en production |
SSL | Oui | Non | Minimum recommandé |
X509 | Oui | Oui | Automatisation, services critiques |
ISSUER '...' SUBJECT '...' | Oui | Oui + vérifie l’émetteur/sujet | Très restrictif |
Test de connexion avec TLS forcé :
# Connexion chiffrée — fonctionnemysql -u app_secure -h 10.0.1.5 -p --ssl-mode=REQUIRED
# Connexion sans TLS — échouemysql -u app_secure -h 10.0.1.5 -p --ssl-mode=DISABLEDERROR 1045 (28000): Access denied for user 'app_secure'@'10.0.1.5'Chiffrement vs vérification d’identité (côté client)
Section intitulée « Chiffrement vs vérification d’identité (côté client) »REQUIRE SSL sur le compte force le chiffrement du transport, mais ne vérifie pas que le client se connecte au bon serveur. Côté client, le paramètre --ssl-mode contrôle le niveau de vérification :
--ssl-mode | Chiffrement | Vérifie le certificat serveur | Vérifie le hostname | Usage |
|---|---|---|---|---|
DISABLED | Non | Non | Non | Interdit en production |
PREFERRED | Si possible | Non | Non | Défaut — chiffre si le serveur le supporte |
REQUIRED | Oui | Non | Non | Force le chiffrement, mais pas la vérification |
VERIFY_CA | Oui | Oui | Non | Vérifie que le certificat est signé par une CA de confiance |
VERIFY_IDENTITY | Oui | Oui | Oui | Le plus sûr — vérifie aussi que le hostname correspond au CN/SAN du certificat |
Recommandation : en production, configurez REQUIRE SSL côté serveur et --ssl-mode=VERIFY_CA (ou VERIFY_IDENTITY) côté client pour protéger contre les attaques man-in-the-middle.
Recharger les certificats à chaud
Section intitulée « Recharger les certificats à chaud »Quand vous renouvelez les certificats, rechargez-les sans redémarrer MySQL :
ALTER INSTANCE RELOAD TLS;Vérifiez ensuite :
SHOW STATUS LIKE 'Ssl_server_not_after';Restreindre l’accès réseau
Section intitulée « Restreindre l’accès réseau »bind_address : ne pas écouter sur 0.0.0.0
Section intitulée « bind_address : ne pas écouter sur 0.0.0.0 »bind_address est configuré dans le fichier mysqld.cnf. Le défaut MySQL 8.4 est * (toutes les interfaces), mais le packaging Debian/Ubuntu restreint la valeur à 127.0.0.1 — c’est la configuration la plus sûre :
SHOW VARIABLES LIKE 'bind_address';+---------------+-----------+| Variable_name | Value |+---------------+-----------+| bind_address | 127.0.0.1 |+---------------+-----------+Si vous devez accepter des connexions réseau, restreignez à une seule interface :
[mysqld]bind_address = 127.0.0.1,10.0.1.5| Configuration | Exposition | Usage |
|---|---|---|
127.0.0.1 | Local uniquement | Dev, lab |
127.0.0.1,10.0.1.5 | Local + une IP réseau | Production — réseau applicatif dédié |
0.0.0.0 | Toutes les interfaces | Déconseillé sauf derrière un firewall/proxy |
skip_name_resolve : désactiver le DNS inversé
Section intitulée « skip_name_resolve : désactiver le DNS inversé »Par défaut, MySQL fait une résolution DNS inversée pour chaque connexion. Ça ajoute du délai et crée une dépendance au DNS. Désactivez-le :
[mysqld]skip_name_resolve = ONAprès activation, utilisez uniquement des adresses IP dans la partie @host des comptes CREATE USER.
Firewall système
Section intitulée « Firewall système »Ajoutez un firewall système en complément de la restriction bind_address :
nft add rule inet filter input tcp dport 3306 ip saddr 10.0.1.0/24 acceptnft add rule inet filter input tcp dport 3306 dropsudo ufw allow from 10.0.1.0/24 to any port 3306sudo ufw deny 3306sudo firewall-cmd --new-zone=mysql --permanentsudo firewall-cmd --zone=mysql --add-source=10.0.1.0/24 --permanentsudo firewall-cmd --zone=mysql --add-port=3306/tcp --permanentsudo firewall-cmd --reloadAudit des connexions et requêtes
Section intitulée « Audit des connexions et requêtes »connection_control : limiter les tentatives de connexion
Section intitulée « connection_control : limiter les tentatives de connexion »Le plugin connection_control ralentit les connexions après un certain nombre d’échecs — une protection contre le brute-force :
-- Installer le pluginINSTALL PLUGIN CONNECTION_CONTROL SONAME 'connection_control.so';INSTALL PLUGIN CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS SONAME 'connection_control.so';
-- ConfigurerSET PERSIST connection_control_failed_connections_threshold = 3;SET PERSIST connection_control_min_connection_delay = 1000; -- 1 secondeSET PERSIST connection_control_max_connection_delay = 86400000; -- 24 heures maxAprès 3 échecs d’authentification, MySQL impose un délai croissant avant chaque nouvelle tentative.
Vérifier les tentatives échouées :
SELECT * FROM information_schema.CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS;Slow query log pour l’audit des requêtes
Section intitulée « Slow query log pour l’audit des requêtes »Le slow query log, configuré dans le guide Configuration, est aussi un outil d’audit : il trace les requêtes qui dépassent un seuil de temps et les requêtes sans index.
Audit plugin (MySQL Enterprise) vs alternatives open source
Section intitulée « Audit plugin (MySQL Enterprise) vs alternatives open source »| Solution | Licence | Fonctionnalités |
|---|---|---|
| MySQL Enterprise Audit | Commercial | Audit complet (connexions, requêtes, DDL), format XML/JSON, filtrage par user/event |
| Percona Audit Log | Open source (Percona Server) | Compatible Enterprise Audit, format XML/JSON |
| MariaDB Audit Plugin | Open source | Compatible MySQL Community (avec limitations de version) |
| McAfee MySQL Audit Plugin | Open source (archivé) | Audit basique, plus maintenu |
Pour MySQL Community, la combinaison slow_query_log + general_log (temporaire) + connection_control + log_error couvre les besoins basiques d’audit. Pour un audit complet, envisagez Percona Server ou MySQL Enterprise.
Checklist de durcissement
Section intitulée « Checklist de durcissement »| Vérification | Commande | Attendu |
|---|---|---|
| Pas de compte sans mot de passe | SELECT user, host FROM mysql.user WHERE authentication_string = ''; | Aucune ligne |
Pas de @'%' pour l’admin | SELECT user, host FROM mysql.user WHERE host = '%' AND Super_priv = 'Y'; | Aucune ligne |
| TLS configuré | SHOW VARIABLES LIKE 'ssl_cert'; | Chemin vers le certificat (non vide) |
| Connexion courante chiffrée | SHOW SESSION STATUS LIKE 'Ssl_cipher'; | Non vide |
validate_password actif | SHOW VARIABLES LIKE 'validate_password.policy'; | MEDIUM ou STRONG |
mysql_native_password désactivé | SELECT PLUGIN_STATUS FROM information_schema.PLUGINS WHERE PLUGIN_NAME='mysql_native_password'; | DISABLED |
bind_address restreint | SHOW VARIABLES LIKE 'bind_address'; | Pas 0.0.0.0 ni * |
skip_name_resolve activé | SHOW VARIABLES LIKE 'skip_name_resolve'; | ON |
| Rôles séparés | SELECT user, host FROM mysql.user; | Admin, writer, reader, monitoring, backup distincts |
connection_control installé | SHOW PLUGINS LIKE 'CONNECTION_CONTROL%'; | ACTIVE |
| Slow query log activé | SHOW VARIABLES LIKE 'slow_query_log'; | ON |
Dépannage
Section intitulée « Dépannage »| Symptôme | Cause probable | Solution |
|---|---|---|
Authentication plugin 'caching_sha2_password' cannot be loaded | Client MySQL ancien (5.x) sans support SHA2 | Mettre à jour le client ou réactiver temporairement mysql_native_password |
Access denied après migration vers 8.4 | mysql_native_password désactivé | ALTER USER ... IDENTIFIED WITH caching_sha2_password BY '...' |
ERROR 2026: SSL connection error | Certificat serveur expiré ou invalide | Vérifier Ssl_server_not_after, renouveler et ALTER INSTANCE RELOAD TLS |
| Connexion TLS impossible depuis l’application | L’application ne passe pas --ssl-mode=REQUIRED | Configurer le connecteur avec SSL obligatoire |
SELECT CURRENT_ROLE() retourne NONE | Les rôles ne sont pas activés par défaut | SET DEFAULT ROLE ALL TO user@host; ou SET PERSIST activate_all_roles_on_login = ON; |
| Rôle accordé mais privilèges absents | activate_all_roles_on_login = OFF | SET PERSIST activate_all_roles_on_login = ON; |
| Oubli du mot de passe root | — | Redémarrer avec --skip-grant-tables, réinitialiser puis redémarrer normalement (voir guide Installation) |
validate_password bloque la création | Mot de passe trop simple | Respecter la politique (longueur, majuscule, chiffre, spécial) ou baisser temporairement la policy |
À retenir
Section intitulée « À retenir »caching_sha2_passwordest le plugin par défaut (contrôlé parauthentication_policy, plus pardefault_authentication_pluginqui n’existe plus en 8.4).mysql_native_passwordest déprécié depuis 8.0.34, désactivé par défaut en 8.4, et supprimé en 9.0.- La restriction réseau se fait au niveau du compte (
@host) contrairement à PostgreSQL qui utilisepg_hba.conf. Un compte@'%'avec des privilèges élevés est un risque majeur. REQUIRE SSLdansCREATE USERforce le chiffrement — ajoutez--ssl-mode=VERIFY_CAouVERIFY_IDENTITYcôté client pour vérifier l’identité du serveur.- Les rôles ne sont pas activés automatiquement à la connexion — pensez à
SET DEFAULT ROLE ALLouactivate_all_roles_on_login = ON. - N’accordez jamais
GRANT ALL ON *.*niSUPER— utilisez les privilèges granulaires de MySQL 8.4 (FLUSH_PRIVILEGES, SYSTEM_VARIABLES_ADMIN, etc.). partial_revokespermet de révoquer un privilège global sur un schéma précis — indispensable pour protéger le schémamysql.- Installez
connection_controlpour ralentir le brute-force après 3 tentatives échouées. bind_address = 127.0.0.1+skip_name_resolve = ON+ firewall système : trois couches de restriction réseau.- Le slow query log (
long_query_time = 1) sert aussi d’outil d’audit — activez-le dès le premier jour.