Пример #1
0
// AddUser adds a user to the state.
func (st *State) AddUser(name, password string) (*User, error) {
	if !validUser.MatchString(name) {
		return nil, fmt.Errorf("invalid user name %q", name)
	}
	u := &User{
		st: st,
		doc: userDoc{
			Name:         name,
			PasswordHash: utils.PasswordHash(password),
		},
	}
	ops := []txn.Op{{
		C:      st.users.Name,
		Id:     name,
		Assert: txn.DocMissing,
		Insert: &u.doc,
	}}
	err := st.runTransaction(ops)
	if err == txn.ErrAborted {
		err = fmt.Errorf("user already exists")
	}
	if err != nil {
		return nil, err
	}
	return u, nil
}
Пример #2
0
func (utilsSuite) 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 := utils.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 := utils.PasswordHash(t)
		c.Assert(h1, Equals, h)
	}
}
Пример #3
0
func (e *environ) Bootstrap(cons constraints.Value) 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")
	}

	possibleTools, err := environs.FindBootstrapTools(e, cons)
	if err != nil {
		return err
	}
	log.Infof("environs/dummy: would pick tools from %s", possibleTools)
	cfg, err := environs.BootstrapConfig(e.Config())
	if err != nil {
		return fmt.Errorf("cannot make bootstrap config: %v", err)
	}

	e.state.mu.Lock()
	defer e.state.mu.Unlock()
	if e.state.bootstrapped {
		return fmt.Errorf("environment is already bootstrapped")
	}
	if e.ecfg().stateServer() {
		// TODO(rog) factor out relevant code from cmd/jujud/bootstrap.go
		// so that we can call it here.

		info := stateInfo()
		st, err := state.Initialize(info, cfg, state.DefaultDialOpts())
		if err != nil {
			panic(err)
		}
		if err := st.SetEnvironConstraints(cons); err != nil {
			panic(err)
		}
		if err := st.SetAdminMongoPassword(utils.PasswordHash(password)); err != nil {
			panic(err)
		}
		_, err = st.AddUser("admin", password)
		if err != nil {
			panic(err)
		}
		e.state.apiServer, err = apiserver.NewServer(st, "localhost:0", []byte(testing.ServerCert), []byte(testing.ServerKey))
		if err != nil {
			panic(err)
		}
		e.state.apiState = st
	}
	e.state.bootstrapped = true
	e.state.ops <- OpBootstrap{Env: e.state.name, Constraints: cons}
	return nil
}
Пример #4
0
// 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", utils.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}}}})
}
Пример #5
0
func (s *UserSuite) TestSetPasswordHash(c *C) {
	u, err := s.State.AddUser("someuser", "")
	c.Assert(err, IsNil)

	err = u.SetPasswordHash(utils.PasswordHash("foo"))
	c.Assert(err, IsNil)

	c.Assert(u.PasswordValid("foo"), Equals, true)
	c.Assert(u.PasswordValid("bar"), Equals, false)
}
Пример #6
0
// 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")
	}
	err = environs.CheckEnvironment(environ)
	if err != nil {
		return nil, err
	}

	info.Password = password
	opts := state.DefaultDialOpts()
	st, err := state.Open(info, opts)
	if errors.IsUnauthorizedError(err) {
		log.Noticef("juju: authorization error while connecting to state server; retrying")
		// We can't connect with the administrator password,;
		// perhaps this was the first connection and the
		// password has not been changed yet.
		info.Password = utils.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, opts)
			if !errors.IsUnauthorizedError(err) {
				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
}
Пример #7
0
// FinishMachineConfig sets fields on a MachineConfig that can be determined by
// inspecting a plain config.Config and the machine constraints at the last
// moment before bootstrapping. It assumes that the supplied Config comes from
// an environment that has passed through all the validation checks in the
// Bootstrap func, and that has set an agent-version (via FindBootstrapTools,
// or otherwise).
// TODO(fwereade) This function is not meant to be "good" in any serious way:
// it is better that this functionality be collected in one place here than
// that it be spread out across 3 or 4 providers, but this is its only
// redeeming feature.
func FinishMachineConfig(mcfg *cloudinit.MachineConfig, cfg *config.Config, cons constraints.Value) (err error) {
	defer utils.ErrorContextf(&err, "cannot complete machine configuration")

	// Everything needs the environment's authorized keys.
	authKeys := cfg.AuthorizedKeys()
	if authKeys == "" {
		return fmt.Errorf("environment configuration has no authorized-keys")
	}
	mcfg.AuthorizedKeys = authKeys
	if mcfg.MachineEnvironment == nil {
		mcfg.MachineEnvironment = make(map[string]string)
	}
	mcfg.MachineEnvironment[osenv.JujuProviderType] = cfg.Type()
	if !mcfg.StateServer {
		return nil
	}

	// These settings are only appropriate at bootstrap time. At the
	// moment, the only state server is the bootstrap node, but this
	// will probably change.
	if mcfg.APIInfo != nil || mcfg.StateInfo != nil {
		return fmt.Errorf("machine configuration already has api/state info")
	}
	caCert, hasCACert := cfg.CACert()
	if !hasCACert {
		return fmt.Errorf("environment configuration has no ca-cert")
	}
	password := cfg.AdminSecret()
	if password == "" {
		return fmt.Errorf("environment configuration has no admin-secret")
	}
	passwordHash := utils.PasswordHash(password)
	mcfg.APIInfo = &api.Info{Password: passwordHash, CACert: caCert}
	mcfg.StateInfo = &state.Info{Password: passwordHash, CACert: caCert}
	mcfg.StatePort = cfg.StatePort()
	mcfg.APIPort = cfg.APIPort()
	mcfg.Constraints = cons
	if mcfg.Config, err = BootstrapConfig(cfg); err != nil {
		return err
	}

	// These really are directly relevant to running a state server.
	cert, key, err := cfg.GenerateStateServerCertAndKey()
	if err != nil {
		return fmt.Errorf("cannot generate state server certificate: %v", err)
	}
	mcfg.StateServerCert = cert
	mcfg.StateServerKey = key
	return nil
}
Пример #8
0
// SetPassword sets the password for the machine's agent.
func (m *Machine) SetPassword(password string) error {
	hp := utils.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.runTransaction(ops); err != nil {
		return fmt.Errorf("cannot set password of machine %v: %v", m, onAbort(err, errDead))
	}
	m.doc.PasswordHash = hp
	return nil
}
Пример #9
0
// SetPassword sets the password for the machine's agent.
func (u *Unit) SetPassword(password string) error {
	hp := utils.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.runTransaction(ops)
	if err != nil {
		return fmt.Errorf("cannot set password of unit %q: %v", u, onAbort(err, errDead))
	}
	u.doc.PasswordHash = hp
	return nil
}
Пример #10
0
func (s *CloudInitSuite) TestFinishBootstrapConfig(c *C) {
	cfg, err := config.New(map[string]interface{}{
		"name":            "barbara",
		"type":            "dummy",
		"admin-secret":    "lisboan-pork",
		"authorized-keys": "we-are-the-keys",
		"agent-version":   "1.2.3",
		"ca-cert":         testing.CACert,
		"ca-private-key":  testing.CAKey,
		"state-server":    false,
		"secret":          "british-horse",
	})
	c.Assert(err, IsNil)
	oldAttrs := cfg.AllAttrs()
	mcfg := &cloudinit.MachineConfig{
		StateServer: true,
	}
	cons := constraints.MustParse("mem=1T cpu-power=999999999")
	err = environs.FinishMachineConfig(mcfg, cfg, cons)
	c.Check(err, IsNil)
	c.Check(mcfg.AuthorizedKeys, Equals, "we-are-the-keys")
	password := utils.PasswordHash("lisboan-pork")
	c.Check(mcfg.APIInfo, DeepEquals, &api.Info{
		Password: password, CACert: []byte(testing.CACert),
	})
	c.Check(mcfg.StateInfo, DeepEquals, &state.Info{
		Password: password, CACert: []byte(testing.CACert),
	})
	c.Check(mcfg.StatePort, Equals, cfg.StatePort())
	c.Check(mcfg.APIPort, Equals, cfg.APIPort())
	c.Check(mcfg.Constraints, DeepEquals, cons)

	oldAttrs["ca-private-key"] = ""
	oldAttrs["admin-secret"] = ""
	delete(oldAttrs, "secret")
	c.Check(mcfg.Config.AllAttrs(), DeepEquals, oldAttrs)
	srvCertPEM := mcfg.StateServerCert
	srvKeyPEM := mcfg.StateServerKey
	_, _, err = cert.ParseCertAndKey(srvCertPEM, srvKeyPEM)
	c.Check(err, IsNil)

	err = cert.Verify(srvCertPEM, []byte(testing.CACert), time.Now())
	c.Assert(err, IsNil)
	err = cert.Verify(srvCertPEM, []byte(testing.CACert), time.Now().AddDate(9, 0, 0))
	c.Assert(err, IsNil)
	err = cert.Verify(srvCertPEM, []byte(testing.CACert), time.Now().AddDate(10, 0, 1))
	c.Assert(err, NotNil)
}
Пример #11
0
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, constraints.Value{})
	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 = utils.PasswordHash("nutkin")
	st, err := state.Open(info, state.DefaultDialOpts())
	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, state.DefaultDialOpts())
	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)
}
Пример #12
0
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, constraints.Value{})
	c.Assert(err, IsNil)
	info, _, err := env.StateInfo()
	c.Assert(err, IsNil)
	info.Password = utils.PasswordHash("side-effect secret")
	st, err := state.Open(info, state.DefaultDialOpts())
	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)
}
Пример #13
0
func (env *localEnviron) initialStateConfiguration(addr string, cons constraints.Value) (*state.State, error) {
	// We don't check the existance of the CACert here as if it wasn't set, we
	// wouldn't get this far.
	cfg := env.config.Config
	caCert, _ := cfg.CACert()
	addr = fmt.Sprintf("%s:%d", addr, cfg.StatePort())
	info := &state.Info{
		Addrs:  []string{addr},
		CACert: caCert,
	}
	timeout := state.DialOpts{60 * time.Second}
	bootstrap, err := environs.BootstrapConfig(cfg)
	if err != nil {
		return nil, err
	}
	st, err := state.Initialize(info, bootstrap, timeout)
	if err != nil {
		logger.Errorf("failed to initialize state: %v", err)
		return nil, err
	}
	logger.Debugf("state initialized")

	passwordHash := utils.PasswordHash(cfg.AdminSecret())
	if err := environs.BootstrapUsers(st, cfg, passwordHash); err != nil {
		st.Close()
		return nil, err
	}
	jobs := []state.MachineJob{state.JobManageEnviron, state.JobManageState}

	if err := environs.ConfigureBootstrapMachine(
		st, cons, env.config.rootDir(), jobs, instance.Id(boostrapInstanceId), instance.HardwareCharacteristics{}); err != nil {
		st.Close()
		return nil, err
	}

	// Return an open state reference.
	return st, nil
}
Пример #14
0
func testPasswordHash() string {
	return utils.PasswordHash(testPassword)
}
Пример #15
0
// PasswordValid returns whether the given password is valid
// for the given machine.
func (m *Machine) PasswordValid(password string) bool {
	return utils.PasswordHash(password) == m.doc.PasswordHash
}
Пример #16
0
// SetPassword sets the password associated with the user.
func (u *User) SetPassword(password string) error {
	return u.SetPasswordHash(utils.PasswordHash(password))
}
Пример #17
0
// PasswordValid returns whether the given password is valid
// for the given unit.
func (u *Unit) PasswordValid(password string) bool {
	return utils.PasswordHash(password) == u.doc.PasswordHash
}