diff --git a/executor/executor_test.go b/executor/executor_test.go index 6a454bb85a9ea..7e6a51799d778 100644 --- a/executor/executor_test.go +++ b/executor/executor_test.go @@ -280,6 +280,7 @@ func TestShow(t *testing.T) { "RESTRICTED_USER_ADMIN Server Admin ", "RESTRICTED_CONNECTION_ADMIN Server Admin ", "RESTRICTED_REPLICA_WRITER_ADMIN Server Admin ", + "RESOURCE_GROUP_ADMIN Server Admin ", )) require.Len(t, tk.MustQuery("show table status").Rows(), 1) } diff --git a/planner/core/planbuilder.go b/planner/core/planbuilder.go index 649a60415b359..c4a31f0374d19 100644 --- a/planner/core/planbuilder.go +++ b/planner/core/planbuilder.go @@ -4755,6 +4755,9 @@ func (b *PlanBuilder) buildDDL(ctx context.Context, node ast.DDLNode) (Plan, err case *ast.DropPlacementPolicyStmt, *ast.CreatePlacementPolicyStmt, *ast.AlterPlacementPolicyStmt: err := ErrSpecificAccessDenied.GenWithStackByArgs("SUPER or PLACEMENT_ADMIN") b.visitInfo = appendDynamicVisitInfo(b.visitInfo, "PLACEMENT_ADMIN", false, err) + case *ast.CreateResourceGroupStmt, *ast.DropResourceGroupStmt, *ast.AlterResourceGroupStmt: + err := ErrSpecificAccessDenied.GenWithStackByArgs("SUPER or RESOURCE_GROUP_ADMIN") + b.visitInfo = appendDynamicVisitInfo(b.visitInfo, "RESOURCE_GROUP_ADMIN", false, err) } p := &DDL{Statement: node} return p, nil diff --git a/privilege/privileges/privileges.go b/privilege/privileges/privileges.go index 6f7fcc0d508cd..288415c7bcdb4 100644 --- a/privilege/privileges/privileges.go +++ b/privilege/privileges/privileges.go @@ -62,6 +62,7 @@ var dynamicPrivs = []string{ "RESTRICTED_USER_ADMIN", // User can not have their access revoked by SUPER users. "RESTRICTED_CONNECTION_ADMIN", // Can not be killed by PROCESS/CONNECTION_ADMIN privilege "RESTRICTED_REPLICA_WRITER_ADMIN", // Can write to the sever even when tidb_restriced_read_only is turned on. + "RESOURCE_GROUP_ADMIN", // Create/Drop/Alter RESOURCE GROUP } var dynamicPrivLock sync.Mutex var defaultTokenLife = 15 * time.Minute diff --git a/privilege/privileges/privileges_test.go b/privilege/privileges/privileges_test.go index 18de50ae11036..4c749702ae2f8 100644 --- a/privilege/privileges/privileges_test.go +++ b/privilege/privileges/privileges_test.go @@ -2571,6 +2571,46 @@ func TestPlacementPolicyStmt(t *testing.T) { tk.MustExec(dropStmt) } +func TestResourceGroupAdminDynamicPriv(t *testing.T) { + store := createStoreAndPrepareDB(t) + + tk1 := testkit.NewTestKit(t, store) + // tk1 is the root user, create a new user for test. + tk1.Session().Auth(&auth.UserIdentity{ + Username: "root", + Hostname: "localhost", + }, nil, nil) + tk1.MustExec("CREATE USER resource_group_user") + tk1.MustExec("set @@global.tidb_enable_resource_control = 1") + + // tk2 is the new user. + tk2 := testkit.NewTestKit(t, store) + tk2.Session().Auth(&auth.UserIdentity{ + Username: "resource_group_user", + Hostname: "localhost", + }, nil, nil) + err := tk2.ExecToErr("CREATE RESOURCE GROUP test RRU_PER_SEC = 666") + require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the SUPER or RESOURCE_GROUP_ADMIN privilege(s) for this operation") + + // grant the RESOURCE_GROUP_ADMIN dynamic privilege to the user. + tk1.MustExec("GRANT RESOURCE_GROUP_ADMIN ON *.* TO resource_group_user") + tk1.MustQuery("SHOW GRANTS FOR resource_group_user").Check(testkit.Rows( + `GRANT USAGE ON *.* TO 'resource_group_user'@'%'`, + `GRANT RESOURCE_GROUP_ADMIN ON *.* TO 'resource_group_user'@'%'`)) + + tk2.MustExec("CREATE RESOURCE GROUP test RRU_PER_SEC = 666") + tk2.MustExec("CREATE RESOURCE GROUP test2 WRU_PER_SEC = 999") + + tk2.MustExec("ALTER RESOURCE GROUP test2 WRU_PER_SEC = 1000") + tk2.MustExec("DROP RESOURCE GROUP test2") + + tk1.MustExec("REVOKE RESOURCE_GROUP_ADMIN ON *.* FROM resource_group_user") + err = tk2.ExecToErr("ALTER RESOURCE GROUP test RRU_PER_SEC = 667") + require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the SUPER or RESOURCE_GROUP_ADMIN privilege(s) for this operation") + err = tk2.ExecToErr("DROP RESOURCE GROUP test") + require.EqualError(t, err, "[planner:1227]Access denied; you need (at least one of) the SUPER or RESOURCE_GROUP_ADMIN privilege(s) for this operation") +} + func TestDBNameCaseSensitivityInTableLevel(t *testing.T) { store := createStoreAndPrepareDB(t) tk := testkit.NewTestKit(t, store)