def __get_ssh_credentials(self): try: f = open(self.ssh_credentials, 'r') data = f.readlines() f.close() except IOError as ex: self.error_logger.error('Could not access credential file. IOError: %s' % ex) return None, None username, password = None, None for line in data: if 'username:'******':') if len(toks) < 2: self.logger.error('Username was None') raise paramiko.AuthenticationException('Username not found.') username = toks[1].strip() elif 'password' in line: toks = line.split(':') if len(toks) < 2: self.logger.error('Password was None') raise paramiko.AuthenticationException('Password not found.') password = toks[1].strip() return username, password
def _connect(self): self._ssh = paramiko.SSHClient() known_host_file = self._known_host_file or os.path.expanduser( os.path.join("~", ".ssh", "known_hosts")) if os.path.exists(known_host_file): self._ssh.load_host_keys(known_host_file) # and automatically add new host keys for hosts we haven't seen before. self._ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: self._ssh.connect(self._host, **self._params) except paramiko.AuthenticationException as e: if self._interactive and 'password' not in self._params: # If authentication has failed, and we haven't already tried # username/password, and configuration allows it, then try # again with username/password. if 'username' not in self._params: self._params['username'] = getpass.getuser() self._params['password'] = getpass.getpass() self._connect() else: raise paramiko.AuthenticationException(e) if self._ssh.get_transport(): self._sftp = self._ssh.open_sftp()
def connect_with_key(self): """Try connecting with key string.""" LOG.debug("Trying to connect with private key string") if not self.private_key: raise paramiko.AuthenticationException("No key supplied") pkey = make_pkey(self.private_key) return self._connect(pkey=pkey, look_for_keys=False, allow_agent=False)
def _connect_transport(self, pkey): for _ in xrange(self.CONNECT_TIMEOUT_RETRIES): transport = paramiko.Transport(self._connect_socket()) completed = threading.Event() transport.start_client(completed) completed.wait(self.CONNECT_TIMEOUT_SECONDS) if completed.isSet(): self._check_transport_error(transport) completed.clear() transport.auth_publickey(self.user, pkey, completed) completed.wait(self.CONNECT_TIMEOUT_SECONDS) if completed.isSet(): self._check_transport_error(transport) if not transport.is_authenticated(): transport.close() raise paramiko.AuthenticationException() return transport logging.warn("SSH negotiation (%s:%d) timed out, retrying", self.hostname, self.port) # HACK: we can't count on transport.join not hanging now, either transport.join = lambda: None transport.close() logging.error( "SSH negotiation (%s:%d) has timed out %s times, " "giving up", self.hostname, self.port, self.CONNECT_TIMEOUT_RETRIES) raise error.AutoservSSHTimeout("SSH negotiation timed out")
def _connect_to_gateway(self): """ Open connection to SSH gateway - First try with all keys loaded from an SSH agent (if allowed) - Then with those passed directly or read from ~/.ssh/config - As last resort, try with a provided password """ for key in self.ssh_private_keys: self.logger.debug('Trying to log in with key: {0}'.format( hexlify(key.get_fingerprint()))) try: self._transport.connect(hostkey=self.ssh_host_key, username=self.ssh_username, pkey=key) return except paramiko.AuthenticationException: self.logger.error('Could not open connection to gateway') self._stop_transport() if self.ssh_password: # avoid conflict using both pass and pkey self.logger.debug('Logging in with password {0}'.format( '*' * len(self.ssh_password))) self._transport.connect(hostkey=self.ssh_host_key, username=self.ssh_username, password=self.ssh_password) else: raise paramiko.AuthenticationException( 'No authentication methods available')
def __build_ssh_client(self): self.ssh_client = paramiko.SSHClient() # paramiko.util.log_to_file(self.__ssh_logfile, 10) self.ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) us, pw = self.__get_ssh_credentials() if not us: self.logger.error('Credentials could not be retrieved. Reason: username was None') raise paramiko.AuthenticationException('Credentials could not be retrieved.') try: time.sleep(2 * random.randrange(8)) self.ssh_client.connect(self.ssh_server, port=self.ssh_server_port, username=us, password=pw) except paramiko.AuthenticationException as ex: self.logger.error('Could not authenticate to remote server "%s:%d". Reason: %s' % (self.ssh_server, self.ssh_server_port, ex)) return except paramiko.BadHostKeyException as ex: self.logger.error('Host key was invalid. Reason: %s' % ex) return except paramiko.SSHException as ex: self.logger.error('There was a problem with the SSH connection. Reason: %s' % ex) return except Exception as ex: self.logger.error('Could not allocate socket for SSH. Reason: %s' % ex) return
def run(self): """ Override multiprocessing.Process's run() method with our own that executes a command over ssh. """ try: self.ssh = paramiko.SSHClient() assert (self.ssh) self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) self.ssh.connect(hostname=self.host, username=self.user, password=self.pwd, timeout=self.ssh_timeout_in_seconds, banner_timeout=_banner_timeout_in_seconds) if self.cmd: logger.debug("Trying to send the command %s to the server %s" % (self.cmd, self.host)) self._send_command() except KeyboardInterrupt as e: logger.exception(e.message) pass except (paramiko.SSHException, paramiko.AuthenticationException) as e: if self.errQueue: if isinstance(e, paramiko.BadAuthenticationType): e = paramiko.AuthenticationException(e.__str__()) self.errQueue.put(e) except Exception, e: if self.errQueue: self.errQueue.put(Exception("%r" % e))
def get_client(self): """Get SSH Client.""" if self.ssh_client is not None: return self.ssh_client keys = [] if self._key_file_path: keys.append( paramiko.RSAKey.from_private_key_file(self._key_file_path)) else: agent = paramiko.Agent() keys = agent.get_keys() if not keys: raise paramiko.AuthenticationException( "ERROR: No SSH Agent keys found!") client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) if self.verbose: key_file_path = '' if self._key_file_path: key_file_path = " -i %s" % (self._key_file_path) log.verbose( "ssh%s -p %d %s@%s" % (key_file_path, self.port, self.username, self.hostname)) saved_exception = paramiko.AuthenticationException( "ERROR: SSH Authentication Error!") for key in keys: if isinstance(key, paramiko.AgentKey): fp = hexlify(key.get_fingerprint()) log.info("Trying SSH Agent key: {0}".format(fp)) try: client.connect(hostname=self.hostname, username=self.username, port=self.port, pkey=key, timeout=self.timeout) return client except paramiko.SSHException, e: saved_exception = e
def connect_with_key_file(self): """Try connecting with key file.""" LOG.debug("Trying to connect with key file") if not self.key_filename: raise paramiko.AuthenticationException("No key file supplied") return self._connect(key_filename=os.path.expanduser( self.key_filename), look_for_keys=False, allow_agent=False)
def start_session_using_password(self, user, password): logger.debug(u"Validating with Password") transport = None try: transport = self.get_transport() transport.auth_password(user, password) self._start_session(transport) except Exception as e: logger.error(e.message) self._session.close_session() if transport: transport.close() self._socket.close() raise paramiko.AuthenticationException(u"Invalid Password")
def connect(self, user=None, port=None, timeout: timedelta = timedelta(seconds=30)): user = user or self.user port = port or self.port self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: self.ssh.connect(self.ip, username=user, port=port, timeout=timeout.total_seconds()) except paramiko.AuthenticationException as e: raise paramiko.AuthenticationException( f"Authentication exception occurred while trying to connect to DUT. " f"Please check your SSH key-based authentication.\n{e}") except (paramiko.SSHException, socket.timeout) as e: raise ConnectionError(f"An exception of type '{type(e)}' occurred while trying to " f"connect to {self.ip}.\n {e}")
def connect_ssh(username, hostname, port, key): key_f = StringIO.StringIO(key) pkey = paramiko.RSAKey.from_private_key(key_f) ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) for _ in range(10): try: ssh.connect(hostname, username=username, pkey=pkey) break except paramiko.AuthenticationException as e: raise paramiko.AuthenticationException(e) except socket.error: time.sleep(3) else: raise RuntimeError('SSH Connection Error') return ssh
def _connect_transport(self, transport, username=None, password=None): if not username: username = self.username if not password: password = self.password try: transport.start_client() except paramiko.SSHException: raise ConnectionError("SSH negotiation failed") hostkeys = HostKeys() hostkey_file = os.path.expanduser('~/.ssh/known_hosts') hostkeys.load(hostkey_file) server_hostkey_name = ("[%s]:%d" % (self.hostname, self.port) if self.port != 22 else self.hostname) server_hostkey_type = transport.host_key.get_name() try: # Raises KeyError if no host key is present expected_key = hostkeys[server_hostkey_name][server_hostkey_type] if expected_key != transport.host_key: if self.hostkey_change_cb(): raise KeyError else: raise SSHException( "SSH host key changed to %s" % binascii.hexlify(transport.host_key.get_fingerprint())) except KeyError: hostkeys.add(server_hostkey_name, server_hostkey_type, transport.host_key) hostkeys.save(hostkey_file) try: transport.auth_password(username, password) # double check, auth_password should already raise the exception if not transport.is_authenticated(): raise paramiko.AuthenticationException() except paramiko.AuthenticationException: raise LoginFailedException("SSH login failed for user %s" % username)
def connect(self, client, hostname=None, port=22, log=True): """Connect SSH client object using credentials :type client: paramiko.client.SSHClient paramiko.transport.Transport :type log: bool :raises paramiko.AuthenticationException """ kwargs = { 'username': self.username, 'password': self.__password} if hostname is not None: kwargs['hostname'] = hostname kwargs['port'] = port keys = [self.__key] keys.extend([k for k in self.__keys if k != self.__key]) for key in keys: kwargs['pkey'] = key try: client.connect(**kwargs) if self.__key != key: self.__key = key logger.debug( 'Main key has been updated, public key is: \n' '{}'.format(self.public_key)) return except paramiko.PasswordRequiredException: if self.__password is None: logger.exception('No password has been set!') raise else: logger.critical( 'Unexpected PasswordRequiredException, ' 'when password is set!') raise except (paramiko.AuthenticationException, paramiko.BadHostKeyException): continue msg = 'Connection using stored authentication info failed!' if log: logger.exception( 'Connection using stored authentication info failed!') raise paramiko.AuthenticationException(msg)
def run(self): ''' Override multiprocessing.Process's run() method with our own that executes a command over ssh. ''' try: key_file = '/etc/skyscraper/esx.pem' self.ssh = paramiko.SSHClient() self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) if tvpxglobals.standaloneMode and os.path.exists(key_file): self.ssh.connect(hostname=self.host, username=self.user, password=self.pwd, timeout=self.sshTimeout, key_filename=key_file) else: self.ssh.connect(hostname=self.host, username=self.user, password=self.pwd, timeout=self.sshTimeout) if self.cmd: self._send_command() except KeyboardInterrupt: pass except (paramiko.SSHException, paramiko.AuthenticationException) as e: if self.errQueue: # Workaround paramiko bug (BadAuthenticationType is not # serializable) if isinstance(e, paramiko.BadAuthenticationType): e = paramiko.AuthenticationException(e.__str__()) self.errQueue.put(e) except Exception as e: if self.errQueue: # Always convert to string in case exception is not serializable self.errQueue.put(Exception("%r" % e)) finally: self.ssh.close() #Allow the process to join even when items added to queue are not #consumed. self.queue.cancel_join_thread() self.errQueue.cancel_join_thread()
def connect( self, client, # type: typing.Union[paramiko.SSHClient, paramiko.Transport] hostname=None, # type: typing.Optional[str] port=22, # type: int log=True, # type: bool ): # type: (...) -> None """Connect SSH client object using credentials. :param client: SSH Client (low level) :type client: typing.Union[paramiko.SSHClient, paramiko.Transport] :param hostname: remote hostname :type hostname: str :param port: remote ssh port :type port: int :param log: Log on generic connection failure :type log: bool :raises paramiko.AuthenticationException: Authentication failed. """ kwargs = { 'username': self.username, 'password': self.__password, } # type: typing.Dict[str, typing.Any] if hostname is not None: kwargs['hostname'] = hostname kwargs['port'] = port if isinstance(client, paramiko.client.SSHClient): # pragma: no cover # paramiko.transport.Transport still do not allow passphrase and key filename if self.key_filename is not None: kwargs['key_filename'] = self.key_filename if self.__passphrase is not None: kwargs['passphrase'] = self.__passphrase keys = [self.__key] keys.extend([k for k in self.__keys if k != self.__key]) for key in keys: kwargs['pkey'] = key try: client.connect(**kwargs) if self.__key != key: self.__key = key logger.debug('Main key has been updated, public key is: \n' '{}'.format(self.public_key)) return except paramiko.PasswordRequiredException: if self.__password is None: logger.exception('No password has been set!') raise else: logger.critical( 'Unexpected PasswordRequiredException, when password is set!' ) raise except (paramiko.AuthenticationException, paramiko.BadHostKeyException): continue msg = 'Connection using stored authentication info failed!' if log: logger.exception(msg) raise paramiko.AuthenticationException(msg)
def connect( self, client: paramiko.SSHClient, hostname: str, port: int = 22, log: bool = True, *, sock: paramiko.ProxyCommand | paramiko.Channel | socket.socket | None = None, ) -> None: """Connect SSH client object using credentials. :param client: SSH Client (low level) :type client: paramiko.SSHClient :param hostname: remote hostname :type hostname: str :param port: remote ssh port :type port: int :param log: Log on generic connection failure :type log: bool :param sock: socket for connection. Useful for ssh proxies support :type sock: typing.Optional[typing.Union[paramiko.ProxyCommand, paramiko.Channel, socket.socket]] :raises PasswordRequiredException: No password has been set, but required. :raises AuthenticationException: Authentication failed. """ kwargs: dict[str, typing.Any] = {} if self.__passphrase is not None: kwargs["passphrase"] = self.__passphrase if sock is not None: kwargs["sock"] = sock for index, key in sorted(enumerate(self.__keys), key=lambda i_k: i_k[0] != self.__key_index): kwargs["pkey"] = key try: # noinspection PyTypeChecker client.connect( hostname=hostname, port=port, username=self.username, password=self.__password, key_filename=self. __key_filename, # type: ignore[arg-type] # types verified by not signature **kwargs, ) if index != self.__key_index: self.__key_index = index LOGGER.debug( f"Main key has been updated, public key is: \n{self.public_key}" ) return except paramiko.PasswordRequiredException: if self.__password is None: LOGGER.exception("No password has been set!") raise LOGGER.critical( "Unexpected PasswordRequiredException, when password is set!" ) raise except (paramiko.AuthenticationException, paramiko.BadHostKeyException): continue msg: str = "Connection using stored authentication info failed!" if log: LOGGER.exception(msg) raise paramiko.AuthenticationException(msg)