// Validate is called when writing a database or table descriptor. // It takes the descriptor ID which is used to determine if // it belongs to a system descriptor, in which case the maximum // set of allowed privileges is looked up and applied. func (p PrivilegeDescriptor) Validate(id ID) error { userPriv, ok := p.findUser(security.RootUser) if !ok { return fmt.Errorf("user %s does not have privileges", security.RootUser) } if IsSystemConfigID(id) { // System databases and tables have custom maximum allowed privileges. objectPrivileges, ok := SystemConfigAllowedPrivileges[id] if !ok { return fmt.Errorf("no allowed privileges found for system object with ID=%d", id) } // The root user must have all the allowed privileges. allowedPrivileges := objectPrivileges.ToBitField() if userPriv.Privileges&allowedPrivileges != allowedPrivileges { return fmt.Errorf("user %s must have %s privileges on system objects", security.RootUser, privilege.ListFromBitField(allowedPrivileges)) } // For all users (root included), no other privileges must be granted. for _, u := range p.Users { if remaining := u.Privileges &^ allowedPrivileges; remaining != 0 { return fmt.Errorf("user %s must not have %s privileges on system objects", u.User, privilege.ListFromBitField(remaining)) } } } else if !isPrivilegeSet(userPriv.Privileges, privilege.ALL) { // Non-system databases and tables must preserve ALL // privileges for the root user. return fmt.Errorf("user %s does not have ALL privileges", security.RootUser) } return nil }
// Show returns the list of {username, privileges} sorted by username. // 'privileges' is a string of comma-separated sorted privilege names. func (p PrivilegeDescriptor) Show() []UserPrivilegeString { ret := make([]UserPrivilegeString, 0, len(p.Users)) for _, userPriv := range p.Users { ret = append(ret, UserPrivilegeString{ User: userPriv.User, Privileges: privilege.ListFromBitField(userPriv.Privileges).SortedNames(), }) } return ret }
func TestPrivilegeDecode(t *testing.T) { defer leaktest.AfterTest(t)() testCases := []struct { raw uint32 privileges privilege.List stringer, sorted string }{ {0, privilege.List{}, "", ""}, // We avoid 0 as a privilege value even though we use 1 << privValue. {1, privilege.List{}, "", ""}, {2, privilege.List{privilege.ALL}, "ALL", "ALL"}, {10, privilege.List{privilege.ALL, privilege.DROP}, "ALL, DROP", "ALL,DROP"}, {144, privilege.List{privilege.GRANT, privilege.DELETE}, "GRANT, DELETE", "DELETE,GRANT"}, {2047, privilege.List{privilege.ALL, privilege.CREATE, privilege.DROP, privilege.GRANT, privilege.SELECT, privilege.INSERT, privilege.DELETE, privilege.UPDATE}, "ALL, CREATE, DROP, GRANT, SELECT, INSERT, DELETE, UPDATE", "ALL,CREATE,DELETE,DROP,GRANT,INSERT,SELECT,UPDATE", }, } for _, tc := range testCases { pl := privilege.ListFromBitField(tc.raw) if len(pl) != len(tc.privileges) { t.Fatalf("%+v: wrong privilege list from raw: %+v", tc, pl) } for i := 0; i < len(pl); i++ { if pl[i] != tc.privileges[i] { t.Fatalf("%+v: wrong privilege list from raw: %+v", tc, pl) } } if pl.String() != tc.stringer { t.Fatalf("%+v: wrong String() output: %q", tc, pl.String()) } if pl.SortedString() != tc.sorted { t.Fatalf("%+v: wrong SortedString() output: %q", tc, pl.SortedString()) } } }