mysql: Afficher les subventions pour tous les utilisateurs


87

MySQL SHOW GRANTSaffiche les permissions de l'utilisateur actuel.

Existe-t-il un moyen de se connecter en tant que root et d'afficher les autorisations de tous les utilisateurs?

Réponses:


45

Rien intégré. Vous avez deux options:

  • Utilisez common_schemala vue sql_show_grants . Par exemple, vous pouvez interroger:

    SELECT sql_grants FROM common_schema.sql_show_grants;

    Ou vous pouvez interroger des utilisateurs particuliers, par exemple:

    SELECT sql_grants FROM common_schema.sql_show_grants WHERE user='app';

    Pour installer common_schema, suivez les instructions ici .

    Disclaimer: Je suis l'auteur de cet outil.

  • Utilisez la boîte à outils Percona pt-show-grants, par exemple:

    pt-show-grants --host localhost --user root --ask-pass

Dans les deux cas, vous pouvez demander la GRANTcommande ou la commande REVOKE(opposée).

Le premier cas nécessite l'installation d'un schéma, le second nécessite l'installation de scripts PERL + dépendances.


11
Pourriez-vous décrire plus en détail comment utiliser la vue sql_show_grants de common_schema? Je reçois une erreurERROR 1146 (42S02): Table 'common_schema.sql_show_grants' doesn't exist
Martin Vegter

2
@MartinVegter, avez-vous installé common_schema? Téléchargez ici et installez en suivant ces instructions .
Shlomi Noach

1
@ShlomiNoach, Quand vous dites qu'il n'y a "rien d'intégré" ... Y a-t-il des erreurs avec information_schema.user_privileges?
Pacerier

2
Désolé, il n’existe pas de "common_schema". Ça n'existe pas.
Brendan Byrd

2
lien sql_show_grants cassé
Cyzanfar

81
select * from information_schema.user_privileges;

MODIFIER:

Comme mentionné par Shlomi Noach:

Il ne répertorie pas les privilèges spécifiques à la base de données, à la table, à la colonne ou à la routine. Par conséquent, l'octroi GRANT SELECT ON mydb. * TO myuser @ localhost n'apparaît pas dans information_schema.user_privileges. La solution common_schema présentée ci-dessus agrège les données de user_privileges et d'autres tables pour vous donner une image complète.


5
Désolé, cela ne devrait pas être la réponse acceptée. information_schema.user_privilegesrépertorie uniquement les privilèges de niveau utilisateur, tels que SUPER, RELOADetc. Il répertorie également les autorisations DML complètes telles que SELECT. Il ne répertorie pas les privilèges spécifiques aux bases de données, aux tables, aux colonnes et aux sous-programmes. Par GRANT SELECT ON mydb.* TO myuser@localhostconséquent , la subvention ne s'affiche pasinformation_schema.user_privileges . La common_schemasolution présentée ci-dessus regroupe les données de user_privilegeset d'autres tableaux pour vous donner une image complète.
Shlomi Noach

11

Ce fragment de shell Linux parcourt tous les utilisateurs de MySQL et effectue un SHOW GRANTS pour chacun:

mysql --silent --skip-column-names --execute "select concat('\'',User,'\'@\'',Host,'\'') as User from mysql.user" | sort | \
while read u
 do echo "-- $u"; mysql --silent --skip-column-names --execute "show grants for $u" | sed 's/$/;/'
done

Fonctionne mieux si vous pouvez vous connecter à MySQL sans mot de passe.

La sortie est formatée pour pouvoir être exécutée dans un shell MySQL. Attention: La sortie contient également les permissions de l'utilisateur MySQL et le mot de passe! Supprimez ces lignes si vous ne voulez pas que l'utilisateur root de MySQL soit changé.


6
Vous voudrez peut-être ajouter quelques détails sur ce que cela fait ou comment cela répond à la question. Le simple affichage d'un tas de code n'aide personne à comprendre pourquoi votre solution fonctionne.
Max Vernon

Où puis-je donner un mot de passe?
Mian Asbat Ahmad le

Pour fournir un mot de passe, vous pouvez utiliser un fichier d'options ou le drapeau --password de la commande mysql.
mleu

Ne serait-il pas possible de donner un mot de passe root et d'exécuter la requête pour obtenir toutes les autorisations des utilisateurs?
Mian Asbat Ahmad le

2
Vous pouvez diffuser les demandes afin de ne créer qu'une seule connexion et utiliser un fichier d'informations d'identification en mode 400 appartenant à la racine. Ma version:mysql --defaults-file=/auth/root-mysql.cnf --batch --skip-column-names --execute "SELECT User, Host from mysql.user" | while read user host; do echo "SHOW GRANTS FOR '${user}'@'${host}';"; done | mysql --defaults-file=/auth/root-mysql.cnf --batch | sed 's/^Grants for/-- Grants for/'
BaseZen

9

select * from mysql.user;

Peut vous donner la liste des utilisateurs et les privilèges attribués à chacun d'eux, nécessite l'accès à la mysql.usertable et l' rootutilisateur la possède.


4
Cela ne vous donne que les privilèges "de premier niveau" (niveau du serveur). Les privilèges définis sur des schémas spécifiques sont dans mysql.db. Les privilèges sur des tables spécifiques sont inclus mysql.tables_priv, etc. Donc ce n'est pas si simple.
Shlomi Noach

Pour les manigances de table arc-en-ciel, jetez votre mot de passe haché de crackselect * from mysql.user dans crackstation.net et affichez la sortie non hachée.
Pacerier

8

Une doublure (changer -urootpour -u$USER_NAMEpour une utilisation avec d' autres utilisateurs) dans un bash Unix ( en raison des accents graves):

mysql -uroot -p -sNe"`mysql -uroot -p -se"SELECT CONCAT('SHOW GRANTS FOR \'',user,'\'@\'',host,'\';') FROM mysql.user;"`"

ou sans backticks et avec mot de passe inline (l'espace devant la commande l'exclut de l'historique Bash dans Ubuntu):

 mysql -uroot -p"$PASSWORD" -sNe"$(mysql -uroot -p"$PASSWORD" -se"SELECT CONCAT('SHOW GRANTS FOR \'',user,'\'@\'',host,'\';') FROM mysql.user;")"

Sous Windows:

mysql -uroot -p -se"SELECT CONCAT('SHOW GRANTS FOR \'',user,'\'@\'',host,'\';') FROM mysql.user;" > grants.sql
mysql -uroot -p < grants.sql
del grants.sql

4

Si vous pouvez exécuter les instructions SELECT suivantes sans erreur:

/* User-Specific Grants     */   SELECT * FROM mysql.user;
/* Database-Specific Grants */   SELECT * FROM mysql.db;
/* Table-Specific Grants    */   SELECT * FROM mysql.tables_priv;
/* Column-Specific Grants   */   SELECT * FROM mysql.columns_priv;

alors n'hésitez pas à utiliser le code suivant (ci-dessous), écrit en syntaxe .sql.

J'ai conçu cette requête dans le but de reconstruire les instructions GRANT pour toutes les autorisations existantes (pour un entretien fréquent lors de la migration de la base de données). Il existe quelques problèmes à résoudre, tels que la liaison utilisateur-mot de passe, mais étant donné que nous mettons souvent à jour les mots de passe, cela ne faisait pas partie du projet.

/* Get All Grants/Permissions for MySQL Instance */

/* [Database.Table.Column]-Specific Grants */
SELECT
    CONCAT("`",gcl.Db,"`") AS 'Database(s) Affected',
    CONCAT("`",gcl.Table_name,"`") AS 'Table(s) Affected',
    gcl.User AS 'User-Account(s) Affected',
    IF(gcl.Host='%','ALL',gcl.Host) AS 'Remote-IP(s) Affected',
    CONCAT("GRANT ",UPPER(gcl.Column_priv)," (",GROUP_CONCAT(gcl.Column_name),") ",
                 "ON `",gcl.Db,"`.`",gcl.Table_name,"` ",
                 "TO '",gcl.User,"'@'",gcl.Host,"';") AS 'GRANT Statement (Reconstructed)'
FROM mysql.columns_priv gcl
GROUP BY CONCAT(gcl.Db,gcl.Table_name,gcl.User,gcl.Host)
/* SELECT * FROM mysql.columns_priv */

UNION

/* [Database.Table]-Specific Grants */
SELECT
    CONCAT("`",gtb.Db,"`") AS 'Database(s) Affected',
    CONCAT("`",gtb.Table_name,"`") AS 'Table(s) Affected',
    gtb.User AS 'User-Account(s) Affected',
    IF(gtb.Host='%','ALL',gtb.Host) AS 'Remote-IP(s) Affected',
    CONCAT(
        "GRANT ",UPPER(gtb.Table_priv)," ",
        "ON `",gtb.Db,"`.`",gtb.Table_name,"` ",
        "TO '",gtb.User,"'@'",gtb.Host,"';"
    ) AS 'GRANT Statement (Reconstructed)'
FROM mysql.tables_priv gtb
WHERE gtb.Table_priv!=''
/* SELECT * FROM mysql.tables_priv */

UNION

/* Database-Specific Grants */
SELECT
    CONCAT("`",gdb.Db,"`") AS 'Database(s) Affected',
    "ALL" AS 'Table(s) Affected',
    gdb.User AS 'User-Account(s) Affected',
    IF(gdb.Host='%','ALL',gdb.Host) AS 'Remote-IP(s) Affected',
    CONCAT(
        'GRANT ',
        CONCAT_WS(',',
            IF(gdb.Select_priv='Y','SELECT',NULL),
            IF(gdb.Insert_priv='Y','INSERT',NULL),
            IF(gdb.Update_priv='Y','UPDATE',NULL),
            IF(gdb.Delete_priv='Y','DELETE',NULL),
            IF(gdb.Create_priv='Y','CREATE',NULL),
            IF(gdb.Drop_priv='Y','DROP',NULL),
            IF(gdb.Grant_priv='Y','GRANT',NULL),
            IF(gdb.References_priv='Y','REFERENCES',NULL),
            IF(gdb.Index_priv='Y','INDEX',NULL),
            IF(gdb.Alter_priv='Y','ALTER',NULL),
            IF(gdb.Create_tmp_table_priv='Y','CREATE TEMPORARY TABLES',NULL),
            IF(gdb.Lock_tables_priv='Y','LOCK TABLES',NULL),
            IF(gdb.Create_view_priv='Y','CREATE VIEW',NULL),
            IF(gdb.Show_view_priv='Y','SHOW VIEW',NULL),
            IF(gdb.Create_routine_priv='Y','CREATE ROUTINE',NULL),
            IF(gdb.Alter_routine_priv='Y','ALTER ROUTINE',NULL),
            IF(gdb.Execute_priv='Y','EXECUTE',NULL),
            IF(gdb.Event_priv='Y','EVENT',NULL),
            IF(gdb.Trigger_priv='Y','TRIGGER',NULL)
        ),
        " ON `",gdb.Db,"`.* TO '",gdb.User,"'@'",gdb.Host,"';"
    ) AS 'GRANT Statement (Reconstructed)'
FROM mysql.db gdb
WHERE gdb.Db != ''
/* SELECT * FROM mysql.db */

UNION

/* User-Specific Grants */
SELECT
    "ALL" AS 'Database(s) Affected',
    "ALL" AS 'Table(s) Affected',
    gus.User AS 'User-Account(s) Affected',
    IF(gus.Host='%','ALL',gus.Host) AS 'Remote-IP(s) Affected',
    CONCAT(
        "GRANT ",
        IF((gus.Select_priv='N')&(gus.Insert_priv='N')&(gus.Update_priv='N')&(gus.Delete_priv='N')&(gus.Create_priv='N')&(gus.Drop_priv='N')&(gus.Reload_priv='N')&(gus.Shutdown_priv='N')&(gus.Process_priv='N')&(gus.File_priv='N')&(gus.References_priv='N')&(gus.Index_priv='N')&(gus.Alter_priv='N')&(gus.Show_db_priv='N')&(gus.Super_priv='N')&(gus.Create_tmp_table_priv='N')&(gus.Lock_tables_priv='N')&(gus.Execute_priv='N')&(gus.Repl_slave_priv='N')&(gus.Repl_client_priv='N')&(gus.Create_view_priv='N')&(gus.Show_view_priv='N')&(gus.Create_routine_priv='N')&(gus.Alter_routine_priv='N')&(gus.Create_user_priv='N')&(gus.Event_priv='N')&(gus.Trigger_priv='N')&(gus.Create_tablespace_priv='N')&(gus.Grant_priv='N'),
            "USAGE",
            IF((gus.Select_priv='Y')&(gus.Insert_priv='Y')&(gus.Update_priv='Y')&(gus.Delete_priv='Y')&(gus.Create_priv='Y')&(gus.Drop_priv='Y')&(gus.Reload_priv='Y')&(gus.Shutdown_priv='Y')&(gus.Process_priv='Y')&(gus.File_priv='Y')&(gus.References_priv='Y')&(gus.Index_priv='Y')&(gus.Alter_priv='Y')&(gus.Show_db_priv='Y')&(gus.Super_priv='Y')&(gus.Create_tmp_table_priv='Y')&(gus.Lock_tables_priv='Y')&(gus.Execute_priv='Y')&(gus.Repl_slave_priv='Y')&(gus.Repl_client_priv='Y')&(gus.Create_view_priv='Y')&(gus.Show_view_priv='Y')&(gus.Create_routine_priv='Y')&(gus.Alter_routine_priv='Y')&(gus.Create_user_priv='Y')&(gus.Event_priv='Y')&(gus.Trigger_priv='Y')&(gus.Create_tablespace_priv='Y')&(gus.Grant_priv='Y'),
                "ALL PRIVILEGES",
                CONCAT_WS(',',
                    IF(gus.Select_priv='Y','SELECT',NULL),
                    IF(gus.Insert_priv='Y','INSERT',NULL),
                    IF(gus.Update_priv='Y','UPDATE',NULL),
                    IF(gus.Delete_priv='Y','DELETE',NULL),
                    IF(gus.Create_priv='Y','CREATE',NULL),
                    IF(gus.Drop_priv='Y','DROP',NULL),
                    IF(gus.Reload_priv='Y','RELOAD',NULL),
                    IF(gus.Shutdown_priv='Y','SHUTDOWN',NULL),
                    IF(gus.Process_priv='Y','PROCESS',NULL),
                    IF(gus.File_priv='Y','FILE',NULL),
                    IF(gus.References_priv='Y','REFERENCES',NULL),
                    IF(gus.Index_priv='Y','INDEX',NULL),
                    IF(gus.Alter_priv='Y','ALTER',NULL),
                    IF(gus.Show_db_priv='Y','SHOW DATABASES',NULL),
                    IF(gus.Super_priv='Y','SUPER',NULL),
                    IF(gus.Create_tmp_table_priv='Y','CREATE TEMPORARY TABLES',NULL),
                    IF(gus.Lock_tables_priv='Y','LOCK TABLES',NULL),
                    IF(gus.Execute_priv='Y','EXECUTE',NULL),
                    IF(gus.Repl_slave_priv='Y','REPLICATION SLAVE',NULL),
                    IF(gus.Repl_client_priv='Y','REPLICATION CLIENT',NULL),
                    IF(gus.Create_view_priv='Y','CREATE VIEW',NULL),
                    IF(gus.Show_view_priv='Y','SHOW VIEW',NULL),
                    IF(gus.Create_routine_priv='Y','CREATE ROUTINE',NULL),
                    IF(gus.Alter_routine_priv='Y','ALTER ROUTINE',NULL),
                    IF(gus.Create_user_priv='Y','CREATE USER',NULL),
                    IF(gus.Event_priv='Y','EVENT',NULL),
                    IF(gus.Trigger_priv='Y','TRIGGER',NULL),
                    IF(gus.Create_tablespace_priv='Y','CREATE TABLESPACE',NULL)
                )
            )
        ),
        " ON *.* TO '",gus.User,"'@'",gus.Host,"' REQUIRE ",
        CASE gus.ssl_type
            WHEN 'ANY' THEN
                "SSL "
            WHEN 'X509' THEN
                "X509 "
            WHEN 'SPECIFIED' THEN
                CONCAT_WS("AND ",
                    IF((LENGTH(gus.ssl_cipher)>0),CONCAT("CIPHER '",CONVERT(gus.ssl_cipher USING utf8),"' "),NULL),
                    IF((LENGTH(gus.x509_issuer)>0),CONCAT("ISSUER '",CONVERT(gus.ssl_cipher USING utf8),"' "),NULL),
                    IF((LENGTH(gus.x509_subject)>0),CONCAT("SUBJECT '",CONVERT(gus.ssl_cipher USING utf8),"' "),NULL)
                )
            ELSE "NONE "
        END,
        "WITH ",
        IF(gus.Grant_priv='Y',"GRANT OPTION ",""),
        "MAX_QUERIES_PER_HOUR ",gus.max_questions," ",
        "MAX_CONNECTIONS_PER_HOUR ",gus.max_connections," ",
        "MAX_UPDATES_PER_HOUR ",gus.max_updates," ",
        "MAX_USER_CONNECTIONS ",gus.max_user_connections,
        ";"
    ) AS 'GRANT Statement (Reconstructed)'
FROM mysql.user gus
WHERE gus.Password != ''
/* SELECT * FROM mysql.user gus */

/* TODO: */
/* SELECT * FROM mysql.host ghs */
/* SELECT * FROM mysql.procs_priv gpr */

Heureux de répondre / vérifier toute question ou préoccupation


Je sais que ce n'est pas casher, mais ... ton script est incroyable! Maintenant, tout ce que je dois faire est de l’automatiser. Je vais réchauffer mes bash
hanzo2001

2

Cela vous donnera une meilleure vue ...

mysql> select Host, Db, User, Insert_priv, Update_priv, Delete_priv, Create_tmp_table_priv, Alter_priv from mysql.db limit 1;
+------+------+------+-------------+-------------+-------------+-----------------------+------------+
| Host | Db   | User | Insert_priv | Update_priv | Delete_priv | Create_tmp_table_priv | Alter_priv |
+------+------+------+-------------+-------------+-------------+-----------------------+------------+
| %    | test |      | Y           | Y           | Y           | Y                     | Y          |
+------+------+------+-------------+-------------+-------------+-----------------------+------------+
1 row in set (0.00 sec)

1

La commande SHOW GRANTS [FOR user]peut montrer n'importe quel utilisateur que vous voulez. Voir ici pour plus de détails.


0

Comme indiqué dans cette réponse , vous pouvez exécuter le jeu de commandes suivant pour répertorier les privilèges spécifiques à la base de données, à la table, aux colonnes et à la routine de tous les utilisateurs. Notez que vous devez l'exécuter à partir du shell, pas à l'invite de commande MySQL.

mysql -u root --skip-column-names -A -e"SELECT CONCAT('SHOW GRANTS FOR ''',user,'''@''',host,''';') FROM mysql.user WHERE user<>''" | mysql -u root --skip-column-names -A

L'avantage de cette approche est qu'il n'est pas nécessaire d'installer un logiciel supplémentaire.


0

Si vous administrez souvent des bases de données, vous voudrez probablement conserver des privilèges restreints. Vous pouvez utiliser une procédure stockée pour exécuter rapidement une vérification. Cet exemple fonctionne dans mariadb et pourrait nécessiter un ajustement pour fonctionner avec la version standard de mysql.

En utilisant la réponse de Mansur Ali avec un petit ajustement réordonnant les colonnes et en ajoutant un peu d'ordre pour mieux organiser la sortie.

En utilisant un login root:

USE mysql;
DELIMITER //

CREATE PROCEDURE ShowPrivs(start, end)
BEGIN
    SELECT Db, User, Host, Insert_priv, Update_priv, Delete_priv, Create_tmp_table_priv, Alter_priv FROM mysql.db order by Db, Host, User ASC;
END;
//

DELIMITER ;

Vous pouvez changer la procédure pour vérifier la table mysql.user à la place.

Utilisation, en utilisant un login root:

USE mysql;
CALL ShowPrivs();

J'ai utilisé mysql workbench sur Ubuntu pour exécuter la partie procédure de création de cette réponse.

À part un peu en dehors du sujet ici, vous pourriez aussi avoir une procédure pour montrer des hôtes ou des utilisateurs inconnus. Un exemple pour les hôtes inconnus:

USE mysql;

DELIMITER //
CREATE PROCEDURE `ShowUnknownHosts`(IN Hosts_String VARCHAR(200))
BEGIN
    SELECT user,host FROM user
    WHERE FIND_IN_SET(host, Hosts_String) = 0;
END//

DELIMITER ;

Remarque sur l'utilisation: Fournissez une chaîne d'hôtes séparées par des virgules afin qu'un seul jeu de '' soit utilisé:

CALL ShowUnknownHosts('knownhost1,knownhost2');

Vous pouvez également créer la variable de colonne en incluant un autre paramètre dans la procédure et en l'appelant avec ShowUnknownHosts (user, 'user1, user2'); par exemple.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.