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  }