def setup_logfile_logger(log_path, log_level=None, log_format=None, date_format=None): """ Set up logging to a file. """ # Create the handler handler = WatchedFileHandler(log_path, mode='a', encoding='utf-8', delay=0) if log_level: # Grab and set the level level = LOG_LEVELS.get(log_level.lower(), logging.ERROR) handler.setLevel(level) # Set the default console formatter config if not log_format: log_format = '%(asctime)s [%(name)s][%(levelname)s] %(message)s' if not date_format: date_format = '%Y-%m-%d %H:%M:%S' formatter = logging.Formatter(log_format, datefmt=date_format) handler.setFormatter(formatter) root_logger.addHandler(handler) return handler
def verify_log(opts): ''' If an insecre logging configuration is found, show a warning ''' level = LOG_LEVELS.get(str(opts.get('log_level')).lower(), logging.NOTSET) if level < logging.INFO: log.warning('Insecure logging configuration detected! Sensitive data may be logged.')
def setup_logfile_logger(log_path, log_level=None, log_format=None, date_format=None): """ Set up logging to a file. """ # Create the handler handler = WatchedFileHandler(log_path) if log_level: # Grab and set the level level = LOG_LEVELS.get(log_level.lower(), logging.ERROR) handler.setLevel(level) # Set the default console formatter config if not log_format: log_format = '%(asctime)s [%(name)-15s][%(levelname)-8s] %(message)s' if not date_format: date_format = '%Y-%m-%d %H:%M:%S' formatter = logging.Formatter(log_format, datefmt=date_format) handler.setFormatter(formatter) root_logger.addHandler(handler) return handler
def __init__( self, args=None, executable=None, shell=False, cwd=None, env=None, preexec_fn=None, # Terminal Size rows=None, cols=None, # Logging options log_stdin=None, log_stdin_level='debug', log_stdout=None, log_stdout_level='debug', log_stderr=None, log_stderr_level='debug', # sys.stdXYZ streaming options stream_stdout=None, stream_stderr=None, ): # Let's avoid Zombies!!! _cleanup() if not args and not executable and not shell: raise TerminalException( 'You need to pass at least one of \'args\', \'executable\' ' 'or \'shell=True\'') self.args = args self.executable = executable self.shell = shell self.cwd = cwd self.env = env self.preexec_fn = preexec_fn # ----- Set the desired terminal size -------------------------------> if rows is None and cols is None: rows, cols = self.__detect_parent_terminal_size() elif rows is not None and cols is None: _, cols = self.__detect_parent_terminal_size() elif rows is None and cols is not None: rows, _ = self.__detect_parent_terminal_size() self.rows = rows self.cols = cols # <---- Set the desired terminal size -------------------------------- # ----- Internally Set Attributes -----------------------------------> self.pid = None self.stdin = None self.stdout = None self.stderr = None self.child_fd = None self.child_fde = None self.closed = True self.flag_eof_stdout = False self.flag_eof_stderr = False self.terminated = True self.exitstatus = None self.signalstatus = None # status returned by os.waitpid self.status = None self.__irix_hack = 'irix' in sys.platform.lower() # <---- Internally Set Attributes ------------------------------------ # ----- Direct Streaming Setup --------------------------------------> if stream_stdout is True: self.stream_stdout = sys.stdout elif stream_stdout is False: self.stream_stdout = None elif stream_stdout is not None: if not hasattr(stream_stdout, 'write') or \ not hasattr(stream_stdout, 'flush') or \ not hasattr(stream_stdout, 'close'): raise TerminalException( '\'stream_stdout\' needs to have at least 3 methods, ' '\'write()\', \'flush()\' and \'close()\'.') self.stream_stdout = stream_stdout else: raise TerminalException( 'Don\'t know how to handle {0!r} as the VT\'s ' '\'stream_stdout\' parameter.'.format(stream_stdout)) if stream_stderr is True: self.stream_stderr = sys.stderr elif stream_stderr is False: self.stream_stderr = None elif stream_stderr is not None: if not hasattr(stream_stderr, 'write') or \ not hasattr(stream_stderr, 'flush') or \ not hasattr(stream_stderr, 'close'): raise TerminalException( '\'stream_stderr\' needs to have at least 3 methods, ' '\'write()\', \'flush()\' and \'close()\'.') self.stream_stderr = stream_stderr else: raise TerminalException( 'Don\'t know how to handle {0!r} as the VT\'s ' '\'stream_stderr\' parameter.'.format(stream_stderr)) # <---- Direct Streaming Setup --------------------------------------- # ----- Spawn our terminal ------------------------------------------> try: self._spawn() except Exception as err: # pylint: disable=W0703 # A lot can go wrong, so that's why we're catching the most general # exception type log.warning('Failed to spawn the VT: {0}'.format(err), exc_info_on_loglevel=logging.DEBUG) raise TerminalException( 'Failed to spawn the VT. Error: {0}'.format(err)) log.debug('Child Forked! PID: {0} STDOUT_FD: {1} STDERR_FD: ' '{2}'.format(self.pid, self.child_fd, self.child_fde)) log.debug('Terminal Command: {0}'.format(' '.join(self.args))) # <---- Spawn our terminal ------------------------------------------- # ----- Setup Logging -----------------------------------------------> # Setup logging after spawned in order to have a pid value self.stdin_logger_level = LOG_LEVELS.get(log_stdin_level, log_stdin_level) if log_stdin is True: self.stdin_logger = logging.getLogger( '{0}.{1}.PID-{2}.STDIN'.format(__name__, self.__class__.__name__, self.pid)) elif log_stdin is not None: if not isinstance(log_stdin, logging.Logger): raise RuntimeError( '\'log_stdin\' needs to subclass `logging.Logger`') self.stdin_logger = log_stdin else: self.stdin_logger = None self.stdout_logger_level = LOG_LEVELS.get(log_stdout_level, log_stdout_level) if log_stdout is True: self.stdout_logger = logging.getLogger( '{0}.{1}.PID-{2}.STDOUT'.format(__name__, self.__class__.__name__, self.pid)) elif log_stdout is not None: if not isinstance(log_stdout, logging.Logger): raise RuntimeError( '\'log_stdout\' needs to subclass `logging.Logger`') self.stdout_logger = log_stdout else: self.stdout_logger = None self.stderr_logger_level = LOG_LEVELS.get(log_stderr_level, log_stderr_level) if log_stderr is True: self.stderr_logger = logging.getLogger( '{0}.{1}.PID-{2}.STDERR'.format(__name__, self.__class__.__name__, self.pid)) elif log_stderr is not None: if not isinstance(log_stderr, logging.Logger): raise RuntimeError( '\'log_stderr\' needs to subclass `logging.Logger`') self.stderr_logger = log_stderr else: self.stderr_logger = None
def __init__( self, args=None, executable=None, shell=False, cwd=None, env=None, preexec_fn=None, # Terminal Size rows=None, cols=None, # Logging options log_stdin=None, log_stdin_level="debug", log_stdout=None, log_stdout_level="debug", log_stderr=None, log_stderr_level="debug", # sys.stdXYZ streaming options stream_stdout=None, stream_stderr=None, # Used for tests force_receive_encoding=__salt_system_encoding__, ): # Let's avoid Zombies!!! _cleanup() if not args and not executable: raise TerminalException( 'You need to pass at least one of "args", "executable" ') self.args = args self.executable = executable self.shell = shell self.cwd = cwd self.env = env self.preexec_fn = preexec_fn self.receive_encoding = force_receive_encoding # ----- Set the desired terminal size -------------------------------> if rows is None and cols is None: rows, cols = self.__detect_parent_terminal_size() elif rows is not None and cols is None: _, cols = self.__detect_parent_terminal_size() elif rows is None and cols is not None: rows, _ = self.__detect_parent_terminal_size() self.rows = rows self.cols = cols # <---- Set the desired terminal size -------------------------------- # ----- Internally Set Attributes -----------------------------------> self.pid = None self.stdin = None self.stdout = None self.stderr = None self.child_fd = None self.child_fde = None self.partial_data_stdout = b"" self.partial_data_stderr = b"" self.closed = True self.flag_eof_stdout = False self.flag_eof_stderr = False self.terminated = True self.exitstatus = None self.signalstatus = None # status returned by os.waitpid self.status = None self.__irix_hack = "irix" in sys.platform.lower() # <---- Internally Set Attributes ------------------------------------ # ----- Direct Streaming Setup --------------------------------------> if stream_stdout is True: self.stream_stdout = sys.stdout elif stream_stdout is False: self.stream_stdout = None elif stream_stdout is not None: if (not hasattr(stream_stdout, "write") or not hasattr(stream_stdout, "flush") or not hasattr(stream_stdout, "close")): raise TerminalException( "'stream_stdout' needs to have at least 3 methods, " "'write()', 'flush()' and 'close()'.") self.stream_stdout = stream_stdout else: raise TerminalException( "Don't know how to handle '{}' as the VT's " "'stream_stdout' parameter.".format(stream_stdout)) if stream_stderr is True: self.stream_stderr = sys.stderr elif stream_stderr is False: self.stream_stderr = None elif stream_stderr is not None: if (not hasattr(stream_stderr, "write") or not hasattr(stream_stderr, "flush") or not hasattr(stream_stderr, "close")): raise TerminalException( "'stream_stderr' needs to have at least 3 methods, " "'write()', 'flush()' and 'close()'.") self.stream_stderr = stream_stderr else: raise TerminalException( "Don't know how to handle '{}' as the VT's " "'stream_stderr' parameter.".format(stream_stderr)) # <---- Direct Streaming Setup --------------------------------------- # ----- Spawn our terminal ------------------------------------------> try: self._spawn() except Exception as err: # pylint: disable=W0703 # A lot can go wrong, so that's why we're catching the most general # exception type log.warning("Failed to spawn the VT: %s", err, exc_info_on_loglevel=logging.DEBUG) raise TerminalException( "Failed to spawn the VT. Error: {}".format(err)) log.debug( "Child Forked! PID: %s STDOUT_FD: %s STDERR_FD: %s", self.pid, self.child_fd, self.child_fde, ) terminal_command = " ".join(self.args) if ('decode("base64")' in terminal_command or "base64.b64decode(" in terminal_command): log.debug( "VT: Salt-SSH SHIM Terminal Command executed. Logged to TRACE") log.trace("Terminal Command: %s", terminal_command) else: log.debug("Terminal Command: %s", terminal_command) # <---- Spawn our terminal ------------------------------------------- # ----- Setup Logging -----------------------------------------------> # Setup logging after spawned in order to have a pid value self.stdin_logger_level = LOG_LEVELS.get(log_stdin_level, log_stdin_level) if log_stdin is True: self.stdin_logger = logging.getLogger("{}.{}.PID-{}.STDIN".format( __name__, self.__class__.__name__, self.pid)) elif log_stdin is not None: if not isinstance(log_stdin, logging.Logger): raise RuntimeError( "'log_stdin' needs to subclass `logging.Logger`") self.stdin_logger = log_stdin else: self.stdin_logger = None self.stdout_logger_level = LOG_LEVELS.get(log_stdout_level, log_stdout_level) if log_stdout is True: self.stdout_logger = logging.getLogger( "{}.{}.PID-{}.STDOUT".format(__name__, self.__class__.__name__, self.pid)) elif log_stdout is not None: if not isinstance(log_stdout, logging.Logger): raise RuntimeError( "'log_stdout' needs to subclass `logging.Logger`") self.stdout_logger = log_stdout else: self.stdout_logger = None self.stderr_logger_level = LOG_LEVELS.get(log_stderr_level, log_stderr_level) if log_stderr is True: self.stderr_logger = logging.getLogger( "{}.{}.PID-{}.STDERR".format(__name__, self.__class__.__name__, self.pid)) elif log_stderr is not None: if not isinstance(log_stderr, logging.Logger): raise RuntimeError( "'log_stderr' needs to subclass `logging.Logger`") self.stderr_logger = log_stderr else: self.stderr_logger = None
def __init__(self, args=None, executable=None, shell=False, cwd=None, env=None, preexec_fn=None, # Terminal Size rows=None, cols=None, # Logging options log_stdin=None, log_stdin_level='debug', log_stdout=None, log_stdout_level='debug', log_stderr=None, log_stderr_level='debug', # sys.stdXYZ streaming options stream_stdout=None, stream_stderr=None, ): # Let's avoid Zombies!!! _cleanup() if not args and not executable and not shell: raise TerminalException( 'You need to pass at least one of \'args\', \'executable\' ' 'or \'shell=True\'' ) self.args = args self.executable = executable self.shell = shell self.cwd = cwd self.env = env self.preexec_fn = preexec_fn # ----- Set the desired terminal size -------------------------------> if rows is None and cols is None: rows, cols = self.__detect_parent_terminal_size() elif rows is not None and cols is None: _, cols = self.__detect_parent_terminal_size() elif rows is None and cols is not None: rows, _ = self.__detect_parent_terminal_size() self.rows = rows self.cols = cols # <---- Set the desired terminal size -------------------------------- # ----- Internally Set Attributes -----------------------------------> self.pid = None self.stdin = None self.stdout = None self.stderr = None self.child_fd = None self.child_fde = None self.closed = True self.flag_eof_stdout = False self.flag_eof_stderr = False self.terminated = True self.exitstatus = None self.signalstatus = None # status returned by os.waitpid self.status = None self.__irix_hack = 'irix' in sys.platform.lower() # <---- Internally Set Attributes ------------------------------------ # ----- Direct Streaming Setup --------------------------------------> if stream_stdout is True: self.stream_stdout = sys.stdout elif stream_stdout is False: self.stream_stdout = None elif stream_stdout is not None: if not hasattr(stream_stdout, 'write') or \ not hasattr(stream_stdout, 'flush') or \ not hasattr(stream_stdout, 'close'): raise TerminalException( '\'stream_stdout\' needs to have at least 3 methods, ' '\'write()\', \'flush()\' and \'close()\'.' ) self.stream_stdout = stream_stdout else: raise TerminalException( 'Don\'t know how to handle {0!r} as the VT\'s ' '\'stream_stdout\' parameter.'.format(stream_stdout) ) if stream_stderr is True: self.stream_stderr = sys.stderr elif stream_stderr is False: self.stream_stderr = None elif stream_stderr is not None: if not hasattr(stream_stderr, 'write') or \ not hasattr(stream_stderr, 'flush') or \ not hasattr(stream_stderr, 'close'): raise TerminalException( '\'stream_stderr\' needs to have at least 3 methods, ' '\'write()\', \'flush()\' and \'close()\'.' ) self.stream_stderr = stream_stderr else: raise TerminalException( 'Don\'t know how to handle {0!r} as the VT\'s ' '\'stream_stderr\' parameter.'.format(stream_stderr) ) # <---- Direct Streaming Setup --------------------------------------- # ----- Spawn our terminal ------------------------------------------> try: self._spawn() except Exception as err: # pylint: disable=W0703 # A lot can go wrong, so that's why we're catching the most general # exception type log.warning( 'Failed to spawn the VT: {0}'.format(err), exc_info_on_loglevel=logging.DEBUG ) raise TerminalException( 'Failed to spawn the VT. Error: {0}'.format(err) ) log.debug( 'Child Forked! PID: {0} STDOUT_FD: {1} STDERR_FD: ' '{2}'.format(self.pid, self.child_fd, self.child_fde) ) terminal_command = ' '.join(self.args) if 'decode("base64")' in terminal_command: log.debug('VT: Salt-SSH SHIM Terminal Command executed. Logged to TRACE') log.trace('Terminal Command: {0}'.format(terminal_command)) else: log.debug('Terminal Command: {0}'.format(terminal_command)) # <---- Spawn our terminal ------------------------------------------- # ----- Setup Logging -----------------------------------------------> # Setup logging after spawned in order to have a pid value self.stdin_logger_level = LOG_LEVELS.get(log_stdin_level, log_stdin_level) if log_stdin is True: self.stdin_logger = logging.getLogger( '{0}.{1}.PID-{2}.STDIN'.format( __name__, self.__class__.__name__, self.pid ) ) elif log_stdin is not None: if not isinstance(log_stdin, logging.Logger): raise RuntimeError( '\'log_stdin\' needs to subclass `logging.Logger`' ) self.stdin_logger = log_stdin else: self.stdin_logger = None self.stdout_logger_level = LOG_LEVELS.get(log_stdout_level, log_stdout_level) if log_stdout is True: self.stdout_logger = logging.getLogger( '{0}.{1}.PID-{2}.STDOUT'.format( __name__, self.__class__.__name__, self.pid ) ) elif log_stdout is not None: if not isinstance(log_stdout, logging.Logger): raise RuntimeError( '\'log_stdout\' needs to subclass `logging.Logger`' ) self.stdout_logger = log_stdout else: self.stdout_logger = None self.stderr_logger_level = LOG_LEVELS.get(log_stderr_level, log_stderr_level) if log_stderr is True: self.stderr_logger = logging.getLogger( '{0}.{1}.PID-{2}.STDERR'.format( __name__, self.__class__.__name__, self.pid ) ) elif log_stderr is not None: if not isinstance(log_stderr, logging.Logger): raise RuntimeError( '\'log_stderr\' needs to subclass `logging.Logger`' ) self.stderr_logger = log_stderr else: self.stderr_logger = None