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