--- 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)