1
// Copyright 2012, 2013 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
10
jc "github.com/juju/testing/checkers"
11
gc "gopkg.in/check.v1"
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"
23
type AuthorizedKeysSuite struct {
24
coretesting.FakeJujuHomeSuite
27
var _ = gc.Suite(&AuthorizedKeysSuite{})
29
var authKeysCommandNames = []string{
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")
43
subcommandsFound := false
44
for _, line := range lines {
45
f := strings.Fields(line)
46
if len(f) == 1 && f[0] == "commands:" {
47
subcommandsFound = true
50
if !subcommandsFound || len(f) == 0 || !strings.HasPrefix(line, " ") {
53
names = append(names, f[0])
55
// The names should be output in alphabetical order, so don't sort.
56
c.Assert(names, gc.DeepEquals, authKeysCommandNames)
59
func (s *AuthorizedKeysSuite) assertHelpOutput(c *gc.C, cmd, args string) {
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)
69
func (s *AuthorizedKeysSuite) TestHelpList(c *gc.C) {
70
s.assertHelpOutput(c, "list", "")
73
func (s *AuthorizedKeysSuite) TestHelpAdd(c *gc.C) {
74
s.assertHelpOutput(c, "add", "<ssh key> [...]")
77
func (s *AuthorizedKeysSuite) TestHelpDelete(c *gc.C) {
78
s.assertHelpOutput(c, "delete", "<ssh key id> [...]")
81
func (s *AuthorizedKeysSuite) TestHelpImport(c *gc.C) {
82
s.assertHelpOutput(c, "import", "<ssh key id> [...]")
85
type keySuiteBase struct {
86
jujutesting.JujuConnSuite
90
func (s *keySuiteBase) SetUpSuite(c *gc.C) {
91
s.JujuConnSuite.SetUpSuite(c)
92
s.PatchEnvironment(osenv.JujuEnvEnvKey, "dummyenv")
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() })
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)
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"))
118
type ListKeysSuite struct {
122
var _ = gc.Suite(&ListKeysSuite{})
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)
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\\)")
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)
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")
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"})
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\\)")
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"\]`)
166
type AddKeySuite struct {
170
var _ = gc.Suite(&AddKeySuite{})
172
func (s *AddKeySuite) TestAddKey(c *gc.C) {
173
key1 := sshtesting.ValidKeyOne.Key + " user@host"
174
s.setAuthorizedKeys(c, key1)
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)
183
func (s *AddKeySuite) TestBlockAddKey(c *gc.C) {
184
key1 := sshtesting.ValidKeyOne.Key + " user@host"
185
s.setAuthorizedKeys(c, key1)
187
key2 := sshtesting.ValidKeyTwo.Key + " another@host"
189
s.BlockAllChanges(c, "TestBlockAddKey")
190
_, err := coretesting.RunCommand(c, envcmd.Wrap(&AddKeysCommand{}), key2, "invalid-key")
191
s.AssertBlocked(c, err, ".*TestBlockAddKey.*")
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"})
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)
206
type DeleteKeySuite struct {
210
var _ = gc.Suite(&DeleteKeySuite{})
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)
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)
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)
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.*")
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"})
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)
249
type ImportKeySuite struct {
253
var _ = gc.Suite(&ImportKeySuite{})
255
func (s *ImportKeySuite) SetUpTest(c *gc.C) {
256
s.keySuiteBase.SetUpTest(c)
257
s.PatchValue(&keymanagerserver.RunSSHImportId, keymanagertesting.FakeImport)
260
func (s *ImportKeySuite) TestImportKeys(c *gc.C) {
261
key1 := sshtesting.ValidKeyOne.Key + " user@host"
262
s.setAuthorizedKeys(c, key1)
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)
270
func (s *ImportKeySuite) TestBlockImportKeys(c *gc.C) {
271
key1 := sshtesting.ValidKeyOne.Key + " user@host"
272
s.setAuthorizedKeys(c, key1)
275
s.BlockAllChanges(c, "TestBlockImportKeys")
276
_, err := coretesting.RunCommand(c, envcmd.Wrap(&ImportKeysCommand{}), "lp:validuser", "invalid-key")
277
s.AssertBlocked(c, err, ".*TestBlockImportKeys.*")
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"})
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)