From bffbc00302f72d0b643c9dce6244cfbcbb958df4 Mon Sep 17 00:00:00 2001 From: tiancaiamao Date: Thu, 29 Jun 2017 19:01:16 +0800 Subject: [PATCH] *: log some crucial sql for user/privilege related operations. (#3557) --- ast/misc.go | 14 ++++++++++++++ domain/domain.go | 4 +++- session.go | 30 ++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/ast/misc.go b/ast/misc.go index a745900ce4..80ba572e80 100644 --- a/ast/misc.go +++ b/ast/misc.go @@ -414,6 +414,20 @@ type UserSpec struct { AuthOpt *AuthOption } +// SecurityString formats the UserSpec without password information. +func (u *UserSpec) SecurityString() string { + withPassword := false + if opt := u.AuthOpt; opt != nil { + if len(opt.AuthString) > 0 || len(opt.HashString) > 0 { + withPassword = true + } + } + if withPassword { + return fmt.Sprintf("{%s password = ***}", u.User) + } + return u.User +} + // CreateUserStmt creates user account. // See https://dev.mysql.com/doc/refman/5.7/en/create-user.html type CreateUserStmt struct { diff --git a/domain/domain.go b/domain/domain.go index 4cb2ad4def..e48beca83f 100644 --- a/domain/domain.go +++ b/domain/domain.go @@ -465,7 +465,9 @@ func (do *Domain) LoadPrivilegeLoop(ctx context.Context) error { } err := do.privHandle.Update(ctx) if err != nil { - log.Error("load privilege fail:", errors.ErrorStack(err)) + log.Error("[domain] load privilege fail:", errors.ErrorStack(err)) + } else { + log.Info("[domain] reload privilege success.") } } }() diff --git a/session.go b/session.go index 4be9ebb7bf..15d156da1e 100644 --- a/session.go +++ b/session.go @@ -628,6 +628,8 @@ func (s *session) Execute(sql string) ([]ast.RecordSet, error) { if r != nil { rs = append(rs, r) } + + logCrucialStmt(rst) } if s.sessionVars.ClientCapability&mysql.ClientMultiResults == 0 && len(rs) > 1 { @@ -1161,3 +1163,31 @@ func (s *session) ShowProcess() util.ProcessInfo { } return pi } + +// logCrucialStmt logs some crucial SQL including: CREATE USER/GRANT PRIVILEGE/CHANGE PASSWORD etc. +func logCrucialStmt(node ast.StmtNode) { + switch stmt := node.(type) { + case *ast.CreateUserStmt: + for _, user := range stmt.Specs { + log.Infof("[CRUCIAL OPERATION] create user %s.", user.SecurityString()) + } + case *ast.DropUserStmt: + log.Infof("[CRUCIAL OPERATION] drop user %v.", stmt.UserList) + case *ast.AlterUserStmt: + for _, user := range stmt.Specs { + log.Infof("[CRUCIAL OPERATION] alter user %s.", user.SecurityString()) + } + case *ast.SetPwdStmt: + log.Infof("[CRUCIAL OPERATION] set password for user %s.", stmt.User) + case *ast.GrantStmt: + text := stmt.Text() + // Filter "identified by xxx" because it would expose password information. + idx := strings.Index(strings.ToLower(text), "identified") + if idx > 0 { + text = text[:idx] + } + log.Infof("[CRUCIAL OPERATION] %s.", text) + case *ast.RevokeStmt: + log.Infof("[CRUCIAL OPERATION] %s.", stmt.Text()) + } +}