summaryrefslogtreecommitdiffstats
path: root/LogActio/Reporters/SMTPreporter.py
blob: 5781bff90c917478ab2d20e84faefe32cdb862be (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#
#   logactio  -  simple framework for doing configured action on certain
#                log file events
#
#   Copyright 2012 - 2015   David Sommerseth <dazo@eurephia.org>
#
#   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)