Esempio n. 1
0
    def exec_command(self, command, bufsize=-1, check_status=True):
        """Execute a command on the SSH server while preserving underling
        agent forwarding and sudo privileges.
        https://github.com/paramiko/paramiko/blob/1.8/paramiko/client.py#L348

        :param command: the command to execute
        :type command: str
        :param bufsize: interpreted the same way as by the built-in C{file()} function in python
        :type bufsize: int
        :param check_staus: if enabled, waits for the command to complete and return an exception
        if the status is non-zero.
        :type check_staus: bool
        :returns the stdin, stdout, and stderr of the executing command
        :rtype: tuple(L{ChannelFile}, L{ChannelFile}, L{ChannelFile})

        :raises SSHException: if the server fails to execute the command
        """
        channel = self.transport.open_session()

        if self.forward_agent:
            AgentRequestHandler(channel)
        if self.sudoable:
            channel.get_pty()

        channel.exec_command(command)
        if check_status and channel.recv_exit_status() != 0:
            raise RuntimeError("Command execution error: {}".format(command))

        stdin = channel.makefile('wb', bufsize)
        stdout = channel.makefile('rb', bufsize)
        stderr = channel.makefile_stderr('rb', bufsize)
        return (stdin, stdout, stderr)
Esempio n. 2
0
    def connect(self, hostname, **kwargs):
        self.hostname, self.config, forward_agent = self.parse_config(hostname)
        self.config.update(kwargs)
        super(SSHClient, self).connect(self.hostname, **self.config)

        if forward_agent:
            # Enable SSH forwarding
            session = self.get_transport().open_session()
            AgentRequestHandler(session)
Esempio n. 3
0
def connect(state, host, **kwargs):
    '''
    Connect to a single host. Returns the SSH client if succesful. Stateless by
    design so can be run in parallel.
    '''

    logger.debug('Connecting to: {0} ({1})'.format(host.name, kwargs))

    name = host.name
    hostname = host.data.ssh_hostname or name

    try:
        # Create new client & connect to the host
        client = SSHClient()
        client.set_missing_host_key_policy(MissingHostKeyPolicy())
        client.connect(hostname, **kwargs)

        # Enable SSH forwarding
        session = client.get_transport().open_session()
        AgentRequestHandler(session)

        # Log
        logger.info('{0}{1}'.format(
            host.print_prefix,
            click.style('Connected', 'green'),
        ))

        return client

    except AuthenticationException as e:
        auth_kwargs = {}

        for key, value in kwargs.items():
            if key in ('username', 'password'):
                auth_kwargs[key] = value
                continue

            if key == 'pkey' and value:
                auth_kwargs['key'] = host.data.ssh_key

        auth_args = ', '.join('{0}={1}'.format(key, value)
                              for key, value in auth_kwargs.items())

        _log_connect_error(host, 'Authentication error', auth_args)

    except SSHException as e:
        _log_connect_error(host, 'SSH error', e)

    except gaierror:
        _log_connect_error(host, 'Could not resolve hostname', hostname)

    except socket_error as e:
        _log_connect_error(host, 'Could not connect', e)

    except EOFError as e:
        _log_connect_error(host, 'EOF error', e)
Esempio n. 4
0
def connect(state, host):
    '''
    Connect to a single host. Returns the SSH client if succesful. Stateless by
    design so can be run in parallel.
    '''

    kwargs = _make_paramiko_kwargs(state, host)
    logger.debug('Connecting to: {0} ({1})'.format(host.name, kwargs))

    # Hostname can be provided via SSH config (alias), data, or the hosts name
    hostname = kwargs.pop(
        'hostname',
        host.data.ssh_hostname or host.name,
    )

    try:
        # Create new client & connect to the host
        client = SSHClient()
        client.set_missing_host_key_policy(MissingHostKeyPolicy())
        client.connect(hostname, **kwargs)

        # Enable SSH forwarding
        session = client.get_transport().open_session()
        AgentRequestHandler(session)

        return client

    except AuthenticationException:
        auth_kwargs = {}

        for key, value in kwargs.items():
            if key in ('username', 'password'):
                auth_kwargs[key] = value
                continue

            if key == 'pkey' and value:
                auth_kwargs['key'] = host.data.ssh_key

        auth_args = ', '.join('{0}={1}'.format(key, value)
                              for key, value in auth_kwargs.items())

        _raise_connect_error(host, 'Authentication error', auth_args)

    except SSHException as e:
        _raise_connect_error(host, 'SSH error', e)

    except gaierror:
        _raise_connect_error(host, 'Could not resolve hostname', hostname)

    except socket_error as e:
        _raise_connect_error(host, 'Could not connect', e)

    except EOFError as e:
        _raise_connect_error(host, 'EOF error', e)
Esempio n. 5
0
    async def run_async(self,
                        command,
                        stdin_param=None,
                        get_pty=False,
                        interval=10,
                        callback=None,
                        buff_size=1024):
        if not self.is_active():
            log.error('ssh connection is not active')
            return

        transport = self.client.get_transport()
        channel = transport.open_session()

        if self.forward_agent:
            AgentRequestHandler(channel)

        if get_pty:
            channel.get_pty()
            channel.set_combine_stderr(True)

        channel.exec_command(command.encode(sys.stdout.encoding))

        if stdin_param is not None:
            stdin = channel.makefile('wb', -1)
            stdin.write(stdin_param)
            stdin.flush()

        while not channel.exit_status_ready():
            if callback is not None:
                callback(channel)
            await asyncio.sleep(interval)

        if channel.exit_status != 0:
            log.warn('%s exit status is not zero: %d' %
                     (self.host, channel.exit_status))

        stdout = stderr = b''
        while channel.recv_ready():
            stdout += channel.recv(buff_size)
            await asyncio.sleep(1)
        if stdout and self.stdout_queue is not None:
            s = stdout.decode(sys.stdout.encoding)
            self.stdout_queue.put_nowait(s)

        while channel.recv_stderr_ready():
            stderr += channel.recv_stderr(buff_size)
            await asyncio.sleep(1)
        if stderr and self.stderr_queue is not None:
            s = stderr.decode(sys.stderr.encoding)
            self.stderr_queue.put_nowait(s)

        return channel.exit_status, stdout, stderr
Esempio n. 6
0
File: ssh.py Progetto: ge-fa/pyinfra
def connect(state, host, **kwargs):
    '''
    Connect to a single host. Returns the SSH client if succesful. Stateless by
    design so can be run in parallel.
    '''

    logger.debug('Connecting to: {0} ({1})'.format(host.name, kwargs))

    name = host.name
    hostname = host.data.ssh_hostname or name

    try:
        # Create new client & connect to the host
        client = SSHClient()
        client.set_missing_host_key_policy(MissingHostKeyPolicy())
        client.connect(hostname, **kwargs)

        # Enable SSH forwarding
        session = client.get_transport().open_session()
        AgentRequestHandler(session)

        # Log
        logger.info('{0}{1}'.format(
            host.print_prefix,
            click.style('Connected', 'green'),
        ))

        return client

    except AuthenticationException as e:
        logger.error('Auth error on: {0}, {1}'.format(name, e))

    except SSHException as e:
        logger.error('SSH error on: {0}, {1}'.format(name, e))

    except gaierror:
        if hostname == name:
            logger.error('Could not resolve {0}'.format(name))
        else:
            logger.error('Could not resolve for {0} (SSH host: {1})'.format(
                name, hostname))

    except socket_error as e:
        logger.error(
            'Could not connect: {0}:{1}, {2}'.format(name,
                                                     kwargs.get('port', 22),
                                                     e), )

    except EOFError as e:
        logger.error('EOF error connecting to {0}: {1}'.format(name, e))
Esempio n. 7
0
    def connect(
        self,
        hostname,
        _pyinfra_ssh_forward_agent=None,
        _pyinfra_ssh_config_file=None,
        _pyinfra_ssh_known_hosts_file=None,
        _pyinfra_ssh_strict_host_key_checking=None,
        _pyinfra_ssh_paramiko_connect_kwargs=None,
        **kwargs,
    ):
        (
            hostname,
            config,
            forward_agent,
            missing_host_key_policy,
            host_keys_file,
        ) = self.parse_config(
            hostname,
            kwargs,
            ssh_config_file=_pyinfra_ssh_config_file,
            strict_host_key_checking=_pyinfra_ssh_strict_host_key_checking,
        )
        self.set_missing_host_key_policy(missing_host_key_policy)
        config.update(kwargs)

        if _pyinfra_ssh_known_hosts_file:
            host_keys_file = _pyinfra_ssh_known_hosts_file

        # Overwrite paramiko empty defaults with @memoize-d host keys object
        self._host_keys = get_host_keys(host_keys_file)
        self._host_keys_filename = host_keys_file

        if _pyinfra_ssh_paramiko_connect_kwargs:
            config.update(_pyinfra_ssh_paramiko_connect_kwargs)

        self._ssh_config = config
        super(SSHClient, self).connect(hostname, **config)

        if _pyinfra_ssh_forward_agent is not None:
            forward_agent = _pyinfra_ssh_forward_agent

        if forward_agent:
            # Enable SSH forwarding
            session = self.get_transport().open_session()
            AgentRequestHandler(session)
Esempio n. 8
0
def remote_command(task: Task, command: str) -> Result:
    """
    Executes a command remotely on the host

    Arguments:
        command (``str``): command to execute

    Returns:
        Result object with the following attributes set:
          * result (``str``): stderr or stdout
          * stdout (``str``): stdout
          * stderr (``str``): stderr

    Raises:
        :obj:`nornir.core.exceptions.CommandError`: when there is a command error
    """
    client = task.host.get_connection("paramiko", task.nornir.config)
    connection_state = task.host.get_connection_state("paramiko")

    chan = client.get_transport().open_session()

    if connection_state["ssh_forward_agent"]:
        AgentRequestHandler(chan)

    chan.exec_command(command)

    exit_status_code = chan.recv_exit_status()

    with chan.makefile() as f:
        stdout = f.read().decode()
    with chan.makefile_stderr() as f:
        stderr = f.read().decode()

    if exit_status_code:
        raise CommandError(command, exit_status_code, stdout, stderr)

    result = stderr if stderr else stdout
    return Result(result=result, host=task.host, stderr=stderr, stdout=stdout)
Esempio n. 9
0
def remote_command(task, command):
    """
    Executes a command locally

    Arguments:
        command (``str``): command to execute

    Returns:
        :obj:`nornir.core.task.Result`:
          * result (``str``): stderr or stdout
          * stdout (``str``): stdout
          * stderr (``srr``): stderr

    Raises:
        :obj:`nornir.core.exceptions.CommandError`: when there is a command error
    """
    client = task.host.get_connection("paramiko")

    chan = client.get_transport().open_session()

    if task.host._ssh_forward_agent:
        AgentRequestHandler(chan)

    chan.exec_command(command)

    exit_status_code = chan.recv_exit_status()

    with chan.makefile() as f:
        stdout = f.read().decode()
    with chan.makefile_stderr() as f:
        stderr = f.read().decode()

    if exit_status_code:
        raise CommandError(command, exit_status_code, stdout, stderr)

    result = stderr if stderr else stdout
    return Result(result=result, host=task.host, stderr=stderr, stdout=stdout)
Esempio n. 10
0
    def exec_command(self, cmd):
        transport = self._ssh.get_transport()
        ch = transport.open_session()
        AgentRequestHandler(ch)
        ch.exec_command(cmd)

        stdin = ''
        stdout = ''
        stderr = ''
        size = 1024 * 1024
        # TODO: write stdin to channel
        while True:

            r, w, x = select.select([ch], [], [], 1)

            if len(r):
                if ch in r:
                    while True:
                        data = ch.recv_stderr(size)
                        if not data:
                            break
                        stderr += data.decode(errors='replace')
                        # for line in data.decode(errors='replace').splitlines():
                        #     print(line.strip())
                    while True:
                        data = ch.recv(size)
                        if not data:
                            break
                        stdout += data.decode(errors='replace')
                        # for line in data.decode(errors='replace').splitlines():
                        #     print(line.strip())

            if ch.exit_status_ready():
                break

        return stdin, stdout, stderr, ch.recv_exit_status()
Esempio n. 11
0
 def create_session(self):
     channel = self.transport.open_session()
     if self.forward_agent:
         self._agent_handler = AgentRequestHandler(channel)
     return channel
Esempio n. 12
0
    def connect(self):
        """
        Connect server.
        连接服务器
        """
        # now connect
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.connect((self.asset, self.port))
        except Exception as e:
            print('*** {} Connect failed: {}'.format(self.asset, str(e)))
            return

        try:
            t = paramiko.Transport(sock)
            try:
                t.start_client()
            except paramiko.SSHException:
                print('*** SSH negotiation failed.')
                return

            try:
                self.agent_auth(t, self.username)
            except Exception as e:
                print('密钥认证失败,请检查您的密钥: {}'.format(e))
            if not t.is_authenticated():
                try:
                    self.manual_auth(t, self.user, self.asset)
                except Exception as err:
                    print("ssh_key/dss_key/user_pass auth failed. {}".format(
                        err))
                    t.close()
                    return

            global channel
            win_size = self.get_win_size()
            self.channel = channel = t.open_session()
            # Forward local agent
            # Commands executed after this point will see the forwarded agent
            # on the remote end.
            AgentRequestHandler(channel)

            # 获取连接的隧道并设置窗口大小 Make a channel and set windows size
            channel.get_pty(term='xterm',
                            height=win_size[0],
                            width=win_size[1])
            channel.invoke_shell()
            try:
                signal.signal(signal.SIGWINCH, self.set_win_size)
            except Exception as err:
                print("get_pty error {}".format(err))

            self.posix_shell()

            # import pdb;pdb.set_trace()
            # Shutdown channel socket
            channel.close()
        except Exception as e:
            print('*** Caught exception: ' + str(e.__class__) + ': ' + str(e))
            traceback.print_exc()
            try:
                t.close()
            except Exception as err:
                print("{}".format(err))
            return