github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/client/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  	"fmt"
     8  	"strings"
     9  
    10  	jc "github.com/juju/testing/checkers"
    11  	"github.com/juju/utils/ssh"
    12  	sshtesting "github.com/juju/utils/ssh/testing"
    13  	gc "gopkg.in/check.v1"
    14  	"gopkg.in/juju/names.v2"
    15  
    16  	"github.com/juju/juju/apiserver/common"
    17  	commontesting "github.com/juju/juju/apiserver/common/testing"
    18  	"github.com/juju/juju/apiserver/facades/client/keymanager"
    19  	keymanagertesting "github.com/juju/juju/apiserver/facades/client/keymanager/testing"
    20  	"github.com/juju/juju/apiserver/params"
    21  	apiservertesting "github.com/juju/juju/apiserver/testing"
    22  	jujutesting "github.com/juju/juju/juju/testing"
    23  	"github.com/juju/juju/state"
    24  	"github.com/juju/juju/testing/factory"
    25  )
    26  
    27  type keyManagerSuite struct {
    28  	jujutesting.JujuConnSuite
    29  
    30  	keymanager *keymanager.KeyManagerAPI
    31  	resources  *common.Resources
    32  	authoriser apiservertesting.FakeAuthorizer
    33  
    34  	commontesting.BlockHelper
    35  }
    36  
    37  var _ = gc.Suite(&keyManagerSuite{})
    38  
    39  func (s *keyManagerSuite) SetUpTest(c *gc.C) {
    40  	s.JujuConnSuite.SetUpTest(c)
    41  	s.resources = common.NewResources()
    42  	s.AddCleanup(func(_ *gc.C) { s.resources.StopAll() })
    43  
    44  	s.authoriser = apiservertesting.FakeAuthorizer{
    45  		Tag: s.AdminUserTag(c),
    46  	}
    47  	var err error
    48  	s.keymanager, err = keymanager.NewKeyManagerAPI(s.State, s.resources, s.authoriser)
    49  	c.Assert(err, jc.ErrorIsNil)
    50  
    51  	s.BlockHelper = commontesting.NewBlockHelper(s.APIState)
    52  	s.AddCleanup(func(*gc.C) { s.BlockHelper.Close() })
    53  }
    54  
    55  func (s *keyManagerSuite) TestNewKeyManagerAPIAcceptsClient(c *gc.C) {
    56  	endPoint, err := keymanager.NewKeyManagerAPI(s.State, s.resources, s.authoriser)
    57  	c.Assert(err, jc.ErrorIsNil)
    58  	c.Assert(endPoint, gc.NotNil)
    59  }
    60  
    61  func (s *keyManagerSuite) TestNewKeyManagerAPIRefusesController(c *gc.C) {
    62  	s.testNewKeyManagerAPIRefuses(c, names.NewMachineTag("0"), true)
    63  }
    64  
    65  func (s *keyManagerSuite) TestNewKeyManagerAPIRefusesUnit(c *gc.C) {
    66  	s.testNewKeyManagerAPIRefuses(c, names.NewUnitTag("mysql/0"), false)
    67  }
    68  
    69  func (s *keyManagerSuite) TestNewKeyManagerAPIRefusesMachine(c *gc.C) {
    70  	s.testNewKeyManagerAPIRefuses(c, names.NewMachineTag("99"), false)
    71  }
    72  
    73  func (s *keyManagerSuite) testNewKeyManagerAPIRefuses(c *gc.C, tag names.Tag, controller bool) {
    74  	auth := apiservertesting.FakeAuthorizer{
    75  		Tag:        tag,
    76  		Controller: controller,
    77  	}
    78  	endPoint, err := keymanager.NewKeyManagerAPI(s.State, s.resources, auth)
    79  	c.Assert(endPoint, gc.IsNil)
    80  	c.Assert(err, gc.ErrorMatches, "permission denied")
    81  }
    82  
    83  func (s *keyManagerSuite) setAuthorisedKeys(c *gc.C, keys string) {
    84  	s.setAuthorisedKeysForModel(c, s.State, keys)
    85  }
    86  
    87  func (s *keyManagerSuite) setAuthorisedKeysForModel(c *gc.C, st *state.State, keys string) {
    88  	m, err := st.Model()
    89  	c.Assert(err, jc.ErrorIsNil)
    90  
    91  	err = m.UpdateModelConfig(map[string]interface{}{"authorized-keys": keys}, nil)
    92  	c.Assert(err, jc.ErrorIsNil)
    93  
    94  	modelConfig, err := m.ModelConfig()
    95  	c.Assert(err, jc.ErrorIsNil)
    96  	c.Assert(modelConfig.AuthorizedKeys(), gc.Equals, keys)
    97  }
    98  
    99  func (s *keyManagerSuite) TestListKeys(c *gc.C) {
   100  	key1 := sshtesting.ValidKeyOne.Key + " user@host"
   101  	key2 := sshtesting.ValidKeyTwo.Key
   102  	s.setAuthorisedKeys(c, strings.Join([]string{key1, key2, "bad key"}, "\n"))
   103  
   104  	args := params.ListSSHKeys{
   105  		Entities: params.Entities{[]params.Entity{
   106  			{Tag: s.AdminUserTag(c).Name()},
   107  			{Tag: "invalid"},
   108  		}},
   109  		Mode: ssh.FullKeys,
   110  	}
   111  	results, err := s.keymanager.ListKeys(args)
   112  	c.Assert(err, jc.ErrorIsNil)
   113  	c.Assert(results, gc.DeepEquals, params.StringsResults{
   114  		Results: []params.StringsResult{
   115  			{Result: []string{key1, key2, "Invalid key: bad key"}},
   116  			{Result: []string{key1, key2, "Invalid key: bad key"}},
   117  		},
   118  	})
   119  }
   120  
   121  func (s *keyManagerSuite) TestListKeysHidesJujuInternal(c *gc.C) {
   122  	key1 := sshtesting.ValidKeyOne.Key + " juju-client-key"
   123  	key2 := sshtesting.ValidKeyTwo.Key + " juju-system-key"
   124  	s.setAuthorisedKeys(c, strings.Join([]string{key1, key2}, "\n"))
   125  
   126  	args := params.ListSSHKeys{
   127  		Entities: params.Entities{[]params.Entity{
   128  			{Tag: s.AdminUserTag(c).Name()},
   129  		}},
   130  		Mode: ssh.FullKeys,
   131  	}
   132  	results, err := s.keymanager.ListKeys(args)
   133  	c.Assert(err, jc.ErrorIsNil)
   134  	c.Assert(results, gc.DeepEquals, params.StringsResults{
   135  		Results: []params.StringsResult{
   136  			{Result: nil},
   137  		},
   138  	})
   139  }
   140  
   141  func (s *keyManagerSuite) TestListJujuSystemKey(c *gc.C) {
   142  	anAuthoriser := s.authoriser
   143  	anAuthoriser.Tag = names.NewUserTag("fred")
   144  	var err error
   145  	s.keymanager, err = keymanager.NewKeyManagerAPI(s.State, s.resources, anAuthoriser)
   146  	c.Assert(err, jc.ErrorIsNil)
   147  	key1 := sshtesting.ValidKeyOne.Key
   148  	s.setAuthorisedKeys(c, key1)
   149  
   150  	args := params.ListSSHKeys{
   151  		Entities: params.Entities{[]params.Entity{
   152  			{Tag: "juju-system-key"},
   153  		}},
   154  		Mode: ssh.FullKeys,
   155  	}
   156  	results, err := s.keymanager.ListKeys(args)
   157  	c.Assert(err, jc.ErrorIsNil)
   158  	c.Assert(results.Results, gc.HasLen, 1)
   159  	c.Assert(results.Results[0].Error, gc.ErrorMatches, "permission denied")
   160  }
   161  
   162  func (s *keyManagerSuite) assertModelKeys(c *gc.C, expected []string) {
   163  	s.assertKeysForModel(c, s.State, expected)
   164  }
   165  
   166  func (s *keyManagerSuite) assertKeysForModel(c *gc.C, st *state.State, expected []string) {
   167  	m, err := st.Model()
   168  	c.Assert(err, jc.ErrorIsNil)
   169  
   170  	modelConfig, err := m.ModelConfig()
   171  	c.Assert(err, jc.ErrorIsNil)
   172  	keys := modelConfig.AuthorizedKeys()
   173  	c.Assert(keys, gc.Equals, strings.Join(expected, "\n"))
   174  }
   175  
   176  func (s *keyManagerSuite) assertAddKeys(c *gc.C, st *state.State, apiUser names.UserTag, ok bool) {
   177  	key1 := sshtesting.ValidKeyOne.Key + " user@host"
   178  	key2 := sshtesting.ValidKeyTwo.Key
   179  	initialKeys := []string{key1, key2, "bad key"}
   180  	s.setAuthorisedKeysForModel(c, st, strings.Join(initialKeys, "\n"))
   181  
   182  	anAuthoriser := s.authoriser
   183  	anAuthoriser.Tag = apiUser
   184  	var err error
   185  	s.keymanager, err = keymanager.NewKeyManagerAPI(st, s.resources, anAuthoriser)
   186  	c.Assert(err, jc.ErrorIsNil)
   187  
   188  	newKey := sshtesting.ValidKeyThree.Key + " newuser@host"
   189  	args := params.ModifyUserSSHKeys{
   190  		User: s.AdminUserTag(c).Name(),
   191  		Keys: []string{key2, newKey, "invalid-key"},
   192  	}
   193  	results, err := s.keymanager.AddKeys(args)
   194  	if !ok {
   195  		c.Assert(err, gc.ErrorMatches, "permission denied")
   196  		c.Assert(params.ErrCode(err), gc.Equals, params.CodeUnauthorized)
   197  		return
   198  	}
   199  	c.Assert(err, jc.ErrorIsNil)
   200  
   201  	c.Assert(results, gc.DeepEquals, params.ErrorResults{
   202  		Results: []params.ErrorResult{
   203  			{Error: apiservertesting.ServerError(fmt.Sprintf("duplicate ssh key: %s", key2))},
   204  			{Error: nil},
   205  			{Error: apiservertesting.ServerError("invalid ssh key: invalid-key")},
   206  		},
   207  	})
   208  	s.assertKeysForModel(c, st, append(initialKeys, newKey))
   209  }
   210  
   211  func (s *keyManagerSuite) TestAddKeys(c *gc.C) {
   212  	s.assertAddKeys(c, s.State, s.AdminUserTag(c), true)
   213  }
   214  
   215  func (s *keyManagerSuite) TestAddKeysSuperUser(c *gc.C) {
   216  	user := s.Factory.MakeUser(c, &factory.UserParams{Name: "superuser-fred", NoModelUser: true})
   217  	s.assertAddKeys(c, s.State, user.UserTag(), true)
   218  }
   219  
   220  func (s *keyManagerSuite) TestAddKeysModelAdmin(c *gc.C) {
   221  	otherState := s.Factory.MakeModel(c, nil)
   222  	defer otherState.Close()
   223  
   224  	otherModel, err := otherState.Model()
   225  	c.Assert(err, jc.ErrorIsNil)
   226  
   227  	user := s.Factory.MakeUser(c, &factory.UserParams{Name: "admin" + otherModel.ModelTag().String()})
   228  	s.assertAddKeys(c, otherState, user.UserTag(), true)
   229  }
   230  
   231  func (s *keyManagerSuite) TestAddKeysNonAuthorised(c *gc.C) {
   232  	user := s.Factory.MakeUser(c, nil)
   233  	s.assertAddKeys(c, s.State, user.UserTag(), false)
   234  }
   235  
   236  func (s *keyManagerSuite) TestBlockAddKeys(c *gc.C) {
   237  	key1 := sshtesting.ValidKeyOne.Key + " user@host"
   238  	key2 := sshtesting.ValidKeyTwo.Key
   239  	initialKeys := []string{key1, key2, "bad key"}
   240  	s.setAuthorisedKeys(c, strings.Join(initialKeys, "\n"))
   241  
   242  	newKey := sshtesting.ValidKeyThree.Key + " newuser@host"
   243  	args := params.ModifyUserSSHKeys{
   244  		User: s.AdminUserTag(c).Name(),
   245  		Keys: []string{key2, newKey, "invalid-key"},
   246  	}
   247  
   248  	s.BlockAllChanges(c, "TestBlockAddKeys")
   249  	_, err := s.keymanager.AddKeys(args)
   250  	// Check that the call is blocked
   251  	s.AssertBlocked(c, err, "TestBlockAddKeys")
   252  	s.assertModelKeys(c, initialKeys)
   253  }
   254  
   255  func (s *keyManagerSuite) TestAddJujuSystemKey(c *gc.C) {
   256  	anAuthoriser := s.authoriser
   257  	anAuthoriser.Tag = names.NewUserTag("fred")
   258  	var err error
   259  	s.keymanager, err = keymanager.NewKeyManagerAPI(s.State, s.resources, anAuthoriser)
   260  	c.Assert(err, jc.ErrorIsNil)
   261  	key1 := sshtesting.ValidKeyOne.Key
   262  	s.setAuthorisedKeys(c, key1)
   263  
   264  	newKey := sshtesting.ValidKeyThree.Key + " juju-system-key"
   265  	args := params.ModifyUserSSHKeys{
   266  		User: "juju-system-key",
   267  		Keys: []string{newKey},
   268  	}
   269  	_, err = s.keymanager.AddKeys(args)
   270  	c.Assert(err, gc.ErrorMatches, "permission denied")
   271  	c.Assert(params.ErrCode(err), gc.Equals, params.CodeUnauthorized)
   272  	s.assertModelKeys(c, []string{key1})
   273  }
   274  
   275  func (s *keyManagerSuite) assertDeleteKeys(c *gc.C, st *state.State, apiUser names.UserTag, ok bool) {
   276  	anAuthoriser := s.authoriser
   277  	anAuthoriser.Tag = apiUser
   278  	var err error
   279  	s.keymanager, err = keymanager.NewKeyManagerAPI(st, s.resources, anAuthoriser)
   280  	c.Assert(err, jc.ErrorIsNil)
   281  
   282  	key1 := sshtesting.ValidKeyOne.Key + " user@host"
   283  	key2 := sshtesting.ValidKeyTwo.Key
   284  	initialKeys := []string{key1, key2, "bad key"}
   285  	s.setAuthorisedKeysForModel(c, st, strings.Join(initialKeys, "\n"))
   286  
   287  	args := params.ModifyUserSSHKeys{
   288  		User: s.AdminUserTag(c).Name(),
   289  		Keys: []string{sshtesting.ValidKeyTwo.Fingerprint, sshtesting.ValidKeyThree.Fingerprint, "invalid-key"},
   290  	}
   291  	results, err := s.keymanager.DeleteKeys(args)
   292  	if !ok {
   293  		c.Assert(err, gc.ErrorMatches, "permission denied")
   294  		c.Assert(params.ErrCode(err), gc.Equals, params.CodeUnauthorized)
   295  		return
   296  	}
   297  	c.Assert(err, jc.ErrorIsNil)
   298  	c.Assert(results, gc.DeepEquals, params.ErrorResults{
   299  		Results: []params.ErrorResult{
   300  			{Error: nil},
   301  			{Error: apiservertesting.ServerError("invalid ssh key: " + sshtesting.ValidKeyThree.Fingerprint)},
   302  			{Error: apiservertesting.ServerError("invalid ssh key: invalid-key")},
   303  		},
   304  	})
   305  	s.assertKeysForModel(c, st, []string{key1, "bad key"})
   306  }
   307  
   308  func (s *keyManagerSuite) TestDeleteKeys(c *gc.C) {
   309  	s.assertDeleteKeys(c, s.State, s.AdminUserTag(c), true)
   310  }
   311  
   312  func (s *keyManagerSuite) TestDeleteKeysSuperUser(c *gc.C) {
   313  	user := s.Factory.MakeUser(c, &factory.UserParams{Name: "superuser-fred", NoModelUser: true})
   314  	s.assertDeleteKeys(c, s.State, user.UserTag(), true)
   315  }
   316  
   317  func (s *keyManagerSuite) TestDeleteKeysModelAdmin(c *gc.C) {
   318  	otherState := s.Factory.MakeModel(c, nil)
   319  	defer otherState.Close()
   320  
   321  	otherModel, err := otherState.Model()
   322  	c.Assert(err, jc.ErrorIsNil)
   323  
   324  	user := s.Factory.MakeUser(c, &factory.UserParams{Name: "admin" + otherModel.ModelTag().String()})
   325  	s.assertDeleteKeys(c, otherState, user.UserTag(), true)
   326  }
   327  
   328  func (s *keyManagerSuite) TestDeleteKeysNonAuthorised(c *gc.C) {
   329  	user := s.Factory.MakeUser(c, nil)
   330  	s.assertDeleteKeys(c, s.State, user.UserTag(), false)
   331  }
   332  
   333  func (s *keyManagerSuite) TestDeleteKeysNotJujuInternal(c *gc.C) {
   334  	key1 := sshtesting.ValidKeyOne.Key + " juju-client-key"
   335  	key2 := sshtesting.ValidKeyTwo.Key + " juju-system-key"
   336  	key3 := sshtesting.ValidKeyThree.Key + " a user key"
   337  	initialKeys := []string{key1, key2, key3}
   338  	s.setAuthorisedKeys(c, strings.Join(initialKeys, "\n"))
   339  
   340  	args := params.ModifyUserSSHKeys{
   341  		User: s.AdminUserTag(c).Name(),
   342  		Keys: []string{"juju-client-key", "juju-system-key"},
   343  	}
   344  	results, err := s.keymanager.DeleteKeys(args)
   345  	c.Check(results, gc.DeepEquals, params.ErrorResults{
   346  		Results: []params.ErrorResult{
   347  			{Error: apiservertesting.ServerError("may not delete internal key: juju-client-key")},
   348  			{Error: apiservertesting.ServerError("may not delete internal key: juju-system-key")},
   349  		},
   350  	})
   351  	c.Assert(err, jc.ErrorIsNil)
   352  	s.assertModelKeys(c, initialKeys)
   353  }
   354  
   355  func (s *keyManagerSuite) TestBlockDeleteKeys(c *gc.C) {
   356  	key1 := sshtesting.ValidKeyOne.Key + " user@host"
   357  	key2 := sshtesting.ValidKeyTwo.Key
   358  	initialKeys := []string{key1, key2, "bad key"}
   359  	s.setAuthorisedKeys(c, strings.Join(initialKeys, "\n"))
   360  
   361  	args := params.ModifyUserSSHKeys{
   362  		User: s.AdminUserTag(c).Name(),
   363  		Keys: []string{sshtesting.ValidKeyTwo.Fingerprint, sshtesting.ValidKeyThree.Fingerprint, "invalid-key"},
   364  	}
   365  
   366  	s.BlockAllChanges(c, "TestBlockDeleteKeys")
   367  	_, err := s.keymanager.DeleteKeys(args)
   368  	// Check that the call is blocked
   369  	s.AssertBlocked(c, err, "TestBlockDeleteKeys")
   370  	s.assertModelKeys(c, initialKeys)
   371  }
   372  
   373  func (s *keyManagerSuite) TestCannotDeleteAllKeys(c *gc.C) {
   374  	key1 := sshtesting.ValidKeyOne.Key + " user@host"
   375  	key2 := sshtesting.ValidKeyTwo.Key
   376  	initialKeys := []string{key1, key2}
   377  	s.setAuthorisedKeys(c, strings.Join(initialKeys, "\n"))
   378  
   379  	args := params.ModifyUserSSHKeys{
   380  		User: s.AdminUserTag(c).Name(),
   381  		Keys: []string{sshtesting.ValidKeyTwo.Fingerprint, "user@host"},
   382  	}
   383  	_, err := s.keymanager.DeleteKeys(args)
   384  	c.Assert(err, gc.ErrorMatches, "cannot delete all keys")
   385  	s.assertModelKeys(c, initialKeys)
   386  }
   387  
   388  func (s *keyManagerSuite) assertInvalidUserOperation(c *gc.C, runTestLogic func(args params.ModifyUserSSHKeys) error) {
   389  	initialKey := sshtesting.ValidKeyOne.Key + " user@host"
   390  	s.setAuthorisedKeys(c, initialKey)
   391  
   392  	// Set up the params.
   393  	newKey := sshtesting.ValidKeyThree.Key + " newuser@host"
   394  	args := params.ModifyUserSSHKeys{
   395  		User: "invalid",
   396  		Keys: []string{newKey},
   397  	}
   398  	// Run the required test code and check the error.
   399  	err := runTestLogic(args)
   400  	c.Assert(err, gc.DeepEquals, apiservertesting.ErrUnauthorized)
   401  
   402  	// No model changes.
   403  	s.assertModelKeys(c, []string{initialKey})
   404  }
   405  
   406  func (s *keyManagerSuite) TestAddKeysInvalidUser(c *gc.C) {
   407  	c.Skip("no user validation done yet")
   408  	s.assertInvalidUserOperation(c, func(args params.ModifyUserSSHKeys) error {
   409  		_, err := s.keymanager.AddKeys(args)
   410  		return err
   411  	})
   412  }
   413  
   414  func (s *keyManagerSuite) TestDeleteKeysInvalidUser(c *gc.C) {
   415  	c.Skip("no user validation done yet")
   416  	s.assertInvalidUserOperation(c, func(args params.ModifyUserSSHKeys) error {
   417  		_, err := s.keymanager.DeleteKeys(args)
   418  		return err
   419  	})
   420  }
   421  
   422  func (s *keyManagerSuite) assertImportKeys(c *gc.C, st *state.State, apiUser names.UserTag, ok bool) {
   423  	s.PatchValue(&keymanager.RunSSHImportId, keymanagertesting.FakeImport)
   424  
   425  	key1 := sshtesting.ValidKeyOne.Key + " user@host"
   426  	key2 := sshtesting.ValidKeyTwo.Key
   427  	key3 := sshtesting.ValidKeyThree.Key
   428  	key4 := sshtesting.ValidKeyFour.Key
   429  	keymv := strings.Split(sshtesting.ValidKeyMulti, "\n")
   430  	keymp := strings.Split(sshtesting.PartValidKeyMulti, "\n")
   431  	keymi := strings.Split(sshtesting.MultiInvalid, "\n")
   432  	initialKeys := []string{key1, key2, "bad key"}
   433  	s.setAuthorisedKeysForModel(c, st, strings.Join(initialKeys, "\n"))
   434  
   435  	args := params.ModifyUserSSHKeys{
   436  		User: s.AdminUserTag(c).Name(),
   437  		Keys: []string{
   438  			"lp:existing",
   439  			"lp:validuser",
   440  			"invalid-key",
   441  			"lp:multi",
   442  			"lp:multiempty",
   443  			"lp:multipartial",
   444  			"lp:multiinvalid",
   445  			"lp:multionedup",
   446  		},
   447  	}
   448  
   449  	anAuthoriser := s.authoriser
   450  	anAuthoriser.Tag = apiUser
   451  	var err error
   452  	s.keymanager, err = keymanager.NewKeyManagerAPI(st, s.resources, anAuthoriser)
   453  	c.Assert(err, jc.ErrorIsNil)
   454  
   455  	results, err := s.keymanager.ImportKeys(args)
   456  	if !ok {
   457  		c.Assert(err, gc.ErrorMatches, "permission denied")
   458  		c.Assert(params.ErrCode(err), gc.Equals, params.CodeUnauthorized)
   459  		return
   460  	}
   461  	c.Assert(err, jc.ErrorIsNil)
   462  
   463  	c.Assert(results.Results, gc.HasLen, 8)
   464  	c.Assert(results, gc.DeepEquals, params.ErrorResults{
   465  		Results: []params.ErrorResult{
   466  			{Error: apiservertesting.ServerError(fmt.Sprintf("duplicate ssh key: %s", key2))},
   467  			{Error: nil},
   468  			{Error: apiservertesting.ServerError("invalid ssh key id: invalid-key")},
   469  			{Error: nil},
   470  			{Error: apiservertesting.ServerError("invalid ssh key id: lp:multiempty")},
   471  			{Error: apiservertesting.ServerError(fmt.Sprintf(
   472  				`invalid ssh key for lp:multipartial: `+
   473  					`generating key fingerprint: `+
   474  					`invalid authorized_key "%s"`, keymp[1]))},
   475  			{Error: apiservertesting.ServerError(fmt.Sprintf(
   476  				`invalid ssh key for lp:multiinvalid: `+
   477  					`generating key fingerprint: `+
   478  					`invalid authorized_key "%s"`+"\n"+
   479  					`invalid ssh key for lp:multiinvalid: `+
   480  					`generating key fingerprint: `+
   481  					`invalid authorized_key "%s"`, keymi[0], keymi[1]))},
   482  			{Error: apiservertesting.ServerError(fmt.Sprintf("duplicate ssh key: %s", key2))},
   483  		},
   484  	})
   485  	s.assertKeysForModel(c, st, append(initialKeys, key3, keymv[0], keymv[1], keymp[0], key4))
   486  }
   487  
   488  func (s *keyManagerSuite) TestImportKeys(c *gc.C) {
   489  	s.assertImportKeys(c, s.State, s.AdminUserTag(c), true)
   490  }
   491  
   492  func (s *keyManagerSuite) TestImportKeysSuperUser(c *gc.C) {
   493  	user := s.Factory.MakeUser(c, &factory.UserParams{Name: "superuser-fred", NoModelUser: true})
   494  	s.assertImportKeys(c, s.State, user.UserTag(), true)
   495  }
   496  
   497  func (s *keyManagerSuite) TestImportKeysModelAdmin(c *gc.C) {
   498  	otherState := s.Factory.MakeModel(c, nil)
   499  	defer otherState.Close()
   500  
   501  	otherModel, err := otherState.Model()
   502  	c.Assert(err, jc.ErrorIsNil)
   503  
   504  	user := s.Factory.MakeUser(c, &factory.UserParams{Name: "admin" + otherModel.ModelTag().String()})
   505  	s.assertImportKeys(c, otherState, user.UserTag(), true)
   506  }
   507  
   508  func (s *keyManagerSuite) TestImportKeysNonAuthorised(c *gc.C) {
   509  	user := s.Factory.MakeUser(c, nil)
   510  	s.assertImportKeys(c, s.State, user.UserTag(), false)
   511  }
   512  
   513  func (s *keyManagerSuite) TestBlockImportKeys(c *gc.C) {
   514  	s.PatchValue(&keymanager.RunSSHImportId, keymanagertesting.FakeImport)
   515  
   516  	key1 := sshtesting.ValidKeyOne.Key + " user@host"
   517  	key2 := sshtesting.ValidKeyTwo.Key
   518  	initialKeys := []string{key1, key2, "bad key"}
   519  	s.setAuthorisedKeys(c, strings.Join(initialKeys, "\n"))
   520  
   521  	args := params.ModifyUserSSHKeys{
   522  		User: s.AdminUserTag(c).Name(),
   523  		Keys: []string{"lp:existing", "lp:validuser", "invalid-key"},
   524  	}
   525  
   526  	s.BlockAllChanges(c, "TestBlockImportKeys")
   527  	_, err := s.keymanager.ImportKeys(args)
   528  	// Check that the call is blocked
   529  	s.AssertBlocked(c, err, "TestBlockImportKeys")
   530  	s.assertModelKeys(c, initialKeys)
   531  }