From e4a10fd239055ea2320e14b535d997b707c543fb Mon Sep 17 00:00:00 2001 From: Jason Fulghum Date: Fri, 3 Jan 2025 15:55:00 -0800 Subject: [PATCH] Adding a locked superuser account for the event scheduler, and a new utility function to create locked superuser accounts --- eventscheduler/event_scheduler.go | 23 +++++++++++++++++++++++ sql/mysql_db/mysql_db.go | 26 ++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/eventscheduler/event_scheduler.go b/eventscheduler/event_scheduler.go index b3d95b3897..6472dfc165 100644 --- a/eventscheduler/event_scheduler.go +++ b/eventscheduler/event_scheduler.go @@ -20,6 +20,7 @@ import ( "github.com/dolthub/go-mysql-server/sql" "github.com/dolthub/go-mysql-server/sql/analyzer" + "github.com/dolthub/go-mysql-server/sql/mysql_db" ) // ErrEventSchedulerDisabled is returned when user tries to set `event_scheduler_notifier` global system variable to ON or OFF @@ -41,6 +42,9 @@ const ( SchedulerDisabled SchedulerStatus = "DISABLED" ) +// eventSchedulerSuperUserName is the name of the superuser that +const eventSchedulerSuperUserName = "event_scheduler" + var _ sql.EventScheduler = (*EventScheduler)(nil) // EventScheduler is responsible for SQL events execution. @@ -69,10 +73,20 @@ func InitEventScheduler( ctxGetterFunc: getSqlCtxFunc, } + // Ensure the event_scheduler superuser exists so that the event scheduler can read + // events from all databases. + initializeEventSchedulerSuperUser(a.Catalog.MySQLDb) + // If the EventSchedulerStatus is ON, then load enabled // events and start executing events on schedule. if es.status == SchedulerOn { ctx, commit, err := getSqlCtxFunc() + ctx.Session.SetClient(sql.Client{ + User: eventSchedulerSuperUserName, + Address: "localhost", + Capabilities: 0, + }) + if err != nil { return nil, err } @@ -89,6 +103,15 @@ func InitEventScheduler( return es, nil } +// initializeEventSchedulerSuperUser ensures the event_scheduler superuser exists (as a locked +// account that cannot be directly used to log in) so that the event scheduler can read events +// from all databases. +func initializeEventSchedulerSuperUser(mySQLDb *mysql_db.MySQLDb) { + ed := mySQLDb.Editor() + defer ed.Close() + mySQLDb.AddLockedSuperUser(ed, eventSchedulerSuperUserName, "localhost", "") +} + // Close closes the EventScheduler. func (es *EventScheduler) Close() { if es == nil { diff --git a/sql/mysql_db/mysql_db.go b/sql/mysql_db/mysql_db.go index 3aac0e2336..1c76e13b06 100644 --- a/sql/mysql_db/mysql_db.go +++ b/sql/mysql_db/mysql_db.go @@ -563,6 +563,32 @@ func (db *MySQLDb) AddSuperUser(ed *Editor, username string, host string, passwo } } +// AddLockedSuperUser adds a new superuser with the specified |username|, |host|, and |password| +// and sets the account to be locked so that it cannot be used to log in. +func (db *MySQLDb) AddLockedSuperUser(ed *Editor, username string, host string, password string) { + user := db.GetUser(ed, username, host, false) + + // If the user doesn't exist yet, create it and lock it + if user == nil { + db.AddSuperUser(ed, username, host, password) + user = db.GetUser(ed, username, host, false) + if user == nil { + panic("unable to load newly created superuser: " + username) + } + + // Lock the account to prevent it being used to log in + user.Locked = true + ed.PutUser(user) + } + + // If the user exists, but isn't a superuser or locked, fix it + if user.IsSuperUser == false || user.Locked == false { + user.IsSuperUser = true + user.Locked = true + ed.PutUser(user) + } +} + // GetUser returns a user matching the given user and host if it exists. Due to the slight difference between users and // roles, roleSearch changes whether the search matches against user or role rules. func (db *MySQLDb) GetUser(fetcher UserFetcher, user string, host string, roleSearch bool) *User {