From 6c7c2da037307cc4990f110228e06839b8ffedd1 Mon Sep 17 00:00:00 2001
From: "Hahn Axel (hahn)" <axel.hahn@unibe.ch>
Date: Wed, 3 May 2023 14:38:17 +0200
Subject: [PATCH] update for check_snmp_synology for SNMP3

---
 check_snmp_synology | 158 ++++++++++++++++++++++++++++++++------------
 1 file changed, 116 insertions(+), 42 deletions(-)

diff --git a/check_snmp_synology b/check_snmp_synology
index 5b03318..d2502b5 100755
--- a/check_snmp_synology
+++ b/check_snmp_synology
@@ -1,7 +1,8 @@
 #!/bin/bash
-# check_snmp_synology for nagios version 1.1
-# 30.04.2013  Nicolas Ordonez, Switzerland
-# 08.08.2020  Axel Hahn: add update, community string
+# check_snmp_synology for nagios version 1.2
+# 30.04.2013        Nicolas Ordonez, Switzerland
+# 08.08.2020        Axel Hahn: add update, community string
+# 03.05.2023  v1.2  ah  support Snmpv3 connections
 #---------------------------------------------------
 # this plugin check the health of your Synology NAS
 # - System status (Power, Fans)
@@ -9,21 +10,30 @@
 # - RAID status
 # - available updates
 #
-# Tested with DSM 6.2
+# Tested with DSM 6.2 + 6.4 + 7.1
 #---------------------------------------------------
+#
+# ah = axel.hahn@unibe.ch
+#
 # see docs:
 # https://global.download.synology.com/download/Document/Software/DeveloperGuide/Firmware/DSM/All/enu/Synology_DiskStation_MIB_Guide.pdf
 #---------------------------------------------------
 
-. `dirname $0`/inc_pluginfunctions
+. $(dirname $0)/inc_pluginfunctions
 
 # --- basic vars
+
+self_APPNAME=$( basename $0 | tr [:lower:] [:upper:] )
+self_APPVERSION=1.2
+
 SNMPCOMMUNITY="public"
 SNMPVERSION="2c"
 SNMPWALK=$(which snmpwalk)
 SNMPGET=$(which snmpget)
 
-HOSTNAME=""
+SNMPCONFIG=/etc/icingaclient/snmp.cfg
+
+HOSTNAME="localhost"
 option_found=0
 healthString=""
 verbose="no"
@@ -57,15 +67,61 @@ OID_RAIDSize="${OID_syno}.3.1.1.5"
 
 # --- status arrays to show results
 #                0     1          2             3               4                      5
-aStatusDual=(    "???" Normal     Failed)
 aStatusUpgrade=( "???" Yes        "Up to date"  Connecting      Disconnected           Others)
 aStatusDisk=(    "???" Normal     Initialized   NotInitialized  SystemPartitionFailed  Crashed)
 aStatusRaid=(    "???" Normal     Repairing     Migrating       Expanding              Deleting Creating RaidSyncing RaidParityChecking RaidAssembling Canceling Degrade Crashed DataScrubbing RaidDeploying RaidUnDeploying RaidMountCache RaidExpandingUnfinishedSHR RaidConvertSHRToPool RaidMigrateSHR1ToSHR2 RaidUnknownStatus)
 
-aStatusSystem=$aStatusDual
-aStatusPower=$aStatusDual
-aStatusFan=$aStatusDual
+_self=$( basename $0 )
+USAGE="
+______________________________________________________________________
+
+$self_APPNAME 
+v$self_APPVERSION
+
+Based on script of Nicolas Ordonez.
+
+Institute for Medical Education - University of Bern
+Licence: GNU GPL 3
+______________________________________________________________________
+
+check cpu usage and cpu wait
+Cpu infos are taken from output of top command.
+
+On higher cpu usage it can show processes that cause cpu waits and
+with most cpu consumption.
+
+SYNTAX:
+    $_self [options]
 
+OPTIONS:
+    -a   authentication params for snmpwalk/ snmpget to connect to target; 
+         default: \"-v2c -c public\" (Snmpv2 with community string \"public\")
+    -h   host to connect as hostname or ip address
+    -f FILE  
+         read authentication from config file
+         default: \"/etc/icingaclient/snmp.cfg\"
+    -v   detailed output
+
+CONFIG FILE:
+    The config file can be multiline and has the syntax
+    [hostname]:[auth parameters]
+    The auth parameters set the version and all needed values to connect.
+    Snmp v2 uses a community string.
+    Snmp v3 is highly recommended (you should disable Snmp v2) and needs
+    a user and password.
+
+    Example:
+    server-01.example.com:-v 3 -l authnoPriv -a SHA -u snmpmonitor -A password-for-server-01
+    server-02.example.com:-v 3 -l authnoPriv -a SHA -u snmpmonitor -A password-for-server-02
+
+EXAMPLE:
+
+    $_self -h server-01.example.com -v
+        Show Synology status of server-01 using connect data from /etc/icingaclient/snmp.cfg
+
+    $_self -h server-01.example.com -v -f /opt/somewhere/snmp.conf
+        Show Synology status of server-01 using connect data from custom config
+"
 
 #---------------------------------------------------
 # FUNCTIONS
@@ -88,53 +144,70 @@ _get(){
 # --- show usage
 usage()
 {
-        ph.abort "usage: ./check_snmp_synology -h hostname [-C communitystring] [-v verbose]"
+        ph.abort "$USAGE"
+}
+
+read_config(){
+    SNMPAUTH="-v $SNMPVERSION -c $SNMPCOMMUNITY"
+
+    if [ -r "$SNMPCONFIG" ]; then
+        if grep "^${HOSTNAME}:" "$SNMPCONFIG" >/dev/null; then
+            SNMPAUTH="$( grep "^${HOSTNAME}:" "$SNMPCONFIG" | cut -f 2- -d ':' )"
+        else
+            SNMPAUTH="$( grep "^DEFAULT:" "$SNMPCONFIG" | cut -f 2- -d ':' )"
+        fi
+    else
+        ph.setStatus "unknown"
+        echo "ERROR: unable to read config file [$SNMPCONFIG]."
+        ph.exit
+    fi
 }
 
 #---------------------------------------------------
 # MAIN
 #---------------------------------------------------
 
-while getopts h:v OPTNAME; do
-        case "$OPTNAME" in
-
+while getopts a:h:f:v OPTNAME; do
+    case "$OPTNAME" in
+        a)
+            SNMPAUTH="$OPTARG"
+            ;;
+        f)
+            SNMPCONFIG="$OPTARG"
+            ;;
         h)
-                HOSTNAME="$OPTARG"
-                option_found=1
-                ;;
-		C)
-			    SNMPCOMMUNITY="$OPTARG"
-			    ;;
+            HOSTNAME="$OPTARG"
+            option_found=1
+            ;;
         v)
-                verbose="yes"
-                ;;
+            verbose="yes"
+            ;;
         *)
-                usage
-                ;;
-        esac
+            usage
+            ;;
+    esac
 done
 
-if [ "$option_found" = "0" ] || [ "$HOSTNAME" = "" ] ; then
-    usage
-    # remark: script aborts ...
-fi
 
+# --- read config to get the authentication params for snmp commands
+
+test -z "$SNMPAUTH" && read_config
 
 # --- read raid and disks to get its single OIDs
-nbDisk=`$SNMPWALK -OQne -t 10 -v $SNMPVERSION -c $SNMPCOMMUNITY $HOSTNAME $OID_diskID   2> /dev/null | wc -l `
-nbRAID=`$SNMPWALK -OQne -t 10 -v $SNMPVERSION -c $SNMPCOMMUNITY $HOSTNAME $OID_RAIDName 2> /dev/null | wc -l`
+nbDisk=$($SNMPWALK -OQne -t 10 ${SNMPAUTH} $HOSTNAME $OID_diskID   2> /dev/null | wc -l )
+nbRAID=$($SNMPWALK -OQne -t 10 ${SNMPAUTH} $HOSTNAME $OID_RAIDName 2> /dev/null | wc -l)
 
-for i in `seq 1 $nbDisk`;
+for i in $(seq 1 $nbDisk);
 do
     OID_disk="$OID_disk $OID_diskID.$(($i-1)) $OID_diskModel.$(($i-1)) $OID_diskStatus.$(($i-1)) $OID_diskTemp.$(($i-1)) " 
 done
-for i in `seq 1 $nbRAID`;
+for i in $(seq 1 $nbRAID);
 do
     OID_RAID="$OID_RAID $OID_RAIDName.$(($i-1)) $OID_RAIDStatus.$(($i-1)) $OID_RAIDSize.$(($i-1)) $OID_RAIDFree.$(($i-1))" 
 done
 
 # --- SNPGET to all wanted oids
-syno=`$SNMPGET -OQne -t 10 -v $SNMPVERSION -c $SNMPCOMMUNITY $HOSTNAME $OID_model $OID_serialNumber $OID_DSMVersion $OID_DSMUpdateAvailable $OID_systemStatus $OID_powerStatus $OID_systemFanStatus $OID_CPUFanStatus $OID_temp $OID_disk $OID_RAID 2> /dev/null | sed 's/^[ \t]*//;s/[ \t]*$//'`
+syno=$($SNMPGET -OQne -t 10 ${SNMPAUTH} $HOSTNAME $OID_model $OID_serialNumber $OID_DSMVersion $OID_DSMUpdateAvailable $OID_systemStatus $OID_powerStatus $OID_systemFanStatus $OID_CPUFanStatus $OID_temp $OID_disk $OID_RAID 2> /dev/null | sed 's/^[ \t]*//;s/[ \t]*$//')
 
 if [ "$?" != "0" ] ; then
     ph.abort "Problem with SNMP request"
@@ -169,9 +242,9 @@ _wd ""
 
 
 # --- Check system status
-systemStatus=$(_get $OID_systemStatus)
+systemStatus="$(_get $OID_systemStatus)"
 
-if [ $systemStatus != "1" ] ; then
+if [ "$systemStatus" != "1" ] ; then
     if [ "$systemStatus" = "2" ] ; then      systemStatus="Failed";          fi
     ph.setStatus "critical"
     healthString="$healthString, System status: $systemStatus "
@@ -182,9 +255,9 @@ _wd "System Status:     $systemStatus"
 
 
 # --- Check power status
-powerStatus=$(_get $OID_powerStatus)
+powerStatus="$(_get $OID_powerStatus)"
 
-if [ $powerStatus != "1" ] ; then
+if [ "$powerStatus" != "1" ] ; then
     if [ "$powerStatus" = "2" ] ; then       powerStatus="Failed";           fi
     ph.setStatus "critical"
     healthString="$healthString, Power status: $powerStatus "
@@ -196,7 +269,7 @@ _wd "Power Status:      $powerStatus"
 
 # --- Check system fan status
 systemFanStatus=$(_get $OID_systemFanStatus)
-if [ $systemFanStatus != "1" ] ; then
+if [ "$systemFanStatus" != "1" ] ; then
     if [ "$systemFanStatus" = "2" ] ; then   systemFanStatus="Failed";               fi
     ph.setStatus "critical"
     healthString="$healthString, System fan status: $systemFanStatus "
@@ -208,7 +281,7 @@ _wd "System Fan Status: $systemFanStatus"
 
 # --- Check CPU fan status
 CPUFanStatus=$(_get $OID_CPUFanStatus)
-if [ $CPUFanStatus != "1" ] ; then
+if [ "$CPUFanStatus" != "1" ] ; then
     if [ "$CPUFanStatus" = "2" ] ; then      CPUFanStatus="Failed";          fi
     ph.setStatus "critical"
     healthString="$healthString, CPU fan status: $CPUFanStatus "
@@ -232,7 +305,7 @@ _wd "NAS temperature:   $DeviceTemperature °C"
 # --- Check all disk status
 _wd ""
 _wd "Number of disks:   $nbDisk"
-for i in `seq 1 $nbDisk`;
+for i in $(seq 1 $nbDisk);
 do
     diskID[$i]=$(_get $OID_diskID.$(($i-1)))
     diskModel[$i]=$(_get $OID_diskModel.$(($i-1)))
@@ -253,7 +326,7 @@ done
 # --- Check all RAID volume status
 _wd ""
 _wd "Number of RAID volume: $nbRAID"
-for i in `seq 1 $nbRAID`;
+for i in $(seq 1 $nbRAID);
 do
     RAIDName[$i]=$(_get $OID_RAIDName.$(($i-1)))
     iRAIDStatus=$(_get $OID_RAIDStatus.$(($i-1)))
@@ -272,6 +345,7 @@ do
     _wd "${RAIDName[$i]} status: ${RAIDStatus[$i]} ($iRAIDStatus) - size $iRAIDSize GB, free $iRAIDFree GB (${iFree}%)"
 done
 
+# _wd ""; _wd "DEBUG: SNMPAUTH= $( echo "$SNMPAUTH" | sed 's#\-A [^\ ]*#-A **********#g' )"
 
 # --- output status
 ph.status "$healthString"
-- 
GitLab