# # logactio - simple framework for doing configured action on certain # log file events # # Copyright 2012 - 2015 David Sommerseth # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation, version 2 # of the License. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # For the avoidance of doubt the "preferred form" of this code is one which # is in an open unpatent encumbered format. Where cryptographic key signing # forms part of the process of creating an executable the information # including keys needed to generate an equivalently functional executable # are deemed to be part of the source code. # import sys, smtplib from email.mime.text import MIMEText from LogActio import Message, ReporterQueue class SMTPreporter(ReporterQueue.ReporterQueue): """Simple LogActio reporter module, sending alerts via SMTP Example configuration to be used in /etc/logactio.cfg [Reporter:SMTP] module: SMTPreporter sender: logactio@example.com recipients: john.doe@example.com, jane.doe@example.com subject_prefix: LogActio Alert: smtp_host: localhost smtp_port: 25 This will send reports to the configured 'recipients' using the given SMTP server. """ def __init__(self, config, logger = None): if "sender" not in config: raise Exception("SMTPreporter is not configured with a sender address") if "recipients" not in config: raise Exception("SMTPreporter is not configured with any recipients") if "smtp_host" not in config: raise Exception("SMTPreporter is not configured with SMTP host") self.__log = logger and logger or self.__logfnc self.__sender = config["sender"] self.__recipients = config["recipients"].split(",") self.__subjprefix = "subject_prefix" in config and config["subject_prefix"] or None self.__smtphost = config["smtp_host"] self.__smtpport = "smtp_port" in config and (int(config["smtp_port"])) or 25 self.__smtpuser = "smtp_username" in config and config["smtp_username"] or None self.__smtppass = "smtp_password" in config and config["smtp_password"] or None self.__sslmode = "sslmode" in config and config["sslmode"] or None self.__idx = 0; if (self.__smtpuser and not self.__smtppass) or (not self.__smtpuser and self.__smtppass): raise Exception("SMTPreporter must have both smtp_username and smtp_password") if self.__sslmode is not None and self.__sslmode != "SSL" and self.__sslmode != "STARTTLS": raise Exception("SMTPreporter accepts only SSL or STARTTLS as sslmode values") ReporterQueue.ReporterQueue.__init__(self, "SMTPreporter", "SMTP Reporter", self.__processqueue) def __logfnc(self, lvl, msg): print("%s" % msg) sys.stdout.flush() def __processqueue(self): done = False # Process the message queue while not done: msg = self._QueueGet() if( msg.MessageType() == Message.MSG_SHUTDOWN ): # Prepare for shutdown done = True elif( msg.MessageType() == Message.MSG_SEND ): m = msg.Message() msg = MIMEText(m["body"]) msg["From"] = self.__sender msg["To"] = ",".join(self.__recipients) if self.__subjprefix is None: msg["Subject"] = "LogActio Alert: %s" % m["subject"] else: msg["Subject"] = "%s %s" % (self.__subjprefix, m["subject"]) try: self.__log(3, "[SMTPreporter] Connecting to %s:%i" % (self.__smtphost, self.__smtpport)) if self.__sslmode == "SSL": smtp.smtplib.SMTP_SSL(self.__smtphost, self.__smtpport) else: smtp = smtplib.SMTP(self.__smtphost, self.__smtpport) if self.__sslmode == "STARTTLS": smtp.starttls() if self.__smtpuser is not None: self.__log(3, "[SMTPreporter] Logging in as %s" % self.__smtpuser) smtp.login(self.__smtpuser, self.__smtppass) smtp.sendmail(self.__sender, self.__recipients, msg.as_string()) self.__idx += 1 self.__log(1, "[SMTPReporter] {%i} {Rule %s} Logfile: %s, Threshold: %i, Count: %i -- Report sent to: %s" % (self.__idx, m["rulename"], m["logfile"], m["threshold"], m["count"], ", ".join(self.__recipients))) self.__log(2, "[SMTPReporter] {%i} Details: %s" % (self.__idx, str(m["msg"]))) smtp.quit() except Exception as e: self.__log(0, "** ERROR ** SMTPreporter failed: {%i} %s" % (self.__idx, str(e))) def ProcessEvent(self, logfile, rulename, msg, count, threshold): # Format the report message msg = {"rulename": rulename, "threshold": threshold, "count": count, "logfile": logfile, "msg": msg, "subject": "Alerts from %s" % logfile, "body": """ LogActio have detected %s events in the %s log file since it started running.\n The following information was extracted:\n %s """ % (count, logfile, "\n".join(msg))} # Queue the message for sending self._QueueMsg(0, msg) def InitReporter(config, logger = None): return SMTPreporter(config, logger)