Oct 23 2009

Comment faire quand on n’a plus de « root » dans MySQL ?

Category: Divers,Linux,SQL

Hier j'ai fait une grosse bourde... Pour des raisons que je ne vais pas détailler ici il me fallait changer le mot de passe de l'utilisateur « root », qui ne s'appelait d'ailleurs pas « root » pour des raisons évidentes de sécurité, sur une base de données en production.
Fausse manip ! Boum dans le mur ! Plus de super utilisateur dans la base !
Heureusement qu'il y avait un utilisateur SQL différent pour chaque application... tout continuait à tourner rond et personne ne se doutait du profond désarrois dans lequel était plongé l'administrateur devant sa bévue.
Voici donc comment remédier à ce grave problème; dans tous les cas il faut avoir un accès au système, sinon... ben... les carottes sont cuites...

Sous Debian/Ubuntu

Si l'utilisateur « root » existe mais qu'on ne connaît pas son mot de passe

Ce n'est pas une très bonne pratique de le laisser sous ce nom mais, dans le cas présent, ça simplifie la résolution du problème ;-)
Il suffit en effet, en tant que « root » --celui du système--, de lancer la commande dpkg-reconfigure mysql-server-5.0.

Si l'utilisateur « root » (ou son équivalent) n'existe pas

Dans le fichier /etc/mysql/debian.cnf on peut récupérer le mot de passe de l'utilisateur debian-sys-maint. Après s'être loguer avec ces identifiants il n'est pas encore possible de créer un nouvel utilisateur ayant tous les droits; qu'à cela ne tienne... On se logue:

$ mysql -u debian-sys-maint -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 682
Server version: 5.0.51a-24+lenny1 (Debian)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql>
  

On modifie la table mysql.user pour donner à debian-sys-maint le droit de créer un nouvel utilisateur (ne pas oublier le FLUSH PRIVILEGES;)

mysql> use mysql;
Reading table information for completion [...]
Database changed

mysql> UPDATE user SET Create_user_priv='Y' WHERE User='debian-sys-maint';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.07 sec)
  

Il ne reste plus qu'à recréer l'utilisateur « root » avec tous les droits (voir le code en fin d'article). L'avantage de cette solution et qu'il n'y a pas besoin d'arrêter le serveur et que les opérations s'effectuent en toute sécurité (contrairement à la méthode suivante).

Méthode indépendante de la distribution Linux

Dans les deux cas suivants, il faut arrêter le serveur MySQL et le redémarrer avec l'option --skip-grant-tables.
Attention, cette option donne TOUS LES DROITS À TOUS UTILISATEURS SANS AVOIR À DONNER DE MOT DE PASSE. Il faut donc agir vite et ne pas oublier de redémarrer le serveur sans cette option, une fois la réparation effectuée.

/etc/init.d/mysql stop
mysqld --skip-grant-tables &
mysql -u root
  

Si l'utilisateur « root » existe mais qu'on ne connaît pas son mot de passe

Il suffit de mettre à jour le « password » avec les requêtes SQL
UPDATE mysql.user SET Password=PASSWORD('ROOT_PASS') WHERE User='root';
FLUSH PRIVILEGES;

Si l'utilisateur « root » (ou son équivalent) n'existe pas

Il suffit de le créer... voir l'annexe en fin d'article.

Redémarrer le serveur

Ne pas oublier de redémarrer le serveur sans l'option --skip-grant-tables:

killall mysqld
/etc/init.d/mysql start
  




ANNEXE: créer un super utilisateur MySQL « root »

Changer ci-dessous le texte ROOT_PASS par le mot de passe à donner à « root ».

La méthode bulldozer:

INSERT INTO `user`
  (`Host`, `User`, `Password`, `Select_priv`, `Insert_priv`,
   `Update_priv`, `Delete_priv`, `Create_priv`, `Drop_priv`,
   `Reload_priv`, `Shutdown_priv`, `Process_priv`, `File_priv`,
   `Grant_priv`, `References_priv`, `Index_priv`, `Alter_priv`,
   `Show_db_priv`, `Super_priv`, `Create_tmp_table_priv`, `Lock_tables_priv`,
   `Execute_priv`, `Repl_slave_priv`, `Repl_client_priv`, `Create_view_priv`,
   `Show_view_priv`, `Create_routine_priv`, `Alter_routine_priv`,
   `Create_user_priv`, `ssl_type`, `ssl_cipher`, `x509_issuer`,
   `x509_subject`, `max_questions`, `max_updates`, `max_connections`,
   `max_user_connections`)
VALUES
  ('localhost', 'root', PASSWORD('ROOT_PASS'), 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y',
   'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y', 'Y',
   'Y', 'Y', 'Y', '', '', '', '', 0, 0, 0, 0);
  

Une méthode élégante

CREATE USER 'root'@'localhost' IDENTIFIED BY 'ROOT_PASS';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION;