示例#1
0
func (s *StateSuite) TestEnvironConfigWithAdminSecret(c *C) {
	attrs := map[string]interface{}{
		"name":            "test",
		"type":            "test",
		"authorized-keys": "i-am-a-key",
		"default-series":  "precise",
		"development":     true,
		"admin-secret":    "foo",
		"ca-cert":         testing.CACert,
		"ca-private-key":  "",
	}
	cfg, err := config.New(attrs)
	c.Assert(err, IsNil)
	_, err = state.Initialize(state.TestingStateInfo(), cfg)
	c.Assert(err, ErrorMatches, "admin-secret should never be written to the state")

	delete(attrs, "admin-secret")
	cfg, err = config.New(attrs)
	st, err := state.Initialize(state.TestingStateInfo(), cfg)
	c.Assert(err, IsNil)
	st.Close()

	cfg, err = cfg.Apply(map[string]interface{}{"admin-secret": "foo"})
	err = s.State.SetEnvironConfig(cfg)
	c.Assert(err, ErrorMatches, "admin-secret should never be written to the state")
}
示例#2
0
// Run initializes state for an environment.
func (c *BootstrapCommand) Run(_ *cmd.Context) error {
	if err := c.Conf.read("bootstrap"); err != nil {
		return err
	}
	cfg, err := config.New(c.EnvConfig)
	if err != nil {
		return err
	}
	// There is no entity that's created at init time.
	c.Conf.StateInfo.EntityName = ""
	st, err := state.Initialize(c.Conf.StateInfo, cfg)
	if err != nil {
		return err
	}
	defer st.Close()
	m, err := st.InjectMachine(state.InstanceId(c.InstanceId), state.JobManageEnviron)
	if err != nil {
		return err
	}
	if c.Conf.OldPassword != "" {
		if err := m.SetMongoPassword(c.Conf.OldPassword); err != nil {
			return err
		}
		if err := st.SetAdminMongoPassword(c.Conf.OldPassword); err != nil {
			return err
		}
	}
	return nil
}
示例#3
0
func (s *InitializeSuite) TestInitialize(c *C) {
	_, err := s.State.EnvironConfig()
	c.Assert(err, checkers.Satisfies, errors.IsNotFoundError)
	_, err = s.State.Annotator("environment-foo")
	c.Assert(err, checkers.Satisfies, errors.IsNotFoundError)
	_, err = s.State.EnvironConstraints()
	c.Assert(err, checkers.Satisfies, errors.IsNotFoundError)

	cfg := testing.EnvironConfig(c)
	initial := cfg.AllAttrs()
	st, err := state.Initialize(state.TestingStateInfo(), cfg, state.TestingDialOpts())
	c.Assert(err, IsNil)
	c.Assert(st, NotNil)
	err = st.Close()
	c.Assert(err, IsNil)

	cfg, err = s.State.EnvironConfig()
	c.Assert(err, IsNil)
	c.Assert(cfg.AllAttrs(), DeepEquals, initial)
	env, err := s.State.Annotator("environment-" + cfg.Name())
	c.Assert(err, IsNil)
	annotations, err := env.Annotations()
	c.Assert(err, IsNil)
	c.Assert(annotations, HasLen, 0)
	cons, err := s.State.EnvironConstraints()
	c.Assert(err, IsNil)
	c.Assert(cons, DeepEquals, constraints.Value{})
}
示例#4
0
func (s *StateSuite) TestWatchEnvironConfig(c *C) {
	watcher := s.State.WatchEnvironConfig()
	defer func() {
		c.Assert(watcher.Stop(), IsNil)
	}()
	for i, test := range watchEnvironConfigTests {
		c.Logf("test %d", i)
		change, err := config.New(test)
		c.Assert(err, IsNil)
		if i == 0 {
			st, err := state.Initialize(state.TestingStateInfo(), change)
			c.Assert(err, IsNil)
			st.Close()
		} else {
			err = s.State.SetEnvironConfig(change)
			c.Assert(err, IsNil)
		}
		c.Assert(err, IsNil)
		s.State.StartSync()
		select {
		case got, ok := <-watcher.Changes():
			c.Assert(ok, Equals, true)
			c.Assert(got.AllAttrs(), DeepEquals, change.AllAttrs())
		case <-time.After(500 * time.Millisecond):
			c.Fatalf("did not get change: %#v", test)
		}
	}

	select {
	case got := <-watcher.Changes():
		c.Fatalf("got unexpected change: %#v", got)
	case <-time.After(50 * time.Millisecond):
	}
}
示例#5
0
func (s *StateSuite) TestEnvironConfig(c *C) {
	initial := map[string]interface{}{
		"name":                      "test",
		"type":                      "test",
		"authorized-keys":           "i-am-a-key",
		"default-series":            "precise",
		"development":               true,
		"firewall-mode":             "",
		"admin-secret":              "",
		"ca-cert":                   testing.CACert,
		"ca-private-key":            "",
		"ssl-hostname-verification": true,
	}
	cfg, err := config.New(initial)
	c.Assert(err, IsNil)
	st, err := state.Initialize(state.TestingStateInfo(), cfg)
	c.Assert(err, IsNil)
	st.Close()
	c.Assert(err, IsNil)
	cfg, err = s.State.EnvironConfig()
	c.Assert(err, IsNil)
	current := cfg.AllAttrs()
	c.Assert(current, DeepEquals, initial)

	current["authorized-keys"] = "i-am-a-new-key"
	cfg, err = config.New(current)
	c.Assert(err, IsNil)
	err = s.State.SetEnvironConfig(cfg)
	c.Assert(err, IsNil)
	cfg, err = s.State.EnvironConfig()
	c.Assert(err, IsNil)
	final := cfg.AllAttrs()
	c.Assert(final, DeepEquals, current)
}
示例#6
0
func (s *StateSuite) TestDoubleInitialize(c *C) {
	m := map[string]interface{}{
		"type":                      "dummy",
		"name":                      "lisboa",
		"authorized-keys":           "i-am-a-key",
		"default-series":            "precise",
		"development":               true,
		"firewall-mode":             "",
		"admin-secret":              "",
		"ca-cert":                   testing.CACert,
		"ca-private-key":            "",
		"ssl-hostname-verification": true,
	}
	cfg, err := config.New(m)
	c.Assert(err, IsNil)
	st, err := state.Initialize(state.TestingStateInfo(), cfg)
	c.Assert(err, IsNil)
	c.Assert(st, NotNil)
	env1, err := st.EnvironConfig()
	st.Close()

	// initialize again, there should be no error and the
	// environ config should not change.
	m = map[string]interface{}{
		"type":                      "dummy",
		"name":                      "sydney",
		"authorized-keys":           "i-am-not-an-animal",
		"default-series":            "xanadu",
		"development":               false,
		"firewall-mode":             "",
		"admin-secret":              "",
		"ca-cert":                   testing.CACert,
		"ca-private-key":            "",
		"ssl-hostname-verification": false,
	}
	cfg, err = config.New(m)
	c.Assert(err, IsNil)
	st, err = state.Initialize(state.TestingStateInfo(), cfg)
	c.Assert(err, IsNil)
	c.Assert(st, NotNil)
	env2, err := st.EnvironConfig()
	st.Close()

	c.Assert(env1.AllAttrs(), DeepEquals, env2.AllAttrs())
}
示例#7
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
}
示例#8
0
// Run initializes state for an environment.
func (c *BootstrapCommand) Run(_ *cmd.Context) error {
	if err := c.Conf.read("bootstrap"); err != nil {
		return err
	}
	cfg, err := config.New(c.EnvConfig)
	if err != nil {
		return err
	}

	// There is no entity that's created at init time.
	c.Conf.StateInfo.Tag = ""
	st, err := state.Initialize(c.Conf.StateInfo, cfg, state.DefaultDialOpts())
	if err != nil {
		return err
	}
	defer st.Close()

	if err := environs.BootstrapUsers(st, cfg, c.Conf.OldPassword); err != nil {
		return err
	}

	// TODO(fwereade): we need to be able to customize machine jobs,
	// not just hardcode these values; in particular, JobHostUnits
	// on a machine, like this one, that is running JobManageEnviron
	// (not to mention the actual state server itself...) will allow
	// a malicious or compromised unit to trivially access to the
	// user's environment credentials. However, given that this point
	// is currently moot (see Upgrader in this package), the pseudo-
	// local provider mode (in which everything is deployed with
	// `--to 0`) offers enough value to enough people that
	// JobHostUnits is currently always enabled. This will one day
	// have to change, but it's strictly less important than fixing
	// Upgrader, and it's a capability we'll always want to have
	// available for the aforementioned use case.
	jobs := []state.MachineJob{
		state.JobManageEnviron, state.JobManageState, state.JobHostUnits,
	}

	data, err := ioutil.ReadFile(providerStateURLFile)
	if err != nil {
		return fmt.Errorf("cannot read provider-state-url file: %v", err)
	}
	stateInfoURL := strings.Split(string(data), "\n")[0]
	bsState, err := environs.LoadStateFromURL(stateInfoURL)
	if err != nil {
		return fmt.Errorf("cannot load state from URL %q (read from %q): %v", stateInfoURL, providerStateURLFile, err)
	}
	instId := bsState.StateInstances[0]
	var characteristics instance.HardwareCharacteristics
	if len(bsState.Characteristics) > 0 {
		characteristics = bsState.Characteristics[0]
	}

	return environs.ConfigureBootstrapMachine(st, c.Constraints, c.Conf.DataDir, jobs, instance.Id(instId), characteristics)
}
示例#9
0
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
}
示例#10
0
func (s *StateSuite) TestWatchEnvironConfigAfterCreation(c *C) {
	cfg, err := config.New(watchEnvironConfigTests[0])
	c.Assert(err, IsNil)
	st, err := state.Initialize(state.TestingStateInfo(), cfg)
	c.Assert(err, IsNil)
	st.Close()
	s.State.Sync()
	watcher := s.State.WatchEnvironConfig()
	defer watcher.Stop()
	select {
	case got, ok := <-watcher.Changes():
		c.Assert(ok, Equals, true)
		c.Assert(got.AllAttrs(), DeepEquals, cfg.AllAttrs())
	case <-time.After(500 * time.Millisecond):
		c.Fatalf("did not get change")
	}
}
示例#11
0
func (s *InitializeSuite) TestEnvironConfigWithAdminSecret(c *C) {
	// admin-secret blocks Initialize.
	good := testing.EnvironConfig(c)
	bad, err := good.Apply(map[string]interface{}{"admin-secret": "foo"})

	_, err = state.Initialize(state.TestingStateInfo(), bad, state.TestingDialOpts())
	c.Assert(err, ErrorMatches, "admin-secret should never be written to the state")

	// admin-secret blocks SetEnvironConfig.
	st := state.TestingInitialize(c, good)
	st.Close()
	err = s.State.SetEnvironConfig(bad)
	c.Assert(err, ErrorMatches, "admin-secret should never be written to the state")

	// EnvironConfig remains inviolate.
	cfg, err := s.State.EnvironConfig()
	c.Assert(err, IsNil)
	c.Assert(cfg.AllAttrs(), DeepEquals, good.AllAttrs())
}
示例#12
0
func (s *InitializeSuite) TestDoubleInitializeConfig(c *C) {
	cfg := testing.EnvironConfig(c)
	initial := cfg.AllAttrs()
	st := state.TestingInitialize(c, cfg)
	st.Close()

	// A second initialize returns an open *State, but ignores its params.
	// TODO(fwereade) I think this is crazy, but it's what we were testing
	// for originally...
	cfg, err := cfg.Apply(map[string]interface{}{"authorized-keys": "something-else"})
	c.Assert(err, IsNil)
	st, err = state.Initialize(state.TestingStateInfo(), cfg, state.TestingDialOpts())
	c.Assert(err, IsNil)
	c.Assert(st, NotNil)
	st.Close()

	cfg, err = s.State.EnvironConfig()
	c.Assert(err, IsNil)
	c.Assert(cfg.AllAttrs(), DeepEquals, initial)
}
示例#13
0
func (s *InitializeSuite) TestEnvironConfigWithoutAgentVersion(c *C) {
	// admin-secret blocks Initialize.
	good := testing.EnvironConfig(c)
	attrs := good.AllAttrs()
	delete(attrs, "agent-version")
	bad, err := config.New(attrs)
	c.Assert(err, IsNil)

	_, err = state.Initialize(state.TestingStateInfo(), bad, state.TestingDialOpts())
	c.Assert(err, ErrorMatches, "agent-version must always be set in state")

	// Bad agent-version blocks SetEnvironConfig.
	st := state.TestingInitialize(c, good)
	st.Close()
	err = s.State.SetEnvironConfig(bad)
	c.Assert(err, ErrorMatches, "agent-version must always be set in state")

	// EnvironConfig remains inviolate.
	cfg, err := s.State.EnvironConfig()
	c.Assert(err, IsNil)
	c.Assert(cfg.AllAttrs(), DeepEquals, good.AllAttrs())
}
示例#14
0
func (s *StateSuite) TestInitialize(c *C) {
	m := map[string]interface{}{
		"type":                      "dummy",
		"name":                      "lisboa",
		"authorized-keys":           "i-am-a-key",
		"default-series":            "precise",
		"development":               true,
		"firewall-mode":             "",
		"admin-secret":              "",
		"ca-cert":                   testing.CACert,
		"ca-private-key":            "",
		"ssl-hostname-verification": true,
	}
	cfg, err := config.New(m)
	c.Assert(err, IsNil)
	st, err := state.Initialize(state.TestingStateInfo(), cfg)
	c.Assert(err, IsNil)
	c.Assert(st, NotNil)
	defer st.Close()
	env, err := st.EnvironConfig()
	c.Assert(env.AllAttrs(), DeepEquals, m)
}
示例#15
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
}
示例#16
0
func (s *StateSuite) TestWatchEnvironConfigInvalidConfig(c *C) {
	m := map[string]interface{}{
		"type":            "dummy",
		"name":            "lisboa",
		"authorized-keys": "i-am-a-key",
		"ca-cert":         testing.CACert,
		"ca-private-key":  "",
	}
	cfg1, err := config.New(m)
	c.Assert(err, IsNil)
	st, err := state.Initialize(state.TestingStateInfo(), cfg1)
	c.Assert(err, IsNil)
	st.Close()

	// Corrupt the environment configuration.
	settings := s.Session.DB("juju").C("settings")
	err = settings.UpdateId("e", bson.D{{"$unset", bson.D{{"name", 1}}}})
	c.Assert(err, IsNil)

	s.State.Sync()

	// Start watching the configuration.
	watcher := s.State.WatchEnvironConfig()
	defer watcher.Stop()
	done := make(chan *config.Config)
	go func() {
		select {
		case cfg, ok := <-watcher.Changes():
			if !ok {
				c.Errorf("watcher channel closed")
			} else {
				done <- cfg
			}
		case <-time.After(5 * time.Second):
			c.Fatalf("no environment configuration observed")
		}
	}()

	s.State.Sync()

	// The invalid configuration must not have been generated.
	select {
	case <-done:
		c.Fatalf("configuration returned too soon")
	case <-time.After(100 * time.Millisecond):
	}

	// Fix the configuration.
	cfg2, err := config.New(map[string]interface{}{
		"type":            "dummy",
		"name":            "lisboa",
		"authorized-keys": "new-key",
		"ca-cert":         testing.CACert,
		"ca-private-key":  "",
	})
	c.Assert(err, IsNil)
	err = s.State.SetEnvironConfig(cfg2)
	c.Assert(err, IsNil)

	s.State.StartSync()
	select {
	case cfg3 := <-done:
		c.Assert(cfg3.AllAttrs(), DeepEquals, cfg2.AllAttrs())
	case <-time.After(5 * time.Second):
		c.Fatalf("no environment configuration observed")
	}
}