Après l'installation il ne faut pas lancer le daemon mysqld avec les privilèges de l'utilisateur système root.
Après installation du serveur MySQL, beaucoup de personnes ont la fâcheuse habitude de lancer le daemon avec les privilèges de l'utilisateur système root.
Pourquoi certain décident d'utiliser de lancer le daemon mysqld avec les privilèges de l'utilisateur root ?
Que peut il se passer dans ce mode de fonctionnement de super-utilisateur?
Il faut donc:
groupadd _mysql useradd -g _mysql _mysql useradd -d /nonexistent -s /sbin/nologin -g _mysql _mysql
Sur OpenBSD lors de l'installation de mariadb-server qui est le serveur MySQL, l'utilisateur _mysql et le groupe _mysql sont créés. L'utilisateur créé ne permet pas de se logger!
Il suffit de vérifier le fichiers messages
cat /var/log/messages | grep _mysql new group added: name=_mysql, gid=502 new user added: name=_mysql, uid=502, gid=502, home=/nonexistent, shell=/sbin/nologin
On peut vérifier les utilisateurs et groupes créés avec les commandes suivantes:
cat /etc/passwd _mysql: *:502:502:MySQL Account:/nonexistent:/sbin/nologin
cat /etc/group _mysql: *:502:
Vérification des droits d’accès aux fichiers
ls -l /var drwx------ 5 _mysql _mysql 1024 Jul 21 16:39 mysql 700
On spécifie que l'utilisateur _mysql sera le seul propriétaire du daemon mysqld
nano /etc/my.cnf [mysqld] user = _mysql ou cd /var/mysql bin/mysqld_safe --user=_mysql &
On reboot le serveur
rcctl restart mysqld
On vérifie que que le serveur MySQL tourne avec les droits limités
ps -aux | grep '_mysql' _mysql 35202 0.0 2.3 326788 48952
Lors de l'installation, MySQl va créer un utilisateur nommé root qui possède tous les privilèges sur la base de données.Cet utilisateur n'a aucun mot de passe par défaut, ce qui laisse une fois de plus la possibilité et la porte grande ouverte à un pirate !
On va donc ajouter un mot de passe mais aussi changer le nom d'utilisateur root.
Cela rendra encore plus difficile toute tentative de s'approprier les droits d'administration sur le serveur SQL. Il faudra donc que le pirate trouve non seulement le mot de passe mais également le nom de l’utilisateur !
Méthode 1
mysql -u root -p
UPDATE mysql.user SET User = 'votre_nouveau_nom_utilisateur', Password = PASSWORD('votre_nouveau_mot_de_passe') WHERE User='root';
FLUSH PRIVILEGES;
FLUSH PRIVILEGES; (permet de recharger les privilèges des utilisateurs sans avoir à redémarrer le serveur MySQL)
Méthode 2
SET PASSWORD FOR 'root'@'localhost' = PASSWORD('nouveau_mot_de_passe');
ou
SET PASSWORD FOR root@localhost = PASSWORD('nouveau_mot_de_passe');
RENAME USER root@localhost TO nouveau_nom_utilisateur@localhost;
Vérifier la liste des utilisateurs
SELECT Host,User FROM mysql.user;
A ce stade ci le compte root sous MySQL n'existe plus, il faudra utiliser le nom et mot de passe indiqués dans la requête car on a un nouvel administrateur de la base de données.
Attention le script mysql_secure_installation ne fonctionnera plus !
L'installation par défaut de MySQL contient une autre brèche de sécurité : la présence d'un utilisateur anonyme sans mot de passe. Bien que ses droits d'accès soient très limités, il est fortement recommandé de supprimer ce compte.
La requête suivante se charge de l'opération :
mysql -u votre_nouveau_nom_utilisateur -p DELETE FROM mysql.user WHERE User=''; FLUSH PRIVILEGES;
Si on pense avoir créé un utilisateur sans mot de passe :
DELETE FROM mysql.user WHERE Password=''; FLUSH PRIVILEGES;
Par défaut MySQL crée une data base de test. Cette data base est utile lors de la mise en place de la structure de nos data base mais elle doit être supprimée au plus vite car elle est accessible par défaut à tout utilisateur, ce qui est extrèmement dangerux en matire de sécurité. On eut aussi changer les privilèges d'accès au lieu de la supprimer.
DROP DATABASE test; DELETE FROM mysql.db WHERE Db='test' OR Db='test\_%';
La particularité de MySQL est que chaque nom d'utilisateur est associé à un hôte (host). Celui-ci permet donc de définir l'adresse réseau source autorisée pour la connexion d'un utilisateur. Le couple (nom d’utilisateur, hôte) est représenté sous la forme nom_utilisateur@hote.
Il est donc important de profiter de cette fonctionnalité pour renforcer la sécurité de l'accès à notre data base, mais pour éviter toute erreur dangereuse, il faut connaître le comportement de MySQL pour la gestion de ces hôtes !
Pour s'authentifier à un serveur MySQL, il faut fournir:
Il faut donc que le triplet (username, host, password) existe dans la data base.
La valeur du champs hôte peut être une adresse IP ou un nom d'hôte.
S'il s'agit d'un nom d'hôte, celui-ci devra être traduit en adresse IP soit par le serveur DNS ou soit par le fichier /etc/hosts.
Attention que si le serveur DNS sur lequel on dépend pour traduire les noms d'hôte en adresse IP est corrompus (spoofé), la traduction de noms d'hôte en adresse IP sera faussée et un pirate pourra alors assigner n'importe quelle adresse IP à un nom d'hôte.
Il est donc préférable d'éviter au maximum les noms d'hôtes dans MySQL, sous forme de caractères, plutôt que les adresses IP complètes.
CREATE USER 'toto'@'192.168.1.50' IDENTIFIED BY 'motdepasse';
Pour les connexions locales (à partir de l'hôte même) on n'a pas besoin de spécifier des adresses IP complètes et on peut utiliser le nom d'hôte localhost. Ce nom d'hôte n'est pas traduit en adresse IP par un serveur DNS mais la traduction est réalisées localement sur le système hôte. Cela est possible, car le fichier /etc/hosts contient des associations nom de machine / adresse IP et que localhost est associé à l'adresse de loopback 127.0.0.1.
En rajoutant des associations dans /etc/hosts on peut utiliser de manière sécurisée des noms d'hôtes dans MySQL et donc se passer de serveur DNS.
CREATE USER 'toto'@'192.168.1.0/255.255.255.0' IDENTIFIED BY 'motdepasse';
MySQL permet également d'utiliser des jokers (wildcards) dans l'expression des hôtes.
Comme pour la close LIKE en SQL, un joker est représenté par les caractères % ou _.
Le joker % utilisé seul dans un hôte permet de représenter n’importe quelle adresse IP source. Cette utilisation est vivement déconseillée !
Spécifier une adresse IP complète comme dans l'exemple précédent n'est bien sûr possible qu'en cas d'utilisation d'adresses IP fixes pour les postes des utilisateurs. Mais si les adresses IP du réseau local sont dynamiques (ex. : DHCP), on pourra toujours faire mieux que '%', en permettant un nombre restreint d'adresses IP comme en spécifiant l'adresse IP du réseau local.
Ainsi, si quelqu'un réussit à voler le mot de passe d'un utilisateur MySQL, il ne pourra se connecter que s'il se trouve sur le même réseau local.
CREATE USER 'toto'@'192.168.1.%' IDENTIFIED BY '...';
Au lieu d'utiliser le joker %, on peut écrire l'adresse IP du réseau couplé à son masque :
CREATE USER 'toto'@'192.168.110.0/255.255.255.0' IDENTIFIED BY '...';
delete from mysql.user where user='toto@192.168.1.0/255.255.255.0' and host = '%';
Précédemment, nous avons sécurisé le compte root en lui assignant un mot de passe. En réalité, il y a deux utilisateurs root dans une installation par défaut de MySQL. Cela peut sembler étonnant, mais le fait qu'il existe deux utilisateurs root avec des noms d'hôte différents en font deux administrateurs indépendants, qui peuvent ainsi avoir des privilèges et/ou un mot de passe différents.
Les deux utilisateurs root présents dans une installation par défaut sont :
Lorsque l'utilisateur root se connecte au service de MySQL à partir de la machine locale, les deux hôtes localhost et % sont valides ; et MySQL doit donc faire un choix. Lors de l'établissement d'une connexion, si plusieurs correspondances existent, c'est la plus explicite qui est choisie. Ainsi pour une connexion locale, c'est localhost qui est privilégié. L'hôte '%' sera dans tous les cas le dernier choix, car il s'agit de l'hôte le moins explicite.
Enfin, notons que si un utilisateur n'est pas spécifié avec son hôte dans une commande MySQL, l'hôte % sera automatiquement supposé.
Ainsi, les deux commandes suivantes sont équivalentes :
CREATE USER 'toto' IDENTIFIED BY '...'; CREATE USER 'toto@%' IDENTIFIED BY '...';
Exercice:
Je veux que utilisateur :
CREATE USER 'zozo'@'localhost' IDENTIFIED BY 'a'; CREATE USER 'aiko'@192.168.1.202' IDENTIFIED BY 'a'; CREATE USER 'toto'@'192.168.1.0/255.255.255.0' IDENTIFIED BY 'a'; CREATE USER 'spi'@'192.168.1.%' IDENTIFIED BY 'a';
SELECT Host,User FROM mysql.user;
| Host | User |
|---|---|
| localhost | zozo |
| 192.168.1.202 | aiko |
| 192.168.1.0/255.255.255.0 | toto |
| 192.168.1.% | spi |

Test de connexion
mysql -u zozo -p mysql -h 192.168.1.206 -u aiko -p mysql -h 192.168.1.206 -u toto -p mysql -h 192.168.1.206 -u spi -p
Bon reste plus qu'a mettre certains droits pour que mes utilisateurs puissent faire quelque chose
ERROR 2003 (HY000): Can't connect to MySQL server on '192.168.1.206' (111 “Connection refused”)
bind-address = 127.0.0.1
nano /etc/my.cnf [mysqld] #bind-address = 127.0.0.1 bind-address = 192.168.1.206
ERROR 1045 (28000): Access denied for user 'aiko'@'ok.home.lan' (using password: YES)
ERROR 1130 (HY000): Host 'ok.home.lan' is not allowed to connect to this MariaDB server
L'utilisateur n’existe pas il faut le créer
Le compte root sous MySQL est le plus dangereux, puisqu'il correspond au compte DBA, c'est-à-dire à l'administrateur de la base de données. C'est pour cette raison qu'il est nécessaire de prêter une attention toute particulière à la sécurisation de cet accès.
Jusqu'à présent, nous avons spécifié un mot de passe pour le compte root et changé le nom d'utilisateur. En supposant que le mot de passe ne soit pas facilement devinable ou crackable (voir partie « Réflexions sur les mots de passe »), cela constitue une première bonne protection. Mais nous n'allons pas nous arrêter en si bon chemin ! En effet, nous allons aussi interdire tout accès direct au serveur MySQL via l'extérieur.
Si votre serveur MySQL n'est interrogé et administré qu'en local (ex : Apache/PHP et MySQL sur la même machine), le plus sécurisé et le plus rapide est de simplement interdire tout accès provenant d'une autre machine.
Pour cela, nous pouvons configurer un firewall (netfilter / iptables, packet filter…) pour qu'il interdise tout accès entrant vers le port de MySQL, en général 3306.
Cependant, MySQL propose un moyen encore plus simple : ne pas permettre les connexions TCP/IP, mais seulement des connexions faites via un procédé système local, par exemple une socket Unix (la fameuse mysql.sock), des tubes nommés ou par mémoire partagée (sous Windows uniquement).
Afin de désactiver les connexions TCP/IP, il faut démarrer le serveur avec l'option –skip-networking ou bien modifier la partie [mysqld] dans le fichier de configuration du serveur (ex. : /etc/my.cnf) :
[mysqld] skip-networking
Pour faciliter la communication via socket, il est conseillé de spécifier le chemin d'accès à cette socket dans le ou les fichiers de configuration du serveur et des clients MySQL :
[mysqld] socket = /tmp/mysql.sock [client] socket = /tmp/mysql.sock
Maintenant que nous avons bloqué tout accès distant, nous pouvons également nettoyer la table de privilèges, en supprimant les utilisateurs qui pouvaient se connecter à distance :
DELETE FROM mysql.user WHERE Host <> 'localhost'; FLUSH PRIVILEGES;
Par défaut, il s’agit de 127.0.0.1. Si on veut autoriser le réseau local, n’indiquez pas une adresse réseau mais bien l’adresse du serveur sur le réseau. D’où l’intérêt d’avoir des réglages IP fixes ou des baux permanents attribués par le DHCP. Dans le cas contraire, je vous promet des heures de recherche infructueuses avant de revenir dessus.
Si vous avez obligatoirement besoin d'un accès à distance au serveur MySQL, il existe une méthode relativement bien sécurisée, et surtout valide pour de nombreux programmes client/serveur. Cette solution consiste à utiliser un tunnel SSH (Secure SHell) qui non seulement renforcera l'identification, mais en plus, chiffrera toutes les communications entre le client et le serveur MySQL !
Comme son nom l'indique, le but premier du Secure SHell est de permettre un accès sécurisé à une console (un shell) afin d'exécuter des commandes à distance. Cependant, son assurance de la confidentialité et de l'intégrité des données circulant sur le réseau, lui a également donné une autre fonctionnalité : le tunneling.
Le tunneling, aussi appelé port-forwarding (redirection de port), consiste à utiliser SSH comme une sous-couche dont le but est de sécuriser l'échange de données. En pratique, cela revient à se connecter à un serveur SSH et à ouvrir un port en local. Ce port local est utilisé pour se connecter au service (dans notre cas, à MySQL) et le client SSH redirige les données au serveur SSH, qui lui-même les retransmet au service.
Voyons un exemple pour mieux comprendre.
Au vu de ce schéma d'utilisation, nous pouvons déjà remarquer une chose : aucune connexion directe sur le port 3306 du serveur MySQL n'est établie avec le client. Toutes les données provenant du client sont envoyées sur le port SSH du serveur. Pour sécuriser notre serveur MySQL, nous pouvons donc déjà interdire les connexions provenant de l'extérieur.
Nous avons vu comment interdire toute connexion TCP/IP grâce à l'option skip-networking. Cependant, celle-ci ne convient pas dans le cas d'un tunnel SSH. En effet, le serveur SSH doit être capable de rediriger les données vers le serveur MySQL et pour cela, il n'y a pas d'autre solution que TCP/IP. Il est donc nécessaire d'autoriser les connexions TCP/IP locales.
Pour ce faire, nous allons utiliser l'option bind-address qui permet de limiter la provenance des connexions. Voilà ce qui peut être ajouté dans le fichier de configuration de MySQL :
[mysqld] bind-address=127.0.0.1
Après redémarrage du serveur, seules les connexions provenant de 127.0.0.1 (localhost) seront acceptées. Et puisque nous sommes un peu paranoïaques et surtout perfectionnistes, nous allons également modifier les privilèges de l'utilisateur root (ou autre nom si vous l'avez changé, comme il l'a été conseillé précédemment) sous MySQL :
DELETE FROM mysql.user WHERE User='root' AND Host != 'localhost'; FLUSH PRIVILEGES;
Après exécution de ces requêtes, l'utilisateur root ne pourra s'identifier sur MySQL que s'il est sur la même machine.
Nous n'allons pas voir comment mettre en place (et sécuriser) un serveur SSH, ni comment configurer le client pour activer un tunnel. Je vous conseille cependant de regarder du côté de OpenSSH qui comporte un serveur et un client SSH. Par défaut, le serveur d'OpenSSH (sshd) est configuré pour permettre le tunneling. Pour vous en assurer, vérifier que l'option PermitTunnel est à “yes” dans le fichier de configuration de sshd (en général /etc/ssh/sshd_config)
Voici un exemple de connexion tunnelée en utilisant le client console de MySQL et le client SSH d'OpenSSH :
> ssh -f -L 66306:127.0.0.1:3306 mysql.mondomaine.com sleep 10 admin@host1.mondomaine.com's password : xxxxxxx => À partir d'ici, nous sommes connectés au serveur SSH et notre tunnel est activé sur le port local 66306. > mysql -h 127.0.0.1 -P 66306 -u root -p => Pour nous connecter au serveur MySQL, nous utilisons localhost:66306 et non mysql.mondomaine.com:3306
Grâce à ce tunnel, non seulement la communication entre le client et le serveur MySQL sera chiffrée, mais en plus, l'identification sera renforcée puisqu'il faudra également s'identifier sur SSH. À titre d'information, il est possible de désactiver l'identification SSH si le fait d'entrer deux mots de passe vous gêne. Cependant, pensez à sécuriser le compte système utilisé pour la connexion SSH !
Si la machine du serveur MySQL possède également les programmes d'administration (mysql, mysqldump…), il n'est pas nécessaire de mettre en place le port-forwarding. On peut tout simplement lancer les commandes directement sur le shell. Un petit exemple :
> ssh mysql.mondomaine.com /usr/local/mysql/bin/mysqldump -A > backup
La sécurité d'une base de données passe également par une gestion réfléchie des privilèges des utilisateurs. Le langage SQL propose deux mots clés permettant de gérer les privilèges : GRANT et REVOKE. Nous allons apprendre à les utiliser ici, avec les spécificités de MySQL.
Tout d'abord, il est important de rappeler la règle d'or pour une gestion sécurisée des droits utilisateurs : un minimum de droits = un maximum de sécurité. En d'autres termes, il est complètement inutile d'attribuer plus de privilèges que ceux nécessaires pour réaliser les opérations prévues. Tout privilège excessif peut donner lieu à une faille de sécurité.
Ainsi, il est évident que, dans les applications qui utilisent la base de données, l'utilisateur root (ou tout autre administrateur) ne doit pas être utilisé. Il faut donc créer un ou plusieurs utilisateurs sous MySQL qui n'auront que les droits correspondants aux opérations que permet l'application.
La commande GRANT permet d'attribuer des privilèges. La plupart des privilèges peuvent concerner une colonne, une table entière ou une base de données. Certains peuvent même être globaux, c'est-à-dire valides pour toutes les tables et toutes les bases de données. Des privilèges s'appliquent également aux routines : procédures stockées, fonctions et triggers.
Voyons brièvement quelques exemples de la commande GRANT. Pour plus d'informations concernant la syntaxe et les privilèges disponibles dans MySQL, référez-vous à la documentation officielle.
1. Créons tout d'abord une base de données contenant deux tables pour nos tests
mysql> CREATE DATABASE mabase;
mysql> USE mabase;
mysql> CREATE TABLE testGrant1 (id INT, lib VARCHAR(20));
mysql> CREATE TABLE testGrant2 (code VARCHAR(3), prix DECIMAL(5,2));
mysql> INSERT INTO testGrant1 VALUES (1, 'Test'), (2, 'Retest'), (3, 'OK');
mysql> INSERT INTO testGrant2 VALUES ('AAA', 50.23), ('BBB', 24.20);
2. Nous allons maintenant accorder des privilèges à trois utilisateurs :
3. On créé le premier utilisateur et on lui donne les privilèges ⇒ utilisateur1:
mysql> GRANT SELECT (code) ON mabase.testGrant2 TO 'utilisateur1'@'%' IDENTIFIED BY 'pass1';
Ici nous donnons donc le droit SELECT sur la colonne code de la table testGrant2, qui appartient à la base de données mabase, à l'utilisateur “utilisateur1” qui peut se connecter de n'importe quel host ('%') et dont le mot de passe est “pass1”.
Si l'utilisateur n'existe pas, la commande GRANT se charge de le créer. C'est la raison pour laquelle nous spécifions le mot de passe de l'utilisateur.
3.a Connectons-nous maintenant à MySQL avec ce nouvel utilisateur et testons quelques requêtes :
mysql -h 192.168.1.206 -u utilisateur1 -p mysql> SELECT * FROM mabase.testGrant2; ERROR 1143 (42000): SELECT command denied to user 'utilisateur1'@'localhost' for column 'prix' in table 'testgrant2'
mysql> SELECT code FROM mabase.testGrant2; +------+ | code | +------+ | AAA | | BBB | +------+
Nous pouvons donc remarquer que MySQL empêche bien le SELECT sur une autre colonne que code, c'est-à-dire la colonne prix pour notre exemple.
4. On créé le deuxième utilisateur et on lui donne les privilèges ⇒ utilisateur2:
mysql> GRANT INSERT ON mabase.* TO 'utilisateur2'@'%' IDENTIFIED BY 'pass2';
Nous lui donnons le droit d'INSERT dans les deux tables de mabase.
4.a Connectons-nous maintenant à MySQL avec ce nouvel utilisateur et testons quelques requêtes :
mysql -h 192.168.1.206 -u utilisateur2 -p mysql> SELECT * FROM mabase.testGrant1; ERROR 1142 (42000): SELECT command denied to user 'utilisateur2'@'localhost' for table 'testgrant1'
mysql> DELETE FROM mabase.testGrant2; ERROR 1142 (42000) : DELETE command denied to user 'utilisateur2'@'localhost' for table 'testgrant2'
mysql> INSERT INTO mabase.testGrant1 VALUES (1, 'allo ?'); Query OK, 1 row affected (0.00 sec)
L'insertion fonctionne, mais toute autre opération (SELECT, DELETE…) échoue. C'est exactement ce que nous voulons.
5. On créé le troisième utilisateur et on lui donne les privilèges pour les opérations courantes ⇒ utilisateur3:
mysql> GRANT SELECT, INSERT, UPDATE, DELETE ON mabase.* TO 'utilisateur3'@'%' IDENTIFIED BY 'pass3';
Dans la pratique, on peut imaginer que :
Ces exemples montrent quelques possibilités de GRANT qui simplifient parfois bien la vie des administrateurs de bases de données. Cependant, ce ne sont pas forcément des habitudes à prendre quand on désire sécuriser au maximum l'accès aux données.
Tout d'abord, comme nous l'avons déjà vu, l'utilisation de '%' pour les hostnames est tout simplement à proscrire, car il permet à un utilisateur de se connecter de n'importe où. Si vous avez mis en place un tunnel SSH ou si vous avez désactivé les connexions TCP/IP (–skip-networking), cela n'est pas bien grave. Dans le cas contraire, veillez à toujours spécifier un hôte le plus complet possible.
Seconde réflexion à propos de la sécurité dans nos exemples précédents : l'utilisation de * pour attribuer des droits à plusieurs tables avec un seul GRANT. Là encore, c'est très pratique. Pour l'utilisateur n° 2, nous voulions lui attribuer le privilège INSERT sur les deux tables, et comme notre base ne comportait que ces deux tables, l'utilisation de mabase.* semblait parfaite. Or, si maintenant nous rajoutons d'autres tables, l'utilisateur n° 2 pourra également insérer dedans ! Il vaut donc mieux perdre quelques secondes pour faire plusieurs GRANT que risquer de donner dans le futur des privilèges non souhaités.
S'il n'y avait qu'une seule phrase pour résumer l'utilisation judicieuse de GRANT, elle serait la suivante : limiter le plus possible les privilèges pour qu'ils correspondent uniquement aux besoins ; et utiliser le moins possible les jokers (en anglais : wildcards, c'est-à-dire les caractères * et %).
Un moyen simple d'obtenir des privilèges adaptés aux besoins est de créer des vues (depuis MySQL 5) réalisant les SELECT fréquents, et ne donner les droits que sur les vues et non sur les tables directement. En cas de mise à jour de la requête, il suffira de modifier la vue. C'est donc plus simple que de devoir modifier les privilèges des utilisateurs, surtout si plusieurs utilisateurs ont le droit d'exécuter ces SELECT.
Imaginons une table avec dix colonnes (col1, col2…, col10). Nous désirons limiter l'accès en lecture aux cinq premières colonnes pour un utilisateur. Pour ceci, nous créons une vue et donnons le privilège SELECT sur cette vue à l'utilisateur concerné.
mysql> CREATE VIEW vue_req1 AS SELECT col1, col2, col3, col4, col5 FROM uneTable;
mysql> GRANT SELECT ON mabase.vue_req1 TO 'utilisateur1'@'localhost';
Cette méthode est même plus sécurisée que de donner les privilèges de SELECT sur chaque colonne, car grâce à la vue, l'utilisateur ne peut pas connaître les champs des tables auxquels il n'a pas accès.
Dans notre exemple, la vue restreint le nombre de colonnes accessibles. Il est bien sûr possible d'utiliser une vue pour restreindre le nombre de lignes accessibles, et cela grâce à une clause WHERE.
Voyons maintenant la commande REVOKE qui permet de révoquer des privilèges. Sa syntaxe est très proche de celle de GRANT. Si par exemple, nous voulons supprimer le privilège DELETE à un utilisateur sur toutes les bases et tables auxquelles il a accès, nous pouvons exécuter la commande suivante :
mysql> REVOKE DELETE ON *.* FROM 'utilisateur1'@'localhost';
Grâce aux commandes GRANT et REVOKE, vous pouvez donc gérer les privilèges de vos utilisateurs. Une autre commande intéressante à connaître est SHOW GRANTS qui permet à un utilisateur de voir les privilèges qui lui ont été accordés. En tant qu'administrateur, vous pouvez également utiliser cette commande pour lister les privilèges octroyés à un utilisateur spécifique :
mysql> SHOW GRANTS FOR 'utilisateur1'@'localhost';
Il est vivement conseillé d'afficher la liste des privilèges octroyés après une modification de ceux-ci. En effet, certains détails pourraient vous échapper et ainsi laisser des privilèges actifs alors que vous pensiez les avoir supprimés. Prenons un exemple qui pourrait s'avérer dangereux.
Imaginons que vous ayez créé un utilisateur toto@localhost et que vous lui donniez un privilège INSERT sur votre table produits de la base catalogue :
GRANT INSERT ON catalogue.produits TO toto@localhost;
Tout fonctionne à merveille pendant plusieurs mois, jusqu'au jour où vous décidez d'octroyer à toto un privilège d'insertion sur toute la base catalogue. On peut par exemple imaginer que votre application qui fait ses requêtes avec l'utilisateur toto vient d'être dotée de nouvelles fonctionnalités.
Vous exécutez dès lors la commande suivante :
GRANT INSERT ON catalogue.* TO toto@localhost;
Si vous affichez les privilèges donnés à cet utilisateur, vous pouvez remarquer que MySQL n'a pas regroupé les deux privilèges INSERT :
SHOW GRANTS FOR toto@localhost; +--------------------------------------------------------------+ | GRANT USAGE ON *.* TO 'toto'@'localhost' ... | | GRANT INSERT ON `catalogue`.* TO 'toto'@'localhost' | | GRANT INSERT ON `catalogue`.`produits` TO 'toto'@'localhost' | +--------------------------------------------------------------+
Si maintenant vous révoquez le privilège INSERT sur la base entière, l'ancien privilège INSERT restera !
REVOKE INSERT ON catalogue.* FROM toto@localhost;
SHOW GRANTS FOR toto@localhost; +--------------------------------------------------------------+ | GRANT USAGE ON *.* TO 'toto'@'localhost' ... | | GRANT INSERT ON `catalogue`.`produits` TO 'toto'@'localhost' | +--------------------------------------------------------------+
Révoquer un privilège qui s'applique à une base (nom_base.*) ou qui est global (*.*) n'est donc pas équivalent à supprimer tous les privilèges inclus !
Certains privilèges sous MySQL sont très dangereux. Il vaut donc mieux éviter de les attribuer. Ceux-ci sont pour la plupart des privilèges réservés à des tâches d'administration :
mysql> GRANT GRANT OPTION ON *.* TO utilisateur;