From 6771b818a38a72e89d318eb9f1f3a2b8a64f0d5f Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 10 Jul 2015 19:06:42 -0400 Subject: [PATCH] MDEV-8383 : "GRANT role TO user" does not replicate Enable replication of GRANT/REVOKE ROLE commands across galera nodes. --- mysql-test/suite/galera/r/galera_roles.result | 156 ++++++++++++++++ mysql-test/suite/galera/t/galera_roles.test | 167 ++++++++++++++++++ sql/sql_parse.cc | 1 + 3 files changed, 324 insertions(+) create mode 100644 mysql-test/suite/galera/r/galera_roles.result create mode 100644 mysql-test/suite/galera/t/galera_roles.test diff --git a/mysql-test/suite/galera/r/galera_roles.result b/mysql-test/suite/galera/r/galera_roles.result new file mode 100644 index 0000000000000..c0cdbc0e3386c --- /dev/null +++ b/mysql-test/suite/galera/r/galera_roles.result @@ -0,0 +1,156 @@ +# +# Testing CREATE/GRANT role +# + +# On node_1 +CREATE DATABASE test1; +CREATE TABLE test1.t1 (a int, b int); +CREATE TABLE test1.t2 (a int, b int); +INSERT INTO test1.t1 values (1,2),(3,4); +INSERT INTO test1.t2 values (5,6),(7,8); +CREATE PROCEDURE test1.pr1() SELECT "pr1"; +CREATE USER foo@localhost; +CREATE ROLE role1; +GRANT role1 TO foo@localhost; +GRANT RELOAD ON *.* TO role1; +GRANT SELECT ON mysql.* TO role1; +GRANT EXECUTE ON PROCEDURE test1.pr1 TO role1; +GRANT SELECT ON test1.t1 TO role1; +GRANT SELECT (a) ON test1.t2 TO role1; +# Open connections to the 2 nodes using 'foo' user. + +# Connect with foo_node_1 +SHOW GRANTS; +Grants for foo@localhost +GRANT role1 TO 'foo'@'localhost' +GRANT USAGE ON *.* TO 'foo'@'localhost' +FLUSH TABLES; +ERROR 42000: Access denied; you need (at least one of) the RELOAD privilege(s) for this operation +SELECT * FROM mysql.roles_mapping; +ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 'roles_mapping' +SHOW TABLES FROM test1; +ERROR 42000: Access denied for user 'foo'@'localhost' to database 'test1' +SET ROLE role1; +FLUSH TABLES; +SELECT * FROM mysql.roles_mapping; +Host User Role Admin_option +localhost foo role1 N +localhost root role1 Y +SHOW TABLES FROM test1; +Tables_in_test1 +t1 +t2 +SELECT * FROM test1.t1; +a b +1 2 +3 4 +SELECT * FROM test1.t2; +ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 't2' +SELECT a FROM test1.t2; +a +5 +7 +CALL test1.pr1(); +pr1 +pr1 + +# Connect with foo_node_2 +SHOW GRANTS; +Grants for foo@localhost +GRANT role1 TO 'foo'@'localhost' +GRANT USAGE ON *.* TO 'foo'@'localhost' +FLUSH TABLES; +ERROR 42000: Access denied; you need (at least one of) the RELOAD privilege(s) for this operation +SELECT * FROM mysql.roles_mapping; +ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 'roles_mapping' +SHOW TABLES FROM test1; +ERROR 42000: Access denied for user 'foo'@'localhost' to database 'test1' +SET ROLE role1; +FLUSH TABLES; +SELECT * FROM mysql.roles_mapping; +Host User Role Admin_option + role1 Y +localhost foo role1 N +SHOW TABLES FROM test1; +Tables_in_test1 +t1 +t2 +SELECT * FROM test1.t1; +a b +1 2 +3 4 +SELECT * FROM test1.t2; +ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 't2' +SELECT a FROM test1.t2; +a +5 +7 +CALL test1.pr1(); +pr1 +pr1 +# +# Testing REVOKE role +# +# +# Connect with node_1 +REVOKE EXECUTE ON PROCEDURE test1.pr1 FROM role1; + +# Connect with foo_node_1 +CALL test1.pr1(); +ERROR 42000: execute command denied to user 'foo'@'localhost' for routine 'test1.pr1' + +# Connect with foo_node_2 +CALL test1.pr1(); +ERROR 42000: execute command denied to user 'foo'@'localhost' for routine 'test1.pr1' +# +# Testing DROP role +# + +# Connect with node_1 +DROP ROLE role1; + +# Connect with foo_node_1 +FLUSH TABLES; +SELECT * FROM mysql.roles_mapping; +ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 'roles_mapping' +SELECT * FROM test1.t1; +ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 't1' +SELECT a FROM test1.t2; +ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 't2' +SHOW GRANTS; +Grants for foo@localhost +GRANT USAGE ON *.* TO 'foo'@'localhost' +SELECT * FROM INFORMATION_SCHEMA.ENABLED_ROLES; +ROLE_NAME +NULL +SELECT * FROM INFORMATION_SCHEMA.ENABLED_ROLES; +ROLE_NAME +NULL +SELECT CURRENT_ROLE(); +CURRENT_ROLE() +role1 + +# Connect with foo_node_2 +FLUSH TABLES; +SELECT * FROM mysql.roles_mapping; +ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 'roles_mapping' +SELECT * FROM test1.t1; +ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 't1' +SELECT a FROM test1.t2; +ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 't2' +SHOW GRANTS; +Grants for foo@localhost +GRANT USAGE ON *.* TO 'foo'@'localhost' +SELECT * FROM INFORMATION_SCHEMA.ENABLED_ROLES; +ROLE_NAME +NULL +SELECT * FROM INFORMATION_SCHEMA.ENABLED_ROLES; +ROLE_NAME +NULL +SELECT CURRENT_ROLE(); +CURRENT_ROLE() +role1 +# Connect with node_1 +DROP USER foo@localhost; +DROP DATABASE test1; +# End of test diff --git a/mysql-test/suite/galera/t/galera_roles.test b/mysql-test/suite/galera/t/galera_roles.test new file mode 100644 index 0000000000000..f9a15126e5ecd --- /dev/null +++ b/mysql-test/suite/galera/t/galera_roles.test @@ -0,0 +1,167 @@ +# +# Test for CREATE/DROP/GRANT/REVOKE role. +# + +--source include/galera_cluster.inc +--source include/have_innodb.inc + +--echo # +--echo # Testing CREATE/GRANT role +--echo # + +--echo +--echo # On node_1 +--connection node_1 + +CREATE DATABASE test1; +CREATE TABLE test1.t1 (a int, b int); +CREATE TABLE test1.t2 (a int, b int); +INSERT INTO test1.t1 values (1,2),(3,4); +INSERT INTO test1.t2 values (5,6),(7,8); + +CREATE PROCEDURE test1.pr1() SELECT "pr1"; + +CREATE USER foo@localhost; +CREATE ROLE role1; + +GRANT role1 TO foo@localhost; +GRANT RELOAD ON *.* TO role1; +GRANT SELECT ON mysql.* TO role1; +GRANT EXECUTE ON PROCEDURE test1.pr1 TO role1; +GRANT SELECT ON test1.t1 TO role1; +GRANT SELECT (a) ON test1.t2 TO role1; + +--echo # Open connections to the 2 nodes using 'foo' user. +--let $port_1= \$NODE_MYPORT_1 +--connect(foo_node_1,127.0.0.1,foo,,test,$port_1,) + +--let $port_2= \$NODE_MYPORT_2 +--connect(foo_node_2,127.0.0.1,foo,,test,$port_2,) + +--echo +--echo # Connect with foo_node_1 +--connection foo_node_1 + +SHOW GRANTS; + +--error ER_SPECIFIC_ACCESS_DENIED_ERROR +FLUSH TABLES; +--error ER_TABLEACCESS_DENIED_ERROR +SELECT * FROM mysql.roles_mapping; +--error ER_DBACCESS_DENIED_ERROR +SHOW TABLES FROM test1; + +SET ROLE role1; + +FLUSH TABLES; +--sorted_result +SELECT * FROM mysql.roles_mapping; +SHOW TABLES FROM test1; +SELECT * FROM test1.t1; +--error ER_TABLEACCESS_DENIED_ERROR +SELECT * FROM test1.t2; +SELECT a FROM test1.t2; +CALL test1.pr1(); + +--echo +--echo # Connect with foo_node_2 +--connection foo_node_2 + +SHOW GRANTS; + +--error ER_SPECIFIC_ACCESS_DENIED_ERROR +FLUSH TABLES; +--error ER_TABLEACCESS_DENIED_ERROR +SELECT * FROM mysql.roles_mapping; +--error ER_DBACCESS_DENIED_ERROR +SHOW TABLES FROM test1; + +SET ROLE role1; + +FLUSH TABLES; +--sorted_result +SELECT * FROM mysql.roles_mapping; +SHOW TABLES FROM test1; +SELECT * FROM test1.t1; +--error ER_TABLEACCESS_DENIED_ERROR +SELECT * FROM test1.t2; +SELECT a FROM test1.t2; +CALL test1.pr1(); + +--echo # +--echo # Testing REVOKE role +--echo # + +--echo # +--echo # Connect with node_1 +--connection node_1 +REVOKE EXECUTE ON PROCEDURE test1.pr1 FROM role1; + +--echo +--echo # Connect with foo_node_1 +--connection foo_node_1 + +--error ER_PROCACCESS_DENIED_ERROR +CALL test1.pr1(); + +--echo +--echo # Connect with foo_node_2 +--connection foo_node_2 + +--error ER_PROCACCESS_DENIED_ERROR +CALL test1.pr1(); + +--echo # +--echo # Testing DROP role +--echo # + +--echo +--echo # Connect with node_1 +--connection node_1 + +DROP ROLE role1; + +--echo +--echo # Connect with foo_node_1 +--connection foo_node_1 + +FLUSH TABLES; +--error ER_TABLEACCESS_DENIED_ERROR +SELECT * FROM mysql.roles_mapping; +--error ER_TABLEACCESS_DENIED_ERROR +SELECT * FROM test1.t1; +--error ER_TABLEACCESS_DENIED_ERROR +SELECT a FROM test1.t2; + +SHOW GRANTS; +SELECT * FROM INFORMATION_SCHEMA.ENABLED_ROLES; +SELECT * FROM INFORMATION_SCHEMA.ENABLED_ROLES; # yes, repeat it twice +SELECT CURRENT_ROLE(); + +--echo +--echo # Connect with foo_node_2 +--connection foo_node_2 + +FLUSH TABLES; +--error ER_TABLEACCESS_DENIED_ERROR +SELECT * FROM mysql.roles_mapping; +--error ER_TABLEACCESS_DENIED_ERROR +SELECT * FROM test1.t1; +--error ER_TABLEACCESS_DENIED_ERROR +SELECT a FROM test1.t2; + +SHOW GRANTS; +SELECT * FROM INFORMATION_SCHEMA.ENABLED_ROLES; +SELECT * FROM INFORMATION_SCHEMA.ENABLED_ROLES; # yes, repeat it twice +SELECT CURRENT_ROLE(); + +# Cleanup +disconnect foo_node_2; +--echo # Connect with node_1 +--connection node_1 + +DROP USER foo@localhost; +DROP DATABASE test1; + +--source include/galera_end.inc +--echo # End of test diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c561cc73707a7..70602049604ae 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4626,6 +4626,7 @@ case SQLCOM_PREPARE: case SQLCOM_REVOKE_ROLE: case SQLCOM_GRANT_ROLE: { + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) if (!(res= mysql_grant_role(thd, lex->users_list, lex->sql_command != SQLCOM_GRANT_ROLE))) my_ok(thd);