moar fifo/auth.log stuff
authorTero Marttila <terom@paivola.fi>
Wed, 26 Mar 2008 03:03:46 +0200
changeset 18 6348bf9750bc
parent 17 24dc72473ff9
child 19 cbc56b7e7c81
moar fifo/auth.log stuff

committer: Tero Marttila <terom@paivola.fi>
logwatch_config.py.dist
logwatch_filters.py
logwatch_sources.py
logwatcher.py
--- a/logwatch_config.py.dist	Wed Mar 26 02:30:34 2008 +0200
+++ b/logwatch_config.py.dist	Wed Mar 26 03:03:46 2008 +0200
@@ -1,13 +1,19 @@
-from logwatch_filters import *
+import logwatch_filters as filters
+from logwatch_sources import *
 
-# log_files is a sequence of three-tuples
-log_files = (
-    # (name, filename, filter-seq))
-    # name is used for display purposes, filename is the file to follow, and filter-seq is a list of filters to apply to each line of output
-    # filters should inherit from logwatch_filters.Filter
-    ("auth.log", "/var/log/auth.log", (
-        SudoFilter(),
-#       SSHFilter(),
-    )),
-)
+def sources () :
+    """
+        Return a sequence of LogSource objects
+    """
 
+    return (
+        Fifo("auth", "logs/auth.fifo", (
+            filters.sudo,
+            filters.cron_killer,
+            filters.all,
+        )),
+        Fifo("foo", "foo", (
+            filters.all,
+        )),
+    )
+
--- a/logwatch_filters.py	Wed Mar 26 02:30:34 2008 +0200
+++ b/logwatch_filters.py	Wed Mar 26 03:03:46 2008 +0200
@@ -1,43 +1,56 @@
 import re
 
-class Filter (object) :
-    def __init__ (self, regexp, event_type) :
-        self.regexp = re.compile(regexp)
+class FullFilter (object) :
+    def __init__ (self, event_type) :
         self.event_type = event_type
 
     def test (self, line) :
+        return line
+
+class NullFilter (object) :
+    def __init__ (self, pattern, flags=None) :
+        self.regexp = re.compile(pattern, flags)
+    
+    def test (self, line) :
+        match = self.regexp.search(line)
+        
+        if match :
+            return False
+
+class SimpleFilter (object) :
+    def __init__ (self, event_type, pattern, format) :
+        self.event_type = event_type
+
+        self.regexp = re.compile(pattern)
+        self.format = format
+
+    def test (self, line) :
         match = self.regexp.search(line)
         
         if match :
             return self._filter(match)
         
     def _filter (self, match) :
-        return match.string
-
-class AutoFilter (Filter) :
-    # your event type here, as a string
-    EVENT = None
-
-    # your regexp here, with named matchgroups
-    REGEXP = None
+        return self.format % match.groupdict()
 
-    # your output format, with named interpolation params
-    OUTPUT = None
-    
-    def __init__ (self) :
-        super(AutoFilter, self).__init__(self.REGEXP, self.EVENT)
-    
-    def _filter (self, match) :
-        return self.OUTPUT % match.groupdict()
+all = FullFilter("all")
 
-class SudoFilter (AutoFilter) :
-    EVENT   = "sudo"
-    REGEXP  = "sudo:\s*(?P<username>\S+) : TTY=(?P<tty>\S+) ; PWD=(?P<pwd>.+?) ; USER=(?P<target_user>\S+) ; COMMAND=(?P<command>.*)"
-    OUTPUT  = "%(username)s:%(tty)s - %(pwd)s - `%(command)s` as %(target_user)s"
+_timestamp = "\w{3} \d{2} \d{2}:\d{2}:\d{2}"
 
-class SSHFilter (AutoFilter) :
-    EVENT   = "ssh"
-    REGEXP  = "(?P<success>Accepted|Failed) password for (?P<username>\S+) from (?P<ip>\S+) port (?P<port>\S+) (?P<proto>\S+)"
-    OUTPUT  = "%(success)s login for %(username)s from %(ip)s:%(port)s proto %(proto)s"
+sudo = SimpleFilter(
+    "sudo",
+    "(?P<hostname>\S+)\s+sudo:\s*(?P<username>\S+) : TTY=(?P<tty>\S+) ; PWD=(?P<pwd>.+?) ; USER=(?P<target_user>\S+) ; COMMAND=(?P<command>.*)",
+    "%(username)s:%(tty)s - %(target_user)s@%(hostname)s:%(pwd)s - %(command)r"
+)
 
+ssh = SimpleFilter(
+    "ssh",
+    "(?P<success>Accepted|Failed) password for (?P<username>\S+) from (?P<ip>\S+) port (?P<port>\S+) (?P<proto>\S+)",
+    "%(success)s login for %(username)s from %(ip)s:%(port)s proto %(proto)s"
+)
 
+cron_killer = NullFilter(
+        "^" + _timestamp + "\S+\s+CRON\[\d+\]: (\w+) session (opened|closed) for user \w+( by \(uid=\d+\))?$",
+        re.IGNORECASE
+)
+
--- a/logwatch_sources.py	Wed Mar 26 02:30:34 2008 +0200
+++ b/logwatch_sources.py	Wed Mar 26 03:03:46 2008 +0200
@@ -44,6 +44,12 @@
                 log.msg("\t%s: %s" % (filter.event_type, out))
                 self.module.sendEvent(filter.event_type, out)
 
+                break
+            elif out is False :
+                return
+            else :  # None
+                continue
+
 class File (LogSource, protocol.ProcessProtocol) :
     def __init__ (self, name, path, filters) :
         super(File, self).__init__(name, filters)
--- a/logwatcher.py	Wed Mar 26 02:30:34 2008 +0200
+++ b/logwatcher.py	Wed Mar 26 03:03:46 2008 +0200
@@ -5,65 +5,20 @@
 import api
 import logwatch_config as config
 
-class TailProcessProtocol (protocol.ProcessProtocol) :
-    def __init__ (self, module, name, filters) :
-        self.module = module
-        self.name = name
-        self.filters = filters
-
-        self.buf = ""
-
-    def errReceived (self, data) :
-        self.module.error("tail for %s: %s" % (self.name, data))
-
-    def outReceived (self, data) :
-        data = self.buf + data
-        
-        while "\n" in data :
-            line, data = data.split("\n", 1)
-            
-            log.msg("Matching line `%s'..." % line)
-
-            for filter in self.filters :
-                out = filter.test(line)
-
-                if out :
-                    log.msg("\t%s: %s" % (filter.event_type, out))
-                    self.module.sendEvent(filter.event_type, out)
-
-        self.buf = data
-
-    def processEnded (self, reason) :
-        msg = "tail process for %s quit: %s" % (self.name, reason.getErrorMessage())
-
-        log.err(msg)
-        self.module.error(msg)
-
 class LogWatchModule (api.Module) :
     name = "logs"
-    version = 0x0001
+    version = 0x0005
     
     event_types = [
         "error",
         "sudo",
         "ssh",
+        "all"
     ]
     
-    log_files = config.log_files
-
-    log_objs = None
-
     def handleConnect (self) :
-        log.msg("Spawning tail processes...")
-        
-        self.log_objs = dict()
-
-        for name, file, filters in self.log_files :
-            log.msg("\t%s - %s..." % (name, file))
-
-            p = self.log_objs[name] = TailProcessProtocol(self, name, filters)
-
-            reactor.spawnProcess(p, "/usr/bin/tail", ["tail", "-n0", "--follow=name", file])
+        for source in config.sources() :
+            source.setModule(self)
     
     def error (self, msg) :
         self.sendEvent("error", msg)