Skip to content
Snippets Groups Projects
check_ssl_certs 5.22 KiB
#!/bin/bash
# ======================================================================
#
# SSL check - warn if a ssl certificate expires.
#
# Check locally installed SSL client certificates and warn if the 
# expiration date comes closer. 
#
# USAGE: check_ssl_certs [-w WARN_LIMIT] [-c CRITICAL_LIMIT] [-f "FILELIST"]
# HELP: check_ssl_certs -h
#
# ----------------------------------------------------------------------
# 2021-10-06  v0.1  <axel.hahn@iml.unibe.ch>  initial version
# 2022-03-16  v0.2  <axel.hahn@iml.unibe.ch>  shell fixes; shorten perfdata label
# 2022-10-21  v1.3  <axel.hahn@unibe.ch>      remove grep: warning: stray \ before white space
# 2024-04-24  v1.4  <axel.hahn@unibe.ch>      update for newer openssl version; update help
# ======================================================================

. $(dirname $0)/inc_pluginfunctions
self_APPVERSION=1.4

typeset -i iWarn=14
typeset -i iCrit=5
typeset -i iNow=$( date +%s )

bHasCritical=false
bHasWarning=false

shortstatus=""
fullstatus=""

filelist="/etc/ssl/certs/*.cert.cer"

# remove dommain in label in performance data
myDomain=".iml.unibe.ch"

# ----------------------------------------------------------------------
# functions
# ----------------------------------------------------------------------

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

Check locally installed SSL client certificates and warn if the 
expiration date comes closer. 

SYNTAX:
$(basename $0) [-w WARN_LIMIT] [-c CRITICAL_LIMIT] [-f "FILELIST"]

OPTIONS:

    -f FILELIST    file filter to find certificates using globbing 
                   (default: $filelist)
                   To use multiple sources seperate them with a space char.
                   Quote your parameter value if you use multiple sources or * char.
    -w VALUE       warning level in days before expiration (default: $iWarn)
    -c VALUE       critical level in days before expiration (default: $iCrit)

    -h or --help   show this help.

PARAMETERS:

    None.

EXAMPLE:

    $(basename $0) -f "/etc/ssl/certs/*example.com.*.cer /somewhere/else/*.cer"
        Set 2 folders where to find the client certificates.
        They are seperated by space and both use * for globbing

    $(basename $0) -w 30 -c 3 
        Overide the warning and critical level.

EOF
}

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


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


# ----- check required tools

ph.require openssl


# --- override from command line params
filelist=$(ph.getValueWithParam "$filelist" f "$@")
iWarn=$(   ph.getValueWithParam $iWarn      w "$@")
iCrit=$(   ph.getValueWithParam $iCrit      c "$@")


# ----- check cert files

typeset -i iCounter=0
typeset -i iTotal=$( ls -1 $filelist 2>/dev/null | wc -l )
if [ $iTotal -eq 0 ]; then
        bHasWarning=true
        shortstatus="No cert was found."
        fullstatus="!!! Warning: no file matches the file filter. HINT: adjust your file filter in -f FILEFILTER"
fi
for mycert in $( ls -1 $filelist 2>/dev/null )
do
        iCounter=$iCounter+1
        data=$(openssl x509 -noout -text -in $mycert 2>/dev/null )
        mySubject=$( echo "$data" | grep "Subject: CN *= *" | grep -v "," | cut -f 2- -d "=" | tr -d ' ' )
        
        mySubject2="${mySubject//${myDomain}}"
        if [ -z "$mySubject" ]; then
                bHasWarning=true
                fullstatus="${fullstatus}
                !!! WARNING: File $mycert is no client certificate. HINT: adjust your file filter in -f FILEFILTER"
        else

            dateExpire=$( echo "$data" | grep "Not After" | cut -f 2- -d ":" )

            typeset -i iExpire=$( date +%s -d "$dateExpire" )
            typeset -i iLeft=($iExpire-$iNow)/60/60/24

            if [ $iLeft -le $iWarn ]; then
                    if [ $iLeft -le $iCrit ]; then
                            bHasCritical=true
                            if [ $iLeft -lt 0 ]; then
                                    result="EXPIRED ALREADY"
                            else
                                    result="Expires VERY SOON"
                            fi
                    else
                            bHasWarning=true
                            result="Expires soon"
                    fi
            else
                    result="OK"
            fi
            shortstatus="${shortstatus}${result} ${mySubject} [${iLeft}d] ; "
            fullstatus="${fullstatus}
----- [$iCounter of $iTotal] ${mySubject} - expires in $iLeft days
$( echo "$data" | grep -E "(DNS:|Issuer:|Not |Subject:)" | sed 's#^ *##g')
File: $mycert
"

            ph.perfadd "ssl-$mySubject2"       "${iLeft}"       "" "" 0 ""
        fi
done


# ----- set status based on worst result

if [ $bHasCritical = true ]; then
        ph.setStatus critical
elif [ $bHasWarning = true ]; then
        ph.setStatus warning
fi


# ------ outout

ph.status "SSL certs :: $shortstatus"
echo "$fullstatus"
echo "INFO: warning starts $iWarn d before expiration, raising to critical $iCrit days before"
echo

ph.exit

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