func (trivialSuite) TestPasswordHash(c *C) { tests := []string{"", "a", "a longer password than i would usually bother with"} hs := make(map[string]bool) for i, t := range tests { c.Logf("test %d", i) h := trivial.PasswordHash(t) c.Logf("hash %q", h) c.Assert(len(h), Equals, 24) c.Assert(hs[h], Equals, false) // check we're not adding base64 padding. c.Assert(h[len(h)-1], Not(Equals), '=') hs[h] = true // check it's deterministic h1 := trivial.PasswordHash(t) c.Assert(h1, Equals, h) } }
// invalidateEnvironment alters the environment configuration // so the Settings returned from the watcher will not pass // validation. func (s *ProvisionerSuite) invalidateEnvironment(c *C) error { admindb := s.Session.DB("admin") err := admindb.Login("admin", testing.AdminSecret) if err != nil { err = admindb.Login("admin", trivial.PasswordHash(testing.AdminSecret)) } c.Assert(err, IsNil) settings := s.Session.DB("juju").C("settings") return settings.UpdateId("e", bson.D{{"$unset", bson.D{{"type", 1}}}}) }
func (e *environ) Bootstrap(uploadTools bool, cert, key []byte) error { defer delay() if err := e.checkBroken("Bootstrap"); err != nil { return err } password := e.Config().AdminSecret() if password == "" { return fmt.Errorf("admin-secret is required for bootstrap") } if _, ok := e.Config().CACert(); !ok { return fmt.Errorf("no CA certificate in environment configuration") } var tools *state.Tools var err error if uploadTools { tools, err = environs.PutTools(e.Storage(), nil) if err != nil { return err } } else { flags := environs.HighestVersion | environs.CompatVersion tools, err = environs.FindTools(e, version.Current, flags) if err != nil { return err } } e.state.mu.Lock() defer e.state.mu.Unlock() e.state.ops <- OpBootstrap{Env: e.state.name} if e.state.bootstrapped { return fmt.Errorf("environment is already bootstrapped") } if e.ecfg().stateServer() { info := stateInfo() cfg, err := environs.BootstrapConfig(&providerInstance, e.ecfg().Config, tools) if err != nil { return fmt.Errorf("cannot make bootstrap config: %v", err) } st, err := state.Initialize(info, cfg) if err != nil { panic(err) } if err := st.SetAdminMongoPassword(trivial.PasswordHash(password)); err != nil { return err } if err := st.Close(); err != nil { panic(err) } } e.state.bootstrapped = true return nil }
// SetPassword sets the password for the machine's agent. func (m *Machine) SetPassword(password string) (err error) { hp := trivial.PasswordHash(password) ops := []txn.Op{{ C: m.st.machines.Name, Id: m.doc.Id, Assert: notDeadDoc, Update: D{{"$set", D{{"passwordhash", hp}}}}, }} if err := m.st.runner.Run(ops, "", nil); err != nil { return fmt.Errorf("cannot set password of machine %v: %v", m, onAbort(err, errNotAlive)) } m.doc.PasswordHash = hp return nil }
// SetPassword sets the password for the machine's agent. func (u *Unit) SetPassword(password string) error { hp := trivial.PasswordHash(password) ops := []txn.Op{{ C: u.st.units.Name, Id: u.doc.Name, Assert: notDeadDoc, Update: D{{"$set", D{{"passwordhash", hp}}}}, }} err := u.st.runner.Run(ops, "", nil) if err != nil { return fmt.Errorf("cannot set password of unit %q: %v", u, onAbort(err, errNotAlive)) } u.doc.PasswordHash = hp return nil }
func (cs *NewConnSuite) TestConnWithPassword(c *C) { env, err := environs.NewFromAttrs(map[string]interface{}{ "name": "erewhemos", "type": "dummy", "state-server": true, "authorized-keys": "i-am-a-key", "secret": "squirrel", "admin-secret": "nutkin", "ca-cert": coretesting.CACert, "ca-private-key": coretesting.CAKey, }) c.Assert(err, IsNil) err = environs.Bootstrap(env, false, panicWrite) c.Assert(err, IsNil) // Check that Bootstrap has correctly used a hash // of the admin password. info, err := env.StateInfo() c.Assert(err, IsNil) info.Password = trivial.PasswordHash("nutkin") st, err := state.Open(info) c.Assert(err, IsNil) st.Close() // Check that we can connect with the original environment. conn, err := juju.NewConn(env) c.Assert(err, IsNil) conn.Close() // Check that the password has now been changed to the original // admin password. info.Password = "******" st1, err := state.Open(info) c.Assert(err, IsNil) st1.Close() // Check that we can still connect with the original // environment. conn, err = juju.NewConn(env) c.Assert(err, IsNil) defer conn.Close() // Reset the admin password so the state db can be reused. err = conn.State.SetAdminMongoPassword("") c.Assert(err, IsNil) }
// NewConn returns a new Conn that uses the // given environment. The environment must have already // been bootstrapped. func NewConn(environ environs.Environ) (*Conn, error) { info, err := environ.StateInfo() if err != nil { return nil, err } password := environ.Config().AdminSecret() if password == "" { return nil, fmt.Errorf("cannot connect without admin-secret") } info.Password = password st, err := state.Open(info) if err == state.ErrUnauthorized { // We can't connect with the administrator password,; // perhaps this was the first connection and the // password has not been changed yet. info.Password = trivial.PasswordHash(password) // We try for a while because we might succeed in // connecting to mongo before the state has been // initialized and the initial password set. for a := redialStrategy.Start(); a.Next(); { st, err = state.Open(info) if err != state.ErrUnauthorized { break } } if err != nil { return nil, err } if err := st.SetAdminMongoPassword(password); err != nil { return nil, err } } else if err != nil { return nil, err } conn := &Conn{ Environ: environ, State: st, } if err := conn.updateSecrets(); err != nil { conn.Close() return nil, fmt.Errorf("unable to push secrets: %v", err) } return conn, nil }
func (cs *NewConnSuite) TestConnStateSecretsSideEffect(c *C) { attrs := map[string]interface{}{ "name": "erewhemos", "type": "dummy", "state-server": true, "authorized-keys": "i-am-a-key", "secret": "pork", "admin-secret": "side-effect secret", "ca-cert": coretesting.CACert, "ca-private-key": coretesting.CAKey, } env, err := environs.NewFromAttrs(attrs) c.Assert(err, IsNil) err = environs.Bootstrap(env, false, panicWrite) c.Assert(err, IsNil) info, err := env.StateInfo() c.Assert(err, IsNil) info.Password = trivial.PasswordHash("side-effect secret") st, err := state.Open(info) c.Assert(err, IsNil) // Verify we have no secret in the environ config cfg, err := st.EnvironConfig() c.Assert(err, IsNil) c.Assert(cfg.UnknownAttrs()["secret"], IsNil) // Make a new Conn, which will push the secrets. conn, err := juju.NewConn(env) c.Assert(err, IsNil) defer conn.Close() cfg, err = conn.State.EnvironConfig() c.Assert(err, IsNil) c.Assert(cfg.UnknownAttrs()["secret"], Equals, "pork") // Reset the admin password so the state db can be reused. err = conn.State.SetAdminMongoPassword("") c.Assert(err, IsNil) }
func (e *environ) Bootstrap(uploadTools bool, cert, key []byte) error { password := e.Config().AdminSecret() if password == "" { return fmt.Errorf("admin-secret is required for bootstrap") } log.Printf("environs/ec2: bootstrapping environment %q", e.name) // If the state file exists, it might actually have just been // removed by Destroy, and eventual consistency has not caught // up yet, so we retry to verify if that is happening. var err error for a := shortAttempt.Start(); a.Next(); { _, err = e.loadState() if err != nil { break } } if err == nil { return fmt.Errorf("environment is already bootstrapped") } if _, notFound := err.(*environs.NotFoundError); !notFound { return fmt.Errorf("cannot query old bootstrap state: %v", err) } var tools *state.Tools if uploadTools { tools, err = environs.PutTools(e.Storage(), nil) if err != nil { return fmt.Errorf("cannot upload tools: %v", err) } } else { flags := environs.HighestVersion | environs.CompatVersion v := version.Current v.Series = e.Config().DefaultSeries() tools, err = environs.FindTools(e, v, flags) if err != nil { return fmt.Errorf("cannot find tools: %v", err) } } config, err := environs.BootstrapConfig(providerInstance, e.Config(), tools) if err != nil { return fmt.Errorf("unable to determine inital configuration: %v", err) } caCert, hasCert := e.Config().CACert() if !hasCert { return fmt.Errorf("no CA certificate in environment configuration") } info := &state.Info{ Password: trivial.PasswordHash(password), CACert: caCert, } inst, err := e.startInstance(&startInstanceParams{ machineId: "0", info: info, tools: tools, stateServer: true, config: config, stateServerCert: cert, stateServerKey: key, }) if err != nil { return fmt.Errorf("cannot start bootstrap instance: %v", err) } err = e.saveState(&bootstrapState{ StateInstances: []state.InstanceId{inst.Id()}, }) if err != nil { // ignore error on StopInstance because the previous error is // more important. e.StopInstances([]environs.Instance{inst}) return fmt.Errorf("cannot save state: %v", err) } // TODO make safe in the case of racing Bootstraps // If two Bootstraps are called concurrently, there's // no way to use S3 to make sure that only one succeeds. // Perhaps consider using SimpleDB for state storage // which would enable that possibility. return nil }
// PasswordValid returns whether the given password is valid // for the given unit. func (u *Unit) PasswordValid(password string) bool { return trivial.PasswordHash(password) == u.doc.PasswordHash }
// PasswordValid returns whether the given password is valid // for the given machine. func (m *Machine) PasswordValid(password string) bool { return trivial.PasswordHash(password) == m.doc.PasswordHash }