示例#1
0
// OpenState tries to open the state using the given Conf.  If
// passwordChanged is returned as true, c.StateInfo.Password has been
// changed, and the caller should write the configuration
// and set the entity's password accordingly (in that order).
func (c *Conf) OpenState() (st *state.State, passwordChanged bool, err error) {
	info := *c.StateInfo
	if info.Password != "" {
		st, err := state.Open(&info)
		if err == nil {
			return st, false, nil
		}
		if err != state.ErrUnauthorized {
			return nil, false, err
		}
		// Access isn't authorized even though we have a password
		// This can happen if we crash after saving the
		// password but before changing it, so we'll try again
		// with the old password.
	}
	info.Password = c.OldPassword
	st, err = state.Open(&info)
	if err != nil {
		return nil, false, err
	}
	// We've succeeded in connecting with the old password, so
	// we can now change it to something more private.
	password, err := trivial.RandomPassword()
	if err != nil {
		st.Close()
		return nil, false, err
	}
	c.StateInfo.Password = password
	return st, true, nil
}
示例#2
0
func (s *BootstrapSuite) TestInitialPassword(c *C) {
	machineConf, cmd, err := s.initBootstrapCommand(c, "--env-config", testConfig)
	c.Assert(err, IsNil)

	err = cmd.Run(nil)
	c.Assert(err, IsNil)

	// Check that we cannot now connect to the state without a
	// password.
	info := &state.Info{
		Addrs:  []string{testing.MgoAddr},
		CACert: []byte(testing.CACert),
	}
	testOpenState(c, info, errors.Unauthorizedf(""))

	// Check we can log in to mongo as admin.
	info.Tag, info.Password = "", testPasswordHash()
	st, err := state.Open(info, state.DefaultDialOpts())
	c.Assert(err, IsNil)
	// Reset password so the tests can continue to use the same server.
	defer st.Close()
	defer st.SetAdminMongoPassword("")

	// Check that the admin user has been given an appropriate
	// password
	u, err := st.User("admin")
	c.Assert(err, IsNil)
	c.Assert(u.PasswordValid(testPassword), Equals, true)

	// Check that the machine configuration has been given a new
	// password and that we can connect to mongo as that machine
	// and that the in-mongo password also verifies correctly.

	machineConf1, err := agent.ReadConf(machineConf.DataDir, "machine-0")
	c.Assert(err, IsNil)

	c.Assert(machineConf1.OldPassword, Equals, "")
	c.Assert(machineConf1.APIInfo.Password, Not(Equals), "")
	c.Assert(machineConf1.StateInfo.Password, Equals, machineConf1.APIInfo.Password)

	// Check that no other information has been lost.
	machineConf.OldPassword = ""
	machineConf.APIInfo.Password = machineConf1.APIInfo.Password
	machineConf.StateInfo.Password = machineConf1.StateInfo.Password
	c.Assert(machineConf1, DeepEquals, machineConf)

	info.Tag, info.Password = "******", machineConf1.StateInfo.Password
	st, err = state.Open(info, state.DefaultDialOpts())
	c.Assert(err, IsNil)
	defer st.Close()

	m, err := st.Machine("0")
	c.Assert(err, IsNil)
	c.Assert(m.PasswordValid(machineConf1.StateInfo.Password), Equals, true)
}
示例#3
0
func testSetMongoPassword(c *C, getEntity func(st *state.State) (entity, error)) {
	info := state.TestingStateInfo()
	st, err := state.Open(info)
	c.Assert(err, IsNil)
	defer st.Close()
	// Turn on fully-authenticated mode.
	err = st.SetAdminMongoPassword("admin-secret")
	c.Assert(err, IsNil)

	// Set the password for the entity
	ent, err := getEntity(st)
	c.Assert(err, IsNil)
	err = ent.SetMongoPassword("foo")
	c.Assert(err, IsNil)

	// Check that we cannot log in with the wrong password.
	info.EntityName = ent.EntityName()
	info.Password = "******"
	err = tryOpenState(info)
	c.Assert(err, Equals, state.ErrUnauthorized)

	// Check that we can log in with the correct password.
	info.Password = "******"
	st1, err := state.Open(info)
	c.Assert(err, IsNil)
	defer st1.Close()

	// Change the password with an entity derived from the newly
	// opened and authenticated state.
	ent, err = getEntity(st)
	c.Assert(err, IsNil)
	err = ent.SetMongoPassword("bar")
	c.Assert(err, IsNil)

	// Check that we cannot log in with the old password.
	info.Password = "******"
	err = tryOpenState(info)
	c.Assert(err, Equals, state.ErrUnauthorized)

	// Check that we can log in with the correct password.
	info.Password = "******"
	err = tryOpenState(info)
	c.Assert(err, IsNil)

	// Check that the administrator can still log in.
	info.EntityName, info.Password = "", "admin-secret"
	err = tryOpenState(info)
	c.Assert(err, IsNil)

	// Remove the admin password so that the test harness can reset the state.
	err = st.SetAdminMongoPassword("")
	c.Assert(err, IsNil)
}
示例#4
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
}
示例#5
0
func (s *BootstrapSuite) TestSetMachineId(c *C) {
	args := []string{
		"--instance-id", "over9000",
		"--env-config", b64yaml{
			"name":            "dummyenv",
			"type":            "dummy",
			"state-server":    false,
			"authorized-keys": "i-am-a-key",
			"ca-cert":         testing.CACert,
		}.encode(),
	}
	_, cmd, err := s.initBootstrapCommand(c, args...)
	c.Assert(err, IsNil)
	err = cmd.Run(nil)
	c.Assert(err, IsNil)

	st, err := state.Open(&state.Info{
		Addrs:  []string{testing.MgoAddr},
		CACert: []byte(testing.CACert),
	})
	c.Assert(err, IsNil)
	defer st.Close()
	machines, err := st.AllMachines()
	c.Assert(err, IsNil)
	c.Assert(len(machines), Equals, 1)

	instid, err := machines[0].InstanceId()
	c.Assert(err, IsNil)
	c.Assert(instid, Equals, state.InstanceId("over9000"))
}
示例#6
0
func (s *BootstrapSuite) TestMachinerWorkers(c *C) {
	args := []string{
		"--instance-id", "over9000",
		"--env-config", b64yaml{
			"name":            "dummyenv",
			"type":            "dummy",
			"state-server":    false,
			"authorized-keys": "i-am-a-key",
			"ca-cert":         testing.CACert,
		}.encode(),
	}
	_, cmd, err := s.initBootstrapCommand(c, args...)
	c.Assert(err, IsNil)
	err = cmd.Run(nil)
	c.Assert(err, IsNil)

	st, err := state.Open(&state.Info{
		Addrs:  []string{testing.MgoAddr},
		CACert: []byte(testing.CACert),
	})
	c.Assert(err, IsNil)
	defer st.Close()
	m, err := st.Machine("0")
	c.Assert(err, IsNil)
	c.Assert(m.Jobs(), DeepEquals, []state.MachineJob{state.JobManageEnviron})
}
示例#7
0
func (s *BootstrapSuite) TestInitializeEnvironment(c *C) {
	_, cmd, err := s.initBootstrapCommand(c, "--env-config", testConfig)
	c.Assert(err, IsNil)
	err = cmd.Run(nil)
	c.Assert(err, IsNil)

	st, err := state.Open(&state.Info{
		Addrs:    []string{testing.MgoAddr},
		CACert:   []byte(testing.CACert),
		Password: testPasswordHash(),
	}, state.DefaultDialOpts())
	c.Assert(err, IsNil)
	defer st.Close()
	machines, err := st.AllMachines()
	c.Assert(err, IsNil)
	c.Assert(machines, HasLen, 1)

	instid, err := machines[0].InstanceId()
	c.Assert(err, IsNil)
	c.Assert(instid, Equals, instance.Id("dummy.instance.id"))

	cons, err := st.EnvironConstraints()
	c.Assert(err, IsNil)
	c.Assert(cons, DeepEquals, constraints.Value{})
}
示例#8
0
func tryOpenState(info *state.Info) error {
	st, err := state.Open(info, state.DialOpts{})
	if err == nil {
		st.Close()
	}
	return err
}
示例#9
0
func (s *InitializeSuite) SetUpTest(c *C) {
	s.LoggingSuite.SetUpTest(c)
	s.MgoSuite.SetUpTest(c)
	var err error
	s.State, err = state.Open(state.TestingStateInfo(), state.TestingDialOpts())
	c.Assert(err, IsNil)
}
示例#10
0
func (s *BootstrapSuite) TestSetConstraints(c *C) {
	tcons := constraints.Value{Mem: uint64p(2048), CpuCores: uint64p(2)}
	_, cmd, err := s.initBootstrapCommand(c, "--env-config", testConfig, "--constraints", tcons.String())
	c.Assert(err, IsNil)
	err = cmd.Run(nil)
	c.Assert(err, IsNil)

	st, err := state.Open(&state.Info{
		Addrs:    []string{testing.MgoAddr},
		CACert:   []byte(testing.CACert),
		Password: testPasswordHash(),
	}, state.DefaultDialOpts())
	c.Assert(err, IsNil)
	defer st.Close()
	cons, err := st.EnvironConstraints()
	c.Assert(err, IsNil)
	c.Assert(cons, DeepEquals, tcons)

	machines, err := st.AllMachines()
	c.Assert(err, IsNil)
	c.Assert(machines, HasLen, 1)
	cons, err = machines[0].Constraints()
	c.Assert(err, IsNil)
	c.Assert(cons, DeepEquals, tcons)
}
示例#11
0
func (s *suite) TestMachineSetPassword(c *C) {
	m, err := s.st.MachineAgent().Machine(s.machine.Tag())
	c.Assert(err, IsNil)

	err = m.SetPassword("foo")
	c.Assert(err, IsNil)

	err = s.machine.Refresh()
	c.Assert(err, IsNil)
	c.Assert(s.machine.PasswordValid("bar"), Equals, false)
	c.Assert(s.machine.PasswordValid("foo"), Equals, true)

	// Check that we cannot log in to mongo with the wrong password.
	info := s.StateInfo(c)
	info.Tag = m.Tag()
	info.Password = "******"
	err = tryOpenState(info)
	c.Assert(err, checkers.Satisfies, errors.IsUnauthorizedError)

	// Check that we can log in with the correct password
	info.Password = "******"
	st, err := state.Open(info, state.DialOpts{})
	c.Assert(err, IsNil)
	st.Close()
}
示例#12
0
// checkStartInstance checks that an instance has been started
// with a machine id the same as m's, and that the machine's
// instance id has been set appropriately.
func (s *ProvisionerSuite) checkStartInstance(c *C, m *state.Machine, secret string) {
	s.State.StartSync()
	for {
		select {
		case o := <-s.op:
			switch o := o.(type) {
			case dummy.OpStartInstance:
				info := s.StateInfo(c)
				info.EntityName = m.EntityName()
				c.Assert(o.Info.Password, Not(HasLen), 0)
				info.Password = o.Info.Password
				c.Assert(o.Info, DeepEquals, info)

				// Check we can connect to the state with
				// the machine's entity name and password.
				st, err := state.Open(o.Info)
				c.Assert(err, IsNil)
				st.Close()

				c.Assert(o.MachineId, Equals, m.Id())
				c.Assert(o.Instance, NotNil)
				s.checkInstanceId(c, m, o.Instance)
				c.Assert(o.Secret, Equals, secret)
				return
			default:
				c.Logf("ignoring unexpected operation %#v", o)
			}
		case <-time.After(2 * time.Second):
			c.Errorf("provisioner did not start an instance")
			return
		}
	}
}
示例#13
0
// OpenState tries to open the state using the given Conf.
func (c *Conf) OpenState() (*state.State, error) {
	info := *c.StateInfo
	if info.Password != "" {
		st, err := state.Open(&info, state.DefaultDialOpts())
		if err == nil {
			return st, nil
		}
		// TODO(rog) remove this fallback behaviour when
		// all initial connections are via the API.
		if !errors.IsUnauthorizedError(err) {
			return nil, err
		}
	}
	info.Password = c.OldPassword
	return state.Open(&info, state.DefaultDialOpts())
}
示例#14
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)
}
示例#15
0
func (s *StateSuite) TestDialAgain(c *C) {
	// Ensure idempotent operations on Dial are working fine.
	for i := 0; i < 2; i++ {
		st, err := state.Open(state.TestingStateInfo())
		c.Assert(err, IsNil)
		c.Assert(st.Close(), IsNil)
	}
}
示例#16
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")
	}
	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
}
示例#17
0
func testOpenState(c *C, info *state.Info, expectErr error) {
	st, err := state.Open(info)
	if st != nil {
		st.Close()
	}
	if expectErr != nil {
		c.Assert(err, Equals, expectErr)
	} else {
		c.Assert(err, IsNil)
	}
}
示例#18
0
func testOpenState(c *C, info *state.Info, expectErrType error) {
	st, err := state.Open(info, state.DefaultDialOpts())
	if st != nil {
		st.Close()
	}
	if expectErrType != nil {
		c.Assert(err, FitsTypeOf, expectErrType)
	} else {
		c.Assert(err, IsNil)
	}
}
示例#19
0
func (cs *ConnSuite) SetUpTest(c *C) {
	cs.LoggingSuite.SetUpTest(c)
	cs.MgoSuite.SetUpTest(c)
	cs.charms = cs.MgoSuite.Session.DB("juju").C("charms")
	cs.machines = cs.MgoSuite.Session.DB("juju").C("machines")
	cs.relations = cs.MgoSuite.Session.DB("juju").C("relations")
	cs.services = cs.MgoSuite.Session.DB("juju").C("services")
	cs.units = cs.MgoSuite.Session.DB("juju").C("units")
	var err error
	cs.State, err = state.Open(state.TestingStateInfo())
	c.Assert(err, IsNil)
}
func (s *CommonProvisionerSuite) checkStartInstanceCustom(c *C, m *state.Machine, secret string, cons constraints.Value) (inst instance.Instance) {
	s.State.StartSync()
	for {
		select {
		case o := <-s.op:
			switch o := o.(type) {
			case dummy.OpStartInstance:
				inst = o.Instance
				s.waitInstanceId(c, m, inst.Id())

				// Check the instance was started with the expected params.
				c.Assert(o.MachineId, Equals, m.Id())
				nonceParts := strings.SplitN(o.MachineNonce, ":", 2)
				c.Assert(nonceParts, HasLen, 2)
				c.Assert(nonceParts[0], Equals, state.MachineTag("0"))
				c.Assert(nonceParts[1], checkers.Satisfies, utils.IsValidUUIDString)
				c.Assert(o.Secret, Equals, secret)
				c.Assert(o.Constraints, DeepEquals, cons)

				// Check we can connect to the state with
				// the machine's entity name and password.
				info := s.StateInfo(c)
				info.Tag = m.Tag()
				c.Assert(o.Info.Password, Not(HasLen), 0)
				info.Password = o.Info.Password
				c.Assert(o.Info, DeepEquals, info)
				// Check we can connect to the state with
				// the machine's entity name and password.
				st, err := state.Open(o.Info, state.DefaultDialOpts())
				c.Assert(err, IsNil)

				// All provisioned machines in this test suite have their hardware characteristics
				// attributes set to the same values as the constraints due to the dummy environment being used.
				hc, err := m.HardwareCharacteristics()
				c.Assert(err, IsNil)
				c.Assert(*hc, DeepEquals, instance.HardwareCharacteristics{
					Arch:     cons.Arch,
					Mem:      cons.Mem,
					CpuCores: cons.CpuCores,
					CpuPower: cons.CpuPower,
				})
				st.Close()
				return
			default:
				c.Logf("ignoring unexpected operation %#v", o)
			}
		case <-time.After(2 * time.Second):
			c.Fatalf("provisioner did not start an instance")
			return
		}
	}
	return
}
示例#21
0
func (s *baseSuite) tryOpenState(c *C, e apiAuthenticator, password string) error {
	stateInfo := s.StateInfo(c)
	stateInfo.Tag = e.Tag()
	stateInfo.Password = password
	st, err := state.Open(stateInfo, state.DialOpts{
		Timeout: 25 * time.Millisecond,
	})
	if err == nil {
		st.Close()
	}
	return err
}
示例#22
0
func (s *BootstrapSuite) TestMachinerWorkers(c *C) {
	_, cmd, err := s.initBootstrapCommand(c, "--env-config", testConfig)
	c.Assert(err, IsNil)
	err = cmd.Run(nil)
	c.Assert(err, IsNil)

	st, err := state.Open(&state.Info{
		Addrs:    []string{testing.MgoAddr},
		CACert:   []byte(testing.CACert),
		Password: testPasswordHash(),
	}, state.DefaultDialOpts())
	c.Assert(err, IsNil)
	defer st.Close()
	m, err := st.Machine("0")
	c.Assert(err, IsNil)
	c.Assert(m.Jobs(), DeepEquals, []state.MachineJob{
		state.JobManageEnviron, state.JobManageState, state.JobHostUnits,
	})
}
示例#23
0
func (s *ProvisionerSuite) checkStartInstanceCustom(c *C, m *state.Machine, secret string, cons constraints.Value) {
	s.State.StartSync()
	for {
		select {
		case o := <-s.op:
			switch o := o.(type) {
			case dummy.OpStartInstance:
				s.waitInstanceId(c, m, o.Instance.Id())

				// Check the instance was started with the expected params.
				c.Assert(o.MachineId, Equals, m.Id())
				nonceParts := strings.SplitN(o.MachineNonce, ":", 2)
				c.Assert(nonceParts, HasLen, 2)
				c.Assert(nonceParts[0], Equals, state.MachineTag("0"))
				c.Assert(utils.IsValidUUIDString(nonceParts[1]), Equals, true)
				c.Assert(o.Secret, Equals, secret)
				c.Assert(o.Constraints, DeepEquals, cons)

				// Check we can connect to the state with
				// the machine's entity name and password.
				info := s.StateInfo(c)
				info.Tag = m.Tag()
				c.Assert(o.Info.Password, Not(HasLen), 0)
				info.Password = o.Info.Password
				c.Assert(o.Info, DeepEquals, info)
				// Check we can connect to the state with
				// the machine's entity name and password.
				st, err := state.Open(o.Info, state.DefaultDialOpts())
				c.Assert(err, IsNil)

				st.Close()
				return
			default:
				c.Logf("ignoring unexpected operation %#v", o)
			}
		case <-time.After(2 * time.Second):
			c.Fatalf("provisioner did not start an instance")
			return
		}
	}
}
示例#24
0
func (s *BootstrapSuite) TestInitialPassword(c *C) {
	args := []string{
		"--instance-id", "over9000",
		"--env-config", b64yaml{
			"name":            "dummyenv",
			"type":            "dummy",
			"state-server":    false,
			"authorized-keys": "i-am-a-key",
			"ca-cert":         testing.CACert,
		}.encode(),
	}
	conf, cmd, err := s.initBootstrapCommand(c, args...)
	c.Assert(err, IsNil)
	conf.OldPassword = "******"
	err = conf.Write()
	c.Assert(err, IsNil)

	err = cmd.Run(nil)
	c.Assert(err, IsNil)

	// Check that we cannot now connect to the state
	// without a password.
	info := &state.Info{
		Addrs:  []string{testing.MgoAddr},
		CACert: []byte(testing.CACert),
	}
	testOpenState(c, info, state.ErrUnauthorized)

	info.EntityName, info.Password = "******", "foo"
	testOpenState(c, info, nil)

	info.EntityName = ""
	st, err := state.Open(info)
	c.Assert(err, IsNil)
	defer st.Close()

	// Reset password so the tests can continue to use the same server.
	err = st.SetAdminMongoPassword("")
	c.Assert(err, IsNil)
}
示例#25
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)
}
示例#26
0
func (s *UnitSuite) TestSetMongoPasswordOnUnitAfterConnectingAsMachineEntity(c *C) {
	// Make a second unit to use later. (Subordinate units can only be created
	// as a side-effect of a principal entering relation scope.)
	subCharm := s.AddTestingCharm(c, "logging")
	_, err := s.State.AddService("logging", subCharm)
	c.Assert(err, IsNil)
	eps, err := s.State.InferEndpoints([]string{"wordpress", "logging"})
	c.Assert(err, IsNil)
	rel, err := s.State.AddRelation(eps...)
	c.Assert(err, IsNil)
	ru, err := rel.Unit(s.unit)
	c.Assert(err, IsNil)
	err = ru.EnterScope(nil)
	c.Assert(err, IsNil)
	subUnit, err := s.State.Unit("logging/0")
	c.Assert(err, IsNil)

	info := state.TestingStateInfo()
	st, err := state.Open(info, state.TestingDialOpts())
	c.Assert(err, IsNil)
	defer st.Close()
	// Turn on fully-authenticated mode.
	err = st.SetAdminMongoPassword("admin-secret")
	c.Assert(err, IsNil)

	// Add a new machine, assign the units to it
	// and set its password.
	m, err := st.AddMachine("series", state.JobHostUnits)
	c.Assert(err, IsNil)
	unit, err := st.Unit(s.unit.Name())
	c.Assert(err, IsNil)
	subUnit, err = st.Unit(subUnit.Name())
	c.Assert(err, IsNil)
	err = unit.AssignToMachine(m)
	c.Assert(err, IsNil)
	err = m.SetMongoPassword("foo")
	c.Assert(err, IsNil)

	// Sanity check that we cannot connect with the wrong
	// password
	info.Tag = m.Tag()
	info.Password = "******"
	err = tryOpenState(info)
	c.Assert(err, checkers.Satisfies, errors.IsUnauthorizedError)

	// Connect as the machine entity.
	info.Tag = m.Tag()
	info.Password = "******"
	st1, err := state.Open(info, state.TestingDialOpts())
	c.Assert(err, IsNil)
	defer st1.Close()

	// Change the password for a unit derived from
	// the machine entity's state.
	unit, err = st1.Unit(s.unit.Name())
	c.Assert(err, IsNil)
	err = unit.SetMongoPassword("bar")
	c.Assert(err, IsNil)

	// Now connect as the unit entity and, as that
	// that entity, change the password for a new unit.
	info.Tag = unit.Tag()
	info.Password = "******"
	st2, err := state.Open(info, state.TestingDialOpts())
	c.Assert(err, IsNil)
	defer st2.Close()

	// Check that we can set its password.
	unit, err = st2.Unit(subUnit.Name())
	c.Assert(err, IsNil)
	err = unit.SetMongoPassword("bar2")
	c.Assert(err, IsNil)

	// Clear the admin password, so tests can reset the db.
	err = st.SetAdminMongoPassword("")
	c.Assert(err, IsNil)
}