func ensureSystemSSHKey(context Context) error { identityFile := context.AgentConfig().SystemIdentityPath() // Don't generate a key unless we have to. keyExists, err := systemKeyExists(identityFile) if err != nil { return fmt.Errorf("failed to check system key exists: %v", err) } if keyExists { return nil } privateKey, publicKey, err := ssh.GenerateKey(config.JujuSystemKey) if err != nil { return fmt.Errorf("failed to create system key: %v", err) } // Write new authorised key. keyManager := keymanager.NewClient(context.APIState()) errResults, err := keyManager.AddKeys(config.JujuSystemKey, publicKey) apiErr := err if apiErr == nil { apiErr = errResults[0].Error } if err != nil || errResults[0].Error != nil { return fmt.Errorf("failed to update authoised keys with new system key: %v", apiErr) } return ioutil.WriteFile(identityFile, []byte(privateKey), 0600) }
// NewKeyManagerClient returns a keymanager client for the root api endpoint // that the environment command returns. func (c *SSHKeysBase) NewKeyManagerClient() (*keymanager.Client, error) { root, err := c.NewAPIRoot() if err != nil { return nil, err } return keymanager.NewClient(root), nil }
func updateAuthorizedKeys(context Context, publicKey string) error { // Look for an existing authorized key. logger.Infof("setting new authorized key for %q", publicKey) keyManager := keymanager.NewClient(context.APIState()) result, err := keyManager.ListKeys(ssh.FullKeys, config.JujuSystemKey) if err != nil { return errors.Trace(err) } if result[0].Error != nil { return errors.Trace(result[0].Error) } keys := result[0].Result // Loop through the keys. If we find a key that matches the publicKey // then we are good, and done. If the comment on the key is for the system identity // but it is not the same, remove it. var keysToRemove []string for _, key := range keys { // The list of keys returned don't have carriage returns, but the // publicKey does, so add one one before testing for equality. if (key + "\n") == publicKey { logger.Infof("system identity key already in authorized list") return nil } fingerprint, comment, err := ssh.KeyFingerprint(key) if err != nil { // Log the error, but it doesn't stop us doing what we need to do. logger.Errorf("bad key in authorized keys: %v", err) } else if comment == config.JujuSystemKey { keysToRemove = append(keysToRemove, fingerprint) } } if keysToRemove != nil { logger.Infof("removing %d keys", len(keysToRemove)) results, err := keyManager.DeleteKeys(config.JujuSystemKey, keysToRemove...) if err != nil { // Log the error but continue. logger.Errorf("failed to remove keys: %v", err) } else { for _, err := range results { if err.Error != nil { // Log the error but continue. logger.Errorf("failed to remove key: %v", err.Error) } } } } errResults, err := keyManager.AddKeys(config.JujuSystemKey, publicKey) if err != nil { return errors.Annotate(err, "failed to update authorised keys with new system key") } if err := errResults[0].Error; err != nil { return errors.Annotate(err, "failed to update authorised keys with new system key") } return nil }
func (s *keymanagerSuite) TestAddSystemKeyWrongUser(c *gc.C) { key1 := sshtesting.ValidKeyOne.Key + " user@host" s.setAuthorisedKeys(c, key1) apiState, _ := s.OpenAPIAsNewMachine(c, state.JobManageEnviron) keyManager := keymanager.NewClient(apiState) defer keyManager.Close() newKey := sshtesting.ValidKeyTwo.Key _, err := keyManager.AddKeys("some-user", newKey) c.Assert(err, gc.ErrorMatches, "permission denied") s.assertEnvironKeys(c, []string{key1}) }
func (s *keymanagerSuite) TestAddSystemKey(c *gc.C) { key1 := sshtesting.ValidKeyOne.Key + " user@host" s.setAuthorisedKeys(c, key1) apiState, _ := s.OpenAPIAsNewMachine(c, state.JobManageModel) keyManager := keymanager.NewClient(apiState) defer keyManager.Close() newKey := sshtesting.ValidKeyTwo.Key errResults, err := keyManager.AddKeys("juju-system-key", newKey) c.Assert(err, jc.ErrorIsNil) c.Assert(errResults, gc.DeepEquals, []params.ErrorResult{ {Error: nil}, }) s.assertModelKeys(c, []string{key1, newKey}) }
func (s *keymanagerSuite) TestAddSystemKeyWrongUser(c *gc.C) { key1 := sshtesting.ValidKeyOne.Key + " user@host" s.setAuthorisedKeys(c, key1) apiState, _ := s.OpenAPIAsNewMachine(c, state.JobManageModel) keyManager := keymanager.NewClient(apiState) defer keyManager.Close() newKey := sshtesting.ValidKeyTwo.Key _, err := keyManager.AddKeys("some-user", newKey) c.Assert(errors.Cause(err), gc.DeepEquals, &rpc.RequestError{ Message: "permission denied", Code: "unauthorized access", }) s.assertModelKeys(c, []string{key1}) }
func (s *keymanagerSuite) SetUpTest(c *gc.C) { s.JujuConnSuite.SetUpTest(c) s.keymanager = keymanager.NewClient(s.APIState) c.Assert(s.keymanager, gc.NotNil) }