#!/bin/bash # ====================================================================== # # NAGIOS CLIENT CHECK :: check SSL certificate # this pligin show a warning if certificate expires in less than # ${iWarnDaysBefore} days # # REQUIREMENTS # - openssl # - single cert on a host ?? # # ---------------------------------------------------------------------- # # ah=axel.hahn@iml.unibe.ch # ds=daniel.schueler@iml.unibe.ch # # 2017-03-03 v1.0 ah,ds # 2020-03-05 v1.1 <axel.hahn@iml.unibe.ch> switch to ph.* helper functions # 2023-02-13 v1.2 <axel.hahn@unibe.ch> some shell fixes # 2023-08-23 v1.3 <axel.hahn@unibe.ch> fix wrong exitcode to "critical" # 2025-02-12 v1.4 <axel.hahn@unibe.ch> add IML header in help; add warning and critical level # 2025-02-10 v1.5 <axel.hahn@unibe.ch> harden sourcing files # ====================================================================== # shellcheck source=/dev/null . "$( dirname "$0" )/inc_pluginfunctions" || exit 1 self_APPVERSION=1.5 sDomain= iPort=443 typeset -i iErrors=0 typeset -i iWarnings=0 sStatus= # ---------------------------------------------------------------------- # functions # ---------------------------------------------------------------------- # show help with syntax function showHelp(){ local _self; _self="$( basename "$0" )" cat <<EOH $( ph.showImlHelpHeader ) Check if ssl certificate of a given domain is still valid. You can check https or any other port of a ssl enabled service like LDAPS, IMPAS and others. You can customize the values for warning and critical level. SYNTAX: $_self [options] DOMAIN [PORT] OPTIONS -w VALUE warning level for expiration in days (default: 28) -c VALUE critical level for expiration in days (default: 7) PARAMETERS DOMAIN domain to verify the ssl vertificate from (required) PORT optional: port number to connect (default: 443) EXAMPLES $_self www.iml.unibe.ch 443 check https port 443 $_self -w 30 -c 14 ldap.example.com 636 check ldaps port 636 and set custom warning and critical level EOH } # ---------------------------------------------------------------------- # MAIN # ---------------------------------------------------------------------- # --- check requirements ph.require openssl if [ $# -eq 0 ]; then showHelp exit 0 fi # --- start # set default / override from command line params typeset -i iWarnLimit; iWarnLimit=$( ph.getValueWithParam 28 w "$@") typeset -i iCriticalLimit; iCriticalLimit=$( ph.getValueWithParam 7 c "$@") sParams="$*" sP1="$( rev <<< $sParams | cut -f 2 -d ' ' | rev )" sP2="$( rev <<< $sParams | cut -f 1 -d ' ' | rev )" if grep -q "^[0-9]*$" <<< $sP2; then sDomain=$sP1 iPort=$sP2 else sDomain=$sP2 fi # --- try to connect echo | openssl s_client -connect ${sDomain}:${iPort} >/dev/null 2>&1 if [ $? -ne 0 ]; then ph.setStatus "critical" ph.status "unable to connect to ${sDomain} via port :${iPort} - maybe wrong host ... or port ... wrong chaining" # repeat the last command without redirecting output echo | openssl s_client -connect ${sDomain}:${iPort} ph.exit fi echo | openssl s_client -connect ${sDomain}:${iPort} 2>/dev/null | openssl x509 -noout -subject | grep -F ${sDomain} >/dev/null if [ $? -ne 0 ]; then ph.setStatus "unknown" echo SORRY, openssl was unable to fetch the right certificate - this happens on multiple ssl webs - it finds echo | openssl s_client -connect ${sDomain}:${iPort} 2>/dev/null | openssl x509 -noout -subject ph.exit fi # --- unix timestamps valid from .. to dateFrom=$(echo | openssl s_client -connect ${sDomain}:${iPort} 2>/dev/null | openssl x509 -noout -startdate | cut -f 2 -d "=") dateTo=$(echo | openssl s_client -connect ${sDomain}:${iPort} 2>/dev/null | openssl x509 -noout -enddate | cut -f 2 -d "=") tsFrom=$(date -d "${dateFrom}" +%s) tsTo=$(date -d "${dateTo}" +%s) tsNow=$(date +%s) typeset -i iDaysLeft=($tsTo-$tsNow)/60/60/24 # --- check date if [ ${tsFrom} -gt ${tsNow} ]; then ph.setStatus "critical" ph.status "certificate ${sDomain}:${iPort} is not valid yet - ${dateFrom}" else if [ ${tsTo} -lt ${tsNow} ]||[ ${iDaysLeft} -le $iCriticalLimit ]; then ph.setStatus "critical" ph.status "certificate ${sDomain}:${iPort} is out of date - ${dateTo} - ${iDaysLeft} days" else # --- check close ending day if [ ${iDaysLeft} -lt ${iWarnLimit} ]; then ph.setStatus "warning" ph.status "certificate ${sDomain}:${iPort} is out of date - ${dateTo} - ${iDaysLeft} days" else ph.setStatus "ok" ph.status "${sDomain}:${iPort} - valid to ${dateTo} (${iDaysLeft} days left)" fi fi fi ph.exit # ----------------------------------------------------------------------