launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/state/apiserver/keymanager/keymanager_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package keymanager_test
     5  
     6  import (
     7  	"strings"
     8  
     9  	gc "launchpad.net/gocheck"
    10  
    11  	"fmt"
    12  	jujutesting "launchpad.net/juju-core/juju/testing"
    13  	"launchpad.net/juju-core/state/api/params"
    14  	"launchpad.net/juju-core/state/apiserver/common"
    15  	"launchpad.net/juju-core/state/apiserver/keymanager"
    16  	keymanagertesting "launchpad.net/juju-core/state/apiserver/keymanager/testing"
    17  	apiservertesting "launchpad.net/juju-core/state/apiserver/testing"
    18  	statetesting "launchpad.net/juju-core/state/testing"
    19  	"launchpad.net/juju-core/utils/ssh"
    20  	sshtesting "launchpad.net/juju-core/utils/ssh/testing"
    21  )
    22  
    23  type keyManagerSuite struct {
    24  	jujutesting.JujuConnSuite
    25  
    26  	keymanager *keymanager.KeyManagerAPI
    27  	resources  *common.Resources
    28  	authoriser apiservertesting.FakeAuthorizer
    29  }
    30  
    31  var _ = gc.Suite(&keyManagerSuite{})
    32  
    33  func (s *keyManagerSuite) SetUpTest(c *gc.C) {
    34  	s.JujuConnSuite.SetUpTest(c)
    35  	s.resources = common.NewResources()
    36  	s.AddCleanup(func(_ *gc.C) { s.resources.StopAll() })
    37  
    38  	s.authoriser = apiservertesting.FakeAuthorizer{
    39  		Tag:      "user-admin",
    40  		LoggedIn: true,
    41  		Client:   true,
    42  	}
    43  	var err error
    44  	s.keymanager, err = keymanager.NewKeyManagerAPI(s.State, s.resources, s.authoriser)
    45  	c.Assert(err, gc.IsNil)
    46  }
    47  
    48  func (s *keyManagerSuite) TestNewKeyManagerAPIAcceptsClient(c *gc.C) {
    49  	endPoint, err := keymanager.NewKeyManagerAPI(s.State, s.resources, s.authoriser)
    50  	c.Assert(err, gc.IsNil)
    51  	c.Assert(endPoint, gc.NotNil)
    52  }
    53  
    54  func (s *keyManagerSuite) TestNewKeyManagerAPIRefusesNonClient(c *gc.C) {
    55  	anAuthoriser := s.authoriser
    56  	anAuthoriser.Client = false
    57  	endPoint, err := keymanager.NewKeyManagerAPI(s.State, s.resources, anAuthoriser)
    58  	c.Assert(endPoint, gc.IsNil)
    59  	c.Assert(err, gc.ErrorMatches, "permission denied")
    60  }
    61  
    62  func (s *keyManagerSuite) setAuthorisedKeys(c *gc.C, keys string) {
    63  	err := statetesting.UpdateConfig(s.State, map[string]interface{}{"authorized-keys": keys})
    64  	c.Assert(err, gc.IsNil)
    65  	envConfig, err := s.State.EnvironConfig()
    66  	c.Assert(err, gc.IsNil)
    67  	c.Assert(envConfig.AuthorizedKeys(), gc.Equals, keys)
    68  }
    69  
    70  func (s *keyManagerSuite) TestListKeys(c *gc.C) {
    71  	key1 := sshtesting.ValidKeyOne.Key + " user@host"
    72  	key2 := sshtesting.ValidKeyTwo.Key
    73  	s.setAuthorisedKeys(c, strings.Join([]string{key1, key2, "bad key"}, "\n"))
    74  
    75  	args := params.ListSSHKeys{
    76  		Entities: params.Entities{[]params.Entity{
    77  			{Tag: "admin"},
    78  			{Tag: "invalid"},
    79  		}},
    80  		Mode: ssh.FullKeys,
    81  	}
    82  	results, err := s.keymanager.ListKeys(args)
    83  	c.Assert(err, gc.IsNil)
    84  	c.Assert(results, gc.DeepEquals, params.StringsResults{
    85  		Results: []params.StringsResult{
    86  			{Result: []string{key1, key2, "Invalid key: bad key"}},
    87  			{Error: apiservertesting.ErrUnauthorized},
    88  		},
    89  	})
    90  }
    91  
    92  func (s *keyManagerSuite) assertEnvironKeys(c *gc.C, expected []string) {
    93  	envConfig, err := s.State.EnvironConfig()
    94  	c.Assert(err, gc.IsNil)
    95  	keys := envConfig.AuthorizedKeys()
    96  	c.Assert(keys, gc.Equals, strings.Join(expected, "\n"))
    97  }
    98  
    99  func (s *keyManagerSuite) TestAddKeys(c *gc.C) {
   100  	key1 := sshtesting.ValidKeyOne.Key + " user@host"
   101  	key2 := sshtesting.ValidKeyTwo.Key
   102  	initialKeys := []string{key1, key2, "bad key"}
   103  	s.setAuthorisedKeys(c, strings.Join(initialKeys, "\n"))
   104  
   105  	newKey := sshtesting.ValidKeyThree.Key + " newuser@host"
   106  	args := params.ModifyUserSSHKeys{
   107  		User: "admin",
   108  		Keys: []string{key2, newKey, "invalid-key"},
   109  	}
   110  	results, err := s.keymanager.AddKeys(args)
   111  	c.Assert(err, gc.IsNil)
   112  	c.Assert(results, gc.DeepEquals, params.ErrorResults{
   113  		Results: []params.ErrorResult{
   114  			{Error: apiservertesting.ServerError(fmt.Sprintf("duplicate ssh key: %s", key2))},
   115  			{Error: nil},
   116  			{Error: apiservertesting.ServerError("invalid ssh key: invalid-key")},
   117  		},
   118  	})
   119  	s.assertEnvironKeys(c, append(initialKeys, newKey))
   120  }
   121  
   122  func (s *keyManagerSuite) TestDeleteKeys(c *gc.C) {
   123  	key1 := sshtesting.ValidKeyOne.Key + " user@host"
   124  	key2 := sshtesting.ValidKeyTwo.Key
   125  	initialKeys := []string{key1, key2, "bad key"}
   126  	s.setAuthorisedKeys(c, strings.Join(initialKeys, "\n"))
   127  
   128  	args := params.ModifyUserSSHKeys{
   129  		User: "admin",
   130  		Keys: []string{sshtesting.ValidKeyTwo.Fingerprint, sshtesting.ValidKeyThree.Fingerprint, "invalid-key"},
   131  	}
   132  	results, err := s.keymanager.DeleteKeys(args)
   133  	c.Assert(err, gc.IsNil)
   134  	c.Assert(results, gc.DeepEquals, params.ErrorResults{
   135  		Results: []params.ErrorResult{
   136  			{Error: nil},
   137  			{Error: apiservertesting.ServerError("invalid ssh key: " + sshtesting.ValidKeyThree.Fingerprint)},
   138  			{Error: apiservertesting.ServerError("invalid ssh key: invalid-key")},
   139  		},
   140  	})
   141  	s.assertEnvironKeys(c, []string{"bad key", key1})
   142  }
   143  
   144  func (s *keyManagerSuite) TestCannotDeleteAllKeys(c *gc.C) {
   145  	key1 := sshtesting.ValidKeyOne.Key + " user@host"
   146  	key2 := sshtesting.ValidKeyTwo.Key
   147  	initialKeys := []string{key1, key2}
   148  	s.setAuthorisedKeys(c, strings.Join(initialKeys, "\n"))
   149  
   150  	args := params.ModifyUserSSHKeys{
   151  		User: "admin",
   152  		Keys: []string{sshtesting.ValidKeyTwo.Fingerprint, "user@host"},
   153  	}
   154  	_, err := s.keymanager.DeleteKeys(args)
   155  	c.Assert(err, gc.ErrorMatches, "cannot delete all keys")
   156  	s.assertEnvironKeys(c, initialKeys)
   157  }
   158  
   159  func (s *keyManagerSuite) assertInvalidUserOperation(c *gc.C, runTestLogic func(args params.ModifyUserSSHKeys) error) {
   160  	initialKey := sshtesting.ValidKeyOne.Key + " user@host"
   161  	s.setAuthorisedKeys(c, initialKey)
   162  
   163  	// Set up the params.
   164  	newKey := sshtesting.ValidKeyThree.Key + " newuser@host"
   165  	args := params.ModifyUserSSHKeys{
   166  		User: "invalid",
   167  		Keys: []string{newKey},
   168  	}
   169  	// Run the required test code and check the error.
   170  	err := runTestLogic(args)
   171  	c.Assert(err, gc.DeepEquals, apiservertesting.ErrUnauthorized)
   172  
   173  	// No environ changes.
   174  	s.assertEnvironKeys(c, []string{initialKey})
   175  }
   176  
   177  func (s *keyManagerSuite) TestAddKeysInvalidUser(c *gc.C) {
   178  	s.assertInvalidUserOperation(c, func(args params.ModifyUserSSHKeys) error {
   179  		_, err := s.keymanager.AddKeys(args)
   180  		return err
   181  	})
   182  }
   183  
   184  func (s *keyManagerSuite) TestDeleteKeysInvalidUser(c *gc.C) {
   185  	s.assertInvalidUserOperation(c, func(args params.ModifyUserSSHKeys) error {
   186  		_, err := s.keymanager.DeleteKeys(args)
   187  		return err
   188  	})
   189  }
   190  
   191  func (s *keyManagerSuite) TestImportKeys(c *gc.C) {
   192  	s.PatchValue(&keymanager.RunSSHImportId, keymanagertesting.FakeImport)
   193  
   194  	key1 := sshtesting.ValidKeyOne.Key + " user@host"
   195  	key2 := sshtesting.ValidKeyTwo.Key
   196  	key3 := sshtesting.ValidKeyThree.Key
   197  	initialKeys := []string{key1, key2, "bad key"}
   198  	s.setAuthorisedKeys(c, strings.Join(initialKeys, "\n"))
   199  
   200  	args := params.ModifyUserSSHKeys{
   201  		User: "admin",
   202  		Keys: []string{"lp:existing", "lp:validuser", "invalid-key"},
   203  	}
   204  	results, err := s.keymanager.ImportKeys(args)
   205  	c.Assert(err, gc.IsNil)
   206  	c.Assert(results, gc.DeepEquals, params.ErrorResults{
   207  		Results: []params.ErrorResult{
   208  			{Error: apiservertesting.ServerError(fmt.Sprintf("duplicate ssh key: %s", key2))},
   209  			{Error: nil},
   210  			{Error: apiservertesting.ServerError("invalid ssh key id: invalid-key")},
   211  		},
   212  	})
   213  	s.assertEnvironKeys(c, append(initialKeys, key3))
   214  }
   215  
   216  func (s *keyManagerSuite) TestCallSSHImportId(c *gc.C) {
   217  	c.Skip("the landing bot does not run ssh-import-id successfully")
   218  	output, err := keymanager.RunSSHImportId("lp:wallyworld")
   219  	c.Assert(err, gc.IsNil)
   220  	lines := strings.Split(output, "\n")
   221  	var key string
   222  	for _, line := range lines {
   223  		if !strings.HasPrefix(line, "ssh-") {
   224  			continue
   225  		}
   226  		_, _, err := ssh.KeyFingerprint(line)
   227  		if err == nil {
   228  			key = line
   229  		}
   230  	}
   231  	c.Assert(key, gc.Not(gc.Equals), "")
   232  }