github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/worker/authenticationworker/worker_test.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package authenticationworker_test 5 6 import ( 7 "strings" 8 stdtesting "testing" 9 "time" 10 11 "github.com/juju/names" 12 jc "github.com/juju/testing/checkers" 13 gc "gopkg.in/check.v1" 14 15 "github.com/juju/juju/agent" 16 "github.com/juju/juju/api" 17 "github.com/juju/juju/api/keyupdater" 18 jujutesting "github.com/juju/juju/juju/testing" 19 "github.com/juju/juju/state" 20 coretesting "github.com/juju/juju/testing" 21 "github.com/juju/juju/utils/ssh" 22 sshtesting "github.com/juju/juju/utils/ssh/testing" 23 "github.com/juju/juju/worker" 24 "github.com/juju/juju/worker/authenticationworker" 25 ) 26 27 // worstCase is used for timeouts when timing out 28 // will fail the test. Raising this value should 29 // not affect the overall running time of the tests 30 // unless they fail. 31 const worstCase = 5 * time.Second 32 33 func TestAll(t *stdtesting.T) { 34 coretesting.MgoTestPackage(t) 35 } 36 37 var _ = gc.Suite(&workerSuite{}) 38 39 type workerSuite struct { 40 jujutesting.JujuConnSuite 41 stateMachine *state.Machine 42 machine *state.Machine 43 keyupdaterApi *keyupdater.State 44 45 existingEnvKey string 46 existingKeys []string 47 } 48 49 func (s *workerSuite) SetUpTest(c *gc.C) { 50 s.JujuConnSuite.SetUpTest(c) 51 // Default ssh user is currently "ubuntu". 52 c.Assert(authenticationworker.SSHUser, gc.Equals, "ubuntu") 53 // Set the ssh user to empty (the current user) as required by the test infrastructure. 54 s.PatchValue(&authenticationworker.SSHUser, "") 55 56 // Replace the default dummy key in the test environment with a valid one. 57 // This will be added to the ssh authorised keys when the agent starts. 58 s.setAuthorisedKeys(c, sshtesting.ValidKeyOne.Key+" firstuser@host") 59 // Record the existing key with its prefix for testing later. 60 s.existingEnvKey = sshtesting.ValidKeyOne.Key + " Juju:firstuser@host" 61 62 // Set up an existing key (which is not in the environment) in the ssh authorised_keys file. 63 s.existingKeys = []string{sshtesting.ValidKeyTwo.Key + " existinguser@host"} 64 err := ssh.AddKeys(authenticationworker.SSHUser, s.existingKeys...) 65 c.Assert(err, jc.ErrorIsNil) 66 67 var apiRoot *api.State 68 apiRoot, s.machine = s.OpenAPIAsNewMachine(c) 69 c.Assert(apiRoot, gc.NotNil) 70 s.keyupdaterApi = apiRoot.KeyUpdater() 71 c.Assert(s.keyupdaterApi, gc.NotNil) 72 } 73 74 func stop(c *gc.C, w worker.Worker) { 75 c.Assert(worker.Stop(w), gc.IsNil) 76 } 77 78 type mockConfig struct { 79 agent.Config 80 c *gc.C 81 tag names.Tag 82 } 83 84 func (mock *mockConfig) Tag() names.Tag { 85 return mock.tag 86 } 87 88 func agentConfig(c *gc.C, tag names.MachineTag) *mockConfig { 89 return &mockConfig{c: c, tag: tag} 90 } 91 92 func (s *workerSuite) setAuthorisedKeys(c *gc.C, keys ...string) { 93 keyStr := strings.Join(keys, "\n") 94 err := s.BackingState.UpdateEnvironConfig(map[string]interface{}{"authorized-keys": keyStr}, nil, nil) 95 c.Assert(err, jc.ErrorIsNil) 96 s.BackingState.StartSync() 97 } 98 99 func (s *workerSuite) waitSSHKeys(c *gc.C, expected []string) { 100 timeout := time.After(worstCase) 101 for { 102 select { 103 case <-timeout: 104 c.Fatalf("timeout while waiting for authoirsed ssh keys to change") 105 case <-time.After(coretesting.ShortWait): 106 keys, err := ssh.ListKeys(authenticationworker.SSHUser, ssh.FullKeys) 107 c.Assert(err, jc.ErrorIsNil) 108 keysStr := strings.Join(keys, "\n") 109 expectedStr := strings.Join(expected, "\n") 110 if expectedStr != keysStr { 111 continue 112 } 113 return 114 } 115 } 116 } 117 118 func (s *workerSuite) TestKeyUpdateRetainsExisting(c *gc.C) { 119 authWorker := authenticationworker.NewWorker(s.keyupdaterApi, agentConfig(c, s.machine.Tag().(names.MachineTag))) 120 defer stop(c, authWorker) 121 122 newKey := sshtesting.ValidKeyThree.Key + " user@host" 123 s.setAuthorisedKeys(c, newKey) 124 newKeyWithCommentPrefix := sshtesting.ValidKeyThree.Key + " Juju:user@host" 125 s.waitSSHKeys(c, append(s.existingKeys, newKeyWithCommentPrefix)) 126 } 127 128 func (s *workerSuite) TestNewKeysInJujuAreSavedOnStartup(c *gc.C) { 129 newKey := sshtesting.ValidKeyThree.Key + " user@host" 130 s.setAuthorisedKeys(c, newKey) 131 132 authWorker := authenticationworker.NewWorker(s.keyupdaterApi, agentConfig(c, s.machine.Tag().(names.MachineTag))) 133 defer stop(c, authWorker) 134 135 newKeyWithCommentPrefix := sshtesting.ValidKeyThree.Key + " Juju:user@host" 136 s.waitSSHKeys(c, append(s.existingKeys, newKeyWithCommentPrefix)) 137 } 138 139 func (s *workerSuite) TestDeleteKey(c *gc.C) { 140 authWorker := authenticationworker.NewWorker(s.keyupdaterApi, agentConfig(c, s.machine.Tag().(names.MachineTag))) 141 defer stop(c, authWorker) 142 143 // Add another key 144 anotherKey := sshtesting.ValidKeyThree.Key + " another@host" 145 s.setAuthorisedKeys(c, s.existingEnvKey, anotherKey) 146 anotherKeyWithCommentPrefix := sshtesting.ValidKeyThree.Key + " Juju:another@host" 147 s.waitSSHKeys(c, append(s.existingKeys, s.existingEnvKey, anotherKeyWithCommentPrefix)) 148 149 // Delete the original key and check anotherKey plus the existing keys remain. 150 s.setAuthorisedKeys(c, anotherKey) 151 s.waitSSHKeys(c, append(s.existingKeys, anotherKeyWithCommentPrefix)) 152 } 153 154 func (s *workerSuite) TestMultipleChanges(c *gc.C) { 155 authWorker := authenticationworker.NewWorker(s.keyupdaterApi, agentConfig(c, s.machine.Tag().(names.MachineTag))) 156 defer stop(c, authWorker) 157 s.waitSSHKeys(c, append(s.existingKeys, s.existingEnvKey)) 158 159 // Perform a set to add a key and delete a key. 160 // added: key 3 161 // deleted: key 1 (existing env key) 162 s.setAuthorisedKeys(c, sshtesting.ValidKeyThree.Key+" yetanother@host") 163 yetAnotherKeyWithComment := sshtesting.ValidKeyThree.Key + " Juju:yetanother@host" 164 s.waitSSHKeys(c, append(s.existingKeys, yetAnotherKeyWithComment)) 165 } 166 167 func (s *workerSuite) TestWorkerRestart(c *gc.C) { 168 authWorker := authenticationworker.NewWorker(s.keyupdaterApi, agentConfig(c, s.machine.Tag().(names.MachineTag))) 169 defer stop(c, authWorker) 170 s.waitSSHKeys(c, append(s.existingKeys, s.existingEnvKey)) 171 172 // Stop the worker and delete and add keys from the environment while it is down. 173 // added: key 3 174 // deleted: key 1 (existing env key) 175 stop(c, authWorker) 176 s.setAuthorisedKeys(c, sshtesting.ValidKeyThree.Key+" yetanother@host") 177 178 // Restart the worker and check that the ssh auth keys are as expected. 179 authWorker = authenticationworker.NewWorker(s.keyupdaterApi, agentConfig(c, s.machine.Tag().(names.MachineTag))) 180 defer stop(c, authWorker) 181 182 yetAnotherKeyWithCommentPrefix := sshtesting.ValidKeyThree.Key + " Juju:yetanother@host" 183 s.waitSSHKeys(c, append(s.existingKeys, yetAnotherKeyWithCommentPrefix)) 184 }