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 }