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