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_MD5HASH a114568c94d06dc69fdb9d91ed3f7535
|
||||
|
||||
RUN apk add --no-cache curl
|
||||
|
||||
RUN apk add --no-cache wget ca-certificates && \
|
||||
apk --no-cache --update upgrade && \
|
||||
cd /tmp && \
|
||||
|
@ -22,8 +24,13 @@ RUN apk add --no-cache \
|
|||
|
||||
COPY /etc/ /etc/
|
||||
|
||||
COPY discord.sh /bin/discord.sh
|
||||
RUN chmod +x /bin/discord.sh
|
||||
|
||||
EXPOSE 514/udp
|
||||
EXPOSE 601/tcp
|
||||
EXPOSE 6514/tcp
|
||||
|
||||
VOLUME /var/log
|
||||
|
||||
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:
|
||||
|
||||
```
|
||||
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
|
||||
```
|
||||
|
||||
Destinations can be enabled or disabled with environment variables specified with `-e`.
|
||||
|
||||
|
||||
### 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_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
|
||||
|
|
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
|
||||
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 [ -z ${SQL_PORT+set} ]; then
|
||||
|
@ -23,8 +23,8 @@ elif [ -f ${CONFD}/d_sql.conf ]; then
|
|||
rm -f ${CONFD}/d_sql.conf
|
||||
fi
|
||||
|
||||
DO_ENABLE_LOCAL=true
|
||||
|
||||
# Setup local template
|
||||
DO_ENABLE_LOCAL=false
|
||||
if [ ! -z ${ENABLE_LOCAL+set} ]; then
|
||||
case $ENABLE_LOCAL in
|
||||
true|True|TRUE|yes|Yes|YES|1|on|On|ON)
|
||||
|
@ -32,12 +32,34 @@ if [ ! -z ${ENABLE_LOCAL+set} ]; then
|
|||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# enable the local destination if the appropriate environment variable is set
|
||||
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
|
||||
|
||||
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
|
||||
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
|
||||
do
|
||||
echo "] ping from logmonitor..."
|
||||
sleep 10
|
||||
echo "DISCORD_WEBHOOK=${DISCORD_WEBHOOK}" > /.envvars
|
||||
sleep 3600
|
||||
done
|
||||
|
||||
|
|
|
@ -18,7 +18,11 @@ source s_local {
|
|||
};
|
||||
|
||||
source s_network {
|
||||
default-network-drivers(
|
||||
syslog(transport("udp"));
|
||||
};
|
||||
|
||||
#source s_network {
|
||||
# default-network-drivers(
|
||||
# NOTE: TLS support
|
||||
#
|
||||
# the default-network-drivers() source driver opens the TLS
|
||||
|
@ -30,8 +34,8 @@ source s_network {
|
|||
# key-file("/etc/syslog-ng/certs/serverkey.pem")
|
||||
# cert-file("/etc/syslog-ng/certs/servercert.pem")
|
||||
# )
|
||||
);
|
||||
};
|
||||
# );
|
||||
#};
|
||||
|
||||
###
|
||||
# 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 {
|
||||
file("/var/log/messages");
|
||||
file("/var/log/messages-kv.log" template("$ISODATE $HOST $(format-welf --scope all-nv-pairs)\n") frac-digits(3));
|
||||
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));
|
||||
};
|
||||
|
||||
log {
|
||||
source(s_local);
|
||||
source(s_network);
|
||||
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