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