Skip to content
Snippets Groups Projects
check_eol 8.17 KiB
#!/bin/bash
# ======================================================================
#
# Icinga/ Nagios Check
# EOL - End of life detection - Warn before reaching end of life
#
#   - includes inc_pluginfunctions
#   - eol data are organized in check_eol*.cfg
#   - detection functions are in check_eol-detect-[name]
#
# ----------------------------------------------------------------------
#
# REQUIREMENTS:
#   - linux (Centos, Debian, Ubuntu, ...)
#
# ----------------------------------------------------------------------
#
# SYNTAX:
#
# check_eol
#   show help and known product keys
#
# check_eol PRODUCT
#   detect PRODUCT and its EOL date in the *cfg files.
#   Remark: all keys are lowercase. Some product keys are followed by a
#           major version, some by major and a minor version,
#
# check_eol detect[KEY]
#   There is a special prefix "detect".
#   KEY is one of OS|PHP .. you can use uppercase or lowercase.
#
# ----------------------------------------------------------------------
#
# EXAMPLES:
#
#   use a product key and version
#     check_eol centos 7
#     check_eol php 7.4
#
#   use auto detection of a version
#     check_eol os detect
#     check_eol php detect
#
# ----------------------------------------------------------------------
# 2020-02-21  v1.0  <axel.hahn@iml.unibe.ch>
# 2020-03-05  v1.1  <axel.hahn@iml.unibe.ch>  switch to ph.* helper functions
# 2021-03-26  v1.2  <axel.hahn@iml.unibe.ch>  test major version if minor version was not detected
# 2021-11-02  v1.3  <axel.hahn@iml.unibe.ch>  detect centos stream
# 2022-02-28  v1.4  <axel.hahn@iml.unibe.ch>  remove negative performance data
# 2022-08-29  v1.5  <axel.hahn@iml.unibe.ch>  fix help; shell syntax updates 
# 2023-01-30  v1.6  <axel.hahn@unibe.ch>      add max value in performance data
# 2023-07-27  v1.7  <axel.hahn@unibe.ch>      update help page
# ======================================================================

. "$( dirname $0 )/inc_pluginfunctions"
eolcfg="${0}-data/*.cfg"

export self_APPVERSION=1.7

# --- limits
typeset -i iDaysWarn=365
typeset -i iDaysCritical=90
bDebug=false


myKey=
myVersion=
myEolEnd=
typeset -i myDaysLeft=


# ----------------------------------------------------------------------
# automatic detection
# ----------------------------------------------------------------------

# auto detetct an os or a version based on cli output
# used on param detect*
# global string  myKey      name of product
# global string  myVersion  its version
function autodetect(){

    myVersion=

    # --- step 1: autodetection to find a key for os or software derivat
    detectorPlugin="$0-versiondetect/autodetect-$myKey"
    if [ -x "$detectorPlugin" ]; then
        local mydata=$(.  "$detectorPlugin")
        myKey=$(     echo $mydata | rev | cut -f 2 -d "|" | rev )
        myVersion=$( echo $mydata | rev | cut -f 1 -d "|" | rev )
    fi

    # --- stop 2: find version number
    detectorPlugin="$0-versiondetect/detect-$myKey"
    if [ -x "$detectorPlugin" ]; then
        myVersion=$(. "$detectorPlugin")
    fi
    if [ -z "$myVersion" ]; then
        ph.abort "UNKNOWN: [$myKey] was not detected properly. It is unknown or output for version cannot be parsed."
    fi
}


# ----------------------------------------------------------------------
# functions for eol check
# ----------------------------------------------------------------------

# get count of days left to a given date
# param  string  date as "YYYY-MM-DD"
function getDaysLeft(){
    
    local mydate=$1
    echo $mydate | grep "[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]" >/dev/null
    if [ $? -eq 0 ]; then
        typeset -i tsend;     tsend=$(date --date="$mydate" +%s)
        typeset -i daysLeft;  daysLeft=($tsend - $(date +%s))/60/60/24
        echo $daysLeft
    fi
}


# detect product in *cfg files and find its line with EOL information
# global string  myKey       name of product
# global string  myVersion   its version
function findEolDate(){

    local myVerKey="$myVersion."
    local line=''
    local bContinue=0
    while [ $bContinue = 0 ]; do
        myVerKey=$( echo $myVerKey | rev | cut -f 2- -d "." | rev )
        line=$(grep "^$myKey:$myVerKey:" $eolcfg | sort -n | tail -1)

        test -z "$line" || bContinue=1
        echo $myVerKey | grep "\." >/dev/null || bContinue=1

    done

    echo $line

}

function showHelp(){
    local _self; _self=$(basename $0)
    cat <<EOF
$( ph.showImlHelpHeader )

Check and of support of an OS or a product.
The dates are defined in the files check_eol-*.cfg
For detailed information see docs/20_Checks/check_eol.md

USAGE
  $ $_self [-c CRITICAL] [-w WARING] PRODUCT VERSION

PARAMETERS
  PRODUCT  set a product; known product keys are listed below

$( grep "^[a-zA-Z]" $eolcfg | cut -f 2 -d ":" | sort -u | sed "s#^#             #g" )

  VERSION  set a version.
           Autodetection:
           There is a special handling vor version "detect".
           You can set "os" as product to detect the (linux) distribution.
           See examples below.

OPTIONS
  -c  set critical limit; default $iDaysCritical
  -w  set warning limit; default $iDaysWarn

EXAMPLES
  $_self php 8.1
  $_self -w 100 -c 30 php 8.1
  $_self os detect
  $_self php detect

EOF
}

# ----------------------------------------------------------------------
# MAIN
# ----------------------------------------------------------------------

# --- no param? show help

# --- check param -h
case "$1" in
    "--help"|"-h")
        showHelp
        exit 0
        ;;
    *)
esac

if [ $# -lt 2 ]; then
    echo "ERROR: Not enough parameters."
    showHelp
    ph.abort
fi

# --- parse params I: override warning and critical
typeset -i iShift=0
while getopts ":c: :w:" opt
do
    case $opt in
        c)
            iDaysCritical=$OPTARG
            iShift=$iShift+2
            ;;
        w)
            iDaysWarn=$OPTARG
            iShift=$iShift+2
            ;;
        *)
            ph.abort "ERROR: parameter unknown -- $opt"
            
    esac
done
shift $iShift

# --- verify warning and critical
if [ $iDaysWarn -lt $iDaysCritical ]; then
    ph.abort "ERROR: warning limit $iDaysWarn cannot be lower critical $iDaysCritical"
fi


# --- parse params II: get product and version
myKey=$1
myVersion=$2
test $myVersion = "detect" && autodetect $myKey

eol=$( findEolDate "$myKey" "$myVersion" )

if [ -z "$eol" ]; then
        ph.setStatus "unknown"
        echo "UNKNOWN. Sorry, [$myKey $myVersion] was not found in $eolcfg."
        echo
        grep "^$myKey:" $eolcfg >/dev/null
        if [ $? -eq 0 ]; then
            echo "HINT: the product [$myKey] is known ... but not the version [$myVersion] ... or its date is invalid i.e. 30th of feb or not YYYY-MM-DD"
            echo
            grep "^$myKey:" $eolcfg | grep -v ":$myKey:[0-9]" | cut -f 3- -d ":"
            echo
            echo "Maybe an admin can add the version in $(grep -l "^$myKey:" $eolcfg)"
            echo "Existing/ known versions are:"
            grep "^$myKey:[0-9]" $eolcfg | cut -f 3 -d ":" | sort -un
        else
            echo "The product key [$myKey] was not detected in any version."
        fi
else
        myEolVer=$(echo $eol | cut -f 3 -d ":")
        myEolEnd=$(echo $eol | cut -f 4 -d ":")
        myComment=$(echo $eol | cut -f 5 -d ":")

        myDaysLeft=$(getDaysLeft $myEolEnd)
        # --- verify days left with limits
        ph.setStatus "ok"
        if [ $myDaysLeft -lt $iDaysWarn ]; then
            ph.setStatus "warning"
            if [ $myDaysLeft -lt $iDaysCritical ]; then
                ph.setStatus "critical"
            fi
        fi
        if [ $myDaysLeft -ge 0 ]; then
            ph.status "[$myKey $myEolVer] ends on $myEolEnd ... $myDaysLeft days left $myComment" 
        else
            echo "[$myKey $myEolVer] ended on $myEolEnd ... $(echo $myDaysLeft | sed 's#\-##') days EXPIRED ALREADY !!! $myComment" 
        fi
        echo
        grep "^$myKey:" $eolcfg | grep -v ":$myKey:[0-9]" | cut -f 3- -d ":"
        echo
        echo "Limit Info: warn below $iDaysWarn days; critical below $iDaysCritical days"
        
        test ${myDaysLeft} -lt 0 && myDaysLeft=0
        ph.perfadd "$myKey-v$myEolVer" "${myDaysLeft}" $iDaysWarn $iDaysCritical 0 100

fi

# --- bye
ph.exit

# ----------------------------------------------------------------------