From 1d9eb3cbce7ac83c0eebcddd4b5cecb8c901e10c Mon Sep 17 00:00:00 2001 From: imtbkcat Date: Thu, 21 Feb 2019 14:56:14 +0800 Subject: [PATCH 01/14] edit gomod --- go.mod | 2 ++ go.sum | 1 + 2 files changed, 3 insertions(+) diff --git a/go.mod b/go.mod index af5b39b6e0ef0..3d46d7f61ea5c 100644 --- a/go.mod +++ b/go.mod @@ -87,3 +87,5 @@ require ( sourcegraph.com/sourcegraph/appdash v0.0.0-20180531100431-4c381bd170b4 sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67 ) + +replace github.com/pingcap/parser => github.com/imtbkcat/parser v0.0.0-20190221063207-bd4ac4f8b099 diff --git a/go.sum b/go.sum index 4dc0ebf9e9612..47c8f316928f0 100644 --- a/go.sum +++ b/go.sum @@ -75,6 +75,7 @@ github.com/grpc-ecosystem/grpc-gateway v1.5.1 h1:3scN4iuXkNOyP98jF55Lv8a9j1o/Iwv github.com/grpc-ecosystem/grpc-gateway v1.5.1/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/imtbkcat/parser v0.0.0-20190221063207-bd4ac4f8b099/go.mod h1:qupHD3o7J0aBb3bbVyXRnxe9kKy2MTY/6POS6NO/Ei8= github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= From c83ca1d0bbb31afec6f5f4ed555e592e70160bc7 Mon Sep 17 00:00:00 2001 From: imtbkcat Date: Thu, 28 Feb 2019 21:57:54 +0800 Subject: [PATCH 02/14] edit gomod --- go.sum | 1 + 1 file changed, 1 insertion(+) diff --git a/go.sum b/go.sum index 47c8f316928f0..15f735bb1f066 100644 --- a/go.sum +++ b/go.sum @@ -75,6 +75,7 @@ github.com/grpc-ecosystem/grpc-gateway v1.5.1 h1:3scN4iuXkNOyP98jF55Lv8a9j1o/Iwv github.com/grpc-ecosystem/grpc-gateway v1.5.1/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/imtbkcat/parser v0.0.0-20190221063207-bd4ac4f8b099 h1:4qNZPIGbYytH6TmZ7crJDlqknLLKxi9LYGuU2PmS/4E= github.com/imtbkcat/parser v0.0.0-20190221063207-bd4ac4f8b099/go.mod h1:qupHD3o7J0aBb3bbVyXRnxe9kKy2MTY/6POS6NO/Ei8= github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= From bd065da22a0386230070a8decf24f8ca02869f23 Mon Sep 17 00:00:00 2001 From: imtbkcat Date: Tue, 5 Mar 2019 13:42:35 +0800 Subject: [PATCH 03/14] add executor --- executor/simple.go | 32 +++++++++++++++- go.mod | 4 +- go.sum | 2 + planner/core/planbuilder.go | 4 +- privilege/privilege.go | 3 ++ privilege/privileges/cache.go | 59 ++++++++++++++++++++++++++++++ privilege/privileges/privileges.go | 16 ++++++++ sessionctx/variable/session.go | 3 ++ 8 files changed, 118 insertions(+), 5 deletions(-) diff --git a/executor/simple.go b/executor/simple.go index 18bd342f0cc88..4a4feb075fb81 100644 --- a/executor/simple.go +++ b/executor/simple.go @@ -81,11 +81,41 @@ func (e *SimpleExec) Next(ctx context.Context, req *chunk.RecordBatch) (err erro return nil case *ast.DropStatsStmt: err = e.executeDropStats(x) + case *ast.SetRoleStmt: + err = e.executeSetRole(x) } e.done = true return errors.Trace(err) } +func (e *SimpleExec) executeSetRole(s *ast.SetRoleStmt) error { + checkDup := make(map[string]bool) + + // Check whether RoleNameList contain duplicate role name. + for _, r := range s.RoleList { + if r.Hostname == "" { + r.Hostname = "%" + } + if r.Username == "" { + return errors.New("Role name can not be empty") + } + roleName := r.Username + "@" + r.Hostname + _, dup := checkDup[roleName] + if dup { + return errors.New("Duplicate role") + } else { + checkDup[roleName] = true + } + } + + checker := privilege.GetPrivilegeManager(e.ctx) + ok := checker.ActiveRoles(e.ctx, s.RoleList) + if !ok { + return errors.New("Error occur when activing roles") + } + return nil +} + func (e *SimpleExec) dbAccessDenied(dbname string) error { user := e.ctx.GetSessionVars().User u := user.Username @@ -352,7 +382,7 @@ func (e *SimpleExec) executeDropUser(s *ast.DropUserStmt) error { } func userExists(ctx sessionctx.Context, name string, host string) (bool, error) { - sql := fmt.Sprintf(`SELECT * FROM %s.%s WHERE User='%s' AND Host='%s';`, mysql.SystemDB, mysql.UserTable, name, host) + sql := fmt.Sprintf(`SELECT * FROM %s.%s WHERE User='%s' AND Host='%s';`, mysql.SystemDB, mysql.RoleEdgeTable, name, host) rows, _, err := ctx.(sqlexec.RestrictedSQLExecutor).ExecRestrictedSQL(ctx, sql) if err != nil { return false, errors.Trace(err) diff --git a/go.mod b/go.mod index 3d46d7f61ea5c..4fb9bfafdc9d4 100644 --- a/go.mod +++ b/go.mod @@ -80,7 +80,7 @@ require ( golang.org/x/text v0.3.0 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c // indirect golang.org/x/tools v0.0.0-20190130214255-bb1329dc71a0 - google.golang.org/genproto v0.0.0-20190108161440-ae2f86662275 // indirect + google.golang.org/genproto v0.0.0-20190108161440-ae2f86662275 google.golang.org/grpc v1.17.0 gopkg.in/natefinch/lumberjack.v2 v2.0.0 gopkg.in/stretchr/testify.v1 v1.2.2 // indirect @@ -88,4 +88,4 @@ require ( sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67 ) -replace github.com/pingcap/parser => github.com/imtbkcat/parser v0.0.0-20190221063207-bd4ac4f8b099 +replace github.com/pingcap/parser => github.com/imtbkcat/parser v0.0.0-20190303143855-d110705f7c88 diff --git a/go.sum b/go.sum index 15f735bb1f066..f545d62c1d318 100644 --- a/go.sum +++ b/go.sum @@ -77,6 +77,8 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/imtbkcat/parser v0.0.0-20190221063207-bd4ac4f8b099 h1:4qNZPIGbYytH6TmZ7crJDlqknLLKxi9LYGuU2PmS/4E= github.com/imtbkcat/parser v0.0.0-20190221063207-bd4ac4f8b099/go.mod h1:qupHD3o7J0aBb3bbVyXRnxe9kKy2MTY/6POS6NO/Ei8= +github.com/imtbkcat/parser v0.0.0-20190303143855-d110705f7c88 h1:X0AiDP3VsdZ3JLPzbslLbcr9tevlguRhiK25XbdOb8M= +github.com/imtbkcat/parser v0.0.0-20190303143855-d110705f7c88/go.mod h1:qupHD3o7J0aBb3bbVyXRnxe9kKy2MTY/6POS6NO/Ei8= github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= diff --git a/planner/core/planbuilder.go b/planner/core/planbuilder.go index f32e26239cac2..ddc35c3ea43db 100644 --- a/planner/core/planbuilder.go +++ b/planner/core/planbuilder.go @@ -212,8 +212,8 @@ func (b *PlanBuilder) Build(node ast.Node) (Plan, error) { case *ast.AnalyzeTableStmt: return b.buildAnalyze(x) case *ast.BinlogStmt, *ast.FlushStmt, *ast.UseStmt, - *ast.BeginStmt, *ast.CommitStmt, *ast.RollbackStmt, *ast.CreateUserStmt, *ast.SetPwdStmt, - *ast.GrantStmt, *ast.DropUserStmt, *ast.AlterUserStmt, *ast.RevokeStmt, *ast.KillStmt, *ast.DropStatsStmt: + *ast.BeginStmt, *ast.CommitStmt, *ast.RollbackStmt, *ast.CreateUserStmt, *ast.SetPwdStmt, *ast.GrantStmt, + *ast.DropUserStmt, *ast.AlterUserStmt, *ast.RevokeStmt, *ast.KillStmt, *ast.DropStatsStmt, *ast.SetRoleStmt: return b.buildSimple(node.(ast.StmtNode)) case ast.DDLNode: return b.buildDDL(x) diff --git a/privilege/privilege.go b/privilege/privilege.go index 7091f96effee3..399ac72996de6 100644 --- a/privilege/privilege.go +++ b/privilege/privilege.go @@ -52,6 +52,9 @@ type Manager interface { // UserPrivilegesTable provide data for INFORMATION_SCHEMA.USERS_PRIVILEGE table. UserPrivilegesTable() [][]types.Datum + + // ActiveRoles active roles for current session. + ActiveRoles(ctx sessionctx.Context, roleList []*auth.RoleIdentity) bool } const key keyType = 0 diff --git a/privilege/privileges/cache.go b/privilege/privileges/cache.go index 0e5bb5bf5fb4c..ee3a5e8365a18 100644 --- a/privilege/privileges/cache.go +++ b/privilege/privileges/cache.go @@ -16,6 +16,7 @@ package privileges import ( "context" "fmt" + "github.com/pingcap/parser/auth" "sort" "strings" "sync/atomic" @@ -104,12 +105,34 @@ type columnsPrivRecord struct { patTypes []byte } +type RoleGraphEdgesTable struct { + roleList map[string]bool +} + +func (g *RoleGraphEdgesTable) Find(user, host string) bool { + if host == "" { + host = "%" + } + key := user + "@" + host + _, ok := g.roleList[key] + if ok { + return true + } + return false +} + // MySQLPrivilege is the in-memory cache of mysql privilege tables. type MySQLPrivilege struct { User []UserRecord DB []dbRecord TablesPriv []tablesPrivRecord ColumnsPriv []columnsPrivRecord + RoleGraph map[string]*RoleGraphEdgesTable +} + +func (p *MySQLPrivilege) FindRole(user string, host string, role *auth.RoleIdentity) bool { + key := user + "@" + host + return p.RoleGraph[key].Find(role.Username, role.Hostname) } // LoadAll loads the tables from database to memory. @@ -155,6 +178,16 @@ func noSuchTable(err error) bool { return false } +// LoadRoleGraph loads the mysql.role_edges table from database. +func (p *MySQLPrivilege) LoadRoleGraph(ctx sessionctx.Context) error { + p.RoleGraph = make(map[string]*RoleGraphEdgesTable) + err := p.loadTable(ctx, "select FROM_USER, FROM_HOST, TO_USER, TO_HOST from mysql.role_edges;", p.decodeRoleEdgesTable) + if err != nil { + return errors.Trace(err) + } + return nil +} + // LoadUserTable loads the mysql.user table from database. func (p *MySQLPrivilege) LoadUserTable(ctx sessionctx.Context) error { err := p.loadTable(ctx, "select HIGH_PRIORITY Host,User,Password,Select_priv,Insert_priv,Update_priv,Delete_priv,Create_priv,Drop_priv,Process_priv,Grant_priv,References_priv,Alter_priv,Show_db_priv,Super_priv,Execute_priv,Create_view_priv,Show_view_priv,Index_priv,Create_user_priv,Trigger_priv,Create_role_priv,Drop_role_priv,account_locked from mysql.user;", p.decodeUserTableRow) @@ -381,6 +414,32 @@ func (p *MySQLPrivilege) decodeTablesPrivTableRow(row chunk.Row, fs []*ast.Resul return nil } +func (p *MySQLPrivilege) decodeRoleEdgesTable(row chunk.Row, fs []*ast.ResultField) error { + var fromUser, fromHost, toHost, toUser string + for i, f := range fs { + switch { + case f.ColumnAsName.L == "FROM_HOST": + fromHost = row.GetString(i) + case f.ColumnAsName.L == "FROM_USER": + fromHost = row.GetString(i) + case f.ColumnAsName.L == "TO_HOST": + toHost = row.GetString(i) + case f.ColumnAsName.L == "TO_USER": + toUser = row.GetString(i) + } + } + fromKey := fromUser + "@" + fromHost + toKey := toUser + "@" + toHost + if value, ok := p.RoleGraph[toKey]; ok { + value.roleList[fromKey] = true + } else { + p.RoleGraph[toKey] = &RoleGraphEdgesTable{} + p.RoleGraph[toKey].roleList = make(map[string]bool) + p.RoleGraph[toKey].roleList[toKey] = true + } + return nil +} + func (p *MySQLPrivilege) decodeColumnsPrivTableRow(row chunk.Row, fs []*ast.ResultField) error { var value columnsPrivRecord for i, f := range fs { diff --git a/privilege/privileges/privileges.go b/privilege/privileges/privileges.go index 807359ee79594..19c119b7b3641 100644 --- a/privilege/privileges/privileges.go +++ b/privilege/privileges/privileges.go @@ -186,3 +186,19 @@ func (p *UserPrivileges) ShowGrants(ctx sessionctx.Context, user *auth.UserIdent return } + +// ActiveRoles implements privilege.Manager ActiveRoles interface. +func (p *UserPrivileges) ActiveRoles(ctx sessionctx.Context, roleList []*auth.RoleIdentity) bool { + mysqlPrivilege := p.Handle.Get() + u := p.user + h := p.host + for _, r := range roleList { + ok := mysqlPrivilege.FindRole(u, h, r) + if !ok { + log.Errorf("Role: %+v doesn't grant for user", r) + return false + } + } + ctx.GetSessionVars().ActiveRoles = roleList + return true +} diff --git a/sessionctx/variable/session.go b/sessionctx/variable/session.go index 0fa3773e40d4f..a63d397f2ffe5 100644 --- a/sessionctx/variable/session.go +++ b/sessionctx/variable/session.go @@ -191,6 +191,9 @@ type SessionVars struct { // params for prepared statements PreparedParams []types.Datum + // ActiveRoles stores active roles for current user + ActiveRoles []*auth.RoleIdentity + // retry information RetryInfo *RetryInfo // Should be reset on transaction finished. From 0b4323bc1474c42a413957e953e725c8bfef3bcc Mon Sep 17 00:00:00 2001 From: imtbkcat Date: Thu, 7 Mar 2019 10:12:00 +0800 Subject: [PATCH 04/14] add test for role graph --- executor/simple.go | 31 +++++++++----------- expression/builtin.go | 1 + expression/builtin_info.go | 45 ++++++++++++++++++++++++++++ expression/function_traits.go | 1 + go.mod | 4 +-- go.sum | 5 +--- privilege/privilege.go | 3 +- privilege/privileges/cache.go | 47 ++++++++++++++++++++---------- privilege/privileges/cache_test.go | 30 +++++++++++++++++++ privilege/privileges/privileges.go | 6 ++-- sessionctx/variable/session.go | 1 + 11 files changed, 131 insertions(+), 43 deletions(-) diff --git a/executor/simple.go b/executor/simple.go index 4a4feb075fb81..25ea94047a6f3 100644 --- a/executor/simple.go +++ b/executor/simple.go @@ -89,29 +89,24 @@ func (e *SimpleExec) Next(ctx context.Context, req *chunk.RecordBatch) (err erro } func (e *SimpleExec) executeSetRole(s *ast.SetRoleStmt) error { - checkDup := make(map[string]bool) - + checkDup := make(map[string]*auth.RoleIdentity) // Check whether RoleNameList contain duplicate role name. for _, r := range s.RoleList { - if r.Hostname == "" { - r.Hostname = "%" - } - if r.Username == "" { - return errors.New("Role name can not be empty") - } - roleName := r.Username + "@" + r.Hostname - _, dup := checkDup[roleName] - if dup { - return errors.New("Duplicate role") - } else { - checkDup[roleName] = true - } + key := r.String() + checkDup[key] = r + } + roleList := make([]*auth.RoleIdentity, 0, 10) + for _, v := range checkDup { + roleList = append(roleList, v) } checker := privilege.GetPrivilegeManager(e.ctx) - ok := checker.ActiveRoles(e.ctx, s.RoleList) + ok, roleName := checker.ActiveRoles(e.ctx, roleList) if !ok { - return errors.New("Error occur when activing roles") + errCode := mysql.ErrRoleNotGranted + errRoleNotGranted := terror.ClassPrivilege.New(terror.ErrCode(errCode), mysql.MySQLErrName[uint16(errCode)]) + u := e.ctx.GetSessionVars().User + return errRoleNotGranted.GenWithStackByArgs(roleName, u.String()) } return nil } @@ -382,7 +377,7 @@ func (e *SimpleExec) executeDropUser(s *ast.DropUserStmt) error { } func userExists(ctx sessionctx.Context, name string, host string) (bool, error) { - sql := fmt.Sprintf(`SELECT * FROM %s.%s WHERE User='%s' AND Host='%s';`, mysql.SystemDB, mysql.RoleEdgeTable, name, host) + sql := fmt.Sprintf(`SELECT * FROM %s.%s WHERE User='%s' AND Host='%s';`, mysql.SystemDB, mysql.UserTable, name, host) rows, _, err := ctx.(sqlexec.RestrictedSQLExecutor).ExecRestrictedSQL(ctx, sql) if err != nil { return false, errors.Trace(err) diff --git a/expression/builtin.go b/expression/builtin.go index 9a90e81ebc0e1..f779687d863f0 100644 --- a/expression/builtin.go +++ b/expression/builtin.go @@ -470,6 +470,7 @@ var funcs = map[string]functionClass{ // information functions ast.ConnectionID: &connectionIDFunctionClass{baseFunctionClass{ast.ConnectionID, 0, 0}}, ast.CurrentUser: ¤tUserFunctionClass{baseFunctionClass{ast.CurrentUser, 0, 0}}, + ast.CurrentRole: ¤tRoleFunctionClass{baseFunctionClass{ast.CurrentRole, 0, 0}}, ast.Database: &databaseFunctionClass{baseFunctionClass{ast.Database, 0, 0}}, // This function is a synonym for DATABASE(). // See http://dev.mysql.com/doc/refman/5.7/en/information-functions.html#function_schema diff --git a/expression/builtin_info.go b/expression/builtin_info.go index a555bd08d26d5..6739275795d8d 100644 --- a/expression/builtin_info.go +++ b/expression/builtin_info.go @@ -30,6 +30,7 @@ var ( _ functionClass = &databaseFunctionClass{} _ functionClass = &foundRowsFunctionClass{} _ functionClass = ¤tUserFunctionClass{} + _ functionClass = ¤tRoleFunctionClass{} _ functionClass = &userFunctionClass{} _ functionClass = &connectionIDFunctionClass{} _ functionClass = &lastInsertIDFunctionClass{} @@ -156,6 +157,50 @@ func (b *builtinCurrentUserSig) evalString(row chunk.Row) (string, bool, error) return data.User.AuthIdentityString(), false, nil } +type currentRoleFunctionClass struct { + baseFunctionClass +} + +func (c *currentRoleFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) { + if err := c.verifyArgs(args); err != nil { + return nil, err + } + bf := newBaseBuiltinFuncWithTp(ctx, args, types.ETString) + bf.tp.Flen = 64 + sig := &builtinCurrentRoleSig{bf} + return sig, nil +} + +type builtinCurrentRoleSig struct { + baseBuiltinFunc +} + +func (b *builtinCurrentRoleSig) Clone() builtinFunc { + newSig := &builtinCurrentRoleSig{} + newSig.cloneFrom(&b.baseBuiltinFunc) + return newSig +} + +// evalString evals a builtinCurrentUserSig. +// See https://dev.mysql.com/doc/refman/5.7/en/information-functions.html#function_current-user +func (b *builtinCurrentRoleSig) evalString(row chunk.Row) (string, bool, error) { + data := b.ctx.GetSessionVars() + if data == nil || data.ActiveRoles == nil { + return "", true, errors.Errorf("Missing session variable when eval builtin") + } + if len(data.ActiveRoles) == 0 { + return "NONE", false, nil + } + res := "" + for i, r := range data.ActiveRoles { + res += r.String() + if i != len(data.ActiveRoles)-1 { + res += "," + } + } + return res, false, nil +} + type userFunctionClass struct { baseFunctionClass } diff --git a/expression/function_traits.go b/expression/function_traits.go index d7c0ec881f8bd..988c020b18528 100644 --- a/expression/function_traits.go +++ b/expression/function_traits.go @@ -21,6 +21,7 @@ import ( var UnCacheableFunctions = map[string]struct{}{ ast.Database: {}, ast.CurrentUser: {}, + ast.CurrentRole: {}, ast.User: {}, ast.ConnectionID: {}, ast.LastInsertId: {}, diff --git a/go.mod b/go.mod index 4fb9bfafdc9d4..deaa9b04c0da5 100644 --- a/go.mod +++ b/go.mod @@ -80,7 +80,7 @@ require ( golang.org/x/text v0.3.0 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c // indirect golang.org/x/tools v0.0.0-20190130214255-bb1329dc71a0 - google.golang.org/genproto v0.0.0-20190108161440-ae2f86662275 + google.golang.org/genproto v0.0.0-20190108161440-ae2f86662275 // indirect google.golang.org/grpc v1.17.0 gopkg.in/natefinch/lumberjack.v2 v2.0.0 gopkg.in/stretchr/testify.v1 v1.2.2 // indirect @@ -88,4 +88,4 @@ require ( sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67 ) -replace github.com/pingcap/parser => github.com/imtbkcat/parser v0.0.0-20190303143855-d110705f7c88 +replace github.com/pingcap/parser => github.com/imtbkcat/parser v0.0.0-20190306131438-36bf9d091519 diff --git a/go.sum b/go.sum index f545d62c1d318..2a5475261adb4 100644 --- a/go.sum +++ b/go.sum @@ -75,10 +75,7 @@ github.com/grpc-ecosystem/grpc-gateway v1.5.1 h1:3scN4iuXkNOyP98jF55Lv8a9j1o/Iwv github.com/grpc-ecosystem/grpc-gateway v1.5.1/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/imtbkcat/parser v0.0.0-20190221063207-bd4ac4f8b099 h1:4qNZPIGbYytH6TmZ7crJDlqknLLKxi9LYGuU2PmS/4E= -github.com/imtbkcat/parser v0.0.0-20190221063207-bd4ac4f8b099/go.mod h1:qupHD3o7J0aBb3bbVyXRnxe9kKy2MTY/6POS6NO/Ei8= -github.com/imtbkcat/parser v0.0.0-20190303143855-d110705f7c88 h1:X0AiDP3VsdZ3JLPzbslLbcr9tevlguRhiK25XbdOb8M= -github.com/imtbkcat/parser v0.0.0-20190303143855-d110705f7c88/go.mod h1:qupHD3o7J0aBb3bbVyXRnxe9kKy2MTY/6POS6NO/Ei8= +github.com/imtbkcat/parser v0.0.0-20190306131438-36bf9d091519/go.mod h1:qupHD3o7J0aBb3bbVyXRnxe9kKy2MTY/6POS6NO/Ei8= github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= diff --git a/privilege/privilege.go b/privilege/privilege.go index 399ac72996de6..b6aa136c6c806 100644 --- a/privilege/privilege.go +++ b/privilege/privilege.go @@ -54,7 +54,8 @@ type Manager interface { UserPrivilegesTable() [][]types.Datum // ActiveRoles active roles for current session. - ActiveRoles(ctx sessionctx.Context, roleList []*auth.RoleIdentity) bool + // The first illegal role will be returned. + ActiveRoles(ctx sessionctx.Context, roleList []*auth.RoleIdentity) (bool, string) } const key keyType = 0 diff --git a/privilege/privileges/cache.go b/privilege/privileges/cache.go index ee3a5e8365a18..343cecffc0709 100644 --- a/privilege/privileges/cache.go +++ b/privilege/privileges/cache.go @@ -105,15 +105,20 @@ type columnsPrivRecord struct { patTypes []byte } +// RoleGraphEdgesTable is used to cache relationship between and role. type RoleGraphEdgesTable struct { roleList map[string]bool } -func (g *RoleGraphEdgesTable) Find(user, host string) bool { +// Find method is used to find role from table +func (g RoleGraphEdgesTable) Find(user, host string) bool { if host == "" { host = "%" } key := user + "@" + host + if g.roleList == nil { + return false + } _, ok := g.roleList[key] if ok { return true @@ -127,12 +132,17 @@ type MySQLPrivilege struct { DB []dbRecord TablesPriv []tablesPrivRecord ColumnsPriv []columnsPrivRecord - RoleGraph map[string]*RoleGraphEdgesTable + RoleGraph map[string]RoleGraphEdgesTable } +// FindRole is used to detect whether this is an edge between user and role func (p *MySQLPrivilege) FindRole(user string, host string, role *auth.RoleIdentity) bool { - key := user + "@" + host - return p.RoleGraph[key].Find(role.Username, role.Hostname) + rec := p.matchUser(user, host) + if rec != nil && role != nil { + key := rec.User + "@" + rec.Host + return p.RoleGraph[key].Find(role.Username, role.Hostname) + } + return false } // LoadAll loads the tables from database to memory. @@ -165,6 +175,14 @@ func (p *MySQLPrivilege) LoadAll(ctx sessionctx.Context) error { } log.Warn("mysql.columns_priv missing") } + + err = p.LoadRoleGraph(ctx) + if err != nil { + if !noSuchTable(err) { + return errors.Trace(err) + } + log.Warn("mysql.role_edges missing") + } return nil } @@ -180,7 +198,7 @@ func noSuchTable(err error) bool { // LoadRoleGraph loads the mysql.role_edges table from database. func (p *MySQLPrivilege) LoadRoleGraph(ctx sessionctx.Context) error { - p.RoleGraph = make(map[string]*RoleGraphEdgesTable) + p.RoleGraph = make(map[string]RoleGraphEdgesTable) err := p.loadTable(ctx, "select FROM_USER, FROM_HOST, TO_USER, TO_HOST from mysql.role_edges;", p.decodeRoleEdgesTable) if err != nil { return errors.Trace(err) @@ -418,24 +436,23 @@ func (p *MySQLPrivilege) decodeRoleEdgesTable(row chunk.Row, fs []*ast.ResultFie var fromUser, fromHost, toHost, toUser string for i, f := range fs { switch { - case f.ColumnAsName.L == "FROM_HOST": - fromHost = row.GetString(i) - case f.ColumnAsName.L == "FROM_USER": + case f.ColumnAsName.L == "from_host": fromHost = row.GetString(i) - case f.ColumnAsName.L == "TO_HOST": + case f.ColumnAsName.L == "from_user": + fromUser = row.GetString(i) + case f.ColumnAsName.L == "to_host": toHost = row.GetString(i) - case f.ColumnAsName.L == "TO_USER": + case f.ColumnAsName.L == "to_user": toUser = row.GetString(i) } } fromKey := fromUser + "@" + fromHost toKey := toUser + "@" + toHost - if value, ok := p.RoleGraph[toKey]; ok { - value.roleList[fromKey] = true + if _, ok := p.RoleGraph[toKey]; ok { + p.RoleGraph[toKey].roleList[fromKey] = true } else { - p.RoleGraph[toKey] = &RoleGraphEdgesTable{} - p.RoleGraph[toKey].roleList = make(map[string]bool) - p.RoleGraph[toKey].roleList[toKey] = true + p.RoleGraph[toKey] = RoleGraphEdgesTable{roleList: make(map[string]bool)} + p.RoleGraph[toKey].roleList[fromKey] = true } return nil } diff --git a/privilege/privileges/cache_test.go b/privilege/privileges/cache_test.go index ff748750f065b..032b3586ee120 100644 --- a/privilege/privileges/cache_test.go +++ b/privilege/privileges/cache_test.go @@ -185,6 +185,36 @@ func (s *testCacheSuite) TestCaseInsensitive(c *C) { c.Assert(p.RequestVerification("genius", "127.0.0.1", "tctrain", "tctrainorder", "", mysql.SelectPriv), IsTrue) } +func (s *testCacheSuite) TestLoadRoleGraph(c *C) { + se, err := session.CreateSession4Test(s.store) + c.Assert(err, IsNil) + defer se.Close() + mustExec(c, se, "use mysql;") + mustExec(c, se, "truncate table user;") + + var p privileges.MySQLPrivilege + err = p.LoadRoleGraph(se) + c.Assert(err, IsNil) + c.Assert(len(p.User), Equals, 0) + + mustExec(c, se, `INSERT INTO mysql.role_edges (FROM_HOST, FROM_USER, TO_HOST, TO_USER) VALUES ("%", "r_1", "%", "user2")`) + mustExec(c, se, `INSERT INTO mysql.role_edges (FROM_HOST, FROM_USER, TO_HOST, TO_USER) VALUES ("%", "r_2", "%", "root")`) + mustExec(c, se, `INSERT INTO mysql.role_edges (FROM_HOST, FROM_USER, TO_HOST, TO_USER) VALUES ("%", "r_3", "%", "user1")`) + mustExec(c, se, `INSERT INTO mysql.role_edges (FROM_HOST, FROM_USER, TO_HOST, TO_USER) VALUES ("%", "r_4", "%", "root")`) + + p = privileges.MySQLPrivilege{} + err = p.LoadRoleGraph(se) + c.Assert(err, IsNil) + graph := p.RoleGraph + c.Assert(graph["root@%"].Find("r_2", "%"), Equals, true) + c.Assert(graph["root@%"].Find("r_4", "%"), Equals, true) + c.Assert(graph["user2@%"].Find("r_1", "%"), Equals, true) + c.Assert(graph["user1@%"].Find("r_3", "%"), Equals, true) + _, ok := graph["illedal"] + c.Assert(ok, Equals, false) + c.Assert(graph["root@%"].Find("r_1", "%"), Equals, false) +} + func (s *testCacheSuite) TestAbnormalMySQLTable(c *C) { store, err := mockstore.NewMockTikvStore() c.Assert(err, IsNil) diff --git a/privilege/privileges/privileges.go b/privilege/privileges/privileges.go index 19c119b7b3641..d5ba12d757c9b 100644 --- a/privilege/privileges/privileges.go +++ b/privilege/privileges/privileges.go @@ -188,7 +188,7 @@ func (p *UserPrivileges) ShowGrants(ctx sessionctx.Context, user *auth.UserIdent } // ActiveRoles implements privilege.Manager ActiveRoles interface. -func (p *UserPrivileges) ActiveRoles(ctx sessionctx.Context, roleList []*auth.RoleIdentity) bool { +func (p *UserPrivileges) ActiveRoles(ctx sessionctx.Context, roleList []*auth.RoleIdentity) (bool, string) { mysqlPrivilege := p.Handle.Get() u := p.user h := p.host @@ -196,9 +196,9 @@ func (p *UserPrivileges) ActiveRoles(ctx sessionctx.Context, roleList []*auth.Ro ok := mysqlPrivilege.FindRole(u, h, r) if !ok { log.Errorf("Role: %+v doesn't grant for user", r) - return false + return false, r.String() } } ctx.GetSessionVars().ActiveRoles = roleList - return true + return true, "" } diff --git a/sessionctx/variable/session.go b/sessionctx/variable/session.go index a63d397f2ffe5..bbffa19c577d6 100644 --- a/sessionctx/variable/session.go +++ b/sessionctx/variable/session.go @@ -353,6 +353,7 @@ func NewSessionVars() *SessionVars { TxnCtx: &TransactionContext{}, KVVars: kv.NewVariables(), RetryInfo: &RetryInfo{}, + ActiveRoles: make([]*auth.RoleIdentity, 0, 10), StrictSQLMode: true, Status: mysql.ServerStatusAutocommit, StmtCtx: new(stmtctx.StatementContext), From 1e55aaae12f6e10807acba3d1b9b8cb969b72598 Mon Sep 17 00:00:00 2001 From: imtbkcat Date: Thu, 7 Mar 2019 11:56:21 +0800 Subject: [PATCH 05/14] fix package import --- privilege/privileges/cache.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/privilege/privileges/cache.go b/privilege/privileges/cache.go index 343cecffc0709..735131d0b7fde 100644 --- a/privilege/privileges/cache.go +++ b/privilege/privileges/cache.go @@ -16,7 +16,6 @@ package privileges import ( "context" "fmt" - "github.com/pingcap/parser/auth" "sort" "strings" "sync/atomic" @@ -24,6 +23,7 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/parser/ast" + "github.com/pingcap/parser/auth" "github.com/pingcap/parser/mysql" "github.com/pingcap/parser/terror" "github.com/pingcap/tidb/sessionctx" From e3ad310a735359bc223059e8c62cbe721a0d0967 Mon Sep 17 00:00:00 2001 From: imtbkcat Date: Thu, 7 Mar 2019 12:41:16 +0800 Subject: [PATCH 06/14] add test for current role --- expression/builtin_info.go | 2 +- expression/builtin_info_test.go | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/expression/builtin_info.go b/expression/builtin_info.go index 6739275795d8d..0653afef87847 100644 --- a/expression/builtin_info.go +++ b/expression/builtin_info.go @@ -189,7 +189,7 @@ func (b *builtinCurrentRoleSig) evalString(row chunk.Row) (string, bool, error) return "", true, errors.Errorf("Missing session variable when eval builtin") } if len(data.ActiveRoles) == 0 { - return "NONE", false, nil + return "", false, nil } res := "" for i, r := range data.ActiveRoles { diff --git a/expression/builtin_info_test.go b/expression/builtin_info_test.go index 0cc6d0f57ed71..0f82dfef2c510 100644 --- a/expression/builtin_info_test.go +++ b/expression/builtin_info_test.go @@ -95,6 +95,22 @@ func (s *testEvaluatorSuite) TestCurrentUser(c *C) { c.Assert(d.GetString(), Equals, "root@localhost") } +func (s *testEvaluatorSuite) TestCurrentRole(c *C) { + defer testleak.AfterTest(c)() + ctx := mock.NewContext() + sessionVars := ctx.GetSessionVars() + sessionVars.ActiveRoles = make([]*auth.RoleIdentity, 0, 10) + sessionVars.ActiveRoles = append(sessionVars.ActiveRoles, &auth.RoleIdentity{Username: "r_1", Hostname: "%"}) + sessionVars.ActiveRoles = append(sessionVars.ActiveRoles, &auth.RoleIdentity{Username: "r_2", Hostname: "localhost"}) + + fc := funcs[ast.CurrentRole] + f, err := fc.getFunction(ctx, nil) + c.Assert(err, IsNil) + d, err := evalBuiltinFunc(f, chunk.Row{}) + c.Assert(err, IsNil) + c.Assert(d.GetString(), Equals, "`r_1`@`%`,`r_2`@`localhost`") +} + func (s *testEvaluatorSuite) TestConnectionID(c *C) { defer testleak.AfterTest(c)() ctx := mock.NewContext() From 231736f3b0fe419f528d6a149b8d32f131605b3c Mon Sep 17 00:00:00 2001 From: imtbkcat Date: Thu, 7 Mar 2019 15:29:09 +0800 Subject: [PATCH 07/14] add role check --- privilege/privileges/cache.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/privilege/privileges/cache.go b/privilege/privileges/cache.go index 735131d0b7fde..ce3cd3654721f 100644 --- a/privilege/privileges/cache.go +++ b/privilege/privileges/cache.go @@ -138,7 +138,8 @@ type MySQLPrivilege struct { // FindRole is used to detect whether this is an edge between user and role func (p *MySQLPrivilege) FindRole(user string, host string, role *auth.RoleIdentity) bool { rec := p.matchUser(user, host) - if rec != nil && role != nil { + r := p.matchUser(role.Username, role.Hostname) + if rec != nil && r != nil { key := rec.User + "@" + rec.Host return p.RoleGraph[key].Find(role.Username, role.Hostname) } From 6bdae4be47391e5f5b933ca6e9a1fc20261e63f6 Mon Sep 17 00:00:00 2001 From: imtbkcat Date: Tue, 12 Mar 2019 17:28:38 +0800 Subject: [PATCH 08/14] address comment --- executor/errors.go | 1 + executor/simple.go | 4 +--- go.mod | 6 +++--- go.sum | 1 - privilege/privileges/cache.go | 25 +++++++++++-------------- 5 files changed, 16 insertions(+), 21 deletions(-) diff --git a/executor/errors.go b/executor/errors.go index 9b5caa85ac18b..d1fea0047ecd5 100644 --- a/executor/errors.go +++ b/executor/errors.go @@ -49,6 +49,7 @@ var ( ErrTableaccessDenied = terror.ClassExecutor.New(mysql.ErrTableaccessDenied, mysql.MySQLErrName[mysql.ErrTableaccessDenied]) ErrBadDB = terror.ClassExecutor.New(mysql.ErrBadDB, mysql.MySQLErrName[mysql.ErrBadDB]) ErrWrongObject = terror.ClassExecutor.New(mysql.ErrWrongObject, mysql.MySQLErrName[mysql.ErrWrongObject]) + ErrRoleNotGranted = terror.ClassPrivilege.New(mysql.ErrRoleNotGranted, mysql.MySQLErrName[mysql.ErrRoleNotGranted]) ) func init() { diff --git a/executor/simple.go b/executor/simple.go index 25ea94047a6f3..52ee249b52b77 100644 --- a/executor/simple.go +++ b/executor/simple.go @@ -103,10 +103,8 @@ func (e *SimpleExec) executeSetRole(s *ast.SetRoleStmt) error { checker := privilege.GetPrivilegeManager(e.ctx) ok, roleName := checker.ActiveRoles(e.ctx, roleList) if !ok { - errCode := mysql.ErrRoleNotGranted - errRoleNotGranted := terror.ClassPrivilege.New(terror.ErrCode(errCode), mysql.MySQLErrName[uint16(errCode)]) u := e.ctx.GetSessionVars().User - return errRoleNotGranted.GenWithStackByArgs(roleName, u.String()) + return ErrRoleNotGranted.GenWithStackByArgs(roleName, u.String()) } return nil } diff --git a/go.mod b/go.mod index deaa9b04c0da5..d1910ebfa02d5 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/go-sql-driver/mysql v0.0.0-20170715192408-3955978caca4 github.com/gogo/protobuf v1.2.0 // indirect github.com/golang/groupcache v0.0.0-20181024230925-c65c006176ff // indirect - github.com/golang/protobuf v1.2.0 + github.com/golang/protobuf v1.3.0 github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db // indirect github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c github.com/gorilla/context v1.1.1 // indirect @@ -58,7 +58,7 @@ require ( github.com/prometheus/common v0.0.0-20181020173914-7e9e6cabbd39 // indirect github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d // indirect github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446 // indirect - github.com/shirou/gopsutil v2.18.10+incompatible + github.com/shirou/gopsutil v2.18.12+incompatible github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371 // indirect github.com/shurcooL/vfsgen v0.0.0-20181020040650-a97a25d856ca // indirect github.com/sirupsen/logrus v1.2.0 @@ -88,4 +88,4 @@ require ( sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67 ) -replace github.com/pingcap/parser => github.com/imtbkcat/parser v0.0.0-20190306131438-36bf9d091519 +replace github.com/pingcap/parser => github.com/imtbkcat/parser setrole diff --git a/go.sum b/go.sum index 2a5475261adb4..4dc0ebf9e9612 100644 --- a/go.sum +++ b/go.sum @@ -75,7 +75,6 @@ github.com/grpc-ecosystem/grpc-gateway v1.5.1 h1:3scN4iuXkNOyP98jF55Lv8a9j1o/Iwv github.com/grpc-ecosystem/grpc-gateway v1.5.1/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/imtbkcat/parser v0.0.0-20190306131438-36bf9d091519/go.mod h1:qupHD3o7J0aBb3bbVyXRnxe9kKy2MTY/6POS6NO/Ei8= github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= diff --git a/privilege/privileges/cache.go b/privilege/privileges/cache.go index ce3cd3654721f..2731f6f39dad1 100644 --- a/privilege/privileges/cache.go +++ b/privilege/privileges/cache.go @@ -106,12 +106,12 @@ type columnsPrivRecord struct { } // RoleGraphEdgesTable is used to cache relationship between and role. -type RoleGraphEdgesTable struct { +type roleGraphEdgesTable struct { roleList map[string]bool } // Find method is used to find role from table -func (g RoleGraphEdgesTable) Find(user, host string) bool { +func (g roleGraphEdgesTable) Find(user, host string) bool { if host == "" { host = "%" } @@ -120,10 +120,7 @@ func (g RoleGraphEdgesTable) Find(user, host string) bool { return false } _, ok := g.roleList[key] - if ok { - return true - } - return false + return ok } // MySQLPrivilege is the in-memory cache of mysql privilege tables. @@ -132,10 +129,10 @@ type MySQLPrivilege struct { DB []dbRecord TablesPriv []tablesPrivRecord ColumnsPriv []columnsPrivRecord - RoleGraph map[string]RoleGraphEdgesTable + RoleGraph map[string]roleGraphEdgesTable } -// FindRole is used to detect whether this is an edge between user and role +// FindRole is used to detect whether there is edges between users and roles. func (p *MySQLPrivilege) FindRole(user string, host string, role *auth.RoleIdentity) bool { rec := p.matchUser(user, host) r := p.matchUser(role.Username, role.Hostname) @@ -199,7 +196,7 @@ func noSuchTable(err error) bool { // LoadRoleGraph loads the mysql.role_edges table from database. func (p *MySQLPrivilege) LoadRoleGraph(ctx sessionctx.Context) error { - p.RoleGraph = make(map[string]RoleGraphEdgesTable) + p.RoleGraph = make(map[string]roleGraphEdgesTable) err := p.loadTable(ctx, "select FROM_USER, FROM_HOST, TO_USER, TO_HOST from mysql.role_edges;", p.decodeRoleEdgesTable) if err != nil { return errors.Trace(err) @@ -449,12 +446,12 @@ func (p *MySQLPrivilege) decodeRoleEdgesTable(row chunk.Row, fs []*ast.ResultFie } fromKey := fromUser + "@" + fromHost toKey := toUser + "@" + toHost - if _, ok := p.RoleGraph[toKey]; ok { - p.RoleGraph[toKey].roleList[fromKey] = true - } else { - p.RoleGraph[toKey] = RoleGraphEdgesTable{roleList: make(map[string]bool)} - p.RoleGraph[toKey].roleList[fromKey] = true + roleGraph, ok := p.RoleGraph[toKey] + if !ok { + roleGraph = roleGraphEdgesTable{roleList: make(map[string]bool)} + p.RoleGraph[toKey] = roleGraph } + roleGraph.roleList[fromKey] = true return nil } From 7c7bcae1adbfc1cedf87b650b742b887b4bc6ada Mon Sep 17 00:00:00 2001 From: imtbkcat Date: Tue, 12 Mar 2019 17:31:38 +0800 Subject: [PATCH 09/14] edit go sum --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index d1910ebfa02d5..aaf6acb82b543 100644 --- a/go.mod +++ b/go.mod @@ -88,4 +88,4 @@ require ( sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67 ) -replace github.com/pingcap/parser => github.com/imtbkcat/parser setrole +replace github.com/pingcap/parser => github.com/imtbkcat/parser v0.0.0-20190312042141-3e28a494e603 From 31f9078b4c4b2f412cf090d637d8a59a1d711f53 Mon Sep 17 00:00:00 2001 From: imtbkcat Date: Thu, 14 Mar 2019 10:34:09 +0800 Subject: [PATCH 10/14] edit go sum --- go.sum | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/go.sum b/go.sum index 4dc0ebf9e9612..8a9d94d0d3fef 100644 --- a/go.sum +++ b/go.sum @@ -57,6 +57,7 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/protobuf v0.0.0-20180814211427-aa810b61a9c7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw= @@ -75,6 +76,7 @@ github.com/grpc-ecosystem/grpc-gateway v1.5.1 h1:3scN4iuXkNOyP98jF55Lv8a9j1o/Iwv github.com/grpc-ecosystem/grpc-gateway v1.5.1/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/imtbkcat/parser v0.0.0-20190312042141-3e28a494e603/go.mod h1:qupHD3o7J0aBb3bbVyXRnxe9kKy2MTY/6POS6NO/Ei8= github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= @@ -139,6 +141,7 @@ github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446 h1:/NRJ5vAYo github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= github.com/shirou/gopsutil v2.18.10+incompatible h1:cy84jW6EVRPa5g9HAHrlbxMSIjBhDSX0OFYyMYminYs= github.com/shirou/gopsutil v2.18.10+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil v2.18.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371 h1:SWV2fHctRpRrp49VXJ6UZja7gU9QLHwRpIPBN89SKEo= github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/vfsgen v0.0.0-20181020040650-a97a25d856ca h1:3fECS8atRjByijiI8yYiuwLwQ2ZxXobW7ua/8GRB3pI= @@ -208,6 +211,7 @@ golang.org/x/tools v0.0.0-20190130214255-bb1329dc71a0 h1:iRpjPej1fPzmfoBhMFkp3Hd golang.org/x/tools v0.0.0-20190130214255-bb1329dc71a0/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181004005441-af9cb2a35e7f/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190108161440-ae2f86662275 h1:9oFlwfEGIvmxXTcY53ygNyxIQtWciRHjrnUvZJCYXYU= google.golang.org/genproto v0.0.0-20190108161440-ae2f86662275/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= From b6f88614e1c111fa26b8a244b434a2f85543d56b Mon Sep 17 00:00:00 2001 From: imtbkcat Date: Wed, 20 Mar 2019 13:38:29 +0800 Subject: [PATCH 11/14] edit gomod --- go.mod | 4 +--- go.sum | 7 ++++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index aaf6acb82b543..8a3216cbf4aed 100644 --- a/go.mod +++ b/go.mod @@ -49,7 +49,7 @@ require ( github.com/pingcap/goleveldb v0.0.0-20171020122428-b9ff6c35079e github.com/pingcap/kvproto v0.0.0-20190215154024-7f2fc73ef562 github.com/pingcap/log v0.0.0-20190307075452-bd41d9273596 - github.com/pingcap/parser v0.0.0-20190312024907-3f6280b08c8b + github.com/pingcap/parser v0.0.0-20190320053247-fe243e3280cf github.com/pingcap/pd v2.1.0-rc.4+incompatible github.com/pingcap/tidb-tools v2.1.3-0.20190116051332-34c808eef588+incompatible github.com/pingcap/tipb v0.0.0-20190107072121-abbec73437b7 @@ -87,5 +87,3 @@ require ( sourcegraph.com/sourcegraph/appdash v0.0.0-20180531100431-4c381bd170b4 sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67 ) - -replace github.com/pingcap/parser => github.com/imtbkcat/parser v0.0.0-20190312042141-3e28a494e603 diff --git a/go.sum b/go.sum index 8a9d94d0d3fef..5156cd965e695 100644 --- a/go.sum +++ b/go.sum @@ -57,6 +57,7 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/protobuf v0.0.0-20180814211427-aa810b61a9c7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.0 h1:kbxbvI4Un1LUWKxufD+BiE6AEExYYgkQLQmLFqA1LFk= github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -76,7 +77,6 @@ github.com/grpc-ecosystem/grpc-gateway v1.5.1 h1:3scN4iuXkNOyP98jF55Lv8a9j1o/Iwv github.com/grpc-ecosystem/grpc-gateway v1.5.1/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/imtbkcat/parser v0.0.0-20190312042141-3e28a494e603/go.mod h1:qupHD3o7J0aBb3bbVyXRnxe9kKy2MTY/6POS6NO/Ei8= github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= @@ -117,8 +117,8 @@ github.com/pingcap/kvproto v0.0.0-20190215154024-7f2fc73ef562 h1:32oF1/8lVnBR2JV github.com/pingcap/kvproto v0.0.0-20190215154024-7f2fc73ef562/go.mod h1:QMdbTAXCHzzygQzqcG9uVUgU2fKeSN1GmfMiykdSzzY= github.com/pingcap/log v0.0.0-20190307075452-bd41d9273596 h1:t2OQTpPJnrPDGlvA+3FwJptMTt6MEPdzK1Wt99oaefQ= github.com/pingcap/log v0.0.0-20190307075452-bd41d9273596/go.mod h1:WpHUKhNZ18v116SvGrmjkA9CBhYmuUTKL+p8JC9ANEw= -github.com/pingcap/parser v0.0.0-20190312024907-3f6280b08c8b h1:NlvTrxqezIJh6CD5Leky12IZ8E/GtpEEmzgNNb34wbw= -github.com/pingcap/parser v0.0.0-20190312024907-3f6280b08c8b/go.mod h1:1FNvfp9+J0wvc4kl8eGNh7Rqrxveg15jJoWo/a0uHwA= +github.com/pingcap/parser v0.0.0-20190320053247-fe243e3280cf h1:yxK78TmeSK3BIm8Z8SwdZLVzRpY80HZe1VMlA2dL648= +github.com/pingcap/parser v0.0.0-20190320053247-fe243e3280cf/go.mod h1:1FNvfp9+J0wvc4kl8eGNh7Rqrxveg15jJoWo/a0uHwA= github.com/pingcap/pd v2.1.0-rc.4+incompatible h1:/buwGk04aHO5odk/+O8ZOXGs4qkUjYTJ2UpCJXna8NE= github.com/pingcap/pd v2.1.0-rc.4+incompatible/go.mod h1:nD3+EoYes4+aNNODO99ES59V83MZSI+dFbhyr667a0E= github.com/pingcap/tidb-tools v2.1.3-0.20190116051332-34c808eef588+incompatible h1:e9Gi/LP9181HT3gBfSOeSBA+5JfemuE4aEAhqNgoE4k= @@ -141,6 +141,7 @@ github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446 h1:/NRJ5vAYo github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= github.com/shirou/gopsutil v2.18.10+incompatible h1:cy84jW6EVRPa5g9HAHrlbxMSIjBhDSX0OFYyMYminYs= github.com/shirou/gopsutil v2.18.10+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil v2.18.12+incompatible h1:1eaJvGomDnH74/5cF4CTmTbLHAriGFsTZppLXDX93OM= github.com/shirou/gopsutil v2.18.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371 h1:SWV2fHctRpRrp49VXJ6UZja7gU9QLHwRpIPBN89SKEo= github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= From 9d4d422ceb113547d0ae21c2b9fbebdff3811dd0 Mon Sep 17 00:00:00 2001 From: imtbkcat Date: Wed, 20 Mar 2019 13:44:15 +0800 Subject: [PATCH 12/14] fix gosum --- go.sum | 3 --- 1 file changed, 3 deletions(-) diff --git a/go.sum b/go.sum index 5156cd965e695..0bb1faa6b6531 100644 --- a/go.sum +++ b/go.sum @@ -139,8 +139,6 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d h1:GoAlyOgbOEIFd github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446 h1:/NRJ5vAYoqz+7sG51ubIDHXeWO8DlTSrToPu6q11ziA= github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= -github.com/shirou/gopsutil v2.18.10+incompatible h1:cy84jW6EVRPa5g9HAHrlbxMSIjBhDSX0OFYyMYminYs= -github.com/shirou/gopsutil v2.18.10+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/gopsutil v2.18.12+incompatible h1:1eaJvGomDnH74/5cF4CTmTbLHAriGFsTZppLXDX93OM= github.com/shirou/gopsutil v2.18.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371 h1:SWV2fHctRpRrp49VXJ6UZja7gU9QLHwRpIPBN89SKEo= @@ -212,7 +210,6 @@ golang.org/x/tools v0.0.0-20190130214255-bb1329dc71a0 h1:iRpjPej1fPzmfoBhMFkp3Hd golang.org/x/tools v0.0.0-20190130214255-bb1329dc71a0/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181004005441-af9cb2a35e7f/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190108161440-ae2f86662275 h1:9oFlwfEGIvmxXTcY53ygNyxIQtWciRHjrnUvZJCYXYU= google.golang.org/genproto v0.0.0-20190108161440-ae2f86662275/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= From 9bbff7eb3620328f8635d45c1ff25174e5f151f9 Mon Sep 17 00:00:00 2001 From: imtbkcat Date: Wed, 20 Mar 2019 13:45:51 +0800 Subject: [PATCH 13/14] fix gosum --- go.sum | 2 -- 1 file changed, 2 deletions(-) diff --git a/go.sum b/go.sum index 0bb1faa6b6531..f158c94fa7c50 100644 --- a/go.sum +++ b/go.sum @@ -55,8 +55,6 @@ github.com/golang/groupcache v0.0.0-20181024230925-c65c006176ff/go.mod h1:cIg4er github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v0.0.0-20180814211427-aa810b61a9c7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.0 h1:kbxbvI4Un1LUWKxufD+BiE6AEExYYgkQLQmLFqA1LFk= github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= From 1887af2ccded5a0e646bb9587f1f87d64bc626b3 Mon Sep 17 00:00:00 2001 From: imtbkcat Date: Wed, 20 Mar 2019 13:55:49 +0800 Subject: [PATCH 14/14] fix tidy --- executor/simple.go | 2 +- go.mod | 4 ++-- go.sum | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/executor/simple.go b/executor/simple.go index 52ee249b52b77..b23c0b8d6edcf 100644 --- a/executor/simple.go +++ b/executor/simple.go @@ -89,7 +89,7 @@ func (e *SimpleExec) Next(ctx context.Context, req *chunk.RecordBatch) (err erro } func (e *SimpleExec) executeSetRole(s *ast.SetRoleStmt) error { - checkDup := make(map[string]*auth.RoleIdentity) + checkDup := make(map[string]*auth.RoleIdentity, len(s.RoleList)) // Check whether RoleNameList contain duplicate role name. for _, r := range s.RoleList { key := r.String() diff --git a/go.mod b/go.mod index 8a3216cbf4aed..d5d9f9635873e 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/go-sql-driver/mysql v0.0.0-20170715192408-3955978caca4 github.com/gogo/protobuf v1.2.0 // indirect github.com/golang/groupcache v0.0.0-20181024230925-c65c006176ff // indirect - github.com/golang/protobuf v1.3.0 + github.com/golang/protobuf v1.2.0 github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db // indirect github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c github.com/gorilla/context v1.1.1 // indirect @@ -58,7 +58,7 @@ require ( github.com/prometheus/common v0.0.0-20181020173914-7e9e6cabbd39 // indirect github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d // indirect github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446 // indirect - github.com/shirou/gopsutil v2.18.12+incompatible + github.com/shirou/gopsutil v2.18.10+incompatible github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371 // indirect github.com/shurcooL/vfsgen v0.0.0-20181020040650-a97a25d856ca // indirect github.com/sirupsen/logrus v1.2.0 diff --git a/go.sum b/go.sum index f158c94fa7c50..645f02c15f916 100644 --- a/go.sum +++ b/go.sum @@ -55,8 +55,8 @@ github.com/golang/groupcache v0.0.0-20181024230925-c65c006176ff/go.mod h1:cIg4er github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v0.0.0-20180814211427-aa810b61a9c7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.0 h1:kbxbvI4Un1LUWKxufD+BiE6AEExYYgkQLQmLFqA1LFk= -github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= +github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw= @@ -137,8 +137,8 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d h1:GoAlyOgbOEIFd github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446 h1:/NRJ5vAYoqz+7sG51ubIDHXeWO8DlTSrToPu6q11ziA= github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= -github.com/shirou/gopsutil v2.18.12+incompatible h1:1eaJvGomDnH74/5cF4CTmTbLHAriGFsTZppLXDX93OM= -github.com/shirou/gopsutil v2.18.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil v2.18.10+incompatible h1:cy84jW6EVRPa5g9HAHrlbxMSIjBhDSX0OFYyMYminYs= +github.com/shirou/gopsutil v2.18.10+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371 h1:SWV2fHctRpRrp49VXJ6UZja7gU9QLHwRpIPBN89SKEo= github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/vfsgen v0.0.0-20181020040650-a97a25d856ca h1:3fECS8atRjByijiI8yYiuwLwQ2ZxXobW7ua/8GRB3pI=