fixbot/logwatch/filters.py
changeset 48 ba101beeb062
parent 40 b9fdb7710768
child 49 666e638059b2
equal deleted inserted replaced
47:81b37185209c 48:ba101beeb062
     1 import re
     1 import re
     2 
     2 
     3 class FullFilter (object) :
     3 class BaseFilter (object) :
       
     4     """
       
     5         A filter object matches incoming lines, to determine how they are handled, classify them, and optionally reformat them
       
     6     """
       
     7     
       
     8     # the LogWatchModule event to send
       
     9     event_type = None
       
    10     
     4     def __init__ (self, event_type) :
    11     def __init__ (self, event_type) :
     5         self.event_type = event_type
    12         self.event_type = event_type
     6 
    13 
     7     def test (self, line) :
    14     def test (self, line) :
     8         return line
    15         """
       
    16             Match against the given line, and return one of:
     9 
    17 
    10 class NullFilter (object) :
    18                 None        - filter did not match, continue
       
    19                 False       - filter matched, line should be dropped
       
    20                     (type, <str>)
       
    21                             - filter matched, pass formatted output
       
    22         """
       
    23 
       
    24         raise NotImplementedError()
       
    25 
       
    26 class FullFilter (BaseFilter) :
       
    27     """
       
    28         A trivial filter that matches every possible line as-is
       
    29     """
       
    30 
       
    31     def test (self, line) :
       
    32         # pass through
       
    33         return self.event_type, line
       
    34 
       
    35 class NullFilter (BaseFilter) :
       
    36     """
       
    37         A filter that drops every line matching a given regexp
       
    38     """
       
    39     
    11     def __init__ (self, pattern, flags=None) :
    40     def __init__ (self, pattern, flags=None) :
       
    41         # don't need an event_type
       
    42 
    12         self.regexp = re.compile(pattern, flags)
    43         self.regexp = re.compile(pattern, flags)
    13     
    44     
    14     def test (self, line) :
    45     def test (self, line) :
    15         match = self.regexp.search(line)
    46         match = self.regexp.search(line)
    16         
    47         
    17         if match :
    48         if match :
       
    49             # drop
    18             return False
    50             return False
    19 
    51 
    20 class SimpleFilter (object) :
    52 class SimpleFilter (BaseFilter) :
    21     def __init__ (self, event_type, pattern, format) :
    53     """
    22         self.event_type = event_type
    54         A simple filter that passes through any lines that match, optionally reformatting them with the given string
       
    55         pattern, using the regexp match groups as parameters.
       
    56     """
    23 
    57 
       
    58     def __init__ (self, event_type, pattern, format=None) :
       
    59         super(SimpleFilter, self).__init__(event_type)
       
    60         
       
    61         # store
    24         self.regexp = re.compile(pattern)
    62         self.regexp = re.compile(pattern)
    25         self.format = format
    63         self.format = format
    26 
    64 
    27     def test (self, line) :
    65     def test (self, line) :
       
    66         # match
    28         match = self.regexp.search(line)
    67         match = self.regexp.search(line)
    29         
    68         
    30         if match :
    69         if not match :
    31             return self._filter(match)
    70             # continue
       
    71             return None
    32         
    72         
    33     def _filter (self, match) :
    73         # reformat?
    34         return self.format % match.groupdict()
    74         if self.format :
       
    75             # format with regexp match groups
       
    76             return self.event_type, self.format % match.groupdict()
       
    77         
       
    78         else :
       
    79             # match as-is
       
    80             return self.event_type, line
    35 
    81 
       
    82 # matches a timestamp prefix
    36 _timestamp = "\w{3} [0-9 ]\d \d{2}:\d{2}:\d{2}"
    83 _timestamp = "\w{3} [0-9 ]\d \d{2}:\d{2}:\d{2}"
    37 
    84 
       
    85 
       
    86 # matches all lines
    38 all = FullFilter("all")
    87 all = FullFilter("all")
    39 
    88 
       
    89 # match all lines, but drop the prefixed timestamp
    40 all_wo_timestamps = SimpleFilter(
    90 all_wo_timestamps = SimpleFilter(
    41     "all",
    91     "all",
    42     "^" + _timestamp + " (?P<line>.+)$",
    92     "^" + _timestamp + " (?P<line>.+)$",
    43     "%(line)s"
    93     "%(line)s"
    44 )
    94 )
    45 
    95 
       
    96 # match sudo invocations, reformatting them nicely
    46 sudo = SimpleFilter(
    97 sudo = SimpleFilter(
    47     "sudo",
    98     "sudo",
    48     "(?P<hostname>\S+)\s+sudo:\s*(?P<username>\S+) : TTY=(?P<tty>\S+) ; PWD=(?P<pwd>.+?) ; USER=(?P<target_user>\S+) ; COMMAND=(?P<command>.*)",
    99     "(?P<hostname>\S+)\s+sudo:\s*(?P<username>\S+) : TTY=(?P<tty>\S+) ; PWD=(?P<pwd>.+?) ; USER=(?P<target_user>\S+) ; COMMAND=(?P<command>.*)",
    49     "%(username)s:%(tty)s - %(target_user)s@%(hostname)s:%(pwd)s - %(command)r"
   100     "%(username)s:%(tty)s - %(target_user)s@%(hostname)s:%(pwd)s - %(command)r"
    50 )
   101 )
    51 
   102 
       
   103 # match accepted ssh logins
    52 ssh = SimpleFilter(
   104 ssh = SimpleFilter(
    53     "ssh",
   105     "ssh",
    54     "(?P<success>Accepted|Failed) password for (?P<username>\S+) from (?P<ip>\S+) port (?P<port>\S+) (?P<proto>\S+)",
   106     "Accepted password for (?P<username>\S+) from (?P<ip>\S+) port (?P<port>\S+) (?P<proto>\S+)",
    55     "%(success)s login for %(username)s from %(ip)s:%(port)s proto %(proto)s"
   107     "SSH login for %(username)s from %(ip)s:%(port)s"
    56 )
   108 )
    57 
   109 
       
   110 # drops pam output from cron
    58 cron_killer = NullFilter(
   111 cron_killer = NullFilter(
    59         "^" + _timestamp + " \S+\s+(CRON|su)\[\d+\]: pam_unix\(cron:\w+\): session (opened|closed) for user \w+( by \(uid=\d+\))?$",
   112         "^" + _timestamp + " \S+\s+(CRON|su)\[\d+\]: pam_unix\(cron:\w+\): session (opened|closed) for user \w+( by \(uid=\d+\))?$",
    60         re.IGNORECASE
   113         re.IGNORECASE
    61 )
   114 )
    62 
   115 
       
   116 # drops `su nobody` output (from cron)
    63 su_nobody_killer = NullFilter(
   117 su_nobody_killer = NullFilter(
    64     "^" + _timestamp + " \S+\s+su\[\d+\]: (Successful su for nobody by root|\+ \?\?\? root:nobody)$",
   118     "^" + _timestamp + " \S+\s+su\[\d+\]: (Successful su for nobody by root|\+ \?\?\? root:nobody)$",
    65     re.IGNORECASE
   119     re.IGNORECASE
    66 )
   120 )
       
   121