github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/apiserver/keymanager/keymanager_test.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package keymanager_test 5 6 import ( 7 "fmt" 8 "strings" 9 10 "github.com/juju/errors" 11 "github.com/juju/names" 12 jc "github.com/juju/testing/checkers" 13 gc "gopkg.in/check.v1" 14 15 "github.com/juju/juju/apiserver/common" 16 "github.com/juju/juju/apiserver/keymanager" 17 keymanagertesting "github.com/juju/juju/apiserver/keymanager/testing" 18 "github.com/juju/juju/apiserver/params" 19 apiservertesting "github.com/juju/juju/apiserver/testing" 20 jujutesting "github.com/juju/juju/juju/testing" 21 "github.com/juju/juju/utils/ssh" 22 sshtesting "github.com/juju/juju/utils/ssh/testing" 23 ) 24 25 type keyManagerSuite struct { 26 jujutesting.JujuConnSuite 27 28 keymanager *keymanager.KeyManagerAPI 29 resources *common.Resources 30 authoriser apiservertesting.FakeAuthorizer 31 } 32 33 var _ = gc.Suite(&keyManagerSuite{}) 34 35 func (s *keyManagerSuite) SetUpTest(c *gc.C) { 36 s.JujuConnSuite.SetUpTest(c) 37 s.resources = common.NewResources() 38 s.AddCleanup(func(_ *gc.C) { s.resources.StopAll() }) 39 40 s.authoriser = apiservertesting.FakeAuthorizer{ 41 Tag: s.AdminUserTag(c), 42 } 43 var err error 44 s.keymanager, err = keymanager.NewKeyManagerAPI(s.State, s.resources, s.authoriser) 45 c.Assert(err, jc.ErrorIsNil) 46 } 47 48 func (s *keyManagerSuite) TestNewKeyManagerAPIAcceptsClient(c *gc.C) { 49 endPoint, err := keymanager.NewKeyManagerAPI(s.State, s.resources, s.authoriser) 50 c.Assert(err, jc.ErrorIsNil) 51 c.Assert(endPoint, gc.NotNil) 52 } 53 54 func (s *keyManagerSuite) TestNewKeyManagerAPIAcceptsEnvironManager(c *gc.C) { 55 anAuthoriser := s.authoriser 56 anAuthoriser.EnvironManager = true 57 endPoint, err := keymanager.NewKeyManagerAPI(s.State, s.resources, anAuthoriser) 58 c.Assert(err, jc.ErrorIsNil) 59 c.Assert(endPoint, gc.NotNil) 60 } 61 62 func (s *keyManagerSuite) TestNewKeyManagerAPIRefusesNonClient(c *gc.C) { 63 anAuthoriser := s.authoriser 64 anAuthoriser.Tag = names.NewUnitTag("mysql/0") 65 anAuthoriser.EnvironManager = false 66 endPoint, err := keymanager.NewKeyManagerAPI(s.State, s.resources, anAuthoriser) 67 c.Assert(endPoint, gc.IsNil) 68 c.Assert(err, gc.ErrorMatches, "permission denied") 69 } 70 71 func (s *keyManagerSuite) TestNewKeyManagerAPIRefusesNonEnvironManager(c *gc.C) { 72 anAuthoriser := s.authoriser 73 anAuthoriser.Tag = names.NewMachineTag("99") 74 anAuthoriser.EnvironManager = false 75 endPoint, err := keymanager.NewKeyManagerAPI(s.State, s.resources, anAuthoriser) 76 c.Assert(endPoint, gc.IsNil) 77 c.Assert(err, gc.ErrorMatches, "permission denied") 78 } 79 80 func (s *keyManagerSuite) setAuthorisedKeys(c *gc.C, keys string) { 81 err := s.State.UpdateEnvironConfig(map[string]interface{}{"authorized-keys": keys}, nil, nil) 82 c.Assert(err, jc.ErrorIsNil) 83 envConfig, err := s.State.EnvironConfig() 84 c.Assert(err, jc.ErrorIsNil) 85 c.Assert(envConfig.AuthorizedKeys(), gc.Equals, keys) 86 } 87 88 func (s *keyManagerSuite) TestListKeys(c *gc.C) { 89 key1 := sshtesting.ValidKeyOne.Key + " user@host" 90 key2 := sshtesting.ValidKeyTwo.Key 91 s.setAuthorisedKeys(c, strings.Join([]string{key1, key2, "bad key"}, "\n")) 92 93 args := params.ListSSHKeys{ 94 Entities: params.Entities{[]params.Entity{ 95 {Tag: s.AdminUserTag(c).Name()}, 96 {Tag: "invalid"}, 97 }}, 98 Mode: ssh.FullKeys, 99 } 100 results, err := s.keymanager.ListKeys(args) 101 c.Assert(err, jc.ErrorIsNil) 102 c.Assert(results, gc.DeepEquals, params.StringsResults{ 103 Results: []params.StringsResult{ 104 {Result: []string{key1, key2, "Invalid key: bad key"}}, 105 {Result: []string{key1, key2, "Invalid key: bad key"}}, 106 }, 107 }) 108 } 109 110 func (s *keyManagerSuite) assertEnvironKeys(c *gc.C, expected []string) { 111 envConfig, err := s.State.EnvironConfig() 112 c.Assert(err, jc.ErrorIsNil) 113 keys := envConfig.AuthorizedKeys() 114 c.Assert(keys, gc.Equals, strings.Join(expected, "\n")) 115 } 116 117 func (s *keyManagerSuite) TestAddKeys(c *gc.C) { 118 key1 := sshtesting.ValidKeyOne.Key + " user@host" 119 key2 := sshtesting.ValidKeyTwo.Key 120 initialKeys := []string{key1, key2, "bad key"} 121 s.setAuthorisedKeys(c, strings.Join(initialKeys, "\n")) 122 123 newKey := sshtesting.ValidKeyThree.Key + " newuser@host" 124 args := params.ModifyUserSSHKeys{ 125 User: s.AdminUserTag(c).Name(), 126 Keys: []string{key2, newKey, "invalid-key"}, 127 } 128 results, err := s.keymanager.AddKeys(args) 129 c.Assert(err, jc.ErrorIsNil) 130 c.Assert(results, gc.DeepEquals, params.ErrorResults{ 131 Results: []params.ErrorResult{ 132 {Error: apiservertesting.ServerError(fmt.Sprintf("duplicate ssh key: %s", key2))}, 133 {Error: nil}, 134 {Error: apiservertesting.ServerError("invalid ssh key: invalid-key")}, 135 }, 136 }) 137 s.assertEnvironKeys(c, append(initialKeys, newKey)) 138 } 139 140 func (s *keyManagerSuite) TestBlockAddKeys(c *gc.C) { 141 key1 := sshtesting.ValidKeyOne.Key + " user@host" 142 key2 := sshtesting.ValidKeyTwo.Key 143 initialKeys := []string{key1, key2, "bad key"} 144 s.setAuthorisedKeys(c, strings.Join(initialKeys, "\n")) 145 146 newKey := sshtesting.ValidKeyThree.Key + " newuser@host" 147 args := params.ModifyUserSSHKeys{ 148 User: s.AdminUserTag(c).Name(), 149 Keys: []string{key2, newKey, "invalid-key"}, 150 } 151 152 s.AssertConfigParameterUpdated(c, "block-all-changes", true) 153 _, err := s.keymanager.AddKeys(args) 154 // Check that the call is blocked 155 c.Assert(errors.Cause(err), gc.ErrorMatches, common.ErrOperationBlocked.Error()) 156 s.assertEnvironKeys(c, initialKeys) 157 } 158 159 func (s *keyManagerSuite) TestAddJujuSystemKey(c *gc.C) { 160 anAuthoriser := s.authoriser 161 anAuthoriser.EnvironManager = true 162 anAuthoriser.Tag = names.NewMachineTag("0") 163 var err error 164 s.keymanager, err = keymanager.NewKeyManagerAPI(s.State, s.resources, anAuthoriser) 165 c.Assert(err, jc.ErrorIsNil) 166 key1 := sshtesting.ValidKeyOne.Key + " user@host" 167 key2 := sshtesting.ValidKeyTwo.Key 168 initialKeys := []string{key1, key2} 169 s.setAuthorisedKeys(c, strings.Join(initialKeys, "\n")) 170 171 newKey := sshtesting.ValidKeyThree.Key + " juju-system-key" 172 args := params.ModifyUserSSHKeys{ 173 User: "juju-system-key", 174 Keys: []string{newKey}, 175 } 176 results, err := s.keymanager.AddKeys(args) 177 c.Assert(err, jc.ErrorIsNil) 178 c.Assert(results, gc.DeepEquals, params.ErrorResults{ 179 Results: []params.ErrorResult{ 180 {Error: nil}, 181 }, 182 }) 183 s.assertEnvironKeys(c, append(initialKeys, newKey)) 184 } 185 186 func (s *keyManagerSuite) TestAddJujuSystemKeyNotMachine(c *gc.C) { 187 anAuthoriser := s.authoriser 188 anAuthoriser.EnvironManager = true 189 anAuthoriser.Tag = names.NewUnitTag("wordpress/0") 190 var err error 191 s.keymanager, err = keymanager.NewKeyManagerAPI(s.State, s.resources, anAuthoriser) 192 c.Assert(err, jc.ErrorIsNil) 193 key1 := sshtesting.ValidKeyOne.Key 194 s.setAuthorisedKeys(c, key1) 195 196 newKey := sshtesting.ValidKeyThree.Key + " juju-system-key" 197 args := params.ModifyUserSSHKeys{ 198 User: "juju-system-key", 199 Keys: []string{newKey}, 200 } 201 _, err = s.keymanager.AddKeys(args) 202 c.Assert(err, gc.ErrorMatches, "permission denied") 203 s.assertEnvironKeys(c, []string{key1}) 204 } 205 206 func (s *keyManagerSuite) TestDeleteKeys(c *gc.C) { 207 key1 := sshtesting.ValidKeyOne.Key + " user@host" 208 key2 := sshtesting.ValidKeyTwo.Key 209 initialKeys := []string{key1, key2, "bad key"} 210 s.setAuthorisedKeys(c, strings.Join(initialKeys, "\n")) 211 212 args := params.ModifyUserSSHKeys{ 213 User: s.AdminUserTag(c).Name(), 214 Keys: []string{sshtesting.ValidKeyTwo.Fingerprint, sshtesting.ValidKeyThree.Fingerprint, "invalid-key"}, 215 } 216 results, err := s.keymanager.DeleteKeys(args) 217 c.Assert(err, jc.ErrorIsNil) 218 c.Assert(results, gc.DeepEquals, params.ErrorResults{ 219 Results: []params.ErrorResult{ 220 {Error: nil}, 221 {Error: apiservertesting.ServerError("invalid ssh key: " + sshtesting.ValidKeyThree.Fingerprint)}, 222 {Error: apiservertesting.ServerError("invalid ssh key: invalid-key")}, 223 }, 224 }) 225 s.assertEnvironKeys(c, []string{"bad key", key1}) 226 } 227 228 func (s *keyManagerSuite) TestBlockDeleteKeys(c *gc.C) { 229 key1 := sshtesting.ValidKeyOne.Key + " user@host" 230 key2 := sshtesting.ValidKeyTwo.Key 231 initialKeys := []string{key1, key2, "bad key"} 232 s.setAuthorisedKeys(c, strings.Join(initialKeys, "\n")) 233 234 args := params.ModifyUserSSHKeys{ 235 User: s.AdminUserTag(c).Name(), 236 Keys: []string{sshtesting.ValidKeyTwo.Fingerprint, sshtesting.ValidKeyThree.Fingerprint, "invalid-key"}, 237 } 238 239 s.AssertConfigParameterUpdated(c, "block-all-changes", true) 240 _, err := s.keymanager.DeleteKeys(args) 241 // Check that the call is blocked 242 c.Assert(errors.Cause(err), gc.ErrorMatches, common.ErrOperationBlocked.Error()) 243 s.assertEnvironKeys(c, initialKeys) 244 } 245 246 func (s *keyManagerSuite) TestCannotDeleteAllKeys(c *gc.C) { 247 key1 := sshtesting.ValidKeyOne.Key + " user@host" 248 key2 := sshtesting.ValidKeyTwo.Key 249 initialKeys := []string{key1, key2} 250 s.setAuthorisedKeys(c, strings.Join(initialKeys, "\n")) 251 252 args := params.ModifyUserSSHKeys{ 253 User: s.AdminUserTag(c).Name(), 254 Keys: []string{sshtesting.ValidKeyTwo.Fingerprint, "user@host"}, 255 } 256 _, err := s.keymanager.DeleteKeys(args) 257 c.Assert(err, gc.ErrorMatches, "cannot delete all keys") 258 s.assertEnvironKeys(c, initialKeys) 259 } 260 261 func (s *keyManagerSuite) assertInvalidUserOperation(c *gc.C, runTestLogic func(args params.ModifyUserSSHKeys) error) { 262 initialKey := sshtesting.ValidKeyOne.Key + " user@host" 263 s.setAuthorisedKeys(c, initialKey) 264 265 // Set up the params. 266 newKey := sshtesting.ValidKeyThree.Key + " newuser@host" 267 args := params.ModifyUserSSHKeys{ 268 User: "invalid", 269 Keys: []string{newKey}, 270 } 271 // Run the required test code and check the error. 272 err := runTestLogic(args) 273 c.Assert(err, gc.DeepEquals, apiservertesting.ErrUnauthorized) 274 275 // No environ changes. 276 s.assertEnvironKeys(c, []string{initialKey}) 277 } 278 279 func (s *keyManagerSuite) TestAddKeysInvalidUser(c *gc.C) { 280 c.Skip("no user validation done yet") 281 s.assertInvalidUserOperation(c, func(args params.ModifyUserSSHKeys) error { 282 _, err := s.keymanager.AddKeys(args) 283 return err 284 }) 285 } 286 287 func (s *keyManagerSuite) TestDeleteKeysInvalidUser(c *gc.C) { 288 c.Skip("no user validation done yet") 289 s.assertInvalidUserOperation(c, func(args params.ModifyUserSSHKeys) error { 290 _, err := s.keymanager.DeleteKeys(args) 291 return err 292 }) 293 } 294 295 func (s *keyManagerSuite) TestImportKeys(c *gc.C) { 296 s.PatchValue(&keymanager.RunSSHImportId, keymanagertesting.FakeImport) 297 298 key1 := sshtesting.ValidKeyOne.Key + " user@host" 299 key2 := sshtesting.ValidKeyTwo.Key 300 key3 := sshtesting.ValidKeyThree.Key 301 initialKeys := []string{key1, key2, "bad key"} 302 s.setAuthorisedKeys(c, strings.Join(initialKeys, "\n")) 303 304 args := params.ModifyUserSSHKeys{ 305 User: s.AdminUserTag(c).Name(), 306 Keys: []string{"lp:existing", "lp:validuser", "invalid-key"}, 307 } 308 results, err := s.keymanager.ImportKeys(args) 309 c.Assert(err, jc.ErrorIsNil) 310 c.Assert(results, gc.DeepEquals, params.ErrorResults{ 311 Results: []params.ErrorResult{ 312 {Error: apiservertesting.ServerError(fmt.Sprintf("duplicate ssh key: %s", key2))}, 313 {Error: nil}, 314 {Error: apiservertesting.ServerError("invalid ssh key id: invalid-key")}, 315 }, 316 }) 317 s.assertEnvironKeys(c, append(initialKeys, key3)) 318 } 319 320 func (s *keyManagerSuite) TestBlockImportKeys(c *gc.C) { 321 s.PatchValue(&keymanager.RunSSHImportId, keymanagertesting.FakeImport) 322 323 key1 := sshtesting.ValidKeyOne.Key + " user@host" 324 key2 := sshtesting.ValidKeyTwo.Key 325 initialKeys := []string{key1, key2, "bad key"} 326 s.setAuthorisedKeys(c, strings.Join(initialKeys, "\n")) 327 328 args := params.ModifyUserSSHKeys{ 329 User: s.AdminUserTag(c).Name(), 330 Keys: []string{"lp:existing", "lp:validuser", "invalid-key"}, 331 } 332 333 s.AssertConfigParameterUpdated(c, "block-all-changes", true) 334 _, err := s.keymanager.ImportKeys(args) 335 // Check that the call is blocked 336 c.Assert(errors.Cause(err), gc.ErrorMatches, common.ErrOperationBlocked.Error()) 337 s.assertEnvironKeys(c, initialKeys) 338 }