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