Skip to content

Commit 4f20b5b

Browse files
author
Lingyu Song
authored
executor, plan: add revoke role support (#9771)
1 parent 6958760 commit 4f20b5b

File tree

3 files changed

+68
-1
lines changed

3 files changed

+68
-1
lines changed

executor/simple.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ func (e *SimpleExec) Next(ctx context.Context, req *chunk.RecordBatch) (err erro
8585
err = e.executeDropStats(x)
8686
case *ast.SetRoleStmt:
8787
err = e.executeSetRole(x)
88+
case *ast.RevokeRoleStmt:
89+
err = e.executeRevokeRole(x)
8890
}
8991
e.done = true
9092
return err
@@ -165,6 +167,52 @@ func (e *SimpleExec) executeBegin(ctx context.Context, s *ast.BeginStmt) error {
165167
return nil
166168
}
167169

170+
func (e *SimpleExec) executeRevokeRole(s *ast.RevokeRoleStmt) error {
171+
for _, role := range s.Roles {
172+
exists, err := userExists(e.ctx, role.Username, role.Hostname)
173+
if err != nil {
174+
return errors.Trace(err)
175+
}
176+
if !exists {
177+
return ErrCannotUser.GenWithStackByArgs("REVOKE ROLE", role.String())
178+
}
179+
}
180+
181+
// begin a transaction to insert role graph edges.
182+
if _, err := e.ctx.(sqlexec.SQLExecutor).Execute(context.Background(), "begin"); err != nil {
183+
return errors.Trace(err)
184+
}
185+
for _, user := range s.Users {
186+
exists, err := userExists(e.ctx, user.Username, user.Hostname)
187+
if err != nil {
188+
return errors.Trace(err)
189+
}
190+
if !exists {
191+
if _, err := e.ctx.(sqlexec.SQLExecutor).Execute(context.Background(), "rollback"); err != nil {
192+
return errors.Trace(err)
193+
}
194+
return ErrCannotUser.GenWithStackByArgs("REVOKE ROLE", user.String())
195+
}
196+
for _, role := range s.Roles {
197+
if role.Hostname == "" {
198+
role.Hostname = "%"
199+
}
200+
sql := fmt.Sprintf(`DELETE IGNORE FROM %s.%s WHERE FROM_HOST='%s' and FROM_USER='%s' and TO_HOST='%s' and TO_USER='%s'`, mysql.SystemDB, mysql.RoleEdgeTable, role.Hostname, role.Username, user.Hostname, user.Username)
201+
if _, err := e.ctx.(sqlexec.SQLExecutor).Execute(context.Background(), sql); err != nil {
202+
if _, err := e.ctx.(sqlexec.SQLExecutor).Execute(context.Background(), "rollback"); err != nil {
203+
return errors.Trace(err)
204+
}
205+
return ErrCannotUser.GenWithStackByArgs("REVOKE ROLE", role.String())
206+
}
207+
}
208+
}
209+
if _, err := e.ctx.(sqlexec.SQLExecutor).Execute(context.Background(), "commit"); err != nil {
210+
return err
211+
}
212+
err := domain.GetDomain(e.ctx).PrivilegeHandle().Update(e.ctx.(sessionctx.Context))
213+
return errors.Trace(err)
214+
}
215+
168216
func (e *SimpleExec) executeCommit(s *ast.CommitStmt) {
169217
e.ctx.GetSessionVars().SetStatusFlag(mysql.ServerStatusInTrans, false)
170218
}

executor/simple_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,23 @@ func (s *testSuite3) TestRole(c *C) {
141141
tk.MustExec(dropRoleSQL)
142142
dropRoleSQL = `DROP ROLE IF EXISTS 'r_3'@'localhost' ;`
143143
tk.MustExec(dropRoleSQL)
144+
145+
// Test for revoke role
146+
createRoleSQL = `CREATE ROLE 'test'@'localhost', r_1, r_2;`
147+
tk.MustExec(createRoleSQL)
148+
tk.MustExec("insert into mysql.role_edges (FROM_HOST,FROM_USER,TO_HOST,TO_USER) values ('localhost','test','%','root')")
149+
tk.MustExec("insert into mysql.role_edges (FROM_HOST,FROM_USER,TO_HOST,TO_USER) values ('%','r_1','%','root')")
150+
tk.MustExec("insert into mysql.role_edges (FROM_HOST,FROM_USER,TO_HOST,TO_USER) values ('%','r_2','%','root')")
151+
_, err = tk.Exec("revoke test@localhost, r_1 from root;")
152+
c.Check(err, IsNil)
153+
_, err = tk.Exec("revoke `r_2`@`%` from root, u_2;")
154+
c.Check(err, NotNil)
155+
_, err = tk.Exec("revoke `r_2`@`%` from root;")
156+
c.Check(err, IsNil)
157+
result = tk.MustQuery(`SELECT * FROM mysql.default_roles WHERE DEFAULT_ROLE_USER="test" and DEFAULT_ROLE_HOST="localhost"`)
158+
result.Check(nil)
159+
dropRoleSQL = `DROP ROLE 'test'@'localhost', r_1, r_2;`
160+
tk.MustExec(dropRoleSQL)
144161
}
145162

146163
func (s *testSuite3) TestUser(c *C) {

planner/core/planbuilder.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ func (b *PlanBuilder) Build(node ast.Node) (Plan, error) {
268268
case *ast.BinlogStmt, *ast.FlushStmt, *ast.UseStmt,
269269
*ast.BeginStmt, *ast.CommitStmt, *ast.RollbackStmt, *ast.CreateUserStmt, *ast.SetPwdStmt,
270270
*ast.GrantStmt, *ast.DropUserStmt, *ast.AlterUserStmt, *ast.RevokeStmt, *ast.KillStmt, *ast.DropStatsStmt,
271-
*ast.GrantRoleStmt, *ast.SetRoleStmt:
271+
*ast.GrantRoleStmt, *ast.RevokeRoleStmt, *ast.SetRoleStmt:
272272
return b.buildSimple(node.(ast.StmtNode))
273273
case ast.DDLNode:
274274
return b.buildDDL(x)
@@ -1105,6 +1105,8 @@ func (b *PlanBuilder) buildSimple(node ast.StmtNode) (Plan, error) {
11051105
b.visitInfo = appendVisitInfo(b.visitInfo, mysql.GrantPriv, "", "", "", err)
11061106
case *ast.RevokeStmt:
11071107
b.visitInfo = appendVisitInfo(b.visitInfo, mysql.SuperPriv, "", "", "", nil)
1108+
case *ast.RevokeRoleStmt:
1109+
b.visitInfo = appendVisitInfo(b.visitInfo, mysql.SuperPriv, "", "", "", nil)
11081110
case *ast.KillStmt:
11091111
// If you have the SUPER privilege, you can kill all threads and statements.
11101112
// Otherwise, you can kill only your own threads and statements.

0 commit comments

Comments
 (0)