Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

executor, privilege: fix some two bug of RBAC (#11273) #11356

Merged
merged 10 commits into from
Jul 30, 2019
19 changes: 17 additions & 2 deletions executor/simple.go
Original file line number Diff line number Diff line change
Expand Up @@ -471,13 +471,20 @@ func (e *SimpleExec) executeRevokeRole(s *ast.RevokeRoleStmt) error {
}
return ErrCannotUser.GenWithStackByArgs("REVOKE ROLE", role.String())
}
sql = fmt.Sprintf(`DELETE IGNORE FROM %s.%s WHERE DEFAULT_ROLE_HOST='%s' and DEFAULT_ROLE_USER='%s' and HOST='%s' and USER='%s'`, mysql.SystemDB, mysql.DefaultRoleTable, role.Hostname, role.Username, user.Hostname, user.Username)
if _, err := e.ctx.(sqlexec.SQLExecutor).Execute(context.Background(), sql); err != nil {
if _, err := e.ctx.(sqlexec.SQLExecutor).Execute(context.Background(), "rollback"); err != nil {
return errors.Trace(err)
}
return ErrCannotUser.GenWithStackByArgs("REVOKE ROLE", role.String())
}
}
}
if _, err := e.ctx.(sqlexec.SQLExecutor).Execute(context.Background(), "commit"); err != nil {
return err
}
err := domain.GetDomain(e.ctx).PrivilegeHandle().Update(e.ctx.(sessionctx.Context))
return errors.Trace(err)
domain.GetDomain(e.ctx).NotifyUpdatePrivilege(e.ctx)
return nil
}

func (e *SimpleExec) executeCommit(s *ast.CommitStmt) {
Expand Down Expand Up @@ -597,6 +604,14 @@ func (e *SimpleExec) executeAlterUser(s *ast.AlterUserStmt) error {

func (e *SimpleExec) executeGrantRole(s *ast.GrantRoleStmt) error {
failedUsers := make([]string, 0, len(s.Users))
sessionVars := e.ctx.GetSessionVars()
for i, user := range s.Users {
if user.CurrentUser {
s.Users[i].Username = sessionVars.User.AuthUsername
s.Users[i].Hostname = sessionVars.User.AuthHostname
}
}

for _, role := range s.Roles {
exists, err := userExists(e.ctx, role.Username, role.Hostname)
if err != nil {
Expand Down
15 changes: 15 additions & 0 deletions executor/simple_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,15 @@ func (s *testSuite3) TestRole(c *C) {
grantRoleSQL = `GRANT 'r_1'@'localhost' TO 'r_3'@'localhost', 'r_4'@'localhost';`
_, err = tk.Exec(grantRoleSQL)
c.Check(err, NotNil)

// Test grant role for current_user();
sessionVars := tk.Se.GetSessionVars()
originUser := sessionVars.User
sessionVars.User = &auth.UserIdentity{Username: "root", Hostname: "localhost", AuthUsername: "root", AuthHostname: "%"}
tk.MustExec("grant 'r_1'@'localhost' to current_user();")
tk.MustExec("revoke 'r_1'@'localhost' from 'root'@'%';")
sessionVars.User = originUser

result = tk.MustQuery(`SELECT FROM_USER FROM mysql.role_edges WHERE TO_USER="r_3" and TO_HOST="localhost"`)
result.Check(nil)

Expand All @@ -152,14 +161,20 @@ func (s *testSuite3) TestRole(c *C) {
tk.MustExec("insert into mysql.role_edges (FROM_HOST,FROM_USER,TO_HOST,TO_USER) values ('localhost','test','%','root')")
tk.MustExec("insert into mysql.role_edges (FROM_HOST,FROM_USER,TO_HOST,TO_USER) values ('%','r_1','%','root')")
tk.MustExec("insert into mysql.role_edges (FROM_HOST,FROM_USER,TO_HOST,TO_USER) values ('%','r_2','%','root')")
tk.MustExec("flush privileges")
tk.MustExec("SET DEFAULT ROLE r_1, r_2 TO root")
_, err = tk.Exec("revoke test@localhost, r_1 from root;")
c.Check(err, IsNil)
_, err = tk.Exec("revoke `r_2`@`%` from root, u_2;")
c.Check(err, NotNil)
_, err = tk.Exec("revoke `r_2`@`%` from root;")
c.Check(err, IsNil)
_, err = tk.Exec("revoke `r_1`@`%` from root;")
c.Check(err, IsNil)
result = tk.MustQuery(`SELECT * FROM mysql.default_roles WHERE DEFAULT_ROLE_USER="test" and DEFAULT_ROLE_HOST="localhost"`)
result.Check(nil)
result = tk.MustQuery(`SELECT * FROM mysql.default_roles WHERE USER="root" and HOST="%"`)
result.Check(nil)
dropRoleSQL = `DROP ROLE 'test'@'localhost', r_1, r_2;`
tk.MustExec(dropRoleSQL)
}
Expand Down
11 changes: 9 additions & 2 deletions expression/builtin_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
package expression

import (
"sort"

"github.com/pingcap/errors"
"github.com/pingcap/parser/mysql"
"github.com/pingcap/tidb/sessionctx"
Expand Down Expand Up @@ -192,8 +194,13 @@ func (b *builtinCurrentRoleSig) evalString(row chunk.Row) (string, bool, error)
return "", false, nil
}
res := ""
for i, r := range data.ActiveRoles {
res += r.String()
sortedRes := make([]string, 0, 10)
for _, r := range data.ActiveRoles {
sortedRes = append(sortedRes, r.String())
}
sort.Strings(sortedRes)
for i, r := range sortedRes {
res += r
if i != len(data.ActiveRoles)-1 {
res += ","
}
Expand Down
10 changes: 8 additions & 2 deletions privilege/privileges/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -848,13 +848,19 @@ func (p *MySQLPrivilege) showGrants(user, host string, roles []*auth.RoleIdentit
edgeTable, ok := p.RoleGraph[graphKey]
g = ""
if ok {
sortedRes := make([]string, 0, 10)
for k := range edgeTable.roleList {
role := strings.Split(k, "@")
roleName, roleHost := role[0], role[1]
if g != "" {
tmp := fmt.Sprintf("'%s'@'%s'", roleName, roleHost)
sortedRes = append(sortedRes, tmp)
}
sort.Strings(sortedRes)
for i, r := range sortedRes {
g += r
if i != len(sortedRes)-1 {
g += ", "
}
g += fmt.Sprintf("'%s'@'%s'", roleName, roleHost)
}
s := fmt.Sprintf(`GRANT %s TO '%s'@'%s'`, g, user, host)
gs = append(gs, s)
Expand Down