add ssl cert check
This commit is contained in:
66
README_SSL-CERT-CHECK.md
Normal file
66
README_SSL-CERT-CHECK.md
Normal file
@@ -0,0 +1,66 @@
|
||||
# SSL Certification Expiration Checker:
|
||||
|
||||
ssl-cert-check is a Bourne shell script that can be used to report on expiring SSL certificates. The script was designed to be run from cron and can e-mail warnings or log alerts through nagios.
|
||||
|
||||
# Usage:
|
||||
<pre>
|
||||
$ ./ssl-cert-check
|
||||
Usage: ./ssl-cert-check [ -e email address ] [ -E sender email address ] [ -x days ] [-q] [-a] [-b] [-h] [-i] [-n] [-N] [-v]
|
||||
{ [ -s common_name ] && [ -p port] } || { [ -f cert_file ] } || { [ -c cert file ] } || { [ -d cert dir ] }"
|
||||
|
||||
-a : Send a warning message through E-mail
|
||||
-b : Will not print header
|
||||
-c cert file : Print the expiration date for the PEM or PKCS12 formatted certificate in cert file
|
||||
-d cert directory : Print the expiration date for the PEM or PKCS12 formatted certificates in cert directory
|
||||
-e E-mail address : E-mail address to send expiration notices
|
||||
-E E-mail address : Sender E-mail address
|
||||
-f cert file : File with a list of FQDNs and ports
|
||||
-h : Print this screen
|
||||
-i : Print the issuer of the certificate
|
||||
-k password : PKCS12 file password
|
||||
-n : Run as a Nagios plugin
|
||||
-N : Run as a Nagios plugin and output one line summary (implies -n, requires -f or -d)
|
||||
-p port : Port to connect to (interactive mode)
|
||||
-s commmon name : Server to connect to (interactive mode)
|
||||
-t type : Specify the certificate type
|
||||
-q : Don't print anything on the console
|
||||
-v : Specify a specific protocol version to use (tls, ssl2, ssl3)
|
||||
-V : Only print validation data
|
||||
-x days : Certificate expiration interval (eg. if cert_date < days)
|
||||
</pre>
|
||||
|
||||
# Examples:
|
||||
|
||||
Print the expiration times for one or more certificates listed in ssldomains:
|
||||
|
||||
<pre>
|
||||
$ ssl-cert-check -f ssldomains
|
||||
Host Status Expires Days Left
|
||||
----------------------------------------------- ------------ ------------ ----------
|
||||
www.prefetch.com:443 Valid May 23 2006 218
|
||||
mail.prefetch.net:993 Valid Jun 20 2006 246
|
||||
gmail.google.com:443 Valid Jun 7 2006 233
|
||||
www.sun.com:443 Valid May 11 2009 1302
|
||||
www.spotch.com:443 Connection refused Unknown Unknown
|
||||
</pre>
|
||||
|
||||
Check all certificates with file pattern "/etc/haproxy/ssl/\*.pem"
|
||||
|
||||
<pre>
|
||||
$ ssl-cert-check -d "/etc/haproxy/ssl/*.pem"
|
||||
Host Status Expires Days
|
||||
----------------------------------------------- ------------ ------------ ----
|
||||
FILE:/etc/haproxy/ssl/example1.org.pem Valid Jan 6 2017 78
|
||||
FILE:/etc/haproxy/ssl/example2.org.pem Valid Jan 1 2017 73
|
||||
FILE:/etc/haproxy/ssl/example3.org.pem Valid Jan 6 2017 78
|
||||
</pre>
|
||||
|
||||
Send an e-mail to admin@prefetch.net if a domain listed in ssldomains will expire in the next 60-days:
|
||||
|
||||
<pre>
|
||||
$ ssl-cert-check -a -f ssldomains -q -x 60 -e admin@prefetch.net
|
||||
</pre>
|
||||
|
||||
# Additional Documentation
|
||||
|
||||
Documentation And Examples: http://prefetch.net/articles/checkcertificate.html
|
||||
752
ssl-cert-check.sh
Executable file
752
ssl-cert-check.sh
Executable file
@@ -0,0 +1,752 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Program: SSL Certificate Check <ssl-cert-check>
|
||||
#
|
||||
# Source code home: https://github.com/Matty9191/ssl-cert-check
|
||||
#
|
||||
# Documentation: http://prefetch.net/articles/checkcertificate.html
|
||||
#
|
||||
# Author: Matty < matty91 at gmail dot com >
|
||||
#
|
||||
# Current Version: 3.30
|
||||
|
||||
|
||||
PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/ssl/bin:/usr/sfw/bin
|
||||
export PATH
|
||||
|
||||
# Who to page when an expired certificate is detected (cmdline: -e)
|
||||
ADMIN="root"
|
||||
|
||||
# Email sender address for alarm notifications
|
||||
SENDER="postmaster@localhost.localdomain"
|
||||
|
||||
# Number of days in the warning threshhold (cmdline: -x)
|
||||
WARNDAYS=30
|
||||
|
||||
# If QUIET is set to TRUE, don't print anything on the console (cmdline: -q)
|
||||
QUIET="FALSE"
|
||||
|
||||
# Don't send E-mail by default (cmdline: -a)
|
||||
ALARM="FALSE"
|
||||
|
||||
# Don't run as a Nagios plugin by default (cmdline: -n)
|
||||
NAGIOS="FALSE"
|
||||
|
||||
# Don't summarize Nagios output by default (cmdline: -N)
|
||||
NAGIOSSUMMARY="FALSE"
|
||||
|
||||
# NULL out the PKCSDBPASSWD variable for later use (cmdline: -k)
|
||||
PKCSDBPASSWD=""
|
||||
|
||||
# Type of certificate (PEM, DER, NET) (cmdline: -t)
|
||||
CERTTYPE="pem"
|
||||
|
||||
# Protocol version to use (cmdline: -v)
|
||||
VERSION=""
|
||||
|
||||
# Enable debugging
|
||||
DEBUG=0
|
||||
|
||||
# Location of system binaries
|
||||
AWK=$(which awk)
|
||||
DATE=$(which date)
|
||||
GREP=$(which grep)
|
||||
OPENSSL=$(which openssl)
|
||||
PRINTF=$(which printf)
|
||||
SED=$(which sed)
|
||||
MKTEMP=$(which mktemp)
|
||||
FIND=$(which find)
|
||||
|
||||
# Try to find a mail client
|
||||
if [ -f /usr/bin/mailx ]
|
||||
then
|
||||
MAIL="/usr/bin/mailx"
|
||||
MAILMODE="mailx"
|
||||
elif [ -f /bin/mail ]
|
||||
then
|
||||
MAIL="/bin/mail"
|
||||
MAILMODE="mail"
|
||||
elif [ -f /usr/bin/mail ]
|
||||
then
|
||||
MAIL="/usr/bin/mail"
|
||||
MAILMODE="mail"
|
||||
elif [ -f /sbin/mail ]
|
||||
then
|
||||
MAIL="/sbin/mail"
|
||||
MAILMODE="mail"
|
||||
elif [ -f /usr/sbin/mail ]
|
||||
then
|
||||
MAIL="/usr/sbin/mail"
|
||||
MAILMODE="mail"
|
||||
elif [ -f /usr/sbin/sendmail ]
|
||||
then
|
||||
MAIL="/usr/sbin/sendmail"
|
||||
MAILMODE="sendmail"
|
||||
else
|
||||
MAIL="cantfindit"
|
||||
MAILMODE="cantfindit"
|
||||
fi
|
||||
|
||||
# Return code used by nagios. Initialize to 0.
|
||||
RETCODE=0
|
||||
|
||||
# Certificate counters and minimum difference. Initialize to 0.
|
||||
SUMMARY_VALID=0
|
||||
SUMMARY_WILL_EXPIRE=0
|
||||
SUMMARY_EXPIRED=0
|
||||
SUMMARY_MIN_DIFF=0
|
||||
SUMMARY_MIN_DATE=
|
||||
SUMMARY_MIN_HOST=
|
||||
SUMMARY_MIN_PORT=
|
||||
|
||||
# Set the default umask to be somewhat restrictive
|
||||
umask 077
|
||||
|
||||
|
||||
#####################################################
|
||||
### Send email
|
||||
### Accepts three parameters:
|
||||
### $1 -> sender email address
|
||||
### $2 -> email to send mail
|
||||
### $3 -> Subject
|
||||
### $4 -> Message
|
||||
#####################################################
|
||||
send_mail() {
|
||||
|
||||
FROM=${1}
|
||||
TO=${2}
|
||||
SUBJECT=${3}
|
||||
MSG=${4}
|
||||
|
||||
case "${MAILMODE}" in
|
||||
"mail" | "mailx")
|
||||
echo "$MSG" | ${MAIL} -r $FROM -s "$SUBJECT" $TO
|
||||
;;
|
||||
"sendmail")
|
||||
(echo "Subject:$SUBJECT" && echo "TO:$TO" && echo "FROM:$FROM" && echo "$MSG") | ${MAIL} $TO
|
||||
;;
|
||||
"*")
|
||||
echo "ERROR: You enabled automated alerts, but the mail binary could not be found."
|
||||
echo "FIX: Please modify the ${MAIL} and ${$MAILMODE} variable in the program header."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
#############################################################################
|
||||
# Purpose: Convert a date from MONTH-DAY-YEAR to Julian format
|
||||
# Acknowledgements: Code was adapted from examples in the book
|
||||
# "Shell Scripting Recipes: A Problem-Solution Approach"
|
||||
# ( ISBN 1590594711 )
|
||||
# Arguments:
|
||||
# $1 -> Month (e.g., 06)
|
||||
# $2 -> Day (e.g., 08)
|
||||
# $3 -> Year (e.g., 2006)
|
||||
#############################################################################
|
||||
date2julian() {
|
||||
|
||||
if [ "${1}" != "" ] && [ "${2}" != "" ] && [ "${3}" != "" ]
|
||||
then
|
||||
## Since leap years add aday at the end of February,
|
||||
## calculations are done from 1 March 0000 (a fictional year)
|
||||
d2j_tmpmonth=$((12 * ${3} + ${1} - 3))
|
||||
|
||||
## If it is not yet March, the year is changed to the previous year
|
||||
d2j_tmpyear=$(( ${d2j_tmpmonth} / 12))
|
||||
|
||||
## The number of days from 1 March 0000 is calculated
|
||||
## and the number of days from 1 Jan. 4713BC is added
|
||||
echo $(( (734 * ${d2j_tmpmonth} + 15) / 24
|
||||
- 2 * ${d2j_tmpyear} + ${d2j_tmpyear}/4
|
||||
- ${d2j_tmpyear}/100 + ${d2j_tmpyear}/400 + $2 + 1721119 ))
|
||||
else
|
||||
echo 0
|
||||
fi
|
||||
}
|
||||
|
||||
#############################################################################
|
||||
# Purpose: Convert a string month into an integer representation
|
||||
# Arguments:
|
||||
# $1 -> Month name (e.g., Sep)
|
||||
#############################################################################
|
||||
getmonth()
|
||||
{
|
||||
case ${1} in
|
||||
Jan) echo 1 ;;
|
||||
Feb) echo 2 ;;
|
||||
Mar) echo 3 ;;
|
||||
Apr) echo 4 ;;
|
||||
May) echo 5 ;;
|
||||
Jun) echo 6 ;;
|
||||
Jul) echo 7 ;;
|
||||
Aug) echo 8 ;;
|
||||
Sep) echo 9 ;;
|
||||
Oct) echo 10 ;;
|
||||
Nov) echo 11 ;;
|
||||
Dec) echo 12 ;;
|
||||
*) echo 0 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
#############################################################################
|
||||
# Purpose: Calculate the number of seconds between two dates
|
||||
# Arguments:
|
||||
# $1 -> Date #1
|
||||
# $2 -> Date #2
|
||||
#############################################################################
|
||||
date_diff()
|
||||
{
|
||||
if [ "${1}" != "" ] && [ "${2}" != "" ]
|
||||
then
|
||||
echo $((${2} - ${1}))
|
||||
else
|
||||
echo 0
|
||||
fi
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# Purpose: Print a line with the expiraton interval
|
||||
# Arguments:
|
||||
# $1 -> Hostname
|
||||
# $2 -> TCP Port
|
||||
# $3 -> Status of certification (e.g., expired or valid)
|
||||
# $4 -> Date when certificate will expire
|
||||
# $5 -> Days left until the certificate will expire
|
||||
# $6 -> Issuer of the certificate
|
||||
#####################################################################
|
||||
prints()
|
||||
{
|
||||
if [ "${NAGIOSSUMMARY}" == "TRUE" ]
|
||||
then
|
||||
return
|
||||
fi
|
||||
|
||||
if [ "${QUIET}" != "TRUE" ] && [ "${ISSUER}" = "TRUE" ] && [ "${VALIDATION}" != "TRUE" ]
|
||||
then
|
||||
MIN_DATE=$(echo $4 | ${AWK} '{ print $1, $2, $4 }')
|
||||
if [ "${NAGIOS}" == "TRUE" ]
|
||||
then
|
||||
${PRINTF} "%-35s %-17s %-8s %-11s %-4s %-30s\n" "$1:$2" "$6" "$3" "$MIN_DATE" \|days="$5"
|
||||
else
|
||||
${PRINTF} "%-35s %-17s %-8s %-11s %-4s %-30s\n" "$1:$2" "$6" "$3" "$MIN_DATE" "$5"
|
||||
fi
|
||||
elif [ "${QUIET}" != "TRUE" ] && [ "${ISSUER}" = "TRUE" ] && [ "${VALIDATION}" == "TRUE" ]
|
||||
then
|
||||
${PRINTF} "%-35s %-35s %-32s %-17s\n" "$1:$2" "$7" "$8" "$6"
|
||||
|
||||
elif [ "${QUIET}" != "TRUE" ] && [ "${VALIDATION}" != "TRUE" ]
|
||||
then
|
||||
MIN_DATE=$(echo $4 | ${AWK} '{ print $1, $2, $4 }')
|
||||
if [ "${NAGIOS}" == "TRUE" ]
|
||||
then
|
||||
${PRINTF} "%-47s %-12s %-12s %-4s %-30s\n" "$1:$2" "$3" "$MIN_DATE" \|days="$5"
|
||||
else
|
||||
${PRINTF} "%-47s %-12s %-12s %-4s %-30s\n" "$1:$2" "$3" "$MIN_DATE" "$5"
|
||||
fi
|
||||
elif [ "${QUIET}" != "TRUE" ] && [ "${VALIDATION}" == "TRUE" ]
|
||||
then
|
||||
${PRINTF} "%-35s %-35s %-32s\n" "$1:$2" "$7" "$8"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
####################################################
|
||||
# Purpose: Print a heading with the relevant columns
|
||||
# Arguments:
|
||||
# None
|
||||
####################################################
|
||||
print_heading()
|
||||
{
|
||||
if [ "${NOHEADER}" != "TRUE" ]
|
||||
then
|
||||
if [ "${QUIET}" != "TRUE" ] && [ "${ISSUER}" = "TRUE" ] && [ "${NAGIOS}" != "TRUE" ] && [ "${VALIDATION}" != "TRUE" ]
|
||||
then
|
||||
${PRINTF} "\n%-35s %-17s %-8s %-11s %-4s\n" "Host" "Issuer" "Status" "Expires" "Days"
|
||||
echo "----------------------------------- ----------------- -------- ----------- ----"
|
||||
|
||||
elif [ "${QUIET}" != "TRUE" ] && [ "${ISSUER}" = "TRUE" ] && [ "${NAGIOS}" != "TRUE" ] && [ "${VALIDATION}" == "TRUE" ]
|
||||
then
|
||||
${PRINTF} "\n%-35s %-35s %-32s %-17s\n" "Host" "Common Name" "Serial #" "Issuer"
|
||||
echo "----------------------------------- ----------------------------------- -------------------------------- -----------------"
|
||||
|
||||
elif [ "${QUIET}" != "TRUE" ] && [ "${NAGIOS}" != "TRUE" ] && [ "${VALIDATION}" != "TRUE" ]
|
||||
then
|
||||
${PRINTF} "\n%-47s %-12s %-12s %-4s\n" "Host" "Status" "Expires" "Days"
|
||||
echo "----------------------------------------------- ------------ ------------ ----"
|
||||
|
||||
elif [ "${QUIET}" != "TRUE" ] && [ "${NAGIOS}" != "TRUE" ] && [ "${VALIDATION}" == "TRUE" ]
|
||||
then
|
||||
${PRINTF} "\n%-35s %-35s %-32s\n" "Host" "Common Name" "Serial #"
|
||||
echo "----------------------------------- ----------------------------------- --------------------------------"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
####################################################
|
||||
# Purpose: Print a summary for nagios
|
||||
# Arguments:
|
||||
# None
|
||||
####################################################
|
||||
print_summary()
|
||||
{
|
||||
if [ "${NAGIOSSUMMARY}" != "TRUE" ]
|
||||
then
|
||||
return
|
||||
fi
|
||||
|
||||
if [ ${SUMMARY_WILL_EXPIRE} -eq 0 ] && [ ${SUMMARY_EXPIRED} -eq 0 ]
|
||||
then
|
||||
${PRINTF} "%s valid certificate(s)|days=%s\n" "${SUMMARY_VALID}" "${SUMMARY_MIN_DIFF}"
|
||||
|
||||
elif [ ${SUMMARY_EXPIRED} -ne 0 ]
|
||||
then
|
||||
${PRINTF} "%s certificate(s) expired (%s:%s on %s)|days=%s\n" "${SUMMARY_EXPIRED}" "${SUMMARY_MIN_HOST}" "${SUMMARY_MIN_PORT}" "${SUMMARY_MIN_DATE}" "${SUMMARY_MIN_DIFF}"
|
||||
|
||||
elif [ ${SUMMARY_WILL_EXPIRE} -ne 0 ]
|
||||
then
|
||||
${PRINTF} "%s certificate(s) will expire (%s:%s on %s)|days=%s\n" "${SUMMARY_WILL_EXPIRE}" "${SUMMARY_MIN_HOST}" "${SUMMARY_MIN_PORT}" "${SUMMARY_MIN_DATE}" "${SUMMARY_MIN_DIFF}"
|
||||
|
||||
fi
|
||||
}
|
||||
|
||||
#############################################################
|
||||
# Purpose: Set returncode to value if current value is lower
|
||||
# Arguments:
|
||||
# $1 -> New returncorde
|
||||
#############################################################
|
||||
set_returncode()
|
||||
{
|
||||
if [ ${RETCODE} -lt ${1} ]
|
||||
then
|
||||
RETCODE=${1}
|
||||
fi
|
||||
}
|
||||
|
||||
########################################################################
|
||||
# Purpose: Set certificate counters and informations for nagios summary
|
||||
# Arguments:
|
||||
# $1 -> Status of certificate (0: valid, 1: will expire, 2: expired)
|
||||
# $2 -> Hostname
|
||||
# $3 -> TCP Port
|
||||
# $4 -> Date when certificate will expire
|
||||
# $5 -> Days left until the certificate will expire
|
||||
########################################################################
|
||||
set_summary()
|
||||
{
|
||||
if [ ${1} -eq 0 ]
|
||||
then
|
||||
SUMMARY_VALID=$((SUMMARY_VALID+1))
|
||||
|
||||
elif [ ${1} -eq 1 ]
|
||||
then
|
||||
SUMMARY_WILL_EXPIRE=$((SUMMARY_WILL_EXPIRE+1))
|
||||
|
||||
else
|
||||
SUMMARY_EXPIRED=$((SUMMARY_EXPIRED+1))
|
||||
fi
|
||||
|
||||
if [ ${5} -lt ${SUMMARY_MIN_DIFF} ] || [ ${SUMMARY_MIN_DIFF} -eq 0 ]
|
||||
then
|
||||
SUMMARY_MIN_DATE=${4}
|
||||
SUMMARY_MIN_DIFF=${5}
|
||||
SUMMARY_MIN_HOST=${2}
|
||||
SUMMARY_MIN_PORT=${3}
|
||||
fi
|
||||
}
|
||||
|
||||
##########################################
|
||||
# Purpose: Describe how the script works
|
||||
# Arguments:
|
||||
# None
|
||||
##########################################
|
||||
usage()
|
||||
{
|
||||
echo "Usage: $0 [ -e email address ] [-E sender email address] [ -x days ] [-q] [-a] [-b] [-h] [-i] [-n] [-N] [-v]"
|
||||
echo " { [ -s common_name ] && [ -p port] } || { [ -f cert_file ] } || { [ -c cert file ] } || { [ -d cert dir ] }"
|
||||
echo ""
|
||||
echo " -a : Send a warning message through E-mail"
|
||||
echo " -b : Will not print header"
|
||||
echo " -c cert file : Print the expiration date for the PEM or PKCS12 formatted certificate in cert file"
|
||||
echo " -d cert directory : Print the expiration date for the PEM or PKCS12 formatted certificates in cert directory"
|
||||
echo " -e E-mail address : E-mail address to send expiration notices"
|
||||
echo " -E E-mail sender : E-mail address of the sender"
|
||||
echo " -f cert file : File with a list of FQDNs and ports"
|
||||
echo " -h : Print this screen"
|
||||
echo " -i : Print the issuer of the certificate"
|
||||
echo " -k password : PKCS12 file password"
|
||||
echo " -n : Run as a Nagios plugin"
|
||||
echo " -N : Run as a Nagios plugin and output one line summary (implies -n, requires -f or -d)"
|
||||
echo " -p port : Port to connect to (interactive mode)"
|
||||
echo " -s commmon name : Server to connect to (interactive mode)"
|
||||
echo " -t type : Specify the certificate type"
|
||||
echo " -q : Don't print anything on the console"
|
||||
echo " -v : Specify a specific protocol version to use (tls, ssl2, ssl3)"
|
||||
echo " -V : Only print validation data"
|
||||
echo " -x days : Certificate expiration interval (eg. if cert_date < days)"
|
||||
echo ""
|
||||
}
|
||||
|
||||
|
||||
##########################################################################
|
||||
# Purpose: Connect to a server ($1) and port ($2) to see if a certificate
|
||||
# has expired
|
||||
# Arguments:
|
||||
# $1 -> Server name
|
||||
# $2 -> TCP port to connect to
|
||||
##########################################################################
|
||||
check_server_status() {
|
||||
|
||||
if [ "_${2}" = "_smtp" -o "_${2}" = "_25" ]
|
||||
then
|
||||
TLSFLAG="-starttls smtp"
|
||||
|
||||
elif [ "_${2}" = "_ftp" -o "_${2}" = "_21" ]
|
||||
then
|
||||
TLSFLAG="-starttls ftp"
|
||||
|
||||
elif [ "_${2}" = "_pop3" -o "_${2}" = "_110" ]
|
||||
then
|
||||
TLSFLAG="-starttls pop3"
|
||||
|
||||
elif [ "_${2}" = "_imap" -o "_${2}" = "_143" ]
|
||||
then
|
||||
TLSFLAG="-starttls imap"
|
||||
|
||||
elif [ "_${2}" = "_submission" -o "_${2}" = "_587" ]
|
||||
then
|
||||
TLSFLAG="-starttls smtp -port ${2}"
|
||||
else
|
||||
TLSFLAG=""
|
||||
fi
|
||||
|
||||
if [ "${VERSION}" != "" ]
|
||||
then
|
||||
VER="-${VERSION}"
|
||||
fi
|
||||
|
||||
if [ "${TLSSERVERNAME}" = "TRUE" ]
|
||||
then
|
||||
TLSFLAG="${TLSFLAG} -servername $1"
|
||||
fi
|
||||
|
||||
echo "" | ${OPENSSL} s_client -crlf ${VER} -connect ${1}:${2} ${TLSFLAG} 2> ${ERROR_TMP} 1> ${CERT_TMP}
|
||||
|
||||
if ${GREP} -i "Connection refused" ${ERROR_TMP} > /dev/null
|
||||
then
|
||||
prints ${1} ${2} "Connection refused" "Unknown"
|
||||
set_returncode 3
|
||||
|
||||
elif ${GREP} -i "No route to host" ${ERROR_TMP} > /dev/null
|
||||
then
|
||||
prints ${1} ${2} "No route to host" "Unknown"
|
||||
set_returncode 3
|
||||
|
||||
elif ${GREP} -i "gethostbyname failure" ${ERROR_TMP} > /dev/null
|
||||
then
|
||||
prints ${1} ${2} "Cannot resolve domain" "Unknown"
|
||||
set_returncode 3
|
||||
|
||||
elif ${GREP} -i "Operation timed out" ${ERROR_TMP} > /dev/null
|
||||
then
|
||||
prints ${1} ${2} "Operation timed out" "Unknown"
|
||||
set_returncode 3
|
||||
|
||||
elif ${GREP} -i "ssl handshake failure" ${ERROR_TMP} > /dev/null
|
||||
then
|
||||
prints ${1} ${2} "SSL handshake failed" "Unknown"
|
||||
set_returncode 3
|
||||
|
||||
elif ${GREP} -i "connect: Connection timed out" ${ERROR_TMP} > /dev/null
|
||||
then
|
||||
prints ${1} ${2} "Connection timed out" "Unknown"
|
||||
set_returncode 3
|
||||
|
||||
else
|
||||
check_file_status ${CERT_TMP} $1 $2
|
||||
fi
|
||||
}
|
||||
|
||||
#####################################################
|
||||
### Check the expiration status of a certificate file
|
||||
### Accepts three parameters:
|
||||
### $1 -> certificate file to process
|
||||
### $2 -> Server name
|
||||
### $3 -> Port number of certificate
|
||||
#####################################################
|
||||
check_file_status() {
|
||||
|
||||
CERTFILE=${1}
|
||||
HOST=${2}
|
||||
PORT=${3}
|
||||
|
||||
### Check to make sure the certificate file exists
|
||||
if [ ! -r ${CERTFILE} ] || [ ! -s ${CERTFILE} ]
|
||||
then
|
||||
echo "ERROR: The file named ${CERTFILE} is unreadable or doesn't exist"
|
||||
echo "ERROR: Please check to make sure the certificate for ${HOST}:${PORT} is valid"
|
||||
set_returncode 3
|
||||
return
|
||||
fi
|
||||
|
||||
### Grab the expiration date from the X.509 certificate
|
||||
if [ "${PKCSDBPASSWD}" != "" ]
|
||||
then
|
||||
# Extract the certificate from the PKCS#12 database, and
|
||||
# send the informational message to /dev/null
|
||||
${OPENSSL} pkcs12 -nokeys -in ${CERTFILE} \
|
||||
-out ${CERT_TMP} -clcerts -password pass:${PKCSDBPASSWD} 2> /dev/null
|
||||
|
||||
# Extract the expiration date from the certificate
|
||||
CERTDATE=$(${OPENSSL} x509 -in ${CERT_TMP} -enddate -noout | \
|
||||
${SED} 's/notAfter\=//')
|
||||
|
||||
# Extract the issuer from the certificate
|
||||
CERTISSUER=$(${OPENSSL} x509 -in ${CERT_TMP} -issuer -noout | \
|
||||
${AWK} 'BEGIN {RS="/" } $0 ~ /^O=/ \
|
||||
{ print substr($0,3,17)}')
|
||||
|
||||
### Grab the common name (CN) from the X.509 certificate
|
||||
COMMONNAME=$(${OPENSSL} x509 -in ${CERT_TMP} -subject -noout | \
|
||||
${SED} -e 's/.*CN=//' | \
|
||||
${SED} -e 's/\/.*//')
|
||||
|
||||
### Grab the serial number from the X.509 certificate
|
||||
SERIAL=$(${OPENSSL} x509 -in ${CERT_TMP} -serial -noout | \
|
||||
${SED} -e 's/serial=//')
|
||||
else
|
||||
# Extract the expiration date from the ceriticate
|
||||
CERTDATE=$(${OPENSSL} x509 -in ${CERTFILE} -enddate -noout -inform ${CERTTYPE} | \
|
||||
${SED} 's/notAfter\=//')
|
||||
|
||||
# Extract the issuer from the certificate
|
||||
CERTISSUER=$(${OPENSSL} x509 -in ${CERTFILE} -issuer -noout -inform ${CERTTYPE} | \
|
||||
${AWK} 'BEGIN {RS="/" } $0 ~ /^O=/ { print substr($0,3,17)}')
|
||||
|
||||
### Grab the common name (CN) from the X.509 certificate
|
||||
COMMONNAME=$(${OPENSSL} x509 -in ${CERTFILE} -subject -noout -inform ${CERTTYPE} | \
|
||||
${SED} -e 's/.*CN=//' | \
|
||||
${SED} -e 's/\/.*//')
|
||||
|
||||
### Grab the serial number from the X.509 certificate
|
||||
SERIAL=$(${OPENSSL} x509 -in ${CERTFILE} -serial -noout -inform ${CERTTYPE} | \
|
||||
${SED} -e 's/serial=//')
|
||||
fi
|
||||
|
||||
### Split the result into parameters, and pass the relevant pieces to date2julian
|
||||
set -- ${CERTDATE}
|
||||
MONTH=$(getmonth ${1})
|
||||
|
||||
# Convert the date to seconds, and get the diff between NOW and the expiration date
|
||||
CERTJULIAN=$(date2julian ${MONTH#0} ${2#0} ${4})
|
||||
CERTDIFF=$(date_diff ${NOWJULIAN} ${CERTJULIAN})
|
||||
|
||||
if [ ${CERTDIFF} -lt 0 ]
|
||||
then
|
||||
if [ "${ALARM}" = "TRUE" ]
|
||||
then
|
||||
send_mail ${SENDER} ${ADMIN} "Certificate for ${HOST} \"(CN: ${COMMONNAME})\" has expired!" \
|
||||
"The SSL certificate for ${HOST} \"(CN: ${COMMONNAME})\" has expired!"
|
||||
fi
|
||||
|
||||
prints ${HOST} ${PORT} "Expired" "${CERTDATE}" "${CERTDIFF}" "${CERTISSUER}" "${COMMONNAME}" "${SERIAL}"
|
||||
RETCODE_LOCAL=2
|
||||
|
||||
elif [ ${CERTDIFF} -lt ${WARNDAYS} ]
|
||||
then
|
||||
if [ "${ALARM}" = "TRUE" ]
|
||||
then
|
||||
send_mail ${SENDER} ${ADMIN} "Certificate for ${HOST} \"(CN: ${COMMONNAME})\" will expire in ${WARNDAYS}-days or less" \
|
||||
"The SSL certificate for ${HOST} \"(CN: ${COMMONNAME})\" will expire on ${CERTDATE}"
|
||||
fi
|
||||
prints ${HOST} ${PORT} "Expiring" "${CERTDATE}" "${CERTDIFF}" "${CERTISSUER}" "${COMMONNAME}" "${SERIAL}"
|
||||
RETCODE_LOCAL=1
|
||||
|
||||
else
|
||||
prints ${HOST} ${PORT} "Valid" "${CERTDATE}" "${CERTDIFF}" "${CERTISSUER}" "${COMMONNAME}" "${SERIAL}"
|
||||
RETCODE_LOCAL=0
|
||||
fi
|
||||
|
||||
set_returncode ${RETCODE_LOCAL}
|
||||
MIN_DATE=$(echo ${CERTDATE} | ${AWK} '{ print $1, $2, $4 }')
|
||||
set_summary ${RETCODE_LOCAL} ${HOST} ${PORT} "${MIN_DATE}" ${CERTDIFF}
|
||||
}
|
||||
|
||||
#################################
|
||||
### Start of main program
|
||||
#################################
|
||||
while getopts abinNv:e:E:f:c:d:hk:p:s:t:qx:V option
|
||||
do
|
||||
case "${option}"
|
||||
in
|
||||
a) ALARM="TRUE";;
|
||||
b) NOHEADER="TRUE";;
|
||||
c) CERTFILE=${OPTARG};;
|
||||
d) CERTDIRECTORY=${OPTARG};;
|
||||
e) ADMIN=${OPTARG};;
|
||||
E) SENDER=${OPTARG};;
|
||||
f) SERVERFILE=$OPTARG;;
|
||||
h) usage
|
||||
exit 1;;
|
||||
i) ISSUER="TRUE";;
|
||||
k) PKCSDBPASSWD=${OPTARG};;
|
||||
n) NAGIOS="TRUE";;
|
||||
N) NAGIOS="TRUE"
|
||||
NAGIOSSUMMARY="TRUE";;
|
||||
p) PORT=$OPTARG;;
|
||||
s) HOST=$OPTARG;;
|
||||
t) CERTTYPE=$OPTARG;;
|
||||
q) QUIET="TRUE";;
|
||||
v) VERSION=$OPTARG;;
|
||||
V) VALIDATION="TRUE";;
|
||||
x) WARNDAYS=$OPTARG;;
|
||||
\?) usage
|
||||
exit 1;;
|
||||
esac
|
||||
done
|
||||
|
||||
### Check to make sure a openssl utility is available
|
||||
if [ ! -f ${OPENSSL} ]
|
||||
then
|
||||
echo "ERROR: The openssl binary does not exist in ${OPENSSL}."
|
||||
echo "FIX: Please modify the \${OPENSSL} variable in the program header."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
### Check to make sure a date utility is available
|
||||
if [ ! -f ${DATE} ]
|
||||
then
|
||||
echo "ERROR: The date binary does not exist in ${DATE} ."
|
||||
echo "FIX: Please modify the \${DATE} variable in the program header."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
### Check to make sure a grep and find utility is available
|
||||
if [ ! -f ${GREP} ] || [ ! -f ${FIND} ]
|
||||
then
|
||||
echo "ERROR: Unable to locate the greb and find binary."
|
||||
echo "FIX: Please modify the \${GREP} and \${FIND} variables in the program header."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
### Check to make sure the mktemp and printf utilities are available
|
||||
if [ ! -f ${MKTEMP} ] || [ ! -f ${PRINTF} ]
|
||||
then
|
||||
echo "ERROR: Unable to locate the mktemp or printf binary."
|
||||
echo "FIX: Please modify the \${MKTEMP} and \${PRINTF} variables in the program header."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
### Check to make sure the sed and awk binaries are available
|
||||
if [ ! -f ${SED} ] || [ ! -f ${AWK} ]
|
||||
then
|
||||
echo "ERROR: Unable to locate the sed or awk binary."
|
||||
echo "FIX: Please modify the \${SED} and \${AWK} variables in the program header."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
### Check to make sure a mail client is available it automated notifications are requested
|
||||
if [ "${ALARM}" = "TRUE" ] && [ ! -f ${MAIL} ]
|
||||
then
|
||||
echo "ERROR: You enabled automated alerts, but the mail binary could not be found."
|
||||
echo "FIX: Please modify the ${MAIL} variable in the program header."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Send along the servername when TLS is used
|
||||
if ${OPENSSL} s_client -help 2>&1 | grep '-servername' > /dev/null
|
||||
then
|
||||
TLSSERVERNAME="TRUE"
|
||||
else
|
||||
TLSSERVERNAME="FALSE"
|
||||
fi
|
||||
|
||||
# Place to stash temporary files
|
||||
CERT_TMP=$($MKTEMP /var/tmp/cert.XXXXXX)
|
||||
ERROR_TMP=$($MKTEMP /var/tmp/error.XXXXXX)
|
||||
|
||||
### Baseline the dates so we have something to compare to
|
||||
MONTH=$(${DATE} "+%m")
|
||||
DAY=$(${DATE} "+%d")
|
||||
YEAR=$(${DATE} "+%Y")
|
||||
NOWJULIAN=$(date2julian ${MONTH#0} ${DAY#0} ${YEAR})
|
||||
|
||||
### Touch the files prior to using them
|
||||
if [ ! -z "${CERT_TMP}" ] && [ ! -z "${ERROR_TMP}" ]
|
||||
then
|
||||
touch ${CERT_TMP} ${ERROR_TMP}
|
||||
else
|
||||
echo "ERROR: Problem creating temporary files"
|
||||
echo "FIX: Check that mktemp works on your system"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
### If a HOST and PORT were passed on the cmdline, use those values
|
||||
if [ "${HOST}" != "" ] && [ "${PORT}" != "" ]
|
||||
then
|
||||
print_heading
|
||||
check_server_status "${HOST}" "${PORT}"
|
||||
print_summary
|
||||
|
||||
### If a file is passed to the "-f" option on the command line, check
|
||||
### each certificate or server / port combination in the file to see if
|
||||
### they are about to expire
|
||||
elif [ -f "${SERVERFILE}" ]
|
||||
then
|
||||
print_heading
|
||||
|
||||
IFS=$'\n'
|
||||
for LINE in `egrep -v '(^#|^$)' ${SERVERFILE}`
|
||||
do
|
||||
HOST=${LINE%% *}
|
||||
PORT=${LINE#* }
|
||||
IFS=" "
|
||||
if [ "$PORT" = "FILE" ]
|
||||
then
|
||||
check_file_status ${HOST} "FILE" "${HOST}"
|
||||
else
|
||||
check_server_status "${HOST}" "${PORT}"
|
||||
fi
|
||||
done
|
||||
IFS=${OLDIFS}
|
||||
print_summary
|
||||
|
||||
### Check to see if the certificate in CERTFILE is about to expire
|
||||
elif [ "${CERTFILE}" != "" ]
|
||||
then
|
||||
print_heading
|
||||
check_file_status ${CERTFILE} "FILE" "${CERTFILE}"
|
||||
print_summary
|
||||
|
||||
### Check to see if the certificates in CERTDIRECTORY are about to expire
|
||||
elif [ "${CERTDIRECTORY}" != "" ] && (${FIND} -L ${CERTDIRECTORY} -type f > /dev/null 2>&1)
|
||||
then
|
||||
print_heading
|
||||
for FILE in `${FIND} -L ${CERTDIRECTORY} -type f`; do
|
||||
check_file_status ${FILE} "FILE" "${FILE}"
|
||||
done
|
||||
print_summary
|
||||
|
||||
### There was an error, so print a detailed usage message and exit
|
||||
else
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
### Remove the temporary files
|
||||
if [ $DEBUG == 1 ]
|
||||
then
|
||||
echo "DEBUG: Certificate temporary file:"
|
||||
cat ${CERT_TMP}
|
||||
echo "DEBUG: Runtime information file:"
|
||||
cat ${ERROR_TMP}
|
||||
fi
|
||||
|
||||
rm -f ${CERT_TMP} ${ERROR_TMP}
|
||||
|
||||
### Exit with a success indicator
|
||||
if [ "${NAGIOS}" = "TRUE" ]
|
||||
then
|
||||
exit $RETCODE
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
Reference in New Issue
Block a user