diff --git a/Dockerfile b/Dockerfile index da98f46..c89ccef 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,92 +1,38 @@ FROM ubuntu:focal -# Packages: update & install -RUN apt-get update -qq && \ - DEBIAN_FRONTEND=noninteractive apt-get install -qq -y --no-install-recommends python3-pip supervisor build-essential apache2 libapache2-mod-php7.4 snmp-mibs-downloader apache2-utils wget curl samba-common samba-common-bin smbclient snmp whois traceroute libgd-dev libssl-dev libnet-snmp-perl libperl-dev libpq5 libsensors5 libsnmp-base libtalloc2 libtdb1 libwbclient0 libmysqlclient-dev unzip inetutils-ping sudo openssh-client bind9-dnsutils file && \ - pip3 install j2cli && \ - update-alternatives --install /usr/bin/python python $(which python3) 2 # Workaround for nagios scripts wanting python2 as "python" -# Const -ENV NAGIOS_PHP_TIMEZONE=UTC \ - NAGIOS_TARBALL=https://phoenixnap.dl.sourceforge.net/project/nagios/nagios-4.x/nagios-4.4.6/nagios-4.4.6.tar.gz \ - NAGIOS_PLUGINS_TARBALL=https://www.nagios-plugins.org/download/nagios-plugins-2.3.3.tar.gz \ - NAGIOS_NRPE_TARBALL=https://phoenixnap.dl.sourceforge.net/project/nagios/nrpe-4.x/nrpe-4.0.3/nrpe-4.0.3.tar.gz \ - NAGIOS_NSCA_TARBALL=https://phoenixnap.dl.sourceforge.net/project/nagios/nsca-2.x/nsca-2.10.0/nsca-2.10.0.tar.gz -# Using manual: https://raymii.org/s/tutorials/Nagios_Core_4_Installation_on_Ubuntu_12.04.html +# Supervisor +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y supervisor && \ + rm -rf /var/lib/apt/lists/* -#https://kent.dl.sourceforge.net/project/nagios/nrpe-2.x/nrpe-2.15/nrpe-2.15.tar.gz \ -# Users -RUN groupadd -g 3000 nagios && \ - useradd -u 3000 -g nagios -G www-data -m -s /bin/bash nagios +# Apache +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y apache2 libapache2-mod-php7.4 apache2-utils && \ + rm -rf /var/lib/apt/lists/* -# Install nagios -RUN mkdir -p /usr/local/src/nagios4 && \ - cd /usr/local/src/nagios4 && \ - wget -q $NAGIOS_TARBALL -O- | tar -zxp --strip-components 1 && \ - ./configure --prefix=/usr/local/nagios --with-nagios-user=nagios --with-nagios-group=nagios --with-command-user=nagios --with-command-group=nagios && \ - make -j8 all && \ - make install install-init install-config install-commandmode && \ - ln -s /usr/local/nagios/etc /etc/nagios - -# Install nagios plugins -RUN mkdir -p /usr/local/src/nagios4-plugins && \ - cd /usr/local/src/nagios4-plugins && \ - wget -q $NAGIOS_PLUGINS_TARBALL -O- | tar -zxp --strip-components 1 && \ - ./configure --with-nagios-user=nagios --with-nagios-group=nagios --with-openssl=/usr/bin/openssl --enable-perl-modules --enable-libtap && \ - make -j8 && \ - make install - -# Install nagios NRPE -RUN mkdir -p /usr/local/src/nagios4-nrpe && \ - cd /usr/local/src/nagios4-nrpe && \ - wget -q $NAGIOS_NRPE_TARBALL -O- | tar -zxp --strip-components 1 && \ - ./configure --with-ssl=/usr/bin/openssl --with-ssl-lib=/usr/lib/x86_64-linux-gnu && \ - make -j8 all && \ - make install install-plugin install-daemon install-config - -# Install nagios NSCA -RUN mkdir -p /usr/local/src/nagios4-nsca && \ - cd /usr/local/src/nagios4-nsca && \ - wget -q $NAGIOS_NSCA_TARBALL -O- | tar -zxp --strip-components 1 && \ - ./configure --with-nsca-user=nagios --with-nsca-grp=nagios && \ - make -j8 all && \ - cd /usr/local/src/nagios4-nsca && \ - cp sample-config/nsca.cfg sample-config/send_nsca.cfg /etc/nagios/ && \ - cp src/send_nsca src/nsca /usr/local/bin/ && \ - chmod 644 /etc/nagios/nsca.cfg - -# Clean-up -RUN rm -rf /usr/local/src/nagios* - -# Add files -ADD conf /root/conf - -# Configure: php -RUN j2 /root/conf/php.ini > /etc/php/7.4/mods-available/custom.ini && \ - phpenmod custom - -# Configure: apache ADD conf/apache2-site.conf /etc/apache2/sites-available/nagios.conf + RUN a2dissite 000-default && \ a2ensite nagios && \ a2enmod cgi -# Configure: supervisor + +# Nagios +RUN apt-get update && \ + groupadd -g 3000 nagios && \ + useradd -u 3000 -g nagios -G www-data -m -s /bin/bash nagios && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y wget gnupg iputils-ping && \ + wget -qO- "http://artifact.scc.net.davepedu.com/repo/apt/nagios/dists/focal/install" | bash -x /dev/stdin && \ + DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y nagios nagios-nrpe-plugin nagios-nrpe-server nagios-plugins && \ + printf "nagiosadmin:$(openssl passwd -crypt nagiosadmin)\n" >> /etc/nagios/htpasswd.users && \ + update-alternatives --install /usr/bin/python python $(which python3) 2 && \ + rm -rf /var/lib/apt/lists/* + ADD conf/supervisor-all.conf /etc/supervisor/conf.d/ -# Configure: nagios -RUN bash -c 'mkdir -p /etc/nagios/conf.d /etc/nagios/conf.d/{hosts,services,timeperiods,templates,hostgroups,servicegroups,contacts}' && \ - echo 'cfg_dir=/etc/nagios/conf.d/' >> /etc/nagios/nagios.cfg && \ - sed -i 's~^url_html_path=.*~url_html_path=/~' /etc/nagios/cgi.cfg -# Runner -ADD run.sh /root/run.sh +ADD sendmail.py /usr/local/bin/sendmail.py -# Declare -VOLUME ["/etc/nagios/", "/usr/local/nagios/var/"] -EXPOSE 80 -EXPOSE 5666 -EXPOSE 5667 - -CMD ["/root/run.sh"] +ENTRYPOINT ["supervisord", "-c", "/etc/supervisor/supervisord.conf"] diff --git a/conf/apache2-site.conf b/conf/apache2-site.conf index 2aa438b..1aee906 100644 --- a/conf/apache2-site.conf +++ b/conf/apache2-site.conf @@ -1,14 +1,14 @@ ServerName localhost - DocumentRoot /usr/local/nagios/share/ + DocumentRoot /usr/share/nagios4/htdocs/ - ScriptAlias /cgi-bin/ /usr/local/nagios/sbin/ - ScriptAlias /nagios/cgi-bin/ /usr/local/nagios/sbin/ - + ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/nagios4/ + ScriptAlias /nagios/cgi-bin/ /usr/lib/cgi-bin/nagios4/ + Options +ExecCGI - + Options FollowSymLinks DirectoryIndex index.php index.html diff --git a/conf/supervisor-all.conf b/conf/supervisor-all.conf index a4e96ed..211ba9f 100644 --- a/conf/supervisor-all.conf +++ b/conf/supervisor-all.conf @@ -1,14 +1,29 @@ [supervisord] +nodaemon = true logfile = /var/log/supervisord.log logfile_backups = 0 [program:apache] command = /bin/bash -c "source /etc/apache2/envvars && exec /usr/sbin/apache2 -DFOREGROUND" +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 + [program:nagios] user = nagios -command = /usr/local/nagios/bin/nagios /etc/nagios/nagios.cfg +command = /usr/sbin/nagios /etc/nagios/nagios.cfg +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 -[program:nsca] -user = nagios -command = /usr/local/bin/nsca -c /etc/nagios/nsca.cfg + +#[program:nsca] +#user = nagios +#command = /usr/local/bin/nsca -c /etc/nagios/nsca.cfg +#stdout_logfile=/dev/stdout +#stdout_logfile_maxbytes=0 +#stderr_logfile=/dev/stderr +#stderr_logfile_maxbytes=0 diff --git a/sendmail.py b/sendmail.py new file mode 100755 index 0000000..8e6cfdb --- /dev/null +++ b/sendmail.py @@ -0,0 +1,212 @@ +#!/usr/bin/env python3 +############################################## +# SendmailViaSMTP is a kit for sending mail +# under console throught exist SMTP server. +# +# Author: dave@davepedu.com +# +# History: +# 2020-01-04: +# * ported to python3 (dave@davepedu.com) +# 2013-04-23: +# * fixed a bug while adding an attachment(thanks http://weibo.com/u/1738440993). +# 2012-10-29: +# * fixed problem under python 2.3.x. +# 2012-10-09: +# * fixed bug under crontab. +# * adjust priority to --file, --content and piped mode because of the bug above. +# 2012-09-30: +# + add --log option for debugging errors. +# 2012-09-24: +# * restruct the codes. +# * update the version number to 1.2. +# 2012-08-20: +# * fixed homepage link broken in README.rst(thanks http://weibo.com/royshan ). +# 2012-08-15: +# + support attachments(-a or --attach option). +# 2012-03-13: +# * Fixed sending mail under python 2.4x(thanks yong.yang). +# 2011-12-28: +# + add README.rst. +# + add pipe mode -- accept data as mail body which transfered through pipe. +# + implement file mode. +# * adjust the file mode has higher priority than option mode. +# 2011-12-23: +# * Fixed auth not supported issue under 2.5.x(thanks doitmy). +# 2010-09-28: +# * fixed --tls as turn on/off option. +# * optimize help message. +# 2010-09-27: +# + add support for Gmail(smtp.gmail.com). +# * fixed bugs for multi recipients. +# + first release. +############################################## + +import sys +import os +import os.path +import fileinput + +import smtplib +import mimetypes +from email import encoders +from email.mime.base import MIMEBase +from email.mime.multipart import MIMEMultipart +from email.mime.text import MIMEText + + +__author__ = "dave@davepedu.com" +__date__ = "$2020-01-04 14:52:27$" + +__usage__ = """python %prog [--host=smtp.yourdomain.com] <--port=110> [--user=smtpaccount] [--password=smtppass] <--subject=subject> [--file=filename]|[--content=mailbody] [--from=sender] [--to=reciver]. + + example: + 1. echo "blablabla" | python %prog --host="mail.domain.com" --from="myname@yourdomain.com" --to="friends1@domain1.com;friends2@domain.com" --user="myname@yourdomain.com" --password="p4word" --subject="mail title" + 2. python %prog --host="mail.domain.com" --from="myname@yourdomain.com" --to="friends1@domain1.com;friends2@domain.com" --user="myname@yourdomain.com" --password="p4word" --subject="mail title" --file=/path/of/file + 3. python %prog --host="mail.yourdomain.com" --from="myname@yourdomain.com" --to="friends1@domain1.com;friends2@domain2.com;friends3@domain3.com" --user="myname@yourdomain.com" --password="p4word" -s "Hello from MailViaSMTP" -c "This is a mail just for testing." + + The priority of three content inputing method is: piped-data, --file, --content.""" + +__version__ = "%prog 3.0" +__desc__ = """This is a command line kit for sending mail via smtp server which can use in multiple platforms like linux, BSD, Windows etc. + This little kit was written by %s using python. + The minimum version of python required was 2.3.""" % (__author__) + + +class Mail: + """docstring for Mail""" + def __init__(self, subject="", content="", m_from="", m_to="", m_cc=""): + self.subject = subject + self.content = MIMEText(content, "html", "utf-8") + self.m_from = m_from + self.m_to = m_to + self.m_cc = m_cc + + self.body = MIMEMultipart("related") + self.body["Subject"] = self.subject + self.body["From"] = self.m_from + self.body["To"] = self.m_to + self.body.preamble = "This is a multi-part message in MIME format." + + self.alternative = MIMEMultipart("alternative") + self.body.attach(self.alternative) + self.alternative.attach(self.content) + + def attach(self, attachments): + if attachments: + for attachment in attachments: + if not os.path.isfile(attachment): + print("WARNING: Unable to attach %s because it is not a file." % attachment) + continue + + ctype, encoding = mimetypes.guess_type(attachment) + if ctype is None or encoding is not None: + ctype = "application/octet-stream" + maintype, subtype = ctype.split("/", 1) + + fp = open(attachment, "rb") + attachment_mime = MIMEBase("application", "octet-stream") + attachment_mime.set_payload(fp.read()) + fp.close() + + encoders.encode_base64(attachment_mime) + attachment_mime.add_header("Content-Disposition", "attachment", filename=attachment) + self.body.attach(attachment_mime) + + +class SMTPServer: + """docstring for SMTPServer""" + def __init__(self, host="localhost", user="", password="", port=25, tls=False): + self.port = port + self.host = host + self.user = user + self.password = password + self.is_gmail = False + if self.host == "smtp.gmail.com": + self.is_gmail = True + self.port = 587 + self.tls = tls + + def sendmail(self, mail): + smtp = smtplib.SMTP(host=self.host, port=self.port) + if self.tls or self.is_gmail: + smtp.starttls() + smtp.ehlo() + smtp.esmtp_features["auth"] = "LOGIN DIGEST-MD5 PLAIN" + if self.user: + smtp.login(self.user, self.password) + smtp.sendmail(mail.m_from, mail.m_to.split(";"), mail.body.as_string()) + smtp.quit() + + +if __name__ == "__main__": + import optparse + import logging + + parser = optparse.OptionParser(usage=__usage__, version=__version__, description=__desc__) + parser.add_option("-a", "--attach", dest="attach", default=[], action="append", help="Specifies a file as attachment to be attached. Can be specified more than once.") + parser.add_option("-s", "--subject", dest="subject", help="The subject of the mail.") + parser.add_option("-c", "--content", dest="content", help="option mode. Mail body should be passed through this option. Note: this option should be ignored while working with piped-data or --file option.") + parser.add_option("-f", "--from", dest="address_from", metavar="my@domain.com", help="Set envelope from address. If --user option is not empty, commonly this option should be equaled with --user options. Otherwize, the authoration of the smtp server should be failed.") + parser.add_option("-t", "--to", dest="address_to", metavar="friend@domain2.com", help="Set recipient address. Use semicolon to seperate multi recipient, for example: 'a@a.com;b@b.com.'") + parser.add_option("-F", "--file", dest="file", help="File mode. Read mail body from file. NOTE: this option should be ignored while working with piped-data.") + parser.add_option("--host", dest="host", metavar="smtp.domain.com", help="SMTP server host name or ip. Like 'smtp.gmail.com' through GMail(tm) or '192.168.0.99' through your own smtp server.") + parser.add_option("-P", "--port", dest="port", type="int", default=25, help="SMTP server port number. Default is %default.") + parser.add_option("-u", "--user", dest="user", metavar="my@domain.com", help="The username for SMTP server authorcation. Left this option empty for non-auth smtp server.") + parser.add_option("-p", "--password", dest="password", help="The password for SMTP server authorcation. NOTE: if --user option is empty, this option will be ignored.") + parser.add_option("--tls", dest="tls", action="store_true", help="Using tls to communicate with SMTP server. Default is false. NOTE: if --host option equals 'smtp.gmail.com', this option becomes defaults true.") + parser.add_option("--log", dest="log", default="critical", help="specify --log=DEBUG or --log=debug, more info see document for logging module.") + opts, args = parser.parse_args() + + numeric_level = getattr(logging, opts.log.upper(), None) + if not isinstance(numeric_level, int): + raise ValueError("Invalid log level: %s" % opts.log) + if sys.version_info < (3, 0, 0): + raise "Python runtime MUST greater than 3" + else: + logging.basicConfig(level=numeric_level, format="%(asctime)s %(message)s") + + if opts.host is None or opts.address_from is None or opts.address_to is None: + msg = """ERROR: All parameters followed were required: --host, --from and --to. + Use -h to get more help.""" + logging.critical(msg) + sys.exit(msg) + + content = None + filename = None + if opts.content: + logging.debug("[param mode] %s" % opts.content) + content = opts.content # content mode, mail content should read from --content option. + + if opts.file: + logging.debug("[file mode] %s" % opts.file) + filename = opts.file # file mode, mail content should read from file. + if content is None and filename is None and not sys.stdin.isatty(0): + logging.debug("[pip mode]") + filename = "-" # pipe mode - mail content should read from stdin. + if filename: + try: + fi = fileinput.FileInput(filename) + logging.debug("[filename] %s" % filename) + content = "
".join(fi) + except: + logging.critical("can not open %s." % filename) + logging.debug("[content]%s" % content) + if content: + try: + logging.info("preparing mail...") + mail = Mail(opts.subject, content, opts.address_from, opts.address_to) + logging.info("preparing attachments...") + mail.attach(opts.attach) + logging.info("preparing SMTP server...") + smtp = SMTPServer(opts.host, opts.user, opts.password, opts.port, opts.tls) + logging.info("sending mail...") + smtp.sendmail(mail) + logging.info("all done.") + except Exception as e: + logging.critical("[Exception] %s" % e) + else: + msg = """ERROR: Mail content is EMPTY! Please specify one option of listed: piped-data, --file or --content. + Use -h to get more help.""" + logging.critical(msg) + sys.exit(msg)