From e6a18b5a5b529cc5a397e676a90303296f4a2193 Mon Sep 17 00:00:00 2001 From: Thomas Riccardi Date: Sun, 13 Nov 2016 19:25:31 +0100 Subject: [PATCH 1/8] sshd_log: use DERIVE datatype and support logs from journald too Now shows the number of events per time unit, instead of a counter always increasing until logrotate. To use journald, set env.logfile to special value 'journald': It will read the sshd logs from journalctl _COMM=sshd. To configure the source of journald, set env.journalctlarg: Example: "env.journalctlarg --unit=sshd.service" --- plugins/ssh/sshd_log | 89 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 79 insertions(+), 10 deletions(-) diff --git a/plugins/ssh/sshd_log b/plugins/ssh/sshd_log index 608f49ec..dc57e3df 100755 --- a/plugins/ssh/sshd_log +++ b/plugins/ssh/sshd_log @@ -1,12 +1,12 @@ #!/bin/sh # -# Plugin to monitor auth.log for sshd server events. +# Plugin to monitor auth.log or journald for sshd server events. # -# Require read permitions for $LOG +# Require read permitions for $LOG or journald # (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 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 @@ -28,39 +28,108 @@ #env.logfile /var/log/messages #env.category users # +# 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.journalctlarg --unit=sshd.service +# LOG=${logfile:-/var/log/secure} +JOURNALCTL_ARG=${journalctlarg:-_COMM=sshd} if [ "$1" = "autoconf" ]; then - if [ -r "$LOG" ]; then - echo yes - exit 0 + if [ "$LOG" = "journald" ]; then + if journalctl --no-pager --quiet --lines=1 "$JOURNALCTL_ARG" | read -r DUMMY; then + echo yes + exit 0 + else + echo no + exit 1 + fi else - echo no - exit 1 + if [ -r "$LOG" ]; then + echo yes + exit 0 + else + echo no + exit 1 + fi fi fi if [ "$1" = "config" ]; then + if [ "$LOG" = "journald" ]; then + TYPE=ABSOLUTE + else + TYPE=DERIVE + fi + 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 'rootAttempt.min 0' + echo 'rootAttempt.type' "$TYPE" + echo 'InvUsr.label Invalid user login attepmts' + 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" ]; 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 + journalctl --no-pager --quiet --show-cursor ${CURSOR:+"--after-cursor=$CURSOR"} "$JOURNALCTL_ARG" +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 +138,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]} }' From c04acf95ac533b443690d8902357b141f487267e Mon Sep 17 00:00:00 2001 From: Thomas Riccardi Date: Sat, 12 Nov 2016 15:00:18 +0100 Subject: [PATCH 2/8] sshd_log: fix shellcheck warnings --- plugins/ssh/sshd_log | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/ssh/sshd_log b/plugins/ssh/sshd_log index dc57e3df..ac7d21f0 100755 --- a/plugins/ssh/sshd_log +++ b/plugins/ssh/sshd_log @@ -72,7 +72,7 @@ if [ "$1" = "config" ]; then TYPE=DERIVE fi - 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 @@ -127,7 +127,7 @@ fi if [ "$LOG" = "journald" ]; then journalctl --no-pager --quiet --show-cursor ${CURSOR:+"--after-cursor=$CURSOR"} "$JOURNALCTL_ARG" else - cat $LOG + 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"]++} From ff68f64155cc111010bab3682e2814743a6a0516 Mon Sep 17 00:00:00 2001 From: Thomas Riccardi Date: Sat, 12 Nov 2016 15:02:26 +0100 Subject: [PATCH 3/8] sshd_log: cleanup autoconf * always return 0 * add details on autoconf failure --- plugins/ssh/sshd_log | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/plugins/ssh/sshd_log b/plugins/ssh/sshd_log index ac7d21f0..cad2e8ac 100755 --- a/plugins/ssh/sshd_log +++ b/plugins/ssh/sshd_log @@ -47,21 +47,18 @@ JOURNALCTL_ARG=${journalctlarg:-_COMM=sshd} if [ "$1" = "autoconf" ]; then if [ "$LOG" = "journald" ]; then if journalctl --no-pager --quiet --lines=1 "$JOURNALCTL_ARG" | read -r DUMMY; then - echo yes - exit 0 + echo "yes" else - echo no - exit 1 + echo "no (journald empty log for '$JOURNALCTL_ARG' not found)" fi else if [ -r "$LOG" ]; then - echo yes - exit 0 + echo "yes" else - echo no - exit 1 + echo "no (logfile '$LOG' not readable)" fi fi + exit 0 fi if [ "$1" = "config" ]; then From 26181ead335223b439948b3b7436d3c29a757cda Mon Sep 17 00:00:00 2001 From: Thomas Riccardi Date: Sat, 12 Nov 2016 15:38:29 +0100 Subject: [PATCH 4/8] sshd_log: POD style documentation --- plugins/ssh/sshd_log | 103 ++++++++++++++++++++++++++++--------------- 1 file changed, 67 insertions(+), 36 deletions(-) diff --git a/plugins/ssh/sshd_log b/plugins/ssh/sshd_log index cad2e8ac..f8555db5 100755 --- a/plugins/ssh/sshd_log +++ b/plugins/ssh/sshd_log @@ -1,44 +1,75 @@ #!/bin/sh -# -# Plugin to monitor auth.log or journald for sshd server events. -# -# Require read permitions for $LOG or journald -# (set in /etc/munin/plugin-conf.d/munin-node on debian) -# -# $Log$ -# 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 -# 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 + category - graph category. default: system + + journalctlargs - space separated list of arguments to pass to + journalctl to get the sshd logs. + default: _COMM=sshd + +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 "journalctlarg". + + +Config examples for /etc/munin/plugin-conf.d/munin-node: + + [sshd_log] + user root + group root + env.logfile /var/log/messages + env.category users + +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.journalctlarg --unit=sshd.service + +=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 -# -# 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.journalctlarg --unit=sshd.service -# LOG=${logfile:-/var/log/secure} JOURNALCTL_ARG=${journalctlarg:-_COMM=sshd} From bc1e78ae5a8f835bc68ef6d22f8de162977665d3 Mon Sep 17 00:00:00 2001 From: Thomas Riccardi Date: Sat, 12 Nov 2016 17:00:35 +0100 Subject: [PATCH 5/8] sshd_log: remove env.category: it should not be configurable --- plugins/ssh/sshd_log | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/ssh/sshd_log b/plugins/ssh/sshd_log index f8555db5..66061a84 100755 --- a/plugins/ssh/sshd_log +++ b/plugins/ssh/sshd_log @@ -18,7 +18,6 @@ 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 - category - graph category. default: system journalctlargs - space separated list of arguments to pass to journalctl to get the sshd logs. @@ -35,7 +34,6 @@ Config examples for /etc/munin/plugin-conf.d/munin-node: user root group root env.logfile /var/log/messages - env.category users Config example with journald: From e178be6432474c904a1531767840b504ef3fd454 Mon Sep 17 00:00:00 2001 From: Thomas Riccardi Date: Sun, 13 Nov 2016 20:43:46 +0100 Subject: [PATCH 6/8] sshd_log: fix label typo --- plugins/ssh/sshd_log | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/ssh/sshd_log b/plugins/ssh/sshd_log index 66061a84..3c38af1c 100755 --- a/plugins/ssh/sshd_log +++ b/plugins/ssh/sshd_log @@ -123,7 +123,7 @@ if [ "$1" = "config" ]; then echo 'rootAttempt.min 0' echo 'rootAttempt.type' "$TYPE" - echo 'InvUsr.label Invalid user login attepmts' + echo 'InvUsr.label Invalid user login attempts' echo 'InvUsr.min 0' echo 'InvUsr.type' "$TYPE" From cdb82255e9151f42176d36da1d7817bf83d51b81 Mon Sep 17 00:00:00 2001 From: Thomas Riccardi Date: Sun, 29 Apr 2018 00:58:41 +0200 Subject: [PATCH 7/8] sshd_log: allow multiple journalctl args Useful for multiple filtering. At the cost of not being able to pass spaces properly in args, but that's uncommon. --- plugins/ssh/sshd_log | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/plugins/ssh/sshd_log b/plugins/ssh/sshd_log index 3c38af1c..5026d607 100755 --- a/plugins/ssh/sshd_log +++ b/plugins/ssh/sshd_log @@ -25,7 +25,7 @@ The following environment variables are used by this plugin: 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 "journalctlarg". +may be changed using "journalctlargs". Config examples for /etc/munin/plugin-conf.d/munin-node: @@ -46,7 +46,7 @@ Config example with journald on the sshd.service unit only: [sshd_log] group systemd-journal env.logfile journald - env.journalctlarg --unit=sshd.service + env.journalctlargs --unit=sshd.service =head1 MAGIC MARKERS @@ -70,15 +70,16 @@ Revision 1.0 2009/04/22 22:00:00 zlati LOG=${logfile:-/var/log/secure} -JOURNALCTL_ARG=${journalctlarg:-_COMM=sshd} +JOURNALCTL_ARGS=${journalctlargs:-_COMM=sshd} if [ "$1" = "autoconf" ]; then if [ "$LOG" = "journald" ]; then - if journalctl --no-pager --quiet --lines=1 "$JOURNALCTL_ARG" | read -r DUMMY; 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_ARG' not found)" + echo "no (journald empty log for '$JOURNALCTL_ARGS' not found)" fi else if [ -r "$LOG" ]; then @@ -151,7 +152,8 @@ else fi if [ "$LOG" = "journald" ]; then - journalctl --no-pager --quiet --show-cursor ${CURSOR:+"--after-cursor=$CURSOR"} "$JOURNALCTL_ARG" + # shellcheck disable=SC2086 + journalctl --no-pager --quiet --show-cursor ${CURSOR:+"--after-cursor=$CURSOR"} $JOURNALCTL_ARGS else cat "$LOG" fi | \ From 8f68d6e69719024cfa054b3f9d7fec0444e746ae Mon Sep 17 00:00:00 2001 From: Thomas Riccardi Date: Sun, 29 Apr 2018 01:36:32 +0200 Subject: [PATCH 8/8] sshd_log: allow both types GAUGE and DERIVE, default to GAUGE In fact for journald mode internally it really is type ABSOLUTE, because we use journald cursor to get only new logs on each collect. It results in the same value as with a plain log file and type DERIVE: it's the rate of events. type=DERIVE is best for servers with lots of ssh traffic. --- plugins/ssh/sshd_log | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/plugins/ssh/sshd_log b/plugins/ssh/sshd_log index 5026d607..f9b19341 100755 --- a/plugins/ssh/sshd_log +++ b/plugins/ssh/sshd_log @@ -23,6 +23,9 @@ The following environment variables are used by this plugin: 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". @@ -48,6 +51,13 @@ Config example with journald on the sshd.service unit only: 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 @@ -71,6 +81,10 @@ Revision 1.0 2009/04/22 22:00:00 zlati 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 @@ -92,13 +106,6 @@ if [ "$1" = "autoconf" ]; then fi if [ "$1" = "config" ]; then - - if [ "$LOG" = "journald" ]; then - TYPE=ABSOLUTE - else - TYPE=DERIVE - fi - echo 'graph_title SSHD login stats from' "$LOG" echo 'graph_args --base 1000 -l 0' echo 'graph_vlabel logins' @@ -139,7 +146,7 @@ if [ "$1" = "config" ]; then exit 0 fi -if [ "$LOG" = "journald" ]; then +if [ "$LOG" = "journald" -a "$TYPE" = "ABSOLUTE" ]; then CURSOR_FILE="$MUNIN_STATEFILE" # read cursor # format: "journald-cursor " @@ -153,7 +160,11 @@ fi if [ "$LOG" = "journald" ]; then # shellcheck disable=SC2086 - journalctl --no-pager --quiet --show-cursor ${CURSOR:+"--after-cursor=$CURSOR"} $JOURNALCTL_ARGS + 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 | \