def _register_public_key_file_with_ssh_server(self, ssh_client_container_config, ssh_client_container_home_directory, ssh_host_config, host_is_container): """ This function assumes that the ssh client container has a public key file in its ssh_client_container_home_directory. It copies that file to the ssh_server and adds the public key into the authorized keys file. It also adds the ssh_server to the known hosts file on the client machine. The server can be a container or a normal machine in the network. """ ssh_server_machine_id = ssh_host_config.machine_id ssh_server_host_connection = self.connections.get_connection(ssh_server_machine_id) repository_machine_ssh_dir = ssh_host_config.ssh_dir container_name = ssh_client_container_config.container_name container_host_connection = self._get_container_host_connection(container_name) # COPY AND REGISTER THE PUBLIC KEY WITH repositoryMachine public_key_file = _get_public_key_filename(container_name) source_file = ssh_client_container_home_directory.joinpath(public_key_file) target_file = repository_machine_ssh_dir.joinpath(public_key_file) ssh_port = 22 if host_is_container: print('----- Grant container ' + container_name + ' SSH access to container ' + ssh_host_config.container_conf.container_name + ' on machine ' + ssh_server_machine_id) ssh_port = ssh_host_config.container_ssh_port dockerutil.container_to_container_copy(container_host_connection, ssh_client_container_config, ssh_server_host_connection, ssh_host_config.container_conf, source_file, target_file) else: print('----- Grant container ' + container_name + ' SSH access to machine ' + ssh_server_machine_id) dockerutil.containertorcopy(container_host_connection, ssh_client_container_config, ssh_server_host_connection, source_file, target_file) # add the key file to authorized_keys authorized_keys_file = repository_machine_ssh_dir.joinpath('authorized_keys') # Remove previously appended public keys from the given container and append the # new public key to the authorized_keys file. # - print file without lines containing machine name string, then append new key to end of file command = ( 'cat {0} | grep -v {1} >> {2}/keys_temp &&' 'mv -f {2}/keys_temp {0} &&' 'cat {2}/{3} >> {0}' ).format( authorized_keys_file, container_name, repository_machine_ssh_dir, public_key_file) if host_is_container: dockerutil.run_command_in_container(ssh_server_host_connection, ssh_host_config.container_conf, command) else: ssh_server_host_connection.run_command(command) # Add the repository machine as known host to prevent the authentication request on the first run _accept_remote_container_host_key( container_host_connection, ssh_client_container_config, ssh_server_host_connection.info.host_name, ssh_port, ssh_server_host_connection.info.user_name )
def _add_known_ssh_host(client_container_host_connection, client_container_config, ssh_host_name, ssh_port): """ Uses the ssh-keyscan command to add the public key of an ssh server to the known_hosts file of the given container. """ known_hosts_file = PurePosixPath('~/.ssh/known_hosts') dockerutil.run_command_in_container( client_container_host_connection, client_container_config, 'ssh-keyscan -p {0} {1} >> {2}'.format(ssh_port, ssh_host_name, known_hosts_file) )
def _grant_jenkins_master_ssh_access_to_jenkins_windows_slave(self, slave_host_connection ): master_config = self.config.jenkins_master_host_config.container_conf master_container = master_config.container_name print(("----- Grant {0} ssh access to {1}").format(master_container, slave_host_connection.info.host_name)) # configure the script for adding an authorized key to the bitwise ssh server on the # windows machine authorized_keys_script = 'updateAuthorizedKeys.bat' full_authorized_keys_script = _SCRIPT_DIR.joinpath(authorized_keys_script) master_connection = self._get_jenkins_master_host_connection() public_key_file_master = config_data.JENKINS_HOME_JENKINS_MASTER_CONTAINER.joinpath('.ssh/' + _get_public_key_filename(master_container) ) public_key = dockerutil.run_command_in_container( master_connection, master_config, 'cat {0}'.format(public_key_file_master) )[0] configure_file(str(full_authorized_keys_script) + '.in', full_authorized_keys_script, { '@PUBLIC_KEY@' : public_key, '@JENKINS_MASTER_CONTAINER@' : master_container, '@SLAVE_MACHINE_USER@' : slave_host_connection.info.user_name, }) # copy the script to the windows slave machine ssh_dir = PureWindowsPath('C:/Users/' + slave_host_connection.info.user_name + '/.ssh') full_script_path_on_slave = ssh_dir.joinpath(full_authorized_keys_script.name) slave_host_connection.sftp_client.put(str(full_authorized_keys_script), str(full_script_path_on_slave)) # call the script try: call_script_command = '{0} {1}'.format(full_script_path_on_slave, slave_host_connection.info.user_password) slave_host_connection.run_command(call_script_command, print_command=True) except Exception as err: print( "Error: Updating the authorized ssh keys on " + slave_host_connection.info.host_name + " failed. Was the password correct?") raise err # clean up the generated script because of the included password os.remove(str(full_authorized_keys_script)) # Wait a little until the bitvise ssh server is ready to accept the key file. # This can possibly fail on slower machines. time.sleep(1) # Add the slave to the known hosts try: _accept_remote_container_host_key( master_connection, master_config, slave_host_connection.info.host_name, 22, slave_host_connection.info.user_name ) except Exception as err: # This is not really clean but I can not think of a better solution now. print("When this call fails, it is possible that the waiting time before using the ssh connection to the Bitvise SSH server is too short.") raise err
def _create_rsa_key_file_pair_on_container(connection, container_conf, container_home_directory): # copy the scripts that does the job to the container dockerutil.copy_textfile_to_container( connection, container_conf, _SCRIPT_DIR.joinpath(_CREATEKEYPAIR_SCRIPT), container_home_directory.joinpath(_CREATEKEYPAIR_SCRIPT) ) # This will create the key-pair on the container. # We need to do this in the container or ssh will not accept the private key file. dockerutil.run_command_in_container( connection, container_conf, '/bin/bash ' + str(container_home_directory.joinpath(_CREATEKEYPAIR_SCRIPT)) + ' ' + container_conf.container_name )
def _grant_container_access_to_https_repositories(self, container_conf, container_home_directory, https_repository_host_config): """ This function adds the credentials of the given https based repository accesses to the git credential store of that container. """ container_name = container_conf.container_name container_host_connection = self._get_container_host_connection(container_name) # Add the credentials for the repository to the jenkins-git-credentials file. credential_file = container_home_directory.joinpath(_GIT_CREDENTIALS_STORE) command = 'echo https://{0}:{1}@{2} >> {3}'.format( https_repository_host_config.user_name, https_repository_host_config.user_password, https_repository_host_config.host_name, credential_file ) dockerutil.run_command_in_container( container_host_connection, container_conf, command )