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