github.com/rogpeppe/juju@v0.0.0-20140613142852-6337964b789e/state/apiserver/common/password.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package common 5 6 import ( 7 "github.com/juju/loggo" 8 9 "github.com/juju/juju/state" 10 "github.com/juju/juju/state/api/params" 11 ) 12 13 var logger = loggo.GetLogger("juju.state.apiserver.common") 14 15 // PasswordChanger implements a common SetPasswords method for use by 16 // various facades. 17 type PasswordChanger struct { 18 st state.EntityFinder 19 getCanChange GetAuthFunc 20 } 21 22 // NewPasswordChanger returns a new PasswordChanger. The GetAuthFunc will be 23 // used on each invocation of SetPasswords to determine current permissions. 24 func NewPasswordChanger(st state.EntityFinder, getCanChange GetAuthFunc) *PasswordChanger { 25 return &PasswordChanger{ 26 st: st, 27 getCanChange: getCanChange, 28 } 29 } 30 31 // SetPasswords sets the given password for each supplied entity, if possible. 32 func (pc *PasswordChanger) SetPasswords(args params.EntityPasswords) (params.ErrorResults, error) { 33 result := params.ErrorResults{ 34 Results: make([]params.ErrorResult, len(args.Changes)), 35 } 36 if len(args.Changes) == 0 { 37 return result, nil 38 } 39 canChange, err := pc.getCanChange() 40 if err != nil { 41 return params.ErrorResults{}, err 42 } 43 for i, param := range args.Changes { 44 if !canChange(param.Tag) { 45 result.Results[i].Error = ServerError(ErrPerm) 46 continue 47 } 48 if err := pc.setPassword(param.Tag, param.Password); err != nil { 49 result.Results[i].Error = ServerError(err) 50 } 51 } 52 return result, nil 53 } 54 55 func (pc *PasswordChanger) setMongoPassword(entity state.Entity, password string) error { 56 type mongoPassworder interface { 57 SetMongoPassword(password string) error 58 } 59 // We set the mongo password first on the grounds that 60 // if it fails, the agent in question should still be able 61 // to authenticate to another API server and ask it to change 62 // its password. 63 if entity0, ok := entity.(mongoPassworder); ok { 64 if err := entity0.SetMongoPassword(password); err != nil { 65 return err 66 } 67 logger.Infof("setting mongo password for %q", entity.Tag()) 68 return nil 69 } 70 return NotSupportedError(entity.Tag(), "mongo access") 71 } 72 73 func (pc *PasswordChanger) setPassword(tag, password string) error { 74 type jobsGetter interface { 75 Jobs() []state.MachineJob 76 } 77 var err error 78 entity0, err := pc.st.FindEntity(tag) 79 if err != nil { 80 return err 81 } 82 entity, ok := entity0.(state.Authenticator) 83 if !ok { 84 return NotSupportedError(tag, "authentication") 85 } 86 if entity, ok := entity0.(jobsGetter); ok { 87 for _, job := range entity.Jobs() { 88 paramsJob := job.ToParams() 89 if paramsJob.NeedsState() { 90 err = pc.setMongoPassword(entity0, password) 91 break 92 } 93 } 94 } 95 if err == nil { 96 err = entity.SetPassword(password) 97 logger.Infof("setting password for %q", tag) 98 } 99 return err 100 }