2019-07-23 22:28:09 +02:00
|
|
|
#!/bin/sh
|
|
|
|
|
|
|
|
|
|
|
|
# Little custom script to check expiration date of DNS domains
|
|
|
|
|
|
|
|
# Default values
|
|
|
|
#RANGE_WARNING=":2592000" # 30 days
|
|
|
|
#RANGE_CRITICAL=":691200" # 8 days
|
|
|
|
THRESHOLD_WARNING="2592000" # 30 days
|
|
|
|
THRESHOLD_CRITICAL="691200" # 8 days
|
|
|
|
TIMESTAMP_NOW="$( date +%s )"
|
|
|
|
|
|
|
|
|
|
|
|
# Output
|
|
|
|
OUTPUT_EXIT_STATUS=0
|
|
|
|
OUTPUT_DETAIL_WARNING=""
|
|
|
|
OUTPUT_DETAIL_CRITICAL=""
|
|
|
|
OUTPUT_PERFDATA=""
|
|
|
|
|
|
|
|
PROGPATH=$( echo $0 | sed -e 's,[\\/][^\\/][^\\/]*$,,' )
|
|
|
|
REVISION="0.1"
|
|
|
|
|
|
|
|
# Stop at the first non-catched error
|
|
|
|
set -e
|
|
|
|
|
|
|
|
# Include check_range()
|
|
|
|
. $PROGPATH/utils.sh
|
|
|
|
# No real need for this script but then you have to copy the status
|
|
|
|
# Not really clean...
|
|
|
|
#STATE_OK=0
|
|
|
|
#STATE_WARNING=1
|
|
|
|
#STATE_CRITICAL=2
|
|
|
|
#STATE_UNKNOWN=3
|
|
|
|
#STATE_DEPENDENT=4
|
|
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
# Help function
|
|
|
|
#
|
|
|
|
usage() {
|
|
|
|
cat <<EOF
|
|
|
|
Usage :
|
|
|
|
$0 [-w warning_threshold] [-c critical_threshold] domain1 [domain2] ...
|
|
|
|
|
|
|
|
Thresholds in seconds (or suffix by 'd' for days).
|
|
|
|
|
|
|
|
Default values:
|
|
|
|
warning_threshold : $THRESHOLD_WARNING
|
|
|
|
critical_threshold : $THRESHOLD_CRITICAL
|
|
|
|
EOF
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
# Days/Months/Hours to seconds convert function
|
|
|
|
#
|
|
|
|
convert_to_seconds() {
|
|
|
|
local UNIT VALUE
|
|
|
|
UNIT="$( echo "$1" | sed 's/.*\(.\)$/\1/;q' )"
|
|
|
|
VALUE="$( echo "$1" | sed 's/^\([0-9]*\).*/\1/;q' )"
|
|
|
|
|
|
|
|
case "$UNIT" in
|
|
|
|
'd')
|
|
|
|
# Unit is days
|
|
|
|
echo "$( expr "$VALUE" \* 86400 )"
|
|
|
|
;;
|
|
|
|
|
|
|
|
*)
|
|
|
|
echo "$1"
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
# Check if arg is an integer
|
|
|
|
# (copied from jilles @ http://stackoverflow.com/questions/806906/how-do-i-test-if-a-variable-is-a-number-in-bash )
|
|
|
|
#
|
|
|
|
is_int() {
|
|
|
|
case "$1" in
|
|
|
|
''|*[!0-9]*) return 1;;
|
|
|
|
*) return 0;;
|
|
|
|
esac
|
|
|
|
}
|
|
|
|
|
|
|
|
#
|
|
|
|
# Extract the date fs a timestamp rom the whois response
|
|
|
|
# (print 1 line max.)
|
|
|
|
# (exit status = 1 if problem)
|
|
|
|
#
|
|
|
|
extract_date_from_whois() {
|
|
|
|
local EXPIRATION_DATE
|
|
|
|
|
|
|
|
# We put each format on a dedicated line
|
|
|
|
# + filter only the first line
|
|
|
|
# Note : some sed implementations seems not to offer
|
|
|
|
# case-insensitive option, so we try not to
|
|
|
|
# use it for the moment.
|
|
|
|
# 1 - kernel.org, icann.org
|
|
|
|
# 2 - coca-cola.com (we try to ignore lines starting with space...)
|
|
|
|
# 3 - facebook.com (...but if there's nothing else, take it anyway)
|
|
|
|
# 4 - some databases with simple display (.se, .si)
|
2023-10-04 23:26:55 +02:00
|
|
|
# 5 - .it
|
|
|
|
# 6 - .ru
|
|
|
|
# 7 - .jp
|
2019-07-23 22:28:09 +02:00
|
|
|
# Add your own filter here :)
|
|
|
|
EXPIRATION_DATE="$( sed -n \
|
2024-01-07 15:46:07 +01:00
|
|
|
-e 's/^Registry Expiry Date:[[:space:]]\+//p' \
|
2023-10-04 23:26:55 +02:00
|
|
|
-e '/^[^[:space:]]/s/.*\(xpiry\|xpiration\) Date:[[:space:]]\+//p' \
|
|
|
|
-e 's/.*\(xpiry\|xpiration\) Date:[[:space:]]\+//p' \
|
2019-07-23 22:28:09 +02:00
|
|
|
-e 's/^expires\?:[[:space:]]*//p' \
|
2023-10-04 23:26:55 +02:00
|
|
|
-e 's/^Expire Date:[[:space:]]*//p' \
|
|
|
|
-e 's/^paid-till:[[:space:]]*//p' \
|
|
|
|
-e 's/^\[Expires on\][[:space:]]*//p' \
|
2019-07-23 22:28:09 +02:00
|
|
|
| sed 'q'
|
|
|
|
)"
|
|
|
|
|
|
|
|
# Small protection against injection
|
2021-07-27 13:35:07 +02:00
|
|
|
if [ -n "$( echo "$EXPIRATION_DATE" | LANG=C sed -n '/^[a-zA-Z0-9:.\-]\{1,64\}$/p' )" ]; then
|
2019-07-23 22:28:09 +02:00
|
|
|
date --date="$EXPIRATION_DATE" +%s
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
# Some early checks
|
|
|
|
if ! which whois >/dev/null 2>&1; then
|
|
|
|
echo "UNKNOWN: 'whois' command not found."
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
# Parameters management
|
|
|
|
#
|
|
|
|
while [ "$#" -gt 0 ]; do
|
|
|
|
while getopts hw:c: f; do
|
|
|
|
case "$f" in
|
|
|
|
'h')
|
|
|
|
usage
|
|
|
|
exit
|
|
|
|
;;
|
|
|
|
|
|
|
|
'w')
|
|
|
|
THRESHOLD_WARNING="$( convert_to_seconds "$OPTARG" )"
|
|
|
|
;;
|
|
|
|
|
|
|
|
'c')
|
|
|
|
THRESHOLD_CRITICAL="$( convert_to_seconds "$OPTARG" )"
|
|
|
|
;;
|
|
|
|
|
|
|
|
\?)
|
|
|
|
usage
|
|
|
|
exit 1
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
done
|
|
|
|
shift $( expr $OPTIND - 1 )
|
|
|
|
|
|
|
|
# Little checks
|
|
|
|
if ! is_int "$THRESHOLD_WARNING" || ! is_int "$THRESHOLD_CRITICAL"; then
|
|
|
|
echo "UNKNOWN invalid parameter : one of the threshold is not an integer."
|
|
|
|
exit $STATE_UNKNOWN
|
|
|
|
fi
|
|
|
|
|
|
|
|
# End of the options, we get the domain name
|
|
|
|
if [ -z "$1" ]; then
|
|
|
|
# No more options but no domain specified ? Weird but well...
|
|
|
|
break
|
|
|
|
fi
|
|
|
|
DOMAIN="$1"
|
|
|
|
shift
|
|
|
|
|
|
|
|
# get the expiration date for this domain
|
2021-09-15 00:22:13 +02:00
|
|
|
test -n "$EXPIRATION_DATE" && sleep 2 # trying not to flood the whois servers
|
2019-07-23 22:28:09 +02:00
|
|
|
EXPIRATION_DATE="$( whois "$DOMAIN" | extract_date_from_whois )"
|
|
|
|
if [ -z "$EXPIRATION_DATE" ]; then
|
|
|
|
# We couldn't get the date :-(
|
|
|
|
if [ "$OUTPUT_EXIT_STATUS" -eq "$STATE_OK" ]; then
|
|
|
|
OUTPUT_EXIT_STATUS="$STATE_UNKNOWN"
|
|
|
|
fi
|
|
|
|
OUTPUT_DETAIL_UNKNOWN="$OUTPUT_DETAIL_UNKNOWN $DOMAIN:could_not_get_date"
|
|
|
|
break
|
|
|
|
fi
|
|
|
|
|
|
|
|
# Dispatch in the OK/Warning/Critical boxes
|
|
|
|
OUTPUT_DOMAIN_DETAIL="$DOMAIN:$( date --date=@$EXPIRATION_DATE +%FT%T%z)"
|
|
|
|
if [ "$EXPIRATION_DATE" -le "$( expr "$TIMESTAMP_NOW" + "$THRESHOLD_CRITICAL" )" ]; then
|
|
|
|
# Domain is critical
|
|
|
|
OUTPUT_EXIT_STATUS="$STATE_CRITICAL"
|
|
|
|
OUTPUT_DETAIL_CRITICAL="$OUTPUT_DETAIL_CRITICAL $OUTPUT_DOMAIN_DETAIL"
|
|
|
|
elif [ "$EXPIRATION_DATE" -le "$( expr "$TIMESTAMP_NOW" + "$THRESHOLD_WARNING" )" ]; then
|
|
|
|
# Domain is warning
|
|
|
|
OUTPUT_DETAIL_WARNING="$OUTPUT_DETAIL_WARNING $OUTPUT_DOMAIN_DETAIL"
|
|
|
|
# we don't change if the status is already Critical
|
|
|
|
# (but we take precedence over Unknown)
|
|
|
|
if [ "$OUTPUT_EXIT_STATUS" -ne "$STATE_CRITICAL" ]; then
|
|
|
|
OUTPUT_EXIT_STATUS="$STATE_WARNING"
|
|
|
|
fi
|
|
|
|
else
|
|
|
|
# Domain is Ok
|
|
|
|
OUTPUT_DETAIL_OK="$OUTPUT_DETAIL_OK $OUTPUT_DOMAIN_DETAIL"
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
|
|
|
|
# final output
|
|
|
|
case "$OUTPUT_EXIT_STATUS" in
|
|
|
|
"$STATE_OK")
|
|
|
|
echo "OK $OUTPUT_DETAIL_OK"
|
|
|
|
;;
|
|
|
|
|
|
|
|
"$STATE_WARNING")
|
|
|
|
echo "WARNING $OUTPUT_DETAIL_WARNING"
|
|
|
|
;;
|
|
|
|
|
|
|
|
"$STATE_CRITICAL")
|
|
|
|
echo "CRITICAL $OUTPUT_DETAIL_CRITICAL"
|
|
|
|
;;
|
|
|
|
|
|
|
|
"$STATE_UNKNOWN")
|
|
|
|
echo "UNKNOWN $OUTPUT_DETAIL_UNKNOWN"
|
|
|
|
;;
|
|
|
|
|
|
|
|
*)
|
|
|
|
echo "WTF"
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
|
|
|
|
exit "$OUTPUT_EXIT_STATUS"
|