from twisted.internet import protocol, reactor
from twisted.python import log
import sys, re
import api
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 Filter (object) :
def __init__ (self, regexp, event_type) :
self.regexp = re.compile(regexp)
self.event_type = event_type
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
# 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()
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"
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"
class LogWatchModule (api.Module) :
name = "logs"
version = 0x0001
event_types = [
"error",
"sudo",
"ssh",
]
log_files = (
("auth.log", "/var/log/auth.log", (
SudoFilter(),
SSHFilter(),
)),
)
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])
def error (self, msg) :
self.sendEvent("error", msg)
if __name__ == '__main__' :
LogWatchModule().run()