mysql : 모든 사용자에게 GRANT 표시


87

MySQL SHOW GRANTS은 현재 사용자의 권한을 보여줍니다.

루트로 로그인하여 모든 사용자의 권한을 표시하는 방법이 있습니까?

답변:


45

내장 된 것이 없습니다. 그래도 두 가지 옵션이 있습니다.

  • common_schemasql_show_grants 보기를 사용하십시오 . 예를 들어 다음을 쿼리 할 수 ​​있습니다.

    SELECT sql_grants FROM common_schema.sql_show_grants;

    또는 다음과 같은 특정 사용자를 쿼리 할 수 ​​있습니다.

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

    설치하려면 여기common_schema 의 지침을 따르십시오 .

    면책 조항 : 나는이 도구의 저자입니다.

  • Percona Toolkit을 사용하십시오 ( pt-show-grants예 :

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

두 경우 모두 GRANT명령 또는 REVOKE(반대) 명령을 요청할 수 있습니다 .

첫 번째 경우에는 스키마를 설치해야하고, 후자는 PERL 스크립트 + 종속성을 설치해야합니다.


11
common_schema의 sql_show_grants보기를 사용하는 방법에 대해 자세히 설명해 주시겠습니까? 오류가 발생했습니다ERROR 1146 (42S02): Table 'common_schema.sql_show_grants' doesn't exist
Martin Vegter

2
@MartinVegter, common_schema를 설치 했습니까? 여기에서 다운로드 하여 다음 지침에 따라 설치 하십시오 .
Shlomi Noach

1
@ShlomiNoach, 당신은 "내장 된 것이 없다"고 말할 때 ...에 오류가 information_schema.user_privileges있습니까?
Pacerier

2
죄송하지만 'common_schema'와 같은 것은 없습니다. 존재하지 않습니다.
Brendan Byrd

2
링크 sql_show_grants 고장
Cyzanfar

81
select * from information_schema.user_privileges;

편집하다:

Shlomi Noach가 언급했듯이 :

데이터베이스 별, 테이블 별, 열별, 루틴 별 권한은 나열하지 않습니다. 따라서 GRANT SELECT ON mydb. * TO myuser @ localhost 부여는 information_schema.user_privileges에 표시되지 않습니다. 위에 제시된 common_schema 솔루션은 user_privileges 및 기타 테이블의 데이터를 집계하여 전체 그림을 제공합니다.


5
죄송합니다. 정답이 아닙니다. information_schema.user_privileges단지 같은 사용자 수준의 권한을 나열 SUPER, RELOAD또한 DML 보조금이 좋아하는 모든 라운드를 나열 등 SELECT. 데이터베이스 별, 테이블 별, 열별, 루틴 별 권한 은 나열 하지 않습니다 . 따라서 보조금 GRANT SELECT ON mydb.* TO myuser@localhost은에 표시 되지 않습니다information_schema.user_privileges . common_schema집계 데이터 위에 제시된 솔루션 user_privileges과 다른 테이블은 당신에게 전체 그림을 제공합니다.
Shlomi Noach

11

이 Linux 쉘 조각은 모든 MySQL 사용자를 반복하고 각각에 대해 SHOW GRANTS 를 수행합니다.

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

비밀번호없이 MySQL에 연결할 수있는 경우 가장 효과적입니다.

출력은 MySQL 쉘에서 실행될 수 있도록 형식화됩니다. 주의 : 출력에는 MySQL 루트 사용자 권한과 비밀번호도 포함됩니다! MySQL 루트 사용자를 변경하지 않으려면 해당 행을 제거하십시오.


6
이것이하는 일 또는 질문에 대한 답변에 대한 세부 정보를 추가 할 수 있습니다. 많은 코드를 표시해도 솔루션이 작동하는 이유를 이해하는 데 도움이되지 않습니다.
Max Vernon

비밀번호는 어디에서 제공합니까?
미안 아스 밧 아마드

비밀번호를 제공하기 위해 mysql 명령 의 옵션 파일 또는 --password 플래그를 사용할 수 있습니다 .
mleu

하나의 루트 암호를 제공하고 모든 사용자에게 권한을 부여하기 위해 쿼리를 실행할 수 없습니까?
미안 아스 밧 아마드

2
하나의 연결 만 만들기 위해 요청을 스트리밍하고 모드 400 루트 소유 자격 증명 파일을 사용할 수 있습니다. 내 버전 :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;

각 사용자에게 할당 된 사용자 목록 및 권한을 제공 할 수 mysql.user있지만 테이블에 대한 액세스 권한이 있어야 하며 root사용자에게 있습니다.


4
"최상위"(서버 수준) 권한 만 제공합니다. 특정 스키마에 설정된 권한은에 mysql.db있습니다. 특정 테이블에 대한 권한은 mysql.tables_priv에 있습니다. 그렇게 간단하지 않습니다.
Shlomi Noach

레인보우 테이블 shenanigans의 경우 암호 해시 select * from mysql.usercrackstation.net 으로 던져서 해시되지 않은 출력을 확인하십시오.
Pacerier

8

하나의 라이너 (변경 -uroot-u$USER_NAME(인해 역 따옴표) 유닉스 강타 다른 사용자와 함께 사용) :

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

또는 백틱이없고 암호가 인라인되어 있습니다 (명령 앞에 공백이 있으면 우분투의 Bash 기록에서 제외됨).

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

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

오류 없이 다음 SELECT 문 실행할 수있는 경우 :

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

그런 다음 .sql 구문으로 작성된 다음 코드 (아래)를 자유롭게 사용하십시오.

데이터베이스 마이그레이션 중에 자주 유지 관리하기 위해 모든 기존 권한에 대해 GRANT 문을 다시 작성하기 위해이 쿼리를 설계했습니다. 사용자 암호 연결과 같은 몇 가지 문제가 있지만 암호를 자주 업데이트하기 때문에이 프로젝트의 범위를 벗어난 것입니다.

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

궁금한 사항에 대한 답변 / 확인


나는 이것이 정결하지 않다는 것을 알고 있지만 ... 당신의 대본은 훌륭합니다! 이제 자동화해야합니다. 나는 내 배쉬를 따뜻하게 할 것이다
hanzo2001

2

이렇게하면 더 나은 시야를 얻을 수 있습니다 ...

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)


0

이 답변 에서 언급했듯이 다음 명령 집합을 실행하여 모든 사용자의 데이터베이스 별, 테이블 별, 열별 및 루틴 별 권한을 나열 할 수 있습니다. 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

이 방법의 장점은 추가 소프트웨어를 설치할 필요가 없다는 것입니다.


0

데이터베이스를 자주 관리하는 경우 엄격한 권한을 유지하고 싶을 것입니다. 저장 프로 시저를 사용하여 검사를 빠르게 실행할 수 있습니다. 이 예제는 mariadb에서 작동합니다. 표준 mysql 버전으로 작업하려면 조정이 필요할 수 있습니다.

Mansur Ali의 답변을 사용하여 열을 약간 재정렬하고 순서를 추가하여 출력을보다 잘 구성합니다.

루트 로그인 사용

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 ;

대신 mysql.user 테이블을 확인하도록 프로 시저를 변경할 수 있습니다.

루트 로그인을 사용한 사용법 :

USE mysql;
CALL ShowPrivs();

우분투에서 mysql workbench를 사용 하여이 답변의 작성 절차 부분을 실행했습니다.

여기서는 주제를 제외하고는 알지 못하지만 알 수없는 호스트 또는 사용자를 표시하는 절차가있을 수도 있습니다. 알 수없는 호스트의 예 :

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 ;

사용 참고 사항 : 쉼표로 구분 된 호스트 문자열을 제공하여 하나의 ''세트 만 사용하십시오.

CALL ShowUnknownHosts('knownhost1,knownhost2');

프로 시저에 다른 매개 변수를 포함시켜 열 변수를 만들고 ShowUnknownHosts (user, 'user1, user2'); 예를 들어.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.