github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/cmd/juju/commands/authorizedkeys_test.go (about) 1 // Copyright 2012, 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package commands 5 6 import ( 7 "fmt" 8 "strings" 9 10 jc "github.com/juju/testing/checkers" 11 gc "gopkg.in/check.v1" 12 13 keymanagerserver "github.com/juju/juju/apiserver/keymanager" 14 keymanagertesting "github.com/juju/juju/apiserver/keymanager/testing" 15 "github.com/juju/juju/cmd/envcmd" 16 "github.com/juju/juju/juju/osenv" 17 jujutesting "github.com/juju/juju/juju/testing" 18 coretesting "github.com/juju/juju/testing" 19 "github.com/juju/juju/testing/factory" 20 sshtesting "github.com/juju/juju/utils/ssh/testing" 21 ) 22 23 type AuthorizedKeysSuite struct { 24 coretesting.FakeJujuHomeSuite 25 } 26 27 var _ = gc.Suite(&AuthorizedKeysSuite{}) 28 29 var authKeysCommandNames = []string{ 30 "add", 31 "delete", 32 "help", 33 "import", 34 "list", 35 } 36 37 func (s *AuthorizedKeysSuite) TestHelpCommands(c *gc.C) { 38 // Check that we have correctly registered all the sub commands 39 // by checking the help output. 40 out := badrun(c, 0, "authorized-keys", "--help") 41 lines := strings.Split(out, "\n") 42 var names []string 43 subcommandsFound := false 44 for _, line := range lines { 45 f := strings.Fields(line) 46 if len(f) == 1 && f[0] == "commands:" { 47 subcommandsFound = true 48 continue 49 } 50 if !subcommandsFound || len(f) == 0 || !strings.HasPrefix(line, " ") { 51 continue 52 } 53 names = append(names, f[0]) 54 } 55 // The names should be output in alphabetical order, so don't sort. 56 c.Assert(names, gc.DeepEquals, authKeysCommandNames) 57 } 58 59 func (s *AuthorizedKeysSuite) assertHelpOutput(c *gc.C, cmd, args string) { 60 if args != "" { 61 args = " " + args 62 } 63 expected := fmt.Sprintf("usage: juju authorized-keys %s [options]%s", cmd, args) 64 out := badrun(c, 0, "authorized-keys", cmd, "--help") 65 lines := strings.Split(out, "\n") 66 c.Assert(lines[0], gc.Equals, expected) 67 } 68 69 func (s *AuthorizedKeysSuite) TestHelpList(c *gc.C) { 70 s.assertHelpOutput(c, "list", "") 71 } 72 73 func (s *AuthorizedKeysSuite) TestHelpAdd(c *gc.C) { 74 s.assertHelpOutput(c, "add", "<ssh key> [...]") 75 } 76 77 func (s *AuthorizedKeysSuite) TestHelpDelete(c *gc.C) { 78 s.assertHelpOutput(c, "delete", "<ssh key id> [...]") 79 } 80 81 func (s *AuthorizedKeysSuite) TestHelpImport(c *gc.C) { 82 s.assertHelpOutput(c, "import", "<ssh key id> [...]") 83 } 84 85 type keySuiteBase struct { 86 jujutesting.JujuConnSuite 87 CmdBlockHelper 88 } 89 90 func (s *keySuiteBase) SetUpSuite(c *gc.C) { 91 s.JujuConnSuite.SetUpSuite(c) 92 s.PatchEnvironment(osenv.JujuEnvEnvKey, "dummyenv") 93 } 94 95 func (s *keySuiteBase) SetUpTest(c *gc.C) { 96 s.JujuConnSuite.SetUpTest(c) 97 s.CmdBlockHelper = NewCmdBlockHelper(s.APIState) 98 c.Assert(s.CmdBlockHelper, gc.NotNil) 99 s.AddCleanup(func(*gc.C) { s.CmdBlockHelper.Close() }) 100 } 101 102 func (s *keySuiteBase) setAuthorizedKeys(c *gc.C, keys ...string) { 103 keyString := strings.Join(keys, "\n") 104 err := s.State.UpdateEnvironConfig(map[string]interface{}{"authorized-keys": keyString}, nil, nil) 105 c.Assert(err, jc.ErrorIsNil) 106 envConfig, err := s.State.EnvironConfig() 107 c.Assert(err, jc.ErrorIsNil) 108 c.Assert(envConfig.AuthorizedKeys(), gc.Equals, keyString) 109 } 110 111 func (s *keySuiteBase) assertEnvironKeys(c *gc.C, expected ...string) { 112 envConfig, err := s.State.EnvironConfig() 113 c.Assert(err, jc.ErrorIsNil) 114 keys := envConfig.AuthorizedKeys() 115 c.Assert(keys, gc.Equals, strings.Join(expected, "\n")) 116 } 117 118 type ListKeysSuite struct { 119 keySuiteBase 120 } 121 122 var _ = gc.Suite(&ListKeysSuite{}) 123 124 func (s *ListKeysSuite) TestListKeys(c *gc.C) { 125 key1 := sshtesting.ValidKeyOne.Key + " user@host" 126 key2 := sshtesting.ValidKeyTwo.Key + " another@host" 127 s.setAuthorizedKeys(c, key1, key2) 128 129 context, err := coretesting.RunCommand(c, envcmd.Wrap(&ListKeysCommand{})) 130 c.Assert(err, jc.ErrorIsNil) 131 output := strings.TrimSpace(coretesting.Stdout(context)) 132 c.Assert(err, jc.ErrorIsNil) 133 c.Assert(output, gc.Matches, "Keys for user admin:\n.*\\(user@host\\)\n.*\\(another@host\\)") 134 } 135 136 func (s *ListKeysSuite) TestListFullKeys(c *gc.C) { 137 key1 := sshtesting.ValidKeyOne.Key + " user@host" 138 key2 := sshtesting.ValidKeyTwo.Key + " another@host" 139 s.setAuthorizedKeys(c, key1, key2) 140 141 context, err := coretesting.RunCommand(c, envcmd.Wrap(&ListKeysCommand{}), "--full") 142 c.Assert(err, jc.ErrorIsNil) 143 output := strings.TrimSpace(coretesting.Stdout(context)) 144 c.Assert(err, jc.ErrorIsNil) 145 c.Assert(output, gc.Matches, "Keys for user admin:\n.*user@host\n.*another@host") 146 } 147 148 func (s *ListKeysSuite) TestListKeysNonDefaultUser(c *gc.C) { 149 key1 := sshtesting.ValidKeyOne.Key + " user@host" 150 key2 := sshtesting.ValidKeyTwo.Key + " another@host" 151 s.setAuthorizedKeys(c, key1, key2) 152 s.Factory.MakeUser(c, &factory.UserParams{Name: "fred"}) 153 154 context, err := coretesting.RunCommand(c, envcmd.Wrap(&ListKeysCommand{}), "--user", "fred") 155 c.Assert(err, jc.ErrorIsNil) 156 output := strings.TrimSpace(coretesting.Stdout(context)) 157 c.Assert(err, jc.ErrorIsNil) 158 c.Assert(output, gc.Matches, "Keys for user fred:\n.*\\(user@host\\)\n.*\\(another@host\\)") 159 } 160 161 func (s *ListKeysSuite) TestTooManyArgs(c *gc.C) { 162 _, err := coretesting.RunCommand(c, envcmd.Wrap(&ListKeysCommand{}), "foo") 163 c.Assert(err, gc.ErrorMatches, `unrecognized args: \["foo"\]`) 164 } 165 166 type AddKeySuite struct { 167 keySuiteBase 168 } 169 170 var _ = gc.Suite(&AddKeySuite{}) 171 172 func (s *AddKeySuite) TestAddKey(c *gc.C) { 173 key1 := sshtesting.ValidKeyOne.Key + " user@host" 174 s.setAuthorizedKeys(c, key1) 175 176 key2 := sshtesting.ValidKeyTwo.Key + " another@host" 177 context, err := coretesting.RunCommand(c, envcmd.Wrap(&AddKeysCommand{}), key2, "invalid-key") 178 c.Assert(err, jc.ErrorIsNil) 179 c.Assert(coretesting.Stderr(context), gc.Matches, `cannot add key "invalid-key".*\n`) 180 s.assertEnvironKeys(c, key1, key2) 181 } 182 183 func (s *AddKeySuite) TestBlockAddKey(c *gc.C) { 184 key1 := sshtesting.ValidKeyOne.Key + " user@host" 185 s.setAuthorizedKeys(c, key1) 186 187 key2 := sshtesting.ValidKeyTwo.Key + " another@host" 188 // Block operation 189 s.BlockAllChanges(c, "TestBlockAddKey") 190 _, err := coretesting.RunCommand(c, envcmd.Wrap(&AddKeysCommand{}), key2, "invalid-key") 191 s.AssertBlocked(c, err, ".*TestBlockAddKey.*") 192 } 193 194 func (s *AddKeySuite) TestAddKeyNonDefaultUser(c *gc.C) { 195 key1 := sshtesting.ValidKeyOne.Key + " user@host" 196 s.setAuthorizedKeys(c, key1) 197 s.Factory.MakeUser(c, &factory.UserParams{Name: "fred"}) 198 199 key2 := sshtesting.ValidKeyTwo.Key + " another@host" 200 context, err := coretesting.RunCommand(c, envcmd.Wrap(&AddKeysCommand{}), "--user", "fred", key2) 201 c.Assert(err, jc.ErrorIsNil) 202 c.Assert(coretesting.Stderr(context), gc.Equals, "") 203 s.assertEnvironKeys(c, key1, key2) 204 } 205 206 type DeleteKeySuite struct { 207 keySuiteBase 208 } 209 210 var _ = gc.Suite(&DeleteKeySuite{}) 211 212 func (s *DeleteKeySuite) TestDeleteKeys(c *gc.C) { 213 key1 := sshtesting.ValidKeyOne.Key + " user@host" 214 key2 := sshtesting.ValidKeyTwo.Key + " another@host" 215 s.setAuthorizedKeys(c, key1, key2) 216 217 context, err := coretesting.RunCommand(c, envcmd.Wrap(&DeleteKeysCommand{}), 218 sshtesting.ValidKeyTwo.Fingerprint, "invalid-key") 219 c.Assert(err, jc.ErrorIsNil) 220 c.Assert(coretesting.Stderr(context), gc.Matches, `cannot delete key id "invalid-key".*\n`) 221 s.assertEnvironKeys(c, key1) 222 } 223 224 func (s *DeleteKeySuite) TestBlockDeleteKeys(c *gc.C) { 225 key1 := sshtesting.ValidKeyOne.Key + " user@host" 226 key2 := sshtesting.ValidKeyTwo.Key + " another@host" 227 s.setAuthorizedKeys(c, key1, key2) 228 229 // Block operation 230 s.BlockAllChanges(c, "TestBlockDeleteKeys") 231 _, err := coretesting.RunCommand(c, envcmd.Wrap(&DeleteKeysCommand{}), 232 sshtesting.ValidKeyTwo.Fingerprint, "invalid-key") 233 s.AssertBlocked(c, err, ".*TestBlockDeleteKeys.*") 234 } 235 236 func (s *DeleteKeySuite) TestDeleteKeyNonDefaultUser(c *gc.C) { 237 key1 := sshtesting.ValidKeyOne.Key + " user@host" 238 key2 := sshtesting.ValidKeyTwo.Key + " another@host" 239 s.setAuthorizedKeys(c, key1, key2) 240 s.Factory.MakeUser(c, &factory.UserParams{Name: "fred"}) 241 242 context, err := coretesting.RunCommand(c, envcmd.Wrap(&DeleteKeysCommand{}), 243 "--user", "fred", sshtesting.ValidKeyTwo.Fingerprint) 244 c.Assert(err, jc.ErrorIsNil) 245 c.Assert(coretesting.Stderr(context), gc.Equals, "") 246 s.assertEnvironKeys(c, key1) 247 } 248 249 type ImportKeySuite struct { 250 keySuiteBase 251 } 252 253 var _ = gc.Suite(&ImportKeySuite{}) 254 255 func (s *ImportKeySuite) SetUpTest(c *gc.C) { 256 s.keySuiteBase.SetUpTest(c) 257 s.PatchValue(&keymanagerserver.RunSSHImportId, keymanagertesting.FakeImport) 258 } 259 260 func (s *ImportKeySuite) TestImportKeys(c *gc.C) { 261 key1 := sshtesting.ValidKeyOne.Key + " user@host" 262 s.setAuthorizedKeys(c, key1) 263 264 context, err := coretesting.RunCommand(c, envcmd.Wrap(&ImportKeysCommand{}), "lp:validuser", "invalid-key") 265 c.Assert(err, jc.ErrorIsNil) 266 c.Assert(coretesting.Stderr(context), gc.Matches, `cannot import key id "invalid-key".*\n`) 267 s.assertEnvironKeys(c, key1, sshtesting.ValidKeyThree.Key) 268 } 269 270 func (s *ImportKeySuite) TestBlockImportKeys(c *gc.C) { 271 key1 := sshtesting.ValidKeyOne.Key + " user@host" 272 s.setAuthorizedKeys(c, key1) 273 274 // Block operation 275 s.BlockAllChanges(c, "TestBlockImportKeys") 276 _, err := coretesting.RunCommand(c, envcmd.Wrap(&ImportKeysCommand{}), "lp:validuser", "invalid-key") 277 s.AssertBlocked(c, err, ".*TestBlockImportKeys.*") 278 } 279 280 func (s *ImportKeySuite) TestImportKeyNonDefaultUser(c *gc.C) { 281 key1 := sshtesting.ValidKeyOne.Key + " user@host" 282 s.setAuthorizedKeys(c, key1) 283 s.Factory.MakeUser(c, &factory.UserParams{Name: "fred"}) 284 285 context, err := coretesting.RunCommand(c, envcmd.Wrap(&ImportKeysCommand{}), "--user", "fred", "lp:validuser") 286 c.Assert(err, jc.ErrorIsNil) 287 c.Assert(coretesting.Stderr(context), gc.Equals, "") 288 s.assertEnvironKeys(c, key1, sshtesting.ValidKeyThree.Key) 289 }