Ejemplo n.º 1
0
  def testSignBuffer(self):
    intemp = tempfile.NamedTemporaryFile()

    # Simulate osslsign writing the signed file
    outname = "%s.signed" % intemp.name
    open(outname, "w").write("content")

    with mock.patch.object(pexpect, "spawn"):
      with mock.patch.object(signing.subprocess, "check_call"):
        with mock.patch.object(tempfile, "NamedTemporaryFile",
                               return_value=intemp):
          output = self.winsign.SignBuffer("asdflkjlaksjdf")

    self.assertEqual(output, "content")

    with mock.patch.object(pexpect, "spawn",
                           side_effect=pexpect.ExceptionPexpect("blah")):
      with self.assertRaises(pexpect.ExceptionPexpect):
        output = self.winsign.SignBuffer("asdflkjlaksjdf")
Ejemplo n.º 2
0
    def read_nonblocking(self, size=-1, timeout=-1):
        if self.child_fd == -1:
            raise ValueError('I/O operation on closed file')

        if not self.isalive():
            r, w, e = select.select([self.child_fd], [], [], 0)
            if not r:
                self.flag_eof = True
                raise pexpect.EOF('End Of File (EOF) in read(). '
                                  'Braindead platform.')

        if timeout == -1:
            timeout = self.timeout

        r, w, e = select.select([self.child_fd], [], [], timeout)
        if not r:
            raise pexpect.TIMEOUT('Timeout (%s) exceeded in read().' %
                                  str(timeout))

        if self.child_fd in r:
            try:
                s = self.child_fd.recv(size)
            except OSError as e:
                self.flag_eof = True
                raise pexpect.EOF('End Of File (EOF) in read(). '
                                  'Exception style platform.')
            if s == '':
                self.flag_eof = True
                raise pexpect.EOF('End Of File (EOF) in read(). '
                                  'Empty string style platform.')

            if self.logfile is not None:
                self.logfile.write(s)
                self.logfile.flush()

            return s

        raise pexpect.ExceptionPexpect(
            'Reached an unexpected state in read().')
Ejemplo n.º 3
0
    def get_output(self, code_override=None):
        text_output = "before:\n{before}\nafter:\n{after}".format(
            before=self.before if isinstance(
                self.before, basestring) else pformat(self.before, indent=4),
            after=self.after if isinstance(
                self.after, basestring) else pformat(self.after, indent=4))

        if code_override is not None:
            conf.bash_log(pformat(self.args), code_override, text_output)
            return code_override, text_output

        if self.isalive():
            conf.bash_log(
                pformat(self.args),
                'Spawned process running: pid={pid}'.format(pid=self.pid),
                text_output)
            raise pexpect.ExceptionPexpect(
                'Unable to return exit code. Spawned command is still running:\n'
                + text_output)

        conf.bash_log(pformat(self.args), self.exitstatus, text_output)
        return self.exitstatus, text_output
Ejemplo n.º 4
0
class ParamikoSpawn(pexpect.spawn):
    """A pexpect.spawn that works with Paramiko Channel objects.

    The Channel object returned by paramiko.SSHClient.invoke_shell()
    is suitable for use with this class.

    Attributes:
      child_fd: A paramiko.Channel object, the SSH channel (like a socket).
    """

    def _set_channel(self, channel):
        self.child_fd = channel

    channel = property(lambda x: x.child_fd, _set_channel)

    @property
    def transport(self):
        return self.child_fd.get_transport()

    def isalive(self):
        try:
            return self.child_fd.get_transport().is_active()
        except AttributeError:
            return False

    def read_nonblocking(self, size=-1, timeout=-1):
        if self.child_fd == -1:
            raise ValueError('I/O operation on closed file')

        if not self.isalive():
            r, w, e = select.select([self.child_fd], [], [], 0)
            if not r:
                self.flag_eof = True
                raise pexpect.EOF('End Of File (EOF) in read(). '
                                  'Braindead platform.')

        if timeout == -1:
            timeout = self.timeout

        r, w, e = select.select([self.child_fd], [], [], timeout)
        if not r:
            raise pexpect.TIMEOUT('Timeout (%s) exceeded in read().' %
                                  str(timeout))

        if self.child_fd in r:
            try:
                s = self.child_fd.recv(size)
            except OSError, e:
                self.flag_eof = True
                raise pexpect.EOF('End Of File (EOF) in read(). '
                                  'Exception style platform.')
            if s == '':
                self.flag_eof = True
                raise pexpect.EOF('End Of File (EOF) in read(). '
                                  'Empty string style platform.')

            if self.logfile is not None:
                self.logfile.write(s)
                self.logfile.flush()

            return s

        raise pexpect.ExceptionPexpect('Reached an unexpected state in read().')
Ejemplo n.º 5
0
def error_message(exc_info, **options):
    """Formats exception or error information for logging and debugging.

    :param tuple exc_info: Exception details from sys module.
    :param Exception options: The exception object for pexpect's ExceptionPexpect (pex) or
        for subprocess' CalledProcessError (cpe).

    :return: The formatted message.

    .. seealso:: https://realpython.com/the-most-diabolical-python-antipattern/#why-log-the-full-stack-trace
    """
    # Get keyword arguments. Initialize default to None to prevent SonarLint reference error
    pex = options.get("pex", pexpect.ExceptionPexpect(None))
    cpe = options.get("cpe", subprocess.CalledProcessError(0, "", None))

    # Unpack sys.exc_info() to get error information
    e_type, e_value, e_traceback = exc_info
    if pex.value:
        # This code is for pexpect.ExceptionPexpect. It retrieves the device's response to
        # pexpect.sendline() from the state of the spawned object (__str__ from ex) for
        # logging. Otherwise, if you match TIMEOUT or EOF when calling expect or expect_exact,
        # pexpect does not retain the state of the object, since it believes you will
        # handle the exception by other means (e.g., generic message to the user, etc.).
        # https://pexpect.readthedocs.io/en/stable/api/pexpect.html#spawn-class
        # https://pexpect.readthedocs.io/en/stable/_modules/pexpect/exceptions.html#TIMEOUT

        # For pexpect.run calls...
        if "searcher" not in str(pex):
            e_value = str(pex).strip("\r\n")
        # For pexpect.expect-type calls...
        else:
            # Log what was actually found during the pexpect call
            e_value = "Expected {0}, found \"{1}".format(
                str(pex).split("searcher: ")[1].split(
                    "buffer (last 100 chars):")[0],
                str(pex).split("before (last 100 chars): ")[1].split("after:")
                [0])
            # Remove any unwanted escape characters here, like backspaces, etc.
        # e_value = re.sub("[\b\r\n]", " ", e_value).replace("  ", " ")
        e_value = " ".join(e_value.replace("\b", "").split())
    elif cpe.output:
        # This code is for subprocess.CalledProcessError. In Python 2.7, subprocess only
        # returns the reason for a non-zero return code (i.e., the CLI's response) in a
        # CalledProcessError object unless the shell option is set to True, which is unsafe due
        # to potential shell injections.
        # https://docs.python.org/2/library/subprocess.html#subprocess.check_output
        e_value = "'{0}' failed: {1}".format(cpe.cmd, cpe.output)

    # Move up the error stack to retrieve the function or method where the error or exception actually occurred,
    # instead of the line number where the function or method was called.
    if e_traceback.tb_next is not None:
        e_traceback = e_traceback.tb_next
    # Return the formatted message for logging
    # Start with a linefeed to avoid tailing device OS messages
    # Error message format:
    # - e_type: Type of error.
    # - e_value: Error message.
    # - e_traceback.tb_frame.f_code.co_filename: The name of the file that caused the error.
    # - e_traceback.tb_lineno: The line number where the error occurred.
    msg = ("\nType {0}: \"{1}\" in {2} at line {3}.\n".format(
        e_type.__name__, e_value, e_traceback.tb_frame.f_code.co_filename,
        e_traceback.tb_lineno))
    log_message(msg, level=logging.ERROR)
    return msg
Ejemplo n.º 6
0
def main():
    child = None
    try:
        print(
            "Lab 1: Connect to an unconfigured device through the Console port"
        )
        device_hostname = "R2"
        gateway_ip_addr = "192.168.1.1"
        device_console_port = 5002
        console_password = "******"
        # child = labs.lab01_telnet.connect(device_hostname, gateway_ip_addr, device_console_port, password=console_password)
        # TODO: NEED TO FIX EOL FOR VTY!
        child = labs.lab01_telnet.connect(device_hostname,
                                          "192.168.1.30",
                                          username="******",
                                          password="******")
        print("Lab 2: Access a network device's Privileged EXEC Mode")
        # Part 1: Up from User EXEC mode
        child.sendline("disable\r")
        child.expect_exact(device_hostname + ">")
        enable_password = "******"
        child = labs.lab02_exec_mode.run(child, device_hostname,
                                         enable_password)
        # Part 2: Down from Global Configuration mode
        child.sendline("configure terminal\r")
        child.expect_exact(device_hostname + "(config)#")
        child.sendline("interface FastEthernet0/0\r")
        child.expect_exact(device_hostname + "(config-if)#")
        child = labs.lab02_exec_mode.run(child, device_hostname,
                                         enable_password)

        print("Lab 3: Format a network device's flash memory")
        child = labs.lab03_format.run(child, device_hostname)

        print("Lab 4: Get information about a network device")
        child = labs.lab04_info.run(child, device_hostname)

        print("Lab 5: Enable Layer 3 communications")
        child = labs.lab05_enable_layer3.run(child,
                                             device_hostname,
                                             "192.168.1.30",
                                             new_netmask="255.255.255.0",
                                             commit=True)

        print("Lab 6a: Secure a network device")
        child = labs.lab06_secure_device.run(child,
                                             device_hostname,
                                             device_username="******",
                                             device_password="******",
                                             privilege=15,
                                             console_password="******",
                                             auxiliary_password="******",
                                             enable_password="******",
                                             commit=True)

        print("Lab 6b: Ping the device from the host")
        _, exitstatus = pexpect.run("ping -c 4 {0}".format("192.168.1.30"),
                                    withexitstatus=True)
        if exitstatus != 0:
            # No need to read the output. Ping returns a non-zero value if no packets are received
            raise RuntimeError("Cannot connect to netowrk device.")

        print(
            "Lab 6c: Connect to a configured device through the Console port")
        labs.lab01_telnet.disconnect(child)
        child.close()
        child = labs.lab01_telnet.connect(device_hostname,
                                          "192.168.1.30",
                                          username="******",
                                          password="******")

        print("Lab 6d: Access a network device's Privileged EXEC Mode")
        child = labs.lab02_exec_mode.run(child, device_hostname,
                                         enable_password)

        print("Lab 6e: Get information about a network device")
        child = labs.lab04_info.run(child, device_hostname)

    except (
            pexpect.ExceptionPexpect,
            ValueError,
            RuntimeError,
            OSError,
    ):
        # Unpack sys.exc_info() to get error information
        e_type, e_value, _ = sys.exc_info()
        # Instantiate the message container
        err_msg = ""
        if e_type in (
                pexpect.ExceptionPexpect,
                pexpect.EOF,
                pexpect.TIMEOUT,
        ):
            # Add a heading to EOF and TIMEOUT errors
            if pexpect.EOF:
                err_msg += "EOF reached: Child process exited unexpectedly.\n"
            elif pexpect.TIMEOUT:
                err_msg += "Timed-out looking for the expected search string.\n"
            # Add trace
            err_msg += pexpect.ExceptionPexpect(e_type).get_trace()
            # For pexpect.run calls...
            if "searcher" not in str(e_value):
                err_msg += (str(e_value).strip("\r\n"))
            # For pexpect.expect-type calls...
            else:
                # Log what was actually found during the pexpect call
                _e_value = "Expected {0}\nFound {1}.".format(
                    str(e_value).split("searcher: ")[1].split(
                        "buffer (last 100 chars):")[0].strip(),
                    str(e_value).split("before (last 100 chars): ")[1].split(
                        "after:")[0].strip())
                # Remove any unwanted escape characters here, like backspaces, etc.
                e_value = _e_value.replace("\b", "")
                err_msg += _e_value
        elif e_type in (
                ValueError,
                RuntimeError,
                OSError,
        ):
            err_msg += (traceback.format_exc().strip())
        print(err_msg)
    finally:
        # Ensure the child is closed
        if child:
            print("Closing child...")
            child.close()
            print("Child closed.")
        print("Script complete. Have a nice day.")
Ejemplo n.º 7
0
class spawn(pexpect.spawn):
    """This class is a wrapper around pexpect.spawn to be able to talk
    to channels instead of normal file descriptors"""
    def set_channel(self, chan):
        self.child_fd = chan  #.fileno()

    def set_console(self, console):
        self.console = console

    def isalive(self):
        try:
            return self.child_fd.get_transport().is_active()
        except AttributeError:
            return False

    def read_nonblocking(self, size=1, timeout=None):
        """
        This reads at most size characters from the child application.
        It includes a timeout. If the read does not complete within the
        timeout period then a TIMEOUT exception is raised.
        If the end of file is read then an EOF exception will be raised.
        If a log file was set using setlog() then all data will
        also be written to the log file.

        Notice that if this method is called with timeout=None 
        then it actually may block.

        This is a non-blocking wrapper around os.read().
        It uses select.select() to implement a timeout. 
        """

        if self.child_fd == -1:
            raise ValueError('I/O operation on closed file')

        # Note that some systems like Solaris don't seem to ever give
        # an EOF when the child dies. In fact, you can still try to read
        # from the child_fd -- it will block forever or until TIMEOUT.
        # For this case, I test isalive() before doing any reading.
        # If isalive() is false, then I pretend that this is the same as EOF.
        if not self.isalive():
            r, w, e = select.select([self.child_fd], [], [], 0)
            if not r:
                self.flag_eof = 1
                raise pexpect.EOF(
                    'End Of File (EOF) in read(). Braindead platform.')

        timeout = 5.0
        r, w, e = select.select([self.child_fd], [], [], timeout)
        if not r:
            print('Timeout (%s) exceeded in read().' % str(timeout))
            raise pexpect.TIMEOUT('Timeout (%s) exceeded in read().' %
                                  str(timeout))
        if self.child_fd in r:
            try:
                s = self.child_fd.recv(size)


#                s = os.read(self.child_fd, size)
            except OSError, e:
                self.flag_eof = 1
                raise pexpect.EOF(
                    'End Of File (EOF) in read(). Exception style platform.')
            if s == '':
                self.flag_eof = 1
                raise pexpect.EOF(
                    'End Of File (EOF) in read(). Empty string style platform.'
                )

            if self.log_file != None:
                self.log_file.write(s)
                self.log_file.flush()

            if hasattr(self, 'console'):
                self.console.send(s)
            return s

        raise pexpect.ExceptionPexpect(
            'Reached an unexpected state in read().')
Ejemplo n.º 8
0
def create_error_msg(exc_info):
    """Captures and formats exception or error information for logging and debugging.

    :param tuple exc_info: Exception details from the sys module.
    :return: The formatted message.

    .. seealso:: https://realpython.com/the-most-diabolical-python-antipattern/#why-log-the-full-stack-trace
    """
    # Unpack sys.exc_info() to get error information
    e_type, e_value, _ = exc_info
    # Instantiate the message container
    err_msg = ""
    if e_type in (
            pexpect.ExceptionPexpect,
            pexpect.EOF,
            pexpect.TIMEOUT,
    ):
        # This code retrieves the device's response to pexpect.sendline()
        # from the state of the spawned object (__str__ from ex).
        # If you match TIMEOUT or EOF when calling expect or expect_exact,
        # pexpect does not retain the state of the object for examination afterwards.
        # https://pexpect.readthedocs.io/en/stable/api/pexpect.html#spawn-class
        # https://pexpect.readthedocs.io/en/stable/_modules/pexpect/exceptions.html#TIMEOUT

        # Add a heading to EOF and TIMEOUT errors
        if pexpect.EOF:
            err_msg += "EOF reached: Child process exited unexpectedly.\n"
        elif pexpect.TIMEOUT:
            err_msg += "Timed-out looking for the expected search string.\n"

        # Add trace
        err_msg += pexpect.ExceptionPexpect(e_type).get_trace()

        # For pexpect.run calls...
        if "searcher" not in str(e_value):
            err_msg += (str(e_value).strip("\r\n"))
        # For pexpect.expect-type calls...
        else:
            # Log what was actually found during the pexpect call
            e_value = "Expected {0}\nFound {1}.".format(
                str(e_value).split("searcher: ")[1].split(
                    "buffer (last 100 chars):")[0].strip(),
                str(e_value).split("before (last 100 chars): ")[1].split(
                    "after:")[0].strip())
            # Remove any unwanted escape characters here, like backspaces, etc.
            e_value = e_value.replace("\b", "")
            err_msg += e_value
    elif e_type in (
            ValueError,
            RuntimeError,
            OSError,
    ):
        # This application manually raises two types of errors: ValueError and RuntimeError.
        # Invalid inputs will throw ValueErrors.
        # Non-zero exit statuses or other issues (e.g., missing credentials, etc.) will throw RuntimeErrors.
        # OSError captures non-Popen subprocess exceptions. In Python 2.7, subprocess only returns the
        # reason for a non-zero return code (i.e., the CLI's response) unless the shell option is set to True,
        # which is unsafe due to potential injections.
        # https://docs.python.org/2/library/subprocess.html#subprocess.check_output
        # All other errors and exceptions indicate syntax or semantic programming issues.
        err_msg += (traceback.format_exc().strip())
    return err_msg