From b0e893c073c1fa78e763babfaa1afa628e2186ed Mon Sep 17 00:00:00 2001 From: John Shahid Date: Thu, 12 Dec 2013 13:04:46 -0500 Subject: [PATCH] change db user password should be a separate command --- src/coordinator/cluster_configuration.go | 14 ++++++++++++ src/coordinator/command.go | 25 ++++++++++++++++++++++ src/coordinator/coordinator.go | 20 ++++++------------ src/coordinator/interface.go | 1 + src/coordinator/raft_server.go | 27 +++++++++++++++++------- src/coordinator/user.go | 8 ++----- src/coordinator/user_test.go | 8 +++++-- src/server/server_test.go | 2 +- 8 files changed, 75 insertions(+), 30 deletions(-) diff --git a/src/coordinator/cluster_configuration.go b/src/coordinator/cluster_configuration.go index c9e9b7dfff..64766b5ad7 100644 --- a/src/coordinator/cluster_configuration.go +++ b/src/coordinator/cluster_configuration.go @@ -353,6 +353,20 @@ func (self *ClusterConfiguration) SaveDbUser(u *dbUser) { dbUsers[u.GetName()] = u } +func (self *ClusterConfiguration) ChangeDbUserPassword(db, username, hash string) error { + self.usersLock.Lock() + defer self.usersLock.Unlock() + dbUsers := self.dbUsers[db] + if dbUsers == nil { + return fmt.Errorf("Invalid database name %s", db) + } + if dbUsers[username] == nil { + return fmt.Errorf("Invalid username %s", username) + } + dbUsers[username].changePassword(hash) + return nil +} + func (self *ClusterConfiguration) GetClusterAdmins() (names []string) { self.usersLock.RLock() defer self.usersLock.RUnlock() diff --git a/src/coordinator/command.go b/src/coordinator/command.go index a47c865fbb..1a88aa5135 100644 --- a/src/coordinator/command.go +++ b/src/coordinator/command.go @@ -1,6 +1,7 @@ package coordinator import ( + log "code.google.com/p/log4go" "github.com/goraft/raft" ) @@ -61,6 +62,30 @@ func (c *SaveDbUserCommand) Apply(server raft.Server) (interface{}, error) { return nil, nil } +type ChangeDbUserPassword struct { + Database string + Username string + Hash string +} + +func NewChangeDbUserPasswordCommand(db, username, hash string) *ChangeDbUserPassword { + return &ChangeDbUserPassword{ + Database: db, + Username: username, + Hash: hash, + } +} + +func (c *ChangeDbUserPassword) CommandName() string { + return "change_db_user_password" +} + +func (c *ChangeDbUserPassword) Apply(server raft.Server) (interface{}, error) { + log.Debug("(raft:%s) changing db user password for %s:%s", server.Name(), c.Database, c.Username) + config := server.Context().(*ClusterConfiguration) + return nil, config.ChangeDbUserPassword(c.Database, c.Username, c.Hash) +} + type SaveClusterAdminCommand struct { User *clusterAdmin `json:"user"` } diff --git a/src/coordinator/coordinator.go b/src/coordinator/coordinator.go index 1035961dee..d855c5b7a9 100644 --- a/src/coordinator/coordinator.go +++ b/src/coordinator/coordinator.go @@ -672,7 +672,11 @@ func (self *CoordinatorImpl) ChangeClusterAdminPassword(requester common.User, u return fmt.Errorf("Invalid user name %s", username) } - user.changePassword(password) + hash, err := hashPassword(password) + if err != nil { + return err + } + user.changePassword(string(hash)) return self.raftServer.SaveClusterAdminUser(user) } @@ -722,21 +726,11 @@ func (self *CoordinatorImpl) ChangeDbUserPassword(requester common.User, db, use return common.NewAuthorizationError("Insufficient permissions") } - dbUsers := self.clusterConfiguration.dbUsers[db] - if dbUsers == nil { - return fmt.Errorf("Invalid database name %s", db) - } - - if dbUsers[username] == nil { - return fmt.Errorf("Invalid username %s", username) - } - - user := *dbUsers[username] - err := user.changePassword(password) + hash, err := hashPassword(password) if err != nil { return err } - return self.raftServer.SaveDbUser(&user) + return self.raftServer.ChangeDbUserPassword(db, username, hash) } func (self *CoordinatorImpl) SetDbAdmin(requester common.User, db, username string, isAdmin bool) error { diff --git a/src/coordinator/interface.go b/src/coordinator/interface.go index e1d330a550..adfa4bc0ec 100644 --- a/src/coordinator/interface.go +++ b/src/coordinator/interface.go @@ -60,6 +60,7 @@ type ClusterConsensus interface { DropDatabase(name string) error SaveClusterAdminUser(u *clusterAdmin) error SaveDbUser(user *dbUser) error + ChangeDbUserPassword(db, username string, hash []byte) error // an insert index of -1 will append to the end of the ring AddServer(server *ClusterServer, insertIndex int) error diff --git a/src/coordinator/raft_server.go b/src/coordinator/raft_server.go index d66391772e..b7a43f89db 100644 --- a/src/coordinator/raft_server.go +++ b/src/coordinator/raft_server.go @@ -56,6 +56,7 @@ func NewRaftServer(config *configuration.Configuration, clusterConfig *ClusterCo raft.RegisterCommand(&DropDatabaseCommand{}) raft.RegisterCommand(&SaveDbUserCommand{}) raft.RegisterCommand(&SaveClusterAdminCommand{}) + raft.RegisterCommand(&ChangeDbUserPassword{}) } s := &RaftServer{ @@ -151,6 +152,12 @@ func (s *RaftServer) SaveDbUser(u *dbUser) error { return err } +func (s *RaftServer) ChangeDbUserPassword(db, username string, hash []byte) error { + command := NewChangeDbUserPasswordCommand(db, username, string(hash)) + _, err := s.doOrProxyCommand(command, "change_db_user_password") + return err +} + func (s *RaftServer) SaveClusterAdminUser(u *clusterAdmin) error { command := NewSaveClusterAdminCommand(u) _, err := s.doOrProxyCommand(command, "save_cluster_admin_user") @@ -159,7 +166,8 @@ func (s *RaftServer) SaveClusterAdminUser(u *clusterAdmin) error { func (s *RaftServer) CreateRootUser() error { u := &clusterAdmin{CommonUser{"root", "", false}} - u.changePassword(DEFAULT_ROOT_PWD) + hash, _ := hashPassword(DEFAULT_ROOT_PWD) + u.changePassword(string(hash)) return s.SaveClusterAdminUser(u) } @@ -398,20 +406,23 @@ func (s *RaftServer) processCommandHandler(w http.ResponseWriter, req *http.Requ vars := mux.Vars(req) value := vars["command_type"] var command raft.Command - if value == "create_db" { + switch value { + case "create_db": command = &CreateDatabaseCommand{} - } else if value == "drop_db" { + case "drop_db": command = &DropDatabaseCommand{} - } else if value == "save_db_user" { + case "save_db_user": command = &SaveDbUserCommand{} - } else if value == "save_cluster_admin_user" { + case "save_cluster_admin_user": command = &SaveClusterAdminCommand{} - } else if value == "update_state" { + case "update_state": command = &UpdateServerStateCommand{} - } else if value == "add_server" { - fmt.Println("add_server: ", s.name) + case "add_server": command = &AddPotentialServerCommand{} + case "change_db_user_password": + command = &ChangeDbUserPassword{} } + if result, err := s.marshalAndDoCommandFromBody(command, req); err != nil { log.Error("command %T failed: %s", command, err) http.Error(w, err.Error(), http.StatusInternalServerError) diff --git a/src/coordinator/user.go b/src/coordinator/user.go index 28aec0cdd7..fd28e1753b 100644 --- a/src/coordinator/user.go +++ b/src/coordinator/user.go @@ -39,12 +39,8 @@ func (self *CommonUser) IsDeleted() bool { return self.IsUserDeleted } -func (self *CommonUser) changePassword(password string) error { - hash, err := hashPassword(password) - if err != nil { - return err - } - self.Hash = string(hash) +func (self *CommonUser) changePassword(hash string) error { + self.Hash = hash userCache.Delete(self.Name) return nil } diff --git a/src/coordinator/user_test.go b/src/coordinator/user_test.go index 1071085784..30046fe930 100644 --- a/src/coordinator/user_test.go +++ b/src/coordinator/user_test.go @@ -21,7 +21,9 @@ func (self *UserSuite) TestProperties(c *C) { u := clusterAdmin{CommonUser{Name: "root"}} c.Assert(u.IsClusterAdmin(), Equals, true) c.Assert(u.GetName(), Equals, "root") - c.Assert(u.changePassword("foobar"), IsNil) + hash, err := hashPassword("foobar") + c.Assert(err, IsNil) + c.Assert(u.changePassword(string(hash)), IsNil) c.Assert(u.isValidPwd("foobar"), Equals, true) c.Assert(u.isValidPwd("password"), Equals, false) @@ -29,7 +31,9 @@ func (self *UserSuite) TestProperties(c *C) { c.Assert(dbUser.IsClusterAdmin(), Equals, false) c.Assert(dbUser.IsDbAdmin("db"), Equals, true) c.Assert(dbUser.GetName(), Equals, "db_user") - c.Assert(dbUser.changePassword("password"), IsNil) + hash, err = hashPassword("password") + c.Assert(err, IsNil) + c.Assert(dbUser.changePassword(string(hash)), IsNil) c.Assert(dbUser.isValidPwd("password"), Equals, true) c.Assert(dbUser.isValidPwd("password1"), Equals, false) } diff --git a/src/server/server_test.go b/src/server/server_test.go index f8dff62065..e00cb2b94b 100644 --- a/src/server/server_test.go +++ b/src/server/server_test.go @@ -319,7 +319,7 @@ func (self *ServerSuite) TestCrossClusterQueries(c *C) { func (self *ServerSuite) TestFailureAndReplicationReplays(c *C) { servers := self.servers - err := servers[0].RaftServer.CreateDatabase("full_rep", uint8(3)) + _, err := self.postToServer(self.servers[0], "/db?u=root&p=root", `{"name": "full_rep", "replicationFactor": 3}`, c) c.Assert(err, IsNil) time.Sleep(time.Millisecond * 10) _, err = self.postToServer(self.servers[0], "/db/full_rep/users?u=root&p=root", `{"name": "paul", "password": "pass"}`, c)