github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/upgrades/systemsshkey_test.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package upgrades_test
     5  
     6  import (
     7  	"io/ioutil"
     8  	"path/filepath"
     9  
    10  	jc "github.com/juju/testing/checkers"
    11  	gc "gopkg.in/check.v1"
    12  
    13  	"github.com/juju/juju/environs/config"
    14  	jujutesting "github.com/juju/juju/juju/testing"
    15  	"github.com/juju/juju/state"
    16  	"github.com/juju/juju/testing"
    17  	"github.com/juju/juju/upgrades"
    18  	"github.com/juju/juju/utils/ssh"
    19  )
    20  
    21  type systemSSHKeySuiteBase struct {
    22  	jujutesting.JujuConnSuite
    23  	ctx upgrades.Context
    24  }
    25  
    26  func (s *systemSSHKeySuiteBase) keyFile() string {
    27  	return filepath.Join(s.DataDir(), "system-identity")
    28  }
    29  
    30  func (s *systemSSHKeySuiteBase) assertKeyCreation(c *gc.C) string {
    31  	c.Assert(s.keyFile(), jc.IsNonEmptyFile)
    32  
    33  	// Check the private key from the system identify file.
    34  	contents, err := ioutil.ReadFile(s.keyFile())
    35  	c.Assert(err, jc.ErrorIsNil)
    36  	privateKey := string(contents)
    37  	c.Check(privateKey, jc.HasPrefix, "-----BEGIN RSA PRIVATE KEY-----\n")
    38  	c.Check(privateKey, jc.HasSuffix, "-----END RSA PRIVATE KEY-----\n")
    39  	return privateKey
    40  }
    41  
    42  func (s *systemSSHKeySuiteBase) assertHasPublicKeyInAuth(c *gc.C, privateKey string) {
    43  	publicKey, err := ssh.PublicKey([]byte(privateKey), config.JujuSystemKey)
    44  	c.Assert(err, jc.ErrorIsNil)
    45  	// Check the public key from the auth keys config.
    46  	cfg, err := s.JujuConnSuite.State.EnvironConfig()
    47  	c.Assert(err, jc.ErrorIsNil)
    48  	authKeys := ssh.SplitAuthorisedKeys(cfg.AuthorizedKeys())
    49  	// The dummy env is created with 1 fake key. We check that another has been added.
    50  	c.Assert(authKeys, gc.HasLen, 2)
    51  	c.Check(authKeys[1]+"\n", gc.Equals, publicKey)
    52  }
    53  
    54  type systemSSHKeySuite struct {
    55  	systemSSHKeySuiteBase
    56  }
    57  
    58  var _ = gc.Suite(&systemSSHKeySuite{})
    59  
    60  func (s *systemSSHKeySuite) SetUpTest(c *gc.C) {
    61  	s.JujuConnSuite.SetUpTest(c)
    62  	apiState, _ := s.OpenAPIAsNewMachine(c, state.JobManageEnviron)
    63  	s.ctx = &mockContext{
    64  		agentConfig: &mockAgentConfig{dataDir: s.DataDir()},
    65  		apiState:    apiState,
    66  	}
    67  
    68  	c.Assert(s.keyFile(), jc.DoesNotExist)
    69  	// Bootstrap adds juju-system-key; remove it.
    70  	err := s.State.UpdateEnvironConfig(map[string]interface{}{
    71  		"authorized-keys": testing.FakeAuthKeys,
    72  	}, nil, nil)
    73  	c.Assert(err, jc.ErrorIsNil)
    74  }
    75  
    76  func (s *systemSSHKeySuite) TestSystemKeyCreated(c *gc.C) {
    77  	err := upgrades.EnsureSystemSSHKey(s.ctx)
    78  	c.Assert(err, jc.ErrorIsNil)
    79  	pk := s.assertKeyCreation(c)
    80  	s.assertHasPublicKeyInAuth(c, pk)
    81  }
    82  
    83  func (s *systemSSHKeySuite) TestIdempotent(c *gc.C) {
    84  	err := upgrades.EnsureSystemSSHKey(s.ctx)
    85  	c.Assert(err, jc.ErrorIsNil)
    86  
    87  	privateKey, err := ioutil.ReadFile(s.keyFile())
    88  	c.Assert(err, jc.ErrorIsNil)
    89  
    90  	err = upgrades.EnsureSystemSSHKey(s.ctx)
    91  	c.Assert(err, jc.ErrorIsNil)
    92  
    93  	// Ensure we haven't generated the key again a second time.
    94  	privateKey2, err := ioutil.ReadFile(s.keyFile())
    95  	c.Assert(err, jc.ErrorIsNil)
    96  	c.Assert(privateKey, gc.DeepEquals, privateKey2)
    97  }
    98  
    99  type systemSSHKeyReduxSuite struct {
   100  	systemSSHKeySuiteBase
   101  }
   102  
   103  var _ = gc.Suite(&systemSSHKeyReduxSuite{})
   104  
   105  func (s *systemSSHKeyReduxSuite) SetUpTest(c *gc.C) {
   106  	s.JujuConnSuite.SetUpTest(c)
   107  	// no api state.
   108  	s.ctx = &mockContext{
   109  		agentConfig: &mockAgentConfig{dataDir: s.DataDir()},
   110  		state:       s.State,
   111  	}
   112  	c.Assert(s.keyFile(), jc.DoesNotExist)
   113  	// Bootstrap adds juju-system-key; remove it.
   114  	err := s.State.UpdateEnvironConfig(map[string]interface{}{
   115  		"authorized-keys": testing.FakeAuthKeys,
   116  	}, nil, nil)
   117  	c.Assert(err, jc.ErrorIsNil)
   118  }
   119  
   120  func (s *systemSSHKeyReduxSuite) TestReduxSystemKeyCreated(c *gc.C) {
   121  	err := upgrades.EnsureSystemSSHKeyRedux(s.ctx)
   122  	c.Assert(err, jc.ErrorIsNil)
   123  	s.assertKeyCreation(c)
   124  
   125  	// Config authorized keys should be unaltered.
   126  	cfg, err := s.JujuConnSuite.State.EnvironConfig()
   127  	c.Assert(err, jc.ErrorIsNil)
   128  	c.Assert(cfg.AuthorizedKeys(), gc.Equals, testing.FakeAuthKeys)
   129  }
   130  
   131  func (s *systemSSHKeyReduxSuite) TestReduxUpdatesAgentConfig(c *gc.C) {
   132  	err := upgrades.EnsureSystemSSHKeyRedux(s.ctx)
   133  	c.Assert(err, jc.ErrorIsNil)
   134  
   135  	info, _ := s.ctx.AgentConfig().StateServingInfo()
   136  	c.Assert(info.SystemIdentity, gc.Not(gc.Equals), "")
   137  }
   138  
   139  func (s *systemSSHKeyReduxSuite) TestReduxIdempotent(c *gc.C) {
   140  	err := upgrades.EnsureSystemSSHKeyRedux(s.ctx)
   141  	c.Assert(err, jc.ErrorIsNil)
   142  
   143  	privateKey, err := ioutil.ReadFile(s.keyFile())
   144  	c.Assert(err, jc.ErrorIsNil)
   145  
   146  	err = upgrades.EnsureSystemSSHKeyRedux(s.ctx)
   147  	c.Assert(err, jc.ErrorIsNil)
   148  
   149  	// Ensure we haven't generated the key again a second time.
   150  	privateKey2, err := ioutil.ReadFile(s.keyFile())
   151  	c.Assert(err, jc.ErrorIsNil)
   152  	c.Assert(privateKey, gc.DeepEquals, privateKey2)
   153  }
   154  
   155  func (s *systemSSHKeyReduxSuite) TestReduxExistsInStateServingInfo(c *gc.C) {
   156  	err := state.SetSystemIdentity(s.State, "ssh-private-key")
   157  	c.Assert(err, jc.ErrorIsNil)
   158  
   159  	err = upgrades.EnsureSystemSSHKeyRedux(s.ctx)
   160  	c.Assert(err, jc.ErrorIsNil)
   161  
   162  	info, err := s.State.StateServingInfo()
   163  	c.Assert(err, jc.ErrorIsNil)
   164  	c.Assert(info.SystemIdentity, gc.Equals, "ssh-private-key")
   165  }
   166  
   167  func (s *systemSSHKeyReduxSuite) TestReduxExistsOnDisk(c *gc.C) {
   168  	err := ioutil.WriteFile(s.keyFile(), []byte("ssh-private-key"), 0600)
   169  	c.Assert(err, jc.ErrorIsNil)
   170  
   171  	err = upgrades.EnsureSystemSSHKeyRedux(s.ctx)
   172  	c.Assert(err, jc.ErrorIsNil)
   173  
   174  	info, err := s.State.StateServingInfo()
   175  	c.Assert(err, jc.ErrorIsNil)
   176  	c.Assert(info.SystemIdentity, gc.Equals, "ssh-private-key")
   177  }
   178  
   179  type updateAuthKeysSuite struct {
   180  	systemSSHKeySuiteBase
   181  	systemIdentity string
   182  }
   183  
   184  var _ = gc.Suite(&updateAuthKeysSuite{})
   185  
   186  func (s *updateAuthKeysSuite) SetUpTest(c *gc.C) {
   187  	s.JujuConnSuite.SetUpTest(c)
   188  
   189  	mockAgent := &mockAgentConfig{dataDir: s.DataDir()}
   190  	// The ensure system ssh redux has already run.
   191  	err := upgrades.EnsureSystemSSHKeyRedux(&mockContext{
   192  		agentConfig: mockAgent,
   193  		state:       s.State,
   194  	})
   195  	c.Assert(err, jc.ErrorIsNil)
   196  	s.systemIdentity = s.assertKeyCreation(c)
   197  
   198  	apiState, _ := s.OpenAPIAsNewMachine(c, state.JobManageEnviron)
   199  	s.ctx = &mockContext{
   200  		agentConfig: mockAgent,
   201  		apiState:    apiState,
   202  	}
   203  	// Bootstrap adds juju-system-key; remove it.
   204  	err = s.State.UpdateEnvironConfig(map[string]interface{}{
   205  		"authorized-keys": testing.FakeAuthKeys,
   206  	}, nil, nil)
   207  	c.Assert(err, jc.ErrorIsNil)
   208  }
   209  
   210  func (s *updateAuthKeysSuite) TestUpgradeStep(c *gc.C) {
   211  	err := upgrades.UpdateAuthorizedKeysForSystemIdentity(s.ctx)
   212  	c.Assert(err, jc.ErrorIsNil)
   213  
   214  	s.assertHasPublicKeyInAuth(c, s.systemIdentity)
   215  }
   216  
   217  func (s *updateAuthKeysSuite) TestIdempotent(c *gc.C) {
   218  	err := upgrades.UpdateAuthorizedKeysForSystemIdentity(s.ctx)
   219  	c.Assert(err, jc.ErrorIsNil)
   220  
   221  	err = upgrades.UpdateAuthorizedKeysForSystemIdentity(s.ctx)
   222  	c.Assert(err, jc.ErrorIsNil)
   223  
   224  	s.assertHasPublicKeyInAuth(c, s.systemIdentity)
   225  }
   226  
   227  func (s *updateAuthKeysSuite) TestReplacesWrongKey(c *gc.C) {
   228  	// Put a wrong key in there.
   229  	_, publicKey, err := ssh.GenerateKey(config.JujuSystemKey)
   230  	c.Assert(err, jc.ErrorIsNil)
   231  	keys := testing.FakeAuthKeys + "\n" + publicKey
   232  	err = s.State.UpdateEnvironConfig(map[string]interface{}{
   233  		"authorized-keys": keys,
   234  	}, nil, nil)
   235  	c.Assert(err, jc.ErrorIsNil)
   236  
   237  	err = upgrades.UpdateAuthorizedKeysForSystemIdentity(s.ctx)
   238  	c.Assert(err, jc.ErrorIsNil)
   239  
   240  	s.assertHasPublicKeyInAuth(c, s.systemIdentity)
   241  }