mysql: mostra GRANTs para todos os usuários

87

O MySQL SHOW GRANTSmostra as permissões do usuário atual.

Existe uma maneira de fazer login como root e mostrar as permissões de todos os usuários?

Adam Matan
fonte

Respostas:

45

Nada embutido. Você tem duas opções:

  • Use common_schemaa visualização sql_show_grants . Por exemplo, você pode consultar:

    SELECT sql_grants FROM common_schema.sql_show_grants;

    Ou você pode consultar usuários específicos, por exemplo:

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

    Para instalar common_schema, siga as instruções aqui .

    Disclaimer: Eu sou o autor desta ferramenta.

  • Use o Percona Toolkit pt-show-grants, por exemplo:

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

Nos dois casos, você pode solicitar o GRANTcomando ou o comando REVOKE(oposto).

O primeiro caso requer a instalação de um esquema, o último requer a instalação de scripts PERL + dependências.

Shlomi Noach
fonte
11
Você poderia descrever com mais detalhes como usar a visualização sql_show_grants do common_schema? Eu recebo um erroERROR 1146 (42S02): Table 'common_schema.sql_show_grants' doesn't exist
Martin Vegter 24/10
2
@MartinVegter, você instalou o common_schema? Faça o download aqui e instale seguindo estas instruções .
Shlomi Noach
1
@ShlomiNoach, Quando você diz que "não há nada embutido" ... Há algum erro information_schema.user_privileges?
Pacerier
2
Desculpe, mas não existe um 'common_schema'. Isso não existe.
Brendan Byrd
2
link sql_show_grants quebrado
Cyzanfar 6/18
81
select * from information_schema.user_privileges;

EDITAR:

Como mencionado por Shlomi Noach:

Ele não lista privilégios específicos do banco de dados, da tabela, da coluna e da rotina. Portanto, a concessão GRANT SELECT ON mydb. * TO myuser @ localhost não aparece em information_schema.user_privileges. A solução common_schema apresentada acima agrega os dados de user_privileges e outras tabelas para fornecer uma imagem completa.

rumburak
fonte
5
Desculpe, não deve ser a resposta aceita. information_schema.user_privilegeslista apenas privilégios no nível do usuário, como SUPER, RELOADetc. Também lista subvenções DML gerais como SELECT. Ele não lista privilégios específicos de banco de dados, específicos de tabela, específicos de coluna e específicos de rotina. Lá na frente, a concessão GRANT SELECT ON mydb.* TO myuser@localhostse não mostrar em information_schema.user_privileges. A common_schemasolução apresentada acima agrega dados de user_privilegese outras tabelas para fornecer uma visão completa.
Shlomi Noach
11

Este fragmento de shell do Linux faz um loop em todos os usuários do MySQL e faz um SHOW GRANTS para cada um:

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

Funciona melhor se você pode se conectar ao MySQL sem uma senha.

A saída é formatada para que possa ser executada em um shell MySQL. Cuidado: A saída também contém as permissões e a senha do usuário root do MySQL! Remova essas linhas se você não quiser que o usuário root do MySQL seja alterado.

mleu
fonte
6
Você pode adicionar alguns detalhes sobre o que isso faz ou como responde à pergunta. Apenas exibir um monte de código não ajuda ninguém a entender por que sua solução funciona.
Max Vernon
Onde posso dar a senha?
Mian Asbat Ahmad
Para fornecer uma senha, pode-se usar um arquivo de opções ou o sinalizador --password do comando mysql.
mleu
Não seria possível fornecer uma senha root e executar a consulta para obter todas as concessões de usuários?
Mian Asbat Ahmad
2
Você pode transmitir as solicitações para fazer apenas uma conexão e usar um arquivo de credenciais de propriedade do modo 400. Minha versão: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;

Pode dar a você a lista de usuários e privilégios atribuídos a cada um deles, mysql.userembora exija acesso à tabela e o rootusuário a possua.

Mahesh Patil
fonte
4
Isso fornece apenas os privilégios de "nível superior" (nível do servidor). Os privilégios definidos em esquemas específicos estão em mysql.db. Privilégios em tabelas específicas estão dentro mysql.tables_prive assim por diante. Portanto, não é tão simples.
Shlomi Noach
Para travessuras da tabela do arco-íris, jogue seus hashes de senha select * from mysql.userno crackstation.net e veja a saída unificada.
Pacerier 07/07
8

Um liner (mude -urootpara -u$USER_NAMEpara uso com outro usuário) em uma festa do Unix (por causa dos backticks):

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

ou sem backticks e com senha embutida (o espaço na frente do comando o exclui do histórico do Bash no Ubuntu):

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

No 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
inemanja
fonte
4

Se você pode executar as seguintes instruções SELECT sem erro:

/* 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;

fique à vontade para usar o seguinte código (abaixo), escrito na sintaxe .sql.

Projetei essa consulta na tentativa de recriar instruções GRANT para todas as permissões existentes (para manutenção frequente durante a migração do banco de dados). Existem alguns problemas a serem resolvidos, como a vinculação de senha de usuário, mas como atualizamos frequentemente senhas, isso não estava no escopo deste projeto.

/* 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 */

É um prazer responder / verificar quaisquer dúvidas ou preocupações

Cavallo
fonte
Eu sei que isso não é kosher, mas ... seu script é incrível! Agora, tudo o que preciso fazer é automatizá-lo. Eu vou aquecer a minha festa
hanzo2001
2

Isso lhe dará uma visão melhor ...

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)
Mansur Ali
fonte
1

O comando SHOW GRANTS [FOR user]pode mostrar qualquer usuário que você desejar. Veja aqui para mais detalhes.

Eugen Konkov
fonte
0

Conforme mencionado nesta resposta , você pode executar o seguinte conjunto de comandos para listar os privilégios específicos de banco de dados, de tabela, de coluna e de rotina de todos os usuários. Observe que você precisa executar isso no shell, não no prompt de comando do 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

A vantagem dessa abordagem é que você não precisa instalar software adicional.

billyw
fonte
0

Se você estiver administrando bancos de dados com frequência, provavelmente desejará manter privilégios restritos. Você pode usar um procedimento armazenado para executar rapidamente uma verificação. Este exemplo de trabalho no mariadb pode precisar de um ajuste para funcionar com a versão padrão do mysql.

Usando a resposta de Mansur Ali com um pequeno ajuste para reorganizar as colunas e adicionando algumas ordens para organizar melhor a saída.

Usando um login raiz:

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 ;

Você pode alterar o procedimento para verificar a tabela mysql.user.

Uso, usando um login raiz:

USE mysql;
CALL ShowPrivs();

Eu usei o mysql workbench no Ubuntu para executar a parte do procedimento de criação desta resposta.

Como um aparte e um pouco fora do tópico aqui, você também pode ter um procedimento para mostrar hosts ou usuários desconhecidos. Um exemplo para hosts desconhecidos:

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 ;

Nota de uso: forneça uma sequência de hosts separados por vírgulas para que apenas um conjunto de '' seja usado:

CALL ShowUnknownHosts('knownhost1,knownhost2');

Você também pode tornar a coluna variável incluindo outro parâmetro no procedimento e chamá-lo com ShowUnknownHosts (usuário, 'usuário1, usuário2'); por exemplo.

Chris
fonte