func (s *MachineSuite) TestMachineAgentRunsAuthorisedKeysWorker(c *gc.C) { // Start the machine agent. m, _, _ := s.primeAgent(c, version.Current, state.JobHostUnits) a := s.newAgent(c, m) go func() { c.Check(a.Run(nil), gc.IsNil) }() defer func() { c.Check(a.Stop(), gc.IsNil) }() // Update the keys in the environment. sshKey := sshtesting.ValidKeyOne.Key + " user@host" err := s.BackingState.UpdateEnvironConfig(map[string]interface{}{"authorized-keys": sshKey}, nil, nil) c.Assert(err, gc.IsNil) // Wait for ssh keys file to be updated. s.State.StartSync() timeout := time.After(coretesting.LongWait) sshKeyWithCommentPrefix := sshtesting.ValidKeyOne.Key + " Juju:user@host" for { select { case <-timeout: c.Fatalf("timeout while waiting for authorised ssh keys to change") case <-time.After(coretesting.ShortWait): keys, err := ssh.ListKeys(authenticationworker.SSHUser, ssh.FullKeys) c.Assert(err, gc.IsNil) keysStr := strings.Join(keys, "\n") if sshKeyWithCommentPrefix != keysStr { continue } return } } }
// SetUp is defined on the worker.NotifyWatchHandler interface. func (kw *keyupdaterWorker) SetUp() (watcher.NotifyWatcher, error) { // Record the keys Juju knows about. // TODO(dfc) jujuKeys, err := kw.st.AuthorisedKeys(kw.tag.String()) if err != nil { return nil, errors.LoggedErrorf(logger, "reading Juju ssh keys for %q: %v", kw.tag, err) } kw.jujuKeys = set.NewStrings(jujuKeys...) // Read the keys currently in ~/.ssh/authorised_keys. sshKeys, err := ssh.ListKeys(SSHUser, ssh.FullKeys) if err != nil { return nil, errors.LoggedErrorf(logger, "reading ssh authorized keys for %q: %v", kw.tag, err) } // Record any keys not added by Juju. for _, key := range sshKeys { _, comment, err := ssh.KeyFingerprint(key) // Also record keys which we cannot parse. if err != nil || !strings.HasPrefix(comment, ssh.JujuCommentPrefix) { kw.nonJujuKeys = append(kw.nonJujuKeys, key) } } // Write out the ssh authorised keys file to match the current state of the world. if err := kw.writeSSHKeys(jujuKeys); err != nil { return nil, errors.LoggedErrorf(logger, "adding current Juju keys to ssh authorised keys: %v", err) } w, err := kw.st.WatchAuthorisedKeys(kw.tag.String()) if err != nil { return nil, errors.LoggedErrorf(logger, "starting key updater worker: %v", err) } logger.Infof("%q key updater worker started", kw.tag) return w, nil }
func (s *AuthorisedKeysKeysSuite) TestAddNewKey(c *gc.C) { key := sshtesting.ValidKeyOne.Key + " user@host" err := ssh.AddKeys(testSSHUser, key) c.Assert(err, gc.IsNil) actual, err := ssh.ListKeys(testSSHUser, ssh.FullKeys) c.Assert(err, gc.IsNil) c.Assert(actual, gc.DeepEquals, []string{key}) }
func (s *AuthorisedKeysKeysSuite) TestListKeysFull(c *gc.C) { keys := []string{ sshtesting.ValidKeyOne.Key + " user@host", sshtesting.ValidKeyTwo.Key + " anotheruser@host", } writeAuthKeysFile(c, keys) actual, err := ssh.ListKeys(testSSHUser, ssh.FullKeys) c.Assert(err, gc.IsNil) c.Assert(actual, gc.DeepEquals, keys) }
func (s *AuthorisedKeysKeysSuite) TestDeleteKeys(c *gc.C) { firstKey := sshtesting.ValidKeyOne.Key + " user@host" anotherKey := sshtesting.ValidKeyTwo.Key thirdKey := sshtesting.ValidKeyThree.Key + " anotheruser@host" writeAuthKeysFile(c, []string{firstKey, anotherKey, thirdKey}) err := ssh.DeleteKeys(testSSHUser, "user@host", sshtesting.ValidKeyTwo.Fingerprint) c.Assert(err, gc.IsNil) actual, err := ssh.ListKeys(testSSHUser, ssh.FullKeys) c.Assert(err, gc.IsNil) c.Assert(actual, gc.DeepEquals, []string{thirdKey}) }
func (s *AuthorisedKeysKeysSuite) TestListKeys(c *gc.C) { keys := []string{ sshtesting.ValidKeyOne.Key + " user@host", sshtesting.ValidKeyTwo.Key, } writeAuthKeysFile(c, keys) keys, err := ssh.ListKeys(testSSHUser, ssh.Fingerprints) c.Assert(err, gc.IsNil) c.Assert( keys, gc.DeepEquals, []string{sshtesting.ValidKeyOne.Fingerprint + " (user@host)", sshtesting.ValidKeyTwo.Fingerprint}) }
func (s *AuthorisedKeysKeysSuite) TestAddMoreKeys(c *gc.C) { firstKey := sshtesting.ValidKeyOne.Key + " user@host" writeAuthKeysFile(c, []string{firstKey}) moreKeys := []string{ sshtesting.ValidKeyTwo.Key + " anotheruser@host", sshtesting.ValidKeyThree.Key + " yetanotheruser@host", } err := ssh.AddKeys(testSSHUser, moreKeys...) c.Assert(err, gc.IsNil) actual, err := ssh.ListKeys(testSSHUser, ssh.FullKeys) c.Assert(err, gc.IsNil) c.Assert(actual, gc.DeepEquals, append([]string{firstKey}, moreKeys...)) }
func (s *AuthorisedKeysKeysSuite) TestReplaceKeys(c *gc.C) { firstKey := sshtesting.ValidKeyOne.Key + " user@host" anotherKey := sshtesting.ValidKeyTwo.Key writeAuthKeysFile(c, []string{firstKey, anotherKey}) // replaceKey is created without a comment so test that // ReplaceKeys handles keys without comments. This is // because existing keys may not have a comment and // ReplaceKeys is used to rewrite the entire authorized_keys // file when adding new keys. replaceKey := sshtesting.ValidKeyThree.Key err := ssh.ReplaceKeys(testSSHUser, replaceKey) c.Assert(err, gc.IsNil) actual, err := ssh.ListKeys(testSSHUser, ssh.FullKeys) c.Assert(err, gc.IsNil) c.Assert(actual, gc.DeepEquals, []string{replaceKey}) }
func (s *workerSuite) waitSSHKeys(c *gc.C, expected []string) { timeout := time.After(worstCase) for { select { case <-timeout: c.Fatalf("timeout while waiting for authoirsed ssh keys to change") case <-time.After(coretesting.ShortWait): keys, err := ssh.ListKeys(authenticationworker.SSHUser, ssh.FullKeys) c.Assert(err, gc.IsNil) keysStr := strings.Join(keys, "\n") expectedStr := strings.Join(expected, "\n") if expectedStr != keysStr { continue } return } } }