diff --git a/privilege/privileges/privileges.go b/privilege/privileges/privileges.go index a4edaca2782a1..ff583c94b6d3a 100644 --- a/privilege/privileges/privileges.go +++ b/privilege/privileges/privileges.go @@ -99,7 +99,8 @@ func (p *UserPrivileges) RequestVerificationWithUser(db, table, column string, p } mysqlPriv := p.Handle.Get() - return mysqlPriv.RequestVerification(nil, user.Username, user.Hostname, db, table, column, priv) + roles := mysqlPriv.getDefaultRoles(user.Username, user.Hostname) + return mysqlPriv.RequestVerification(roles, user.Username, user.Hostname, db, table, column, priv) } // GetEncodedPassword implements the Manager interface. diff --git a/privilege/privileges/privileges_test.go b/privilege/privileges/privileges_test.go index 0e4500766fa0c..a3c154472241c 100644 --- a/privilege/privileges/privileges_test.go +++ b/privilege/privileges/privileges_test.go @@ -1235,3 +1235,187 @@ func newSession(c *C, store kv.Storage, dbName string) session.Session { mustExec(c, se, "use "+dbName) return se } +<<<<<<< HEAD +======= + +func (s *testPrivilegeSuite) TestDynamicPrivs(c *C) { + rootSe := newSession(c, s.store, s.dbName) + mustExec(c, rootSe, "CREATE USER notsuper") + mustExec(c, rootSe, "CREATE USER otheruser") + mustExec(c, rootSe, "CREATE ROLE anyrolename") + mustExec(c, rootSe, "SET tidb_enable_dynamic_privileges=1") + + se := newSession(c, s.store, s.dbName) + c.Assert(se.Auth(&auth.UserIdentity{Username: "notsuper", Hostname: "%"}, nil, nil), IsTrue) + mustExec(c, se, "SET tidb_enable_dynamic_privileges=1") + + // test SYSTEM_VARIABLES_ADMIN + _, err := se.ExecuteInternal(context.Background(), "SET GLOBAL wait_timeout = 86400") + c.Assert(err.Error(), Equals, "[planner:1227]Access denied; you need (at least one of) the SUPER or SYSTEM_VARIABLES_ADMIN privilege(s) for this operation") + mustExec(c, rootSe, "GRANT SYSTEM_VARIABLES_admin ON *.* TO notsuper") + mustExec(c, se, "SET GLOBAL wait_timeout = 86400") + + // test ROLE_ADMIN + _, err = se.ExecuteInternal(context.Background(), "GRANT anyrolename TO otheruser") + c.Assert(err.Error(), Equals, "[planner:1227]Access denied; you need (at least one of) the SUPER or ROLE_ADMIN privilege(s) for this operation") + mustExec(c, rootSe, "GRANT ROLE_ADMIN ON *.* TO notsuper") + mustExec(c, se, "GRANT anyrolename TO otheruser") + + // revoke SYSTEM_VARIABLES_ADMIN, confirm it is dropped + mustExec(c, rootSe, "REVOKE SYSTEM_VARIABLES_AdmIn ON *.* FROM notsuper") + _, err = se.ExecuteInternal(context.Background(), "SET GLOBAL wait_timeout = 86000") + c.Assert(err.Error(), Equals, "[planner:1227]Access denied; you need (at least one of) the SUPER or SYSTEM_VARIABLES_ADMIN privilege(s) for this operation") + + // grant super, confirm that it is also a substitute for SYSTEM_VARIABLES_ADMIN + mustExec(c, rootSe, "GRANT SUPER ON *.* TO notsuper") + mustExec(c, se, "SET GLOBAL wait_timeout = 86400") + + // revoke SUPER, assign SYSTEM_VARIABLES_ADMIN to anyrolename. + // confirm that a dynamic privilege can be inherited from a role. + mustExec(c, rootSe, "REVOKE SUPER ON *.* FROM notsuper") + mustExec(c, rootSe, "GRANT SYSTEM_VARIABLES_AdmIn ON *.* TO anyrolename") + mustExec(c, rootSe, "GRANT anyrolename TO notsuper") + + // It's not a default role, this should initially fail: + _, err = se.ExecuteInternal(context.Background(), "SET GLOBAL wait_timeout = 86400") + c.Assert(err.Error(), Equals, "[planner:1227]Access denied; you need (at least one of) the SUPER or SYSTEM_VARIABLES_ADMIN privilege(s) for this operation") + mustExec(c, se, "SET ROLE anyrolename") + mustExec(c, se, "SET GLOBAL wait_timeout = 87000") +} + +func (s *testPrivilegeSuite) TestDynamicGrantOption(c *C) { + rootSe := newSession(c, s.store, s.dbName) + mustExec(c, rootSe, "CREATE USER varuser1") + mustExec(c, rootSe, "CREATE USER varuser2") + mustExec(c, rootSe, "CREATE USER varuser3") + mustExec(c, rootSe, "SET tidb_enable_dynamic_privileges=1") + + mustExec(c, rootSe, "GRANT SYSTEM_VARIABLES_ADMIN ON *.* TO varuser1") + mustExec(c, rootSe, "GRANT SYSTEM_VARIABLES_ADMIN ON *.* TO varuser2 WITH GRANT OPTION") + + se1 := newSession(c, s.store, s.dbName) + mustExec(c, se1, "SET tidb_enable_dynamic_privileges=1") + + c.Assert(se1.Auth(&auth.UserIdentity{Username: "varuser1", Hostname: "%"}, nil, nil), IsTrue) + _, err := se1.ExecuteInternal(context.Background(), "GRANT SYSTEM_VARIABLES_ADMIN ON *.* TO varuser3") + c.Assert(err.Error(), Equals, "[planner:1227]Access denied; you need (at least one of) the GRANT OPTION privilege(s) for this operation") + + se2 := newSession(c, s.store, s.dbName) + mustExec(c, se2, "SET tidb_enable_dynamic_privileges=1") + + c.Assert(se2.Auth(&auth.UserIdentity{Username: "varuser2", Hostname: "%"}, nil, nil), IsTrue) + mustExec(c, se2, "GRANT SYSTEM_VARIABLES_ADMIN ON *.* TO varuser3") +} + +func (s *testPrivilegeSuite) TestSecurityEnhancedModeRestrictedTables(c *C) { + // This provides an integration test of the tests in util/security/security_test.go + cloudAdminSe := newSession(c, s.store, s.dbName) + mustExec(c, cloudAdminSe, "CREATE USER cloudadmin") + mustExec(c, cloudAdminSe, "SET tidb_enable_dynamic_privileges=1") + mustExec(c, cloudAdminSe, "GRANT RESTRICTED_TABLES_ADMIN, SELECT ON *.* to cloudadmin") + mustExec(c, cloudAdminSe, "GRANT CREATE ON mysql.* to cloudadmin") + mustExec(c, cloudAdminSe, "CREATE USER uroot") + mustExec(c, cloudAdminSe, "GRANT ALL ON *.* to uroot WITH GRANT OPTION") // A "MySQL" all powerful user. + c.Assert(cloudAdminSe.Auth(&auth.UserIdentity{Username: "cloudadmin", Hostname: "%"}, nil, nil), IsTrue) + urootSe := newSession(c, s.store, s.dbName) + mustExec(c, urootSe, "SET tidb_enable_dynamic_privileges=1") + c.Assert(urootSe.Auth(&auth.UserIdentity{Username: "uroot", Hostname: "%"}, nil, nil), IsTrue) + + sem.Enable() + defer sem.Disable() + + _, err := urootSe.ExecuteInternal(context.Background(), "use metrics_schema") + c.Assert(err.Error(), Equals, "[executor:1044]Access denied for user 'uroot'@'%' to database 'metrics_schema'") + + _, err = urootSe.ExecuteInternal(context.Background(), "SELECT * FROM metrics_schema.uptime") + c.Assert(err.Error(), Equals, "[planner:1142]SELECT command denied to user 'uroot'@'%' for table 'uptime'") + + _, err = urootSe.ExecuteInternal(context.Background(), "CREATE TABLE mysql.abcd (a int)") + c.Assert(err.Error(), Equals, "[planner:1142]CREATE command denied to user 'uroot'@'%' for table 'abcd'") + + mustExec(c, cloudAdminSe, "USE metrics_schema") + mustExec(c, cloudAdminSe, "SELECT * FROM metrics_schema.uptime") + mustExec(c, cloudAdminSe, "CREATE TABLE mysql.abcd (a int)") +} + +func (s *testPrivilegeSuite) TestSecurityEnhancedModeInfoschema(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("CREATE USER uroot1, uroot2, uroot3") + tk.MustExec("GRANT SUPER ON *.* to uroot1 WITH GRANT OPTION") // super not process + tk.MustExec("SET tidb_enable_dynamic_privileges=1") + tk.MustExec("GRANT SUPER, PROCESS, RESTRICTED_TABLES_ADMIN ON *.* to uroot2 WITH GRANT OPTION") + tk.Se.Auth(&auth.UserIdentity{ + Username: "uroot1", + Hostname: "localhost", + AuthUsername: "uroot", + AuthHostname: "%", + }, nil, nil) + + sem.Enable() + defer sem.Disable() + + // Even though we have super, we still can't read protected information from tidb_servers_info, cluster_* tables + tk.MustQuery(`SELECT COUNT(*) FROM information_schema.tidb_servers_info WHERE ip IS NOT NULL`).Check(testkit.Rows("0")) + tk.MustQuery(`SELECT COUNT(*) FROM information_schema.cluster_info WHERE status_address IS NOT NULL`).Check(testkit.Rows("0")) + // 36 = a UUID. Normally it is an IP address. + tk.MustQuery(`SELECT COUNT(*) FROM information_schema.CLUSTER_STATEMENTS_SUMMARY WHERE length(instance) != 36`).Check(testkit.Rows("0")) + + // That is unless we have the RESTRICTED_TABLES_ADMIN privilege + tk.Se.Auth(&auth.UserIdentity{ + Username: "uroot2", + Hostname: "localhost", + AuthUsername: "uroot", + AuthHostname: "%", + }, nil, nil) + + // flip from is NOT NULL etc + tk.MustQuery(`SELECT COUNT(*) FROM information_schema.tidb_servers_info WHERE ip IS NULL`).Check(testkit.Rows("0")) + tk.MustQuery(`SELECT COUNT(*) FROM information_schema.cluster_info WHERE status_address IS NULL`).Check(testkit.Rows("0")) + tk.MustQuery(`SELECT COUNT(*) FROM information_schema.CLUSTER_STATEMENTS_SUMMARY WHERE length(instance) = 36`).Check(testkit.Rows("0")) +} + +func (s *testPrivilegeSuite) TestSecurityEnhancedModeStatusVars(c *C) { + // Without TiKV the status var list does not include tidb_gc_leader_desc + // So we can only test that the dynamic privilege is grantable. + // We will have to use an integration test to run SHOW STATUS LIKE 'tidb_gc_leader_desc' + // and verify if it appears. + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("CREATE USER unostatus, ustatus") + tk.MustExec("SET tidb_enable_dynamic_privileges=1") + tk.MustExec("GRANT RESTRICTED_STATUS_ADMIN ON *.* to ustatus") + tk.Se.Auth(&auth.UserIdentity{ + Username: "unostatus", + Hostname: "localhost", + AuthUsername: "uroot", + AuthHostname: "%", + }, nil, nil) +} + +// TestViewDefiner tests that default roles are correctly applied in the algorithm definer +// See: https://github.com/pingcap/tidb/issues/24414 +func (s *testPrivilegeSuite) TestViewDefiner(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("CREATE DATABASE issue24414") + tk.MustExec("USE issue24414") + tk.MustExec(`create table table1( + col1 int, + col2 int, + col3 int + )`) + tk.MustExec(`insert into table1 values (1,1,1),(2,2,2)`) + tk.MustExec(`CREATE ROLE 'ACL-mobius-admin'`) + tk.MustExec(`CREATE USER 'mobius-admin'`) + tk.MustExec(`CREATE USER 'mobius-admin-no-role'`) + tk.MustExec(`GRANT Select,Insert,Update,Delete,Create,Drop,Alter,Index,Create View,Show View ON issue24414.* TO 'ACL-mobius-admin'@'%'`) + tk.MustExec(`GRANT Select,Insert,Update,Delete,Create,Drop,Alter,Index,Create View,Show View ON issue24414.* TO 'mobius-admin-no-role'@'%'`) + tk.MustExec(`GRANT 'ACL-mobius-admin'@'%' to 'mobius-admin'@'%'`) + tk.MustExec(`SET DEFAULT ROLE ALL TO 'mobius-admin'`) + // create tables + tk.MustExec(`CREATE ALGORITHM = UNDEFINED DEFINER = 'mobius-admin'@'127.0.0.1' SQL SECURITY DEFINER VIEW test_view (col1 , col2 , col3) AS SELECT * from table1`) + tk.MustExec(`CREATE ALGORITHM = UNDEFINED DEFINER = 'mobius-admin-no-role'@'127.0.0.1' SQL SECURITY DEFINER VIEW test_view2 (col1 , col2 , col3) AS SELECT * from table1`) + + // all examples should work + tk.MustExec("select * from test_view") + tk.MustExec("select * from test_view2") +} +>>>>>>> b8cad01be... privilege: fix RequestVerificationWithUser use of default roles (#24442)