diff --git a/plugins/ssh/sshd_log b/plugins/ssh/sshd_log index 608f49ec..f9b19341 100755 --- a/plugins/ssh/sshd_log +++ b/plugins/ssh/sshd_log @@ -1,66 +1,174 @@ #!/bin/sh -# -# Plugin to monitor auth.log for sshd server events. -# -# Require read permitions for $LOG -# (set in /etc/munin/plugin-conf.d/munin-node on debian) -# On busy servers you can change value type to COUNTER and set min to 0 to avoid minus peaks at logrotate -# -# $Log$ -# Revision 1.2 2010/03/19 15:03:00 pmoranga -# Revision 1.1 2009/04/26 23:28:00 ckujau -# Revision 1.0 2009/04/22 22:00:00 zlati -# Initial revision -# -# Parameters: + +: <<=cut + +=head1 NAME + +sshd_log - Munin plugin to monitor auth.log or journald for sshd + server events. + +=head1 CONFIGURATION + +This plugin requires read permission for the logfile or journald. + +On busy servers you can change value type to COUNTER and set min to 0 +to avoid minus peaks at logrotate. + +The following environment variables are used by this plugin: + + logfile - path to the auth log file, or "journald" to use journald. + default: /var/log/secure + + journalctlargs - space separated list of arguments to pass to + journalctl to get the sshd logs. + default: _COMM=sshd + + type - "GAUGE" or "DERIVE" + default: GAUGE + +If the "logfile" environment variable is set to "journald" the sshd +logs are read from journald, filtering on program "sshd". The filtering +may be changed using "journalctlargs". + + +Config examples for /etc/munin/plugin-conf.d/munin-node: + + [sshd_log] + user root + group root + env.logfile /var/log/messages + +Config example with journald: + + [sshd_log] + group systemd-journal + env.logfile journald + +Config example with journald on the sshd.service unit only: + + [sshd_log] + group systemd-journal + env.logfile journald + env.journalctlargs --unit=sshd.service + +Config example with journald and type DERIVE: + + [sshd_log] + group systemd-journal + env.logfile journald + env.type DERIVE + +=head1 MAGIC MARKERS + + #%# family=auto + #%# capabilities=autoconf + +=head1 AUTHOR + +Revision 2.0 2016/11/11 15:42:00 Thomas Riccardi +Revision 1.2 2010/03/19 15:03:00 pmoranga +Revision 1.1 2009/04/26 23:28:00 ckujau +Revision 1.0 2009/04/22 22:00:00 zlati + +=cut + + +# Script parameters: # # config (required) # autoconf (optional - used by munin-config) -# -# Magick markers (optional): -#%# family=auto -#%# capabilities=autoconf -# config example for /etc/munin/plugin-conf.d/munin-node -#[sshd_log] -#user root -#group root -#env.logfile /var/log/messages -#env.category users -# LOG=${logfile:-/var/log/secure} +JOURNALCTL_ARGS=${journalctlargs:-_COMM=sshd} +TYPE=${type:-GAUGE} +if [ "$LOG" = "journald" -a "$TYPE" = "DERIVE" ]; then + TYPE=ABSOLUTE +fi if [ "$1" = "autoconf" ]; then - if [ -r "$LOG" ]; then - echo yes - exit 0 + if [ "$LOG" = "journald" ]; then + # shellcheck disable=SC2086,SC2034 + if journalctl --no-pager --quiet --lines=1 $JOURNALCTL_ARGS | read -r DUMMY; then + echo "yes" + else + echo "no (journald empty log for '$JOURNALCTL_ARGS' not found)" + fi else - echo no - exit 1 + if [ -r "$LOG" ]; then + echo "yes" + else + echo "no (logfile '$LOG' not readable)" + fi fi + exit 0 fi if [ "$1" = "config" ]; then - - echo 'graph_title SSHD login stats from' $LOG + echo 'graph_title SSHD login stats from' "$LOG" echo 'graph_args --base 1000 -l 0' echo 'graph_vlabel logins' echo 'graph_category' security echo 'LogPass.label Successful password logins' + echo 'LogPass.min 0' + echo 'LogPass.type' "$TYPE" + echo 'LogPassPAM.label Successful login via PAM' + echo 'LogPassPAM.min 0' + echo 'LogPassPAM.type' "$TYPE" + echo 'LogKey.label Successful PublicKey logins' + echo 'LogKey.min 0' + echo 'LogKey.type' "$TYPE" + echo 'NoID.label No identification from user' + echo 'NoID.min 0' + echo 'NoID.type' "$TYPE" + echo 'rootAttempt.label Root login attempts' - echo 'InvUsr.label Invalid user login attepmts' + echo 'rootAttempt.min 0' + echo 'rootAttempt.type' "$TYPE" + + echo 'InvUsr.label Invalid user login attempts' + echo 'InvUsr.min 0' + echo 'InvUsr.type' "$TYPE" + echo 'NoRDNS.label No reverse DNS for peer' + echo 'NoRDNS.min 0' + echo 'NoRDNS.type' "$TYPE" + echo 'Breakin.label Potential Breakin Attempts' + echo 'Breakin.min 0' + echo 'Breakin.type' "$TYPE" + exit 0 fi -awk 'BEGIN{c["LogPass"]=0;c["LogKey"]=0;c["NoID"]=0;c["rootAttempt"]=0;c["InvUsr"]=0;c["LogPassPAM"]=0;c["Breakin"]=0;c["NoRDNS"]=0; } +if [ "$LOG" = "journald" -a "$TYPE" = "ABSOLUTE" ]; then + CURSOR_FILE="$MUNIN_STATEFILE" + # read cursor + # format: "journald-cursor " + CURSOR= + if [ -f "$CURSOR_FILE" ]; then + CURSOR=$(awk '/^journald-cursor / {print $2}' "$CURSOR_FILE") + fi +else + CURSOR_FILE= +fi + +if [ "$LOG" = "journald" ]; then + # shellcheck disable=SC2086 + if [ "$TYPE" = "ABSOLUTE" ]; then + journalctl --no-pager --quiet --show-cursor ${CURSOR:+"--after-cursor=$CURSOR"} $JOURNALCTL_ARGS + else + journalctl --no-pager --quiet --since=$(date -dlast-sunday +%Y-%m-%d) $JOURNALCTL_ARGS + fi +else + cat "$LOG" +fi | \ + awk -v cursor_file="$CURSOR_FILE" 'BEGIN{c["LogPass"]=0;c["LogKey"]=0;c["NoID"]=0;c["rootAttempt"]=0;c["InvUsr"]=0;c["LogPassPAM"]=0;c["Breakin"]=0;c["NoRDNS"]=0; } /sshd\[.*Accepted password for/{c["LogPass"]++} /sshd\[.*Accepted publickey for/{c["LogKey"]++} /sshd\[.*Did not receive identification string/{c["NoID"]++} @@ -69,4 +177,4 @@ awk 'BEGIN{c["LogPass"]=0;c["LogKey"]=0;c["NoID"]=0;c["rootAttempt"]=0;c["InvUsr /sshd\[.*POSSIBLE BREAK-IN ATTEMPT!/{c["Breakin"]++} /sshd\[.*keyboard-interactive\/pam/{c["LogPassPAM"]++} /sshd\[.*reverse mapping checking getaddrinfo/{c["NoRDNS"]++}a - END{for(i in c){print i".value " c[i]} }' < $LOG + END{if (cursor_file != "") { print "journald-cursor " $3 > cursor_file };for(i in c){print i".value " c[i]} }'