Beispiel #1
0
 def test_settimout(self):
     """
     The timeout property should be set to the argument of settimeout()
     """
     proxyCommand = ProxyCommand("ls")
     proxyCommand.settimeout(10)
     self.assertEquals(10, proxyCommand.timeout)
def create_worker(host):
    config = SSHConfig()
    proxy = None
    if os.path.exists(os.path.expanduser('~/.ssh/config')):
        with open(os.path.expanduser('~/.ssh/config')) as f:
            config.parse(f)
        if host.hostname is not None and 'proxycommand' in config.lookup(
                host.hostname):
            proxy = ProxyCommand(config.lookup(host.hostname)['proxycommand'])

    worker = SSHClient()
    worker.load_system_host_keys()
    worker.set_missing_host_key_policy(AutoAddPolicy())

    # store data for later reference
    worker.host = host.hostname
    worker.username = host.username
    worker.password = host.password
    worker.key_filename = host.key_filename

    worker.connect(hostname=host.hostname,
                   username=host.username,
                   password=host.password,
                   key_filename=host.key_filename,
                   sock=proxy)
    return worker
def create_worker(host):
    config = SSHConfig()
    proxy = None
    if os.path.exists(os.path.expanduser('~/.ssh/config')):
        config.parse(open(os.path.expanduser('~/.ssh/config')))
        if host.hostname is not None and \
                        'proxycommand' in config.lookup(host.hostname):
            proxy = ProxyCommand(config.lookup(host.hostname)['proxycommand'])

    # proxy = paramiko.ProxyCommand("ssh -o StrictHostKeyChecking=no [email protected] nc 118.138.239.241 22")

    worker = SSHClient()
    worker.load_system_host_keys()
    worker.set_missing_host_key_policy(AutoAddPolicy())

    worker.hostname = host.hostname  # store all this for later reference (e.g., logging, reconnection)
    worker.username = host.username
    worker.password = host.password
    worker.proxy = proxy
    if not host.key_filename is None:
        worker.pkey = RSAKey.from_private_key_file(host.key_filename,
                                                   host.key_password)
    else:
        worker.pkey = None

    # time.sleep(4)
    # worker.connect(hostname=host.hostname, username=host.username, password=host.password, key_filename=host.key_filename, sock=proxy, timeout=3600)

    worker.connect(hostname=host.hostname,
                   username=host.username,
                   password=host.password,
                   pkey=worker.pkey,
                   sock=proxy)

    return worker
Beispiel #4
0
    def _get_from_sftp_with_proxy(self, path):
        """
        Download all data from sftp sever to a local dir

        Args:
            path (str): path to local directory

        Returns:
            None
        """
        proxy = None
        if self.server.get("proxy", "") != "":
            command = "ssh -i ~/.ssh/id_rsa {user}@{proxy} nc {host} {port}".format(
                user=self.server.get("proxy_user", ""),
                proxy=self.server.get("proxy", ""),
                host=self.server.get("host", ""),
                port=self.server.get("port", 22),
            )
            self.logger.info("SSH proxy command: {}".format(command))

            proxy = ProxyCommand(command)

        with paramiko.SSHClient() as client:
            client.set_log_channel(self.logger.name)

            client.set_missing_host_key_policy(paramiko.WarningPolicy())
            parameters = {
                "hostname": str(self.server.get("host", "")),
                "username": str(self.server.get("username", "")),
                "password": str(self.server.get("password", "")),
                "port": int(self.server.get("port", 22)),
            }
            if proxy:
                parameters["sock"] = proxy

            self.logger.info(
                "SSH connection parameters: {}".format(parameters))
            client.connect(**parameters)
            with client.open_sftp() as sftp:
                download_dir(sftp, "./", path)

        if proxy:
            proxy.close()
Beispiel #5
0
    def __init__(self, hostname, user=None, password=None, **kwargs):

        self.hostname = hostname
        self.username = user
        self.password = password

        if not self.username:
            self.username = getuser()

        self.config = kwargs
        self.cwd = '~'
        self.prompt = 'Password for {hostname}:'

        client = ssh.SSHClient()
        client.set_missing_host_key_policy(ssh.AutoAddPolicy())
        client.load_system_host_keys()

        timeout = kwargs.get('timeout', None)
        compress = kwargs.get('compress', False)
        port = kwargs.get('port', 22)
        proxy_command = kwargs.get('proxycommand')

        if proxy_command:
            proxy = ProxyCommand(proxy_command)
        else:
            proxy = None

        try:
            # Try to connect with a ssh key if we can.
            client.connect(self.hostname,
                           username=self.username,
                           port=port,
                           timeout=timeout,
                           compress=compress,
                           sock=proxy)
        except ssh.SSHException:

            if not self.password:
                self.password = getpass(
                    self.prompt.format(hostname=self.hostname))

            client.connect(self.hostname,
                           username=self.username,
                           password=self.password,
                           port=port,
                           timeout=timeout,
                           compress=compress,
                           sock=proxy)

        self.client = client
Beispiel #6
0
    def open_gateway(self):
        """
        Obtain a socket-like object from `gateway`.

        :returns:
            A ``direct-tcpip`` `paramiko.channel.Channel`, if `gateway` was a
            `.Connection`; or a `~paramiko.proxy.ProxyCommand`, if `gateway`
            was a string.

        .. versionadded:: 2.0
        """
        # ProxyCommand is faster to set up, so do it first.
        if isinstance(self.gateway, string_types):
            # Leverage a dummy SSHConfig to ensure %h/%p/etc are parsed.
            # TODO: use real SSH config once loading one properly is
            # implemented.
            ssh_conf = SSHConfig()
            dummy = "Host {}\n    ProxyCommand {}"
            ssh_conf.parse(StringIO(dummy.format(self.host, self.gateway)))
            return ProxyCommand(ssh_conf.lookup(self.host)["proxycommand"])
        # Handle inner-Connection gateway type here.
        # TODO: logging
        self.gateway.open()
        # TODO: expose the opened channel itself as an attribute? (another
        # possible argument for separating the two gateway types...) e.g. if
        # someone wanted to piggyback on it for other same-interpreter socket
        # needs...
        # TODO: and the inverse? allow users to supply their own socket/like
        # object they got via $WHEREEVER?
        # TODO: how best to expose timeout param? reuse general connection
        # timeout from config?
        return self.gateway.transport.open_channel(
            kind="direct-tcpip",
            dest_addr=(self.host, int(self.port)),
            # NOTE: src_addr needs to be 'empty but not None' values to
            # correctly encode into a network message. Theoretically Paramiko
            # could auto-interpret None sometime & save us the trouble.
            src_addr=("", 0),
        )
Beispiel #7
0
    def connect(
        self,
        hostname,
        port=SSH_PORT,
        username=None,
        password=None,
        pkey=None,
        key_filename=None,
        timeout=None,
        allow_agent=True,
        look_for_keys=True,
        compress=False,
        sock=None,
        gss_auth=False,
        gss_kex=False,
        gss_deleg_creds=True,
        gss_host=None,
        banner_timeout=None,
        auth_timeout=None,
        gss_trust_dns=True,
        passphrase=None,
        disabled_algorithms=None,
    ):
        """
        Connect to an SSH server and authenticate to it.  The server's host key
        is checked against the system host keys (see `load_system_host_keys`)
        and any local host keys (`load_host_keys`).  If the server's hostname
        is not found in either set of host keys, the missing host key policy
        is used (see `set_missing_host_key_policy`).  The default policy is
        to reject the key and raise an `.SSHException`.

        Authentication is attempted in the following order of priority:

            - The ``pkey`` or ``key_filename`` passed in (if any)

              - ``key_filename`` may contain OpenSSH public certificate paths
                as well as regular private-key paths; when files ending in
                ``-cert.pub`` are found, they are assumed to match a private
                key, and both components will be loaded. (The private key
                itself does *not* need to be listed in ``key_filename`` for
                this to occur - *just* the certificate.)

            - Any key we can find through an SSH agent
            - Any "id_rsa", "id_dsa" or "id_ecdsa" key discoverable in
              ``~/.ssh/``

              - When OpenSSH-style public certificates exist that match an
                existing such private key (so e.g. one has ``id_rsa`` and
                ``id_rsa-cert.pub``) the certificate will be loaded alongside
                the private key and used for authentication.

            - Plain username/password auth, if a password was given

        If a private key requires a password to unlock it, and a password is
        passed in, that password will be used to attempt to unlock the key.

        :param str hostname: the server to connect to
        :param int port: the server port to connect to
        :param str username:
            the username to authenticate as (defaults to the current local
            username)
        :param str password:
            Used for password authentication; is also used for private key
            decryption if ``passphrase`` is not given.
        :param str passphrase:
            Used for decrypting private keys.
        :param .PKey pkey: an optional private key to use for authentication
        :param str key_filename:
            the filename, or list of filenames, of optional private key(s)
            and/or certs to try for authentication
        :param float timeout:
            an optional timeout (in seconds) for the TCP connect
        :param bool allow_agent:
            set to False to disable connecting to the SSH agent
        :param bool look_for_keys:
            set to False to disable searching for discoverable private key
            files in ``~/.ssh/``
        :param bool compress: set to True to turn on compression
        :param socket sock:
            an open socket or socket-like object (such as a `.Channel`) to use
            for communication to the target host
        :param bool gss_auth:
            ``True`` if you want to use GSS-API authentication
        :param bool gss_kex:
            Perform GSS-API Key Exchange and user authentication
        :param bool gss_deleg_creds: Delegate GSS-API client credentials or not
        :param str gss_host:
            The targets name in the kerberos database. default: hostname
        :param bool gss_trust_dns:
            Indicates whether or not the DNS is trusted to securely
            canonicalize the name of the host being connected to (default
            ``True``).
        :param float banner_timeout: an optional timeout (in seconds) to wait
            for the SSH banner to be presented.
        :param float auth_timeout: an optional timeout (in seconds) to wait for
            an authentication response.
        :param dict disabled_algorithms:
            an optional dict passed directly to `.Transport` and its keyword
            argument of the same name.

        :raises:
            `.BadHostKeyException` -- if the server's host key could not be
            verified
        :raises: `.AuthenticationException` -- if authentication failed
        :raises:
            `.SSHException` -- if there was any other error connecting or
            establishing an SSH session
        :raises socket.error: if a socket error occurred while connecting

        .. versionchanged:: 1.15
            Added the ``banner_timeout``, ``gss_auth``, ``gss_kex``,
            ``gss_deleg_creds`` and ``gss_host`` arguments.
        .. versionchanged:: 2.3
            Added the ``gss_trust_dns`` argument.
        .. versionchanged:: 2.4
            Added the ``passphrase`` argument.
        .. versionchanged:: 2.6
            Added the ``disabled_algorithms`` argument.
        """
        if not sock:
            proxy = ProxyCommand.from_ssh_config(hostname)
            if proxy is not None:
                sock = proxy
            else:
                errors = {}
                # Try multiple possible address families (e.g. IPv4 vs IPv6)
                to_try = list(self._families_and_addresses(hostname, port))
                for af, addr in to_try:
                    try:
                        sock = socket.socket(af, socket.SOCK_STREAM)
                        if timeout is not None:
                            try:
                                sock.settimeout(timeout)
                            except:
                                pass
                        retry_on_signal(lambda: sock.connect(addr))
                        # Break out of the loop on success
                        break
                    except socket.error as e:
                        # Raise anything that isn't a straight up connection error
                        # (such as a resolution error)
                        if e.errno not in (ECONNREFUSED, EHOSTUNREACH):
                            raise
                        # Capture anything else so we know how the run looks once
                        # iteration is complete. Retain info about which attempt
                        # this was.
                        errors[addr] = e

                # Make sure we explode usefully if no address family attempts
                # succeeded. We've no way of knowing which error is the "right"
                # one, so we construct a hybrid exception containing all the real
                # ones, of a subclass that client code should still be watching for
                # (socket.error)
                if len(errors) == len(to_try):
                    raise NoValidConnectionsError(errors)

        t = self._transport = Transport(
            sock,
            gss_kex=gss_kex,
            gss_deleg_creds=gss_deleg_creds,
            disabled_algorithms=disabled_algorithms,
        )
        t.use_compression(compress=compress)
        t.set_gss_host(
            # t.hostname may be None, but GSS-API requires a target name.
            # Therefore use hostname as fallback.
            gss_host=gss_host or hostname,
            trust_dns=gss_trust_dns,
            gssapi_requested=gss_auth or gss_kex,
        )
        if self._log_channel is not None:
            t.set_log_channel(self._log_channel)
        if banner_timeout is not None:
            t.banner_timeout = banner_timeout
        if auth_timeout is not None:
            t.auth_timeout = auth_timeout

        if port == SSH_PORT:
            server_hostkey_name = hostname
        else:
            server_hostkey_name = "[{}]:{}".format(hostname, port)
        our_server_keys = None

        our_server_keys = self._system_host_keys.get(server_hostkey_name)
        if our_server_keys is None:
            our_server_keys = self._host_keys.get(server_hostkey_name)
        if our_server_keys is not None:
            keytype = our_server_keys.keys()[0]
            sec_opts = t.get_security_options()
            other_types = [x for x in sec_opts.key_types if x != keytype]
            sec_opts.key_types = [keytype] + other_types

        t.start_client(timeout=timeout)

        # If GSS-API Key Exchange is performed we are not required to check the
        # host key, because the host is authenticated via GSS-API / SSPI as
        # well as our client.
        if not self._transport.gss_kex_used:
            server_key = t.get_remote_server_key()
            if our_server_keys is None:
                # will raise exception if the key is rejected
                self._policy.missing_host_key(self, server_hostkey_name,
                                              server_key)
            else:
                our_key = our_server_keys.get(server_key.get_name())
                if our_key != server_key:
                    if our_key is None:
                        our_key = list(our_server_keys.values())[0]
                    raise BadHostKeyException(hostname, server_key, our_key)

        if username is None:
            username = getpass.getuser()

        if key_filename is None:
            key_filenames = []
        elif isinstance(key_filename, string_types):
            key_filenames = [key_filename]
        else:
            key_filenames = key_filename

        self._auth(
            username,
            password,
            pkey,
            key_filenames,
            allow_agent,
            look_for_keys,
            gss_auth,
            gss_kex,
            gss_deleg_creds,
            t.gss_host,
            passphrase,
        )
Beispiel #8
0
    def connect(self, keyfile=None, timeout=5):
        """
        Connect to the node via SSH.

        :param keyfile: Path to the SSH host key.
        :param timeout: Maximum time to wait (in seconds) for the TCP
            connection to be established.

        :return: :py:class:`paramiko.SSHClient` - ssh connection or None on
                 failure
        """
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        if keyfile and os.path.exists(keyfile):
            ssh.load_host_keys(keyfile)

        # Try connecting using the `preferred_ip`, if
        # present. Otherwise, try all of them and set `preferred_ip`
        # using the first that is working.
        ips = self.ips[:]
        # This is done in order to "sort" the IPs and put the preferred_ip first.
        if self.preferred_ip:
            if self.preferred_ip in ips:
                ips.remove(self.preferred_ip)
            else:
                # Preferred is changed?
                log.debug(
                    "IP address %s does not seem to belong to %s anymore."
                    " Ignoring it.", self.preferred_ip, self.name)
                self.preferred_ip = ips[0]

        for ip in itertools.chain([self.preferred_ip], ips):
            if not ip:
                continue
            log.debug("Trying to connect to host %s (%s) ...", self.name, ip)
            try:
                addr, port = parse_ip_address_and_port(ip, SSH_PORT)
                extra = {
                    'allow_agent':   True,
                    'key_filename':  self.user_key_private,
                    'look_for_keys': False,
                    'timeout':       timeout,
                    'username':      self.image_user,
                }
                if self.ssh_proxy_command:
                    proxy_command = expand_ssh_proxy_command(
                        self.ssh_proxy_command,
                        self.image_user, addr, port)
                    from paramiko.proxy import ProxyCommand
                    extra['sock'] = ProxyCommand(proxy_command)
                    log.debug("Using proxy command `%s`.", proxy_command)
                ssh.connect(str(addr), port=port, **extra)
                log.debug(
                    "Connection to %s succeeded on port %d,"
                    " will use this IP address for future connections.",
                    ip, port)
                if ip != self.preferred_ip:
                    self.preferred_ip = ip
                # Connection successful.
                return ssh
            except socket.error as ex:
                log.debug(
                    "Host %s (%s) not reachable within %d seconds: %s -- %r",
                    self.name, ip, timeout, ex, type(ex))
            except paramiko.BadHostKeyException as ex:
                log.error(
                    "Invalid SSH host key for %s (%s): %s.",
                    self.name, ip, ex)
            except paramiko.SSHException as ex:
                log.debug(
                    "Ignoring error connecting to %s: %s -- %r",
                    self.name, ex, type(ex))

        return None