#!/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) # Add your own filter here :) EXPIRATION_DATE="$( sed -n \ -e 's/^Registry Expiry Date: //p' \ -e '/^[^[:space:]]/s/.*\(xpiry\|xpiration\) Date: //p' \ -e 's/.*\(xpiry\|xpiration\) Date: //p' \ -e 's/^expires\?:[[:space:]]*//p' \ | sed 'q' )" # Small protection against injection if [ -n "$( echo "$EXPIRATION_DATE" | LANG=C sed -n '/^[a-zA-Z0-9:.\-]\{1,64\}$/p' )" ]; then 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 test -n "$EXPIRATION_DATE" && sleep 2 # trying not to flood the whois servers 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"