Skip to content

Commit 41a0994

Browse files
authored
Merge pull request #2797 from dolthub/fulghum/persist_root_superuser
Persist and load superusers
2 parents e25a1f7 + 57e5666 commit 41a0994

File tree

4 files changed

+106
-6
lines changed

4 files changed

+106
-6
lines changed

eventscheduler/event_scheduler.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020

2121
"github.com/dolthub/go-mysql-server/sql"
2222
"github.com/dolthub/go-mysql-server/sql/analyzer"
23+
"github.com/dolthub/go-mysql-server/sql/mysql_db"
2324
)
2425

2526
// ErrEventSchedulerDisabled is returned when user tries to set `event_scheduler_notifier` global system variable to ON or OFF
@@ -41,6 +42,10 @@ const (
4142
SchedulerDisabled SchedulerStatus = "DISABLED"
4243
)
4344

45+
// eventSchedulerSuperUserName is the name of the locked superuser that the event scheduler
46+
// creates and uses to ensure it has access to read events from all databases.
47+
const eventSchedulerSuperUserName = "event_scheduler"
48+
4449
var _ sql.EventScheduler = (*EventScheduler)(nil)
4550

4651
// EventScheduler is responsible for SQL events execution.
@@ -69,10 +74,20 @@ func InitEventScheduler(
6974
ctxGetterFunc: getSqlCtxFunc,
7075
}
7176

77+
// Ensure the event_scheduler superuser exists so that the event scheduler can read
78+
// events from all databases.
79+
initializeEventSchedulerSuperUser(a.Catalog.MySQLDb)
80+
7281
// If the EventSchedulerStatus is ON, then load enabled
7382
// events and start executing events on schedule.
7483
if es.status == SchedulerOn {
7584
ctx, commit, err := getSqlCtxFunc()
85+
ctx.Session.SetClient(sql.Client{
86+
User: eventSchedulerSuperUserName,
87+
Address: "localhost",
88+
Capabilities: 0,
89+
})
90+
7691
if err != nil {
7792
return nil, err
7893
}
@@ -89,6 +104,25 @@ func InitEventScheduler(
89104
return es, nil
90105
}
91106

107+
// initializeEventSchedulerSuperUser ensures the event_scheduler superuser exists (as a locked
108+
// account that cannot be directly used to log in) so that the event scheduler can read events
109+
// from all databases.
110+
func initializeEventSchedulerSuperUser(mySQLDb *mysql_db.MySQLDb) {
111+
// TODO: Creating a superuser for the event_scheduler causes the mysqldb to be marked as
112+
// enabled, which enables privileges checking for all resources. We want privileges
113+
// enabled only when running in a sql-server context, but currently creating any
114+
// engine starts up the event system, so we reset the mysqldb enabled status after
115+
// we create the event scheduler super user. To clean this up, we can look into
116+
// moving the event system initialization, or possibly just switch to enabling the
117+
// privilege system as part of server startup.
118+
wasEnabled := mySQLDb.Enabled()
119+
defer mySQLDb.SetEnabled(wasEnabled)
120+
121+
ed := mySQLDb.Editor()
122+
defer ed.Close()
123+
mySQLDb.AddLockedSuperUser(ed, eventSchedulerSuperUserName, "localhost", "")
124+
}
125+
92126
// Close closes the EventScheduler.
93127
func (es *EventScheduler) Close() {
94128
if es == nil {

sql/mysql_db/mysql_db.go

Lines changed: 67 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,15 @@ func (db *MySQLDb) LoadData(ctx *sql.Context, buf []byte) (err error) {
413413
ed.PutReplicaSourceInfo(replicaSourceInfo)
414414
}
415415

416+
// Load superusers
417+
for i := 0; i < serialMySQLDb.SuperUserLength(); i++ {
418+
serialUser := new(serial.User)
419+
if !serialMySQLDb.SuperUser(serialUser, i) {
420+
continue
421+
}
422+
ed.PutUser(LoadUser(serialUser))
423+
}
424+
416425
// TODO: fill in other tables when they exist
417426
return
418427
}
@@ -508,11 +517,36 @@ func (db *MySQLDb) AddRootAccount() {
508517
db.AddSuperUser(ed, "root", "localhost", "")
509518
}
510519

520+
// AddEphemeralSuperUser adds a new temporary superuser account for the specified username, host,
521+
// and password. The superuser account will only exist for the lifetime of the server process; once
522+
// the server is restarted, this superuser account will not be present.
523+
func (db *MySQLDb) AddEphemeralSuperUser(ed *Editor, username string, host string, password string) {
524+
db.SetEnabled(true)
525+
526+
if len(password) > 0 {
527+
hash := sha1.New()
528+
hash.Write([]byte(password))
529+
s1 := hash.Sum(nil)
530+
hash.Reset()
531+
hash.Write(s1)
532+
s2 := hash.Sum(nil)
533+
password = "*" + strings.ToUpper(hex.EncodeToString(s2))
534+
}
535+
536+
if _, ok := ed.GetUser(UserPrimaryKey{
537+
Host: host,
538+
User: username,
539+
}); !ok {
540+
addSuperUser(ed, username, host, password, true)
541+
}
542+
}
543+
511544
// AddSuperUser adds the given username and password to the list of accounts. This is a temporary function, which is
512545
// meant to replace the "auth.New..." functions while the remaining functions are added.
513546
func (db *MySQLDb) AddSuperUser(ed *Editor, username string, host string, password string) {
514547
//TODO: remove this function and the called function
515548
db.SetEnabled(true)
549+
516550
if len(password) > 0 {
517551
hash := sha1.New()
518552
hash.Write([]byte(password))
@@ -527,7 +561,33 @@ func (db *MySQLDb) AddSuperUser(ed *Editor, username string, host string, passwo
527561
Host: host,
528562
User: username,
529563
}); !ok {
530-
addSuperUser(ed, username, host, password)
564+
addSuperUser(ed, username, host, password, false)
565+
}
566+
}
567+
568+
// AddLockedSuperUser adds a new superuser with the specified |username|, |host|, and |password|
569+
// and sets the account to be locked so that it cannot be used to log in.
570+
func (db *MySQLDb) AddLockedSuperUser(ed *Editor, username string, host string, password string) {
571+
user := db.GetUser(ed, username, host, false)
572+
573+
// If the user doesn't exist yet, create it and lock it
574+
if user == nil {
575+
db.AddSuperUser(ed, username, host, password)
576+
user = db.GetUser(ed, username, host, false)
577+
if user == nil {
578+
panic("unable to load newly created superuser: " + username)
579+
}
580+
581+
// Lock the account to prevent it being used to log in
582+
user.Locked = true
583+
ed.PutUser(user)
584+
}
585+
586+
// If the user exists, but isn't a superuser or locked, fix it
587+
if user.IsSuperUser == false || user.Locked == false {
588+
user.IsSuperUser = true
589+
user.Locked = true
590+
ed.PutUser(user)
531591
}
532592
}
533593

@@ -803,10 +863,12 @@ func (db *MySQLDb) Persist(ctx *sql.Context, ed *Editor) error {
803863
var users []*User
804864
var superUsers []*User
805865
ed.VisitUsers(func(u *User) {
806-
if !u.IsSuperUser {
807-
users = append(users, u)
808-
} else {
809-
superUsers = append(superUsers, u)
866+
if !u.IsEphemeral {
867+
if !u.IsSuperUser {
868+
users = append(users, u)
869+
} else {
870+
superUsers = append(superUsers, u)
871+
}
810872
}
811873
})
812874
sort.Slice(users, func(i, j int) bool {

sql/mysql_db/user.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ type User struct {
3636
Attributes *string
3737
Identity string
3838
IsSuperUser bool
39+
// IsEphemeral is true if this user is ephemeral, meaning it will only exist
40+
// for the lifetime of the server process and will not be persisted to disk.
41+
IsEphemeral bool
3942
//TODO: add the remaining fields
4043

4144
// IsRole is an additional field that states whether the User represents a role or user. In MySQL this must be a

sql/mysql_db/user_table.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ func init() {
215215
}
216216
}
217217

218-
func addSuperUser(ed *Editor, username string, host string, authString string) {
218+
func addSuperUser(ed *Editor, username string, host string, authString string, ephemeral bool) {
219219
ed.PutUser(&User{
220220
User: username,
221221
Host: host,
@@ -227,6 +227,7 @@ func addSuperUser(ed *Editor, username string, host string, authString string) {
227227
Attributes: nil,
228228
IsRole: false,
229229
IsSuperUser: true,
230+
IsEphemeral: ephemeral,
230231
})
231232
}
232233

0 commit comments

Comments
 (0)