split local and discord destinations and add network security
This commit is contained in:
parent
5b1b201b48
commit
16e1724f31
13 changed files with 199 additions and 24 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
*.pyc
|
|
@ -3,6 +3,8 @@ FROM alpine:3
|
||||||
ENV S6_OVERLAY_VERSION 2.2.0.1
|
ENV S6_OVERLAY_VERSION 2.2.0.1
|
||||||
ENV S6_OVERLAY_MD5HASH a114568c94d06dc69fdb9d91ed3f7535
|
ENV S6_OVERLAY_MD5HASH a114568c94d06dc69fdb9d91ed3f7535
|
||||||
|
|
||||||
|
RUN apk add --no-cache curl
|
||||||
|
|
||||||
RUN apk add --no-cache wget ca-certificates && \
|
RUN apk add --no-cache wget ca-certificates && \
|
||||||
apk --no-cache --update upgrade && \
|
apk --no-cache --update upgrade && \
|
||||||
cd /tmp && \
|
cd /tmp && \
|
||||||
|
@ -22,8 +24,13 @@ RUN apk add --no-cache \
|
||||||
|
|
||||||
COPY /etc/ /etc/
|
COPY /etc/ /etc/
|
||||||
|
|
||||||
|
COPY discord.sh /bin/discord.sh
|
||||||
|
RUN chmod +x /bin/discord.sh
|
||||||
|
|
||||||
EXPOSE 514/udp
|
EXPOSE 514/udp
|
||||||
EXPOSE 601/tcp
|
EXPOSE 601/tcp
|
||||||
EXPOSE 6514/tcp
|
EXPOSE 6514/tcp
|
||||||
|
|
||||||
|
VOLUME /var/log
|
||||||
|
|
||||||
ENTRYPOINT ["/init"]
|
ENTRYPOINT ["/init"]
|
15
README.md
15
README.md
|
@ -7,16 +7,23 @@ A small Alpine container running syslog-ng configured to log to `/var/log/messag
|
||||||
|
|
||||||
Basic usage with the default local destination:
|
Basic usage with the default local destination:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker build -t logmonitor .
|
||||||
|
docker run --env WEBHOOK=https://discordapp.com/api/webhooks/... -p 514:514/udp -d --name logmonitor --rm logmonitor:latest ; docker logs logmonitor --follow
|
||||||
|
docker stop logmonitor ; docker rm logmonitor
|
||||||
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
docker run -d --name syslog-ng -p 514:514/udp -p 601:601/tcp -p 6514:6514/tcp logmonitor
|
docker run -d --name syslog-ng -p 514:514/udp -p 601:601/tcp -p 6514:6514/tcp logmonitor
|
||||||
```
|
```
|
||||||
|
|
||||||
Destinations can be enabled or disabled with environment variables specified with `-e`.
|
|
||||||
|
|
||||||
|
|
||||||
### Environment variables
|
### Environment variables
|
||||||
|
|
||||||
* `ENABLE_LOCAL` - set `True` to log to `/var/log/messages` in container (default: `False`)
|
* `ENABLE_LOCAL` - set `True` to log to `/var/log/system.log` in container (default: `False`)
|
||||||
|
* `ENABLE_DISCORD` - set `True` to log to `Discord` in container (default: `False`)
|
||||||
|
|
||||||
|
* `ALLOWED_SUBNET` - Define allowed network. (default: `10.0.0.0/24`)
|
||||||
|
|
||||||
* `SQL_HOST` - the IP or domain of the destination SQL server
|
* `SQL_HOST` - the IP or domain of the destination SQL server
|
||||||
* `SQL_PORT` - the port the destination SQL server runs on (defaults to `3306` if not specified)
|
* `SQL_PORT` - the port the destination SQL server runs on (defaults to `3306` if not specified)
|
||||||
* `SQL_USER` - the user name used to access the destination SQL server
|
* `SQL_USER` - the user name used to access the destination SQL server
|
||||||
|
|
30
discord.sh
Normal file
30
discord.sh
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
source /.envvars
|
||||||
|
SERVICE_URL="https://localhost:8443/"
|
||||||
|
|
||||||
|
# color codes examples: https://gist.github.com/deflax/e4fe4cced12103819c2663e2369911a5
|
||||||
|
|
||||||
|
while read LINE ; do
|
||||||
|
PRIO=`echo ${LINE} | cut -d ' ' -f 1`
|
||||||
|
if [ "${PRIO}" = "27" ] ; then
|
||||||
|
#test client notice - dark green
|
||||||
|
COLOR=2067276
|
||||||
|
elif [ "${PRIO}" = "134" ] ; then
|
||||||
|
#hpilo notice - grey
|
||||||
|
COLOR=9807270
|
||||||
|
else
|
||||||
|
#fallback to dark orange
|
||||||
|
COLOR=11027200
|
||||||
|
fi
|
||||||
|
SUBJECT=`echo ${LINE} | cut -d ' ' -f 2`
|
||||||
|
MESSAGE=`echo ${LINE} | cut -d ' ' -f 3-`
|
||||||
|
|
||||||
|
PAYLOAD=`printf "{ \"embeds\": [{\"title\": \"%s\", \"url\": \"%s\", \"description\": \"%s\", \"type\": \"link\", \"color\": %s }] }" "${SUBJECT}" "${SERVICE_URL}" "${MESSAGE}" "${COLOR}"`
|
||||||
|
echo ${PAYLOAD} > /var/log/discord.payload
|
||||||
|
HTTP_RESPONSE=`curl --write-out %{http_code} --silent --output /dev/null -X POST -H "Content-Type: application/json" -d @/var/log/discord.payload ${DISCORD_WEBHOOK}`
|
||||||
|
|
||||||
|
if [[ "${HTTP_RESPONSE}" != "204" ]] ; then
|
||||||
|
echo "Received HTTP-Code: ${HTTP_RESPONSE}" >> /var/log/discord.log
|
||||||
|
fi
|
||||||
|
done
|
22
docker-compose.yml
Normal file
22
docker-compose.yml
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
version: "3"
|
||||||
|
|
||||||
|
services:
|
||||||
|
logmonitor:
|
||||||
|
image: logmonitor:latest
|
||||||
|
ports:
|
||||||
|
- "514:514/udp"
|
||||||
|
volumes:
|
||||||
|
- "./data/logmonitor/log:/var/log"
|
||||||
|
environment:
|
||||||
|
ENABLE_LOCAL: true
|
||||||
|
ENABLE_DISCORD: true
|
||||||
|
DISCORD_WEBHOOK: https://discordapp.com/api/webhooks/CHANGEME
|
||||||
|
ALLOWED_SUBNET: 10.0.0.0/24
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- internal
|
||||||
|
labels:
|
||||||
|
- meta.role=logmonitor
|
||||||
|
|
||||||
|
networks:
|
||||||
|
internal: {}
|
|
@ -3,7 +3,7 @@
|
||||||
CONFD=/etc/syslog-ng/conf.d
|
CONFD=/etc/syslog-ng/conf.d
|
||||||
TEMPLATES=/etc/syslog-ng/templates
|
TEMPLATES=/etc/syslog-ng/templates
|
||||||
|
|
||||||
# enable and configure the SQL destination if SQL_* environment variables are set
|
# Setup the SQL destination if SQL_* environment variables are set
|
||||||
if $(env | grep -q SQL); then
|
if $(env | grep -q SQL); then
|
||||||
|
|
||||||
if [ -z ${SQL_PORT+set} ]; then
|
if [ -z ${SQL_PORT+set} ]; then
|
||||||
|
@ -23,8 +23,8 @@ elif [ -f ${CONFD}/d_sql.conf ]; then
|
||||||
rm -f ${CONFD}/d_sql.conf
|
rm -f ${CONFD}/d_sql.conf
|
||||||
fi
|
fi
|
||||||
|
|
||||||
DO_ENABLE_LOCAL=true
|
# Setup local template
|
||||||
|
DO_ENABLE_LOCAL=false
|
||||||
if [ ! -z ${ENABLE_LOCAL+set} ]; then
|
if [ ! -z ${ENABLE_LOCAL+set} ]; then
|
||||||
case $ENABLE_LOCAL in
|
case $ENABLE_LOCAL in
|
||||||
true|True|TRUE|yes|Yes|YES|1|on|On|ON)
|
true|True|TRUE|yes|Yes|YES|1|on|On|ON)
|
||||||
|
@ -32,12 +32,34 @@ if [ ! -z ${ENABLE_LOCAL+set} ]; then
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# enable the local destination if the appropriate environment variable is set
|
|
||||||
if ${DO_ENABLE_LOCAL}; then
|
if ${DO_ENABLE_LOCAL}; then
|
||||||
echo "Logging to /var/log/messages ENABLED."
|
echo "Logging to Local ENABLED."
|
||||||
cp --remove-destination ${TEMPLATES}/d_local.template ${CONFD}/d_local.conf
|
cp --remove-destination ${TEMPLATES}/d_local.template ${CONFD}/d_local.conf
|
||||||
|
|
||||||
else # otherwise make sure it's disabled
|
else # otherwise make sure it's disabled
|
||||||
echo "Logging to /var/log/messages DISABLED."
|
echo "Logging to Local DISABLED."
|
||||||
rm -f ${CONFD}/d_local.conf
|
rm -f ${CONFD}/d_local.conf
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Setup discord template
|
||||||
|
DO_ENABLE_DISCORD=false
|
||||||
|
if [ ! -z ${ENABLE_DISCORD+set} ]; then
|
||||||
|
case $ENABLE_DISCORD in
|
||||||
|
true|True|TRUE|yes|Yes|YES|1|on|On|ON)
|
||||||
|
DO_ENABLE_DISCORD=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
if ${DO_ENABLE_DISCORD}; then
|
||||||
|
echo "Logging to Discord ENABLED."
|
||||||
|
cp --remove-destination ${TEMPLATES}/d_discord.template ${CONFD}/d_discord.conf
|
||||||
|
|
||||||
|
if [ -z ${ALLOWED_SUBNET+set} ]; then
|
||||||
|
ALLOWED_SUBNET="10.0.0.0/24"
|
||||||
|
fi
|
||||||
|
echo "Allowed network subnet is ${ALLOWED_SUBNET}"
|
||||||
|
sed -i "s:ALLOWED_SUBNET:${ALLOWED_SUBNET}:" ${CONFD}/d_discord.conf
|
||||||
|
else # otherwise make sure it's disabled
|
||||||
|
echo "Logging to Discord DISABLED."
|
||||||
|
rm -f ${CONFD}/d_discord.conf
|
||||||
|
fi
|
|
@ -1,8 +1,8 @@
|
||||||
#!/bin/sh
|
#!/usr/bin/with-contenv sh
|
||||||
|
|
||||||
while true
|
while true
|
||||||
do
|
do
|
||||||
echo "] ping from logmonitor..."
|
echo "DISCORD_WEBHOOK=${DISCORD_WEBHOOK}" > /.envvars
|
||||||
sleep 10
|
sleep 3600
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,11 @@ source s_local {
|
||||||
};
|
};
|
||||||
|
|
||||||
source s_network {
|
source s_network {
|
||||||
default-network-drivers(
|
syslog(transport("udp"));
|
||||||
|
};
|
||||||
|
|
||||||
|
#source s_network {
|
||||||
|
# default-network-drivers(
|
||||||
# NOTE: TLS support
|
# NOTE: TLS support
|
||||||
#
|
#
|
||||||
# the default-network-drivers() source driver opens the TLS
|
# the default-network-drivers() source driver opens the TLS
|
||||||
|
@ -30,8 +34,8 @@ source s_network {
|
||||||
# key-file("/etc/syslog-ng/certs/serverkey.pem")
|
# key-file("/etc/syslog-ng/certs/serverkey.pem")
|
||||||
# cert-file("/etc/syslog-ng/certs/servercert.pem")
|
# cert-file("/etc/syslog-ng/certs/servercert.pem")
|
||||||
# )
|
# )
|
||||||
);
|
# );
|
||||||
};
|
#};
|
||||||
|
|
||||||
###
|
###
|
||||||
# Include all config files in /etc/syslog-ng/conf.d/
|
# Include all config files in /etc/syslog-ng/conf.d/
|
||||||
|
|
13
etc/syslog-ng/templates/d_discord.template
Normal file
13
etc/syslog-ng/templates/d_discord.template
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
destination d_discord {
|
||||||
|
program("/bin/discord.sh" mark-mode(none) template("$PRI $HOST $MSGHDR $MSG\n"));
|
||||||
|
};
|
||||||
|
|
||||||
|
filter allowed_hosts {
|
||||||
|
netmask(ALLOWED_SUBNET);
|
||||||
|
};
|
||||||
|
|
||||||
|
log {
|
||||||
|
source(s_network);
|
||||||
|
filter(allowed_hosts);
|
||||||
|
destination(d_discord);
|
||||||
|
};
|
|
@ -1,11 +1,9 @@
|
||||||
destination d_local {
|
destination d_local {
|
||||||
file("/var/log/messages");
|
file("/var/log/system.log" template("$ISODATE $PRI $HOST $MSGHDR $MSG\n"));
|
||||||
file("/var/log/messages-kv.log" template("$ISODATE $HOST $(format-welf --scope all-nv-pairs)\n") frac-digits(3));
|
#file("/var/log/messages-kv.log" template("$ISODATE $HOST $(format-welf --scope all-nv-pairs)\n") frac-digits(3));
|
||||||
};
|
};
|
||||||
|
|
||||||
log {
|
log {
|
||||||
source(s_local);
|
|
||||||
source(s_network);
|
source(s_network);
|
||||||
destination(d_local);
|
destination(d_local);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
10
tools/README.md
Normal file
10
tools/README.md
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
```
|
||||||
|
import syslog_client
|
||||||
|
log = syslog_client.Syslog("127.0.0.1")
|
||||||
|
log.notice("info msg")
|
||||||
|
log.warn("warning msg")
|
||||||
|
log.error("error msg")
|
||||||
|
```
|
||||||
|
```
|
||||||
|
log.send("howdy", syslog_client.WARNING)
|
||||||
|
```
|
61
tools/syslog_client.py
Normal file
61
tools/syslog_client.py
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
"""
|
||||||
|
Remote syslog client.
|
||||||
|
|
||||||
|
Works by sending UDP messages to a remote syslog server. The remote server
|
||||||
|
must be configured to accept logs from the network.
|
||||||
|
|
||||||
|
License: PUBLIC DOMAIN
|
||||||
|
Author: Christian Stigen Larsen
|
||||||
|
|
||||||
|
For more information, see RFC 3164.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import socket
|
||||||
|
|
||||||
|
class Facility:
|
||||||
|
"Syslog facilities"
|
||||||
|
KERN, USER, MAIL, DAEMON, AUTH, SYSLOG, \
|
||||||
|
LPR, NEWS, UUCP, CRON, AUTHPRIV, FTP = range(12)
|
||||||
|
|
||||||
|
LOCAL0, LOCAL1, LOCAL2, LOCAL3, \
|
||||||
|
LOCAL4, LOCAL5, LOCAL6, LOCAL7 = range(16, 24)
|
||||||
|
|
||||||
|
class Level:
|
||||||
|
"Syslog levels"
|
||||||
|
EMERG, ALERT, CRIT, ERR, \
|
||||||
|
WARNING, NOTICE, INFO, DEBUG = range(8)
|
||||||
|
|
||||||
|
class Syslog:
|
||||||
|
"""A syslog client that logs to a remote server.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
>>> log = Syslog(host="foobar.example")
|
||||||
|
>>> log.send("hello", Level.WARNING)
|
||||||
|
"""
|
||||||
|
def __init__(self,
|
||||||
|
host="localhost",
|
||||||
|
port=514,
|
||||||
|
facility=Facility.DAEMON):
|
||||||
|
self.host = host
|
||||||
|
self.port = port
|
||||||
|
self.facility = facility
|
||||||
|
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
|
||||||
|
def send(self, message, level):
|
||||||
|
"Send a syslog message to remote host using UDP."
|
||||||
|
data = "<%d>%s" % (level + self.facility*8, message)
|
||||||
|
self.socket.sendto(data, (self.host, self.port))
|
||||||
|
|
||||||
|
def warn(self, message):
|
||||||
|
"Send a syslog warning message."
|
||||||
|
self.send(message, Level.WARNING)
|
||||||
|
|
||||||
|
def notice(self, message):
|
||||||
|
"Send a syslog notice message."
|
||||||
|
self.send(message, Level.NOTICE)
|
||||||
|
|
||||||
|
def error(self, message):
|
||||||
|
"Send a syslog error message."
|
||||||
|
self.send(message, Level.ERR)
|
||||||
|
|
||||||
|
# ... add your own stuff here
|
Loading…
Reference in a new issue