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