Aller au contenu
medium

Sécuriser MySQL : utilisateurs, TLS, rôles et moindre privilège

28 min de lecture

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).

  • Comprendre l’authentification caching_sha2_password et la fin de mysql_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

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é
  • MySQL installé et le service actif (voir le guide Installation)
  • Accès au compte root via mysql -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.cnf et gérer les certificats)

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, plugin
FROM mysql.user
WHERE 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”.

PluginAlgorithmeSécuritéDéfaut depuis
caching_sha2_passwordSHA-256 + cacheForteMySQL 8.0
mysql_native_passwordSHA-1 doubleFaible (vulnérable aux attaques par rejeu)MySQL 4.1 à 5.7
sha256_passwordSHA-256 sans cacheCorrecte mais lente
auth_socketIdentité 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_STATUS
FROM information_schema.PLUGINS
WHERE 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 = ON

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,,';

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 uniquement
CREATE USER 'admin_app'@'localhost'
IDENTIFIED BY 'AdminApp2026!Secure';
-- Connexion depuis un réseau applicatif
CREATE USER 'app_writer'@'10.0.1.%'
IDENTIFIED BY 'AppWriter2026!Prod';
-- Connexion depuis une IP précise
CREATE USER 'monitoring'@'10.0.1.50'
IDENTIFIED BY 'Monitor2026!Read';
Pattern @hostSignificationUsage
'localhost'Socket Unix + 127.0.0.1Admin, CLI local
'10.0.1.%'Tout le sous-réseau 10.0.1.xRéseau applicatif
'10.0.1.50'Une seule IPMonitoring, service spécifique
'%'N’importe quelle IPDangereux — à é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.

-- Changer le mot de passe
ALTER USER 'app_writer'@'10.0.1.%'
IDENTIFIED BY 'NouveauMDP2026!Fort';
-- Migrer un compte de mysql_native_password vers caching_sha2_password
ALTER 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_locked
FROM mysql.user
WHERE 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éverrouiller
ALTER USER 'alice'@'localhost' ACCOUNT UNLOCK;
-- Forcer le changement de mot de passe à la prochaine connexion
ALTER USER 'alice'@'localhost' PASSWORD EXPIRE;
-- Expiration automatique tous les 90 jours
ALTER 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 verrouillage
CREATE USER 'bob'@'localhost'
IDENTIFIED BY 'Bob2026!Secure'
FAILED_LOGIN_ATTEMPTS 3
PASSWORD_LOCK_TIME 1; -- déverrouillage automatique après 1 jour

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 |
+--------------------------------------+--------+
PolitiqueExigences
LOWLongueur minimale uniquement
MEDIUMLongueur + majuscule + minuscule + chiffre + caractère spécial
STRONGMEDIUM + 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;

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ôles
GRANT 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 utilisateurs
GRANT 'role_reader' TO 'monitoring'@'10.0.1.50';
GRANT 'role_writer' TO 'app_writer'@'10.0.1.%';
GRANT 'role_admin' TO 'admin_app'@'localhost';

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 utilisateur
SET 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;

MySQL 8.4 a décomposé l’ancien privilège SUPER en privilèges plus fins :

Privilège granulaireRemplace (ancien SUPER)Usage
FLUSH_PRIVILEGESFLUSH PRIVILEGESRecharger les tables de privilèges
FLUSH_TABLESFLUSH TABLESVider les caches de tables
OPTIMIZE_LOCAL_TABLEOPTIMIZE TABLEOptimiser les tables
SYSTEM_VARIABLES_ADMINSET GLOBAL/PERSISTConfiguration runtime
CONNECTION_ADMINGérer les connexions des autresDBA uniquement
ROLE_ADMINGRANT role TO userGestion des rôles

Règle : n’accordez jamais SUPER — utilisez les privilèges granulaires correspondant au besoin exact.

RôlePrivilègesCompte typeHost
DBAALL PRIVILEGES + administrationadmin_app@localhostSocket local uniquement
Applicatif (écriture)SELECT, INSERT, UPDATE, DELETE sur le schémaapp_writer@10.0.1.%Réseau applicatif
Applicatif (lecture)SELECT sur le schémaapp_reader@10.0.1.%Réseau applicatif
MonitoringPROCESS, REPLICATION CLIENT, SELECT sur performance_schemamonitoring@10.0.1.50IP du serveur de monitoring
BackupSELECT, RELOAD, LOCK TABLES, SHOW VIEW, EVENT, TRIGGERbackup@localhostLocal uniquement
  1. 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';
  2. Créer le compte backup (mysqldump, xtrabackup) :

    CREATE USER 'backup'@'localhost'
    IDENTIFIED BY 'Backup2026!Secure';
    GRANT SELECT, RELOAD, LOCK TABLES, SHOW VIEW, EVENT, TRIGGER
    ON *.* TO 'backup'@'localhost';
    GRANT BACKUP_ADMIN ON *.* TO 'backup'@'localhost';
  3. 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.%';
À éviterPourquoiAlternative
GRANT ALL PRIVILEGES ON *.*Donne tous les droits sur toutes les basesAccorder par schéma + privilège exact
GRANT SUPERPrivilège monolithique en voie de dépréciationUtiliser les privilèges granulaires 8.4
GRANT ALL ON db.*Inclut DROP, ALTER, GRANTLister SELECT, INSERT, UPDATE, DELETE
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.

Lors de la première initialisation (mysqld --initialize), MySQL génère automatiquement des certificats auto-signés dans le datadir :

Fenêtre de terminal
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.pem

Ces 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.pem
ssl_cert = /etc/mysql/ssl/server-cert.pem
ssl_key = /etc/mysql/ssl/server-key.pem
tls_version = TLSv1.2,TLSv1.3
Fenêtre de terminal
# Permissions sur la clé privée
chown mysql:mysql /etc/mysql/ssl/server-key.pem
chmod 600 /etc/mysql/ssl/server-key.pem
sudo systemctl restart mysql

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 existant
ALTER USER 'app_writer'@'10.0.1.%' REQUIRE SSL;
REQUIREChiffrementVérifie certificat clientUsage
NONENon requisNonDéfaut — dangereux en production
SSLOuiNonMinimum recommandé
X509OuiOuiAutomatisation, services critiques
ISSUER '...' SUBJECT '...'OuiOui + vérifie l’émetteur/sujetTrès restrictif

Test de connexion avec TLS forcé :

Fenêtre de terminal
# Connexion chiffrée — fonctionne
mysql -u app_secure -h 10.0.1.5 -p --ssl-mode=REQUIRED
# Connexion sans TLS — échoue
mysql -u app_secure -h 10.0.1.5 -p --ssl-mode=DISABLED
ERROR 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-modeChiffrementVérifie le certificat serveurVérifie le hostnameUsage
DISABLEDNonNonNonInterdit en production
PREFERREDSi possibleNonNonDéfaut — chiffre si le serveur le supporte
REQUIREDOuiNonNonForce le chiffrement, mais pas la vérification
VERIFY_CAOuiOuiNonVérifie que le certificat est signé par une CA de confiance
VERIFY_IDENTITYOuiOuiOuiLe 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.

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';

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
ConfigurationExpositionUsage
127.0.0.1Local uniquementDev, lab
127.0.0.1,10.0.1.5Local + une IP réseauProduction — réseau applicatif dédié
0.0.0.0Toutes les interfacesDéconseillé sauf derrière un firewall/proxy

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 = ON

Après activation, utilisez uniquement des adresses IP dans la partie @host des comptes CREATE USER.

Ajoutez un firewall système en complément de la restriction bind_address :

Fenêtre de terminal
nft add rule inet filter input tcp dport 3306 ip saddr 10.0.1.0/24 accept
nft add rule inet filter input tcp dport 3306 drop

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 plugin
INSTALL PLUGIN CONNECTION_CONTROL SONAME 'connection_control.so';
INSTALL PLUGIN CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS
SONAME 'connection_control.so';
-- Configurer
SET PERSIST connection_control_failed_connections_threshold = 3;
SET PERSIST connection_control_min_connection_delay = 1000; -- 1 seconde
SET PERSIST connection_control_max_connection_delay = 86400000; -- 24 heures max

Aprè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;

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 »
SolutionLicenceFonctionnalités
MySQL Enterprise AuditCommercialAudit complet (connexions, requêtes, DDL), format XML/JSON, filtrage par user/event
Percona Audit LogOpen source (Percona Server)Compatible Enterprise Audit, format XML/JSON
MariaDB Audit PluginOpen sourceCompatible MySQL Community (avec limitations de version)
McAfee MySQL Audit PluginOpen 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.

VérificationCommandeAttendu
Pas de compte sans mot de passeSELECT user, host FROM mysql.user WHERE authentication_string = '';Aucune ligne
Pas de @'%' pour l’adminSELECT 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éeSHOW SESSION STATUS LIKE 'Ssl_cipher';Non vide
validate_password actifSHOW 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 restreintSHOW 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ésSELECT 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
SymptômeCause probableSolution
Authentication plugin 'caching_sha2_password' cannot be loadedClient MySQL ancien (5.x) sans support SHA2Mettre à jour le client ou réactiver temporairement mysql_native_password
Access denied après migration vers 8.4mysql_native_password désactivéALTER USER ... IDENTIFIED WITH caching_sha2_password BY '...'
ERROR 2026: SSL connection errorCertificat serveur expiré ou invalideVérifier Ssl_server_not_after, renouveler et ALTER INSTANCE RELOAD TLS
Connexion TLS impossible depuis l’applicationL’application ne passe pas --ssl-mode=REQUIREDConfigurer le connecteur avec SSL obligatoire
SELECT CURRENT_ROLE() retourne NONELes rôles ne sont pas activés par défautSET DEFAULT ROLE ALL TO user@host; ou SET PERSIST activate_all_roles_on_login = ON;
Rôle accordé mais privilèges absentsactivate_all_roles_on_login = OFFSET PERSIST activate_all_roles_on_login = ON;
Oubli du mot de passe rootRedémarrer avec --skip-grant-tables, réinitialiser puis redémarrer normalement (voir guide Installation)
validate_password bloque la créationMot de passe trop simpleRespecter la politique (longueur, majuscule, chiffre, spécial) ou baisser temporairement la policy
  • caching_sha2_password est le plugin par défaut (contrôlé par authentication_policy, plus par default_authentication_plugin qui n’existe plus en 8.4). mysql_native_password est 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 utilise pg_hba.conf. Un compte @'%' avec des privilèges élevés est un risque majeur.
  • REQUIRE SSL dans CREATE USER force le chiffrement — ajoutez --ssl-mode=VERIFY_CA ou VERIFY_IDENTITY côté client pour vérifier l’identité du serveur.
  • Les rôles ne sont pas activés automatiquement à la connexion — pensez à SET DEFAULT ROLE ALL ou activate_all_roles_on_login = ON.
  • N’accordez jamais GRANT ALL ON *.* ni SUPER — utilisez les privilèges granulaires de MySQL 8.4 (FLUSH_PRIVILEGES, SYSTEM_VARIABLES_ADMIN, etc.).
  • partial_revokes permet de révoquer un privilège global sur un schéma précis — indispensable pour protéger le schéma mysql.
  • Installez connection_control pour 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.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn