Beispiel #1
0
    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
Beispiel #2
0
    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()
Beispiel #3
0
 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)
Beispiel #4
0
 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")
Beispiel #5
0
    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')
Beispiel #6
0
    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
Beispiel #7
0
    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))
Beispiel #8
0
    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
Beispiel #9
0
 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)
Beispiel #10
0
 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}")
Beispiel #12
0
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
Beispiel #13
0
    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)
Beispiel #14
0
    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()
Beispiel #16
0
    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)