#!/bin/bash

#############################################################################
#                                                                           #
# This script was initially developed by Infoxchange for internal use       #
# and has kindly been made available to the Open Source community for       #
# redistribution and further development under the terms of the             #
# GNU General Public License v3: http://www.gnu.org/licenses/gpl.html       #
#                                                                           #
#############################################################################
#                                                                           #
# This script is supplied 'as-is', in the hope that it will be useful, but  #
# neither Infoxchange nor the authors make any warranties or guarantees     #
# as to its correct operation, including its intended function.             #
#                                                                           #
# Or in other words:                                                        #
#       Test it yourself, and make sure it works for YOU.                   #
#                                                                           #
#############################################################################
# Author: George Hansper                     e-mail:  george@hansper.id.au  #
#############################################################################

TIMEOUT=30
TIME_WARN=5
TIME_CRIT=10
HOST=`hostname --fqdn`
PUPPETMASTER=puppet
PORT=8140
SSLDIR=/var/lib/puppet/ssl

OPTS=`getopt -o ht:H:p:w:c: --long hostname:,timeout:,port:,warn:,crit: \
     -n '$0' -- "$@"`

function usage () {
    cat <<-EOF
        Usage: $0 [ -h ] [ --help ] [ -H hostname ] [ --hostname hostname ]
                  [ -w decimal ] [ --warn decimal ] [ -c decimal ] [ --crit decimal ]
                  [ -t integer ] [ --timeout integer ]
           -H, --hostname ... name of puppetmaster host (default is $PUPPETMASTER)
           -w, --warn     ... Warning  if check takss longer than this many seconds (floating point, default is $TIME_WARN)
           -c, --crit     ... Critical if check takss longer than this many seconds (floating point, default is $TIME_CRIT)
           -t, --timeout  ... timeout for this check (integer, default is $TIMEOUT)
           -p, --port     ... port number (default is $PORT)

        Example
                $0 --warn 2 --crit 3.5 --timeout 60

        Notes
                This check must be run on a host that is a client of the puppetmaster being checked.
                It will look for the key and certificates in the directory $SSLDIR

                In order to read the hosts's private key, this script needs to be run under sudo as the user puppet (or root)
                Sample Configuration:

                    /etc/sudoers
                       nagios  ALL=(puppet) NOPASSWD: /usr/lib/nagios/plugins/check_puppetmaster.sh

                    /etc/nagios/commands.cfg entry
                       define command {
                             command_name       check_puppetmaster
                             command_line       /usr/bin/sudo /usr/lib/nagios/plugins/check_puppetmaster.sh -H \$HOSTNAME\$ \$ARG1\$
                       }

EOF
}

if [ $? != 0 ] ; then
    echo "Terminating..." >&2
    usage
  exit 1
fi
eval set -- "$OPTS"

# This command has to run under sudo - so we need to check the args carefully in case of character-injection (eg ;)
while true ; do
    case "$1" in
        -h|--help)
            usage
            exit
            ;;
        -H|--hostname)
            PUPPETMASTER=$( echo $2 |sed -e 's/[^-0-9a-z._]//ig')
            shift 2
            ;;
        -w|--warn)
            TIME_WARN=$( echo $2 |sed -e 's/[^0-9.]//g')
            shift 2
            ;;
        -c|--crit)
            TIME_CRIT=$( echo $2 |sed -e 's/[^0-9.]//g')
            shift 2
            ;;
        -t|--timeout)
            # We accept floating point, but truncate to integer for curl
            TIMEOUT=$( echo $2 |sed -e 's/[^0-9.]//g; s/\..*//; s/^0$/1/')
            shift 2
            ;;
        -p|--port)
            PORT=$( echo $2 |sed -e 's/[^0-9]//g')
            shift 2
            ;;
        --) shift ; break ;;
        *) echo "Internal error!" ; exit 1 ;;
    esac
done

URL="https://${PUPPETMASTER}:${PORT}/puppet/v3/node/${HOST}?environment=production"
T1=`date +%s.%N`
CURL_NODE="`curl -sS --max-time $TIMEOUT --insecure -H 'Accept: pson'  --cert $SSLDIR/certs/${HOST}.pem  --key $SSLDIR/private_keys/${HOST}.pem  --cacert $SSLDIR/certs/ca.pem "${URL}" 2>&1`"
CURL_RESULT=$?
T2=`date +%s.%N`

PERF_TIME=$( perl -e "printf('%1.3f', $T2 - $T1);" )

if [ "$CURL_RESULT" != 0 ]; then
    EXIT=2
    MESSAGE="${URL} $CURL_NODE"
elif echo $CURL_NODE | grep -q '"environment":'; then
    FOUND=$( echo "$CURL_NODE" | sed -r -e 's/.*"environment":"([^"]+)".*/\1/' )
    EXIT=0
    MESSAGE="found '${FOUND}' in https://${PUPPETMASTER}:${PORT}/puppet/v3/node/${HOST}?environment=production"
else
    EXIT=1
    MESSAGE="environment not found in https://${PUPPETMASTER}:${PORT}/puppet/v3/node/${HOST}?environment=production"
fi

if ! perl -e "exit( $PERF_TIME >= $TIME_CRIT )" ; then
    MESSAGE="Response time $PERF_TIME>=$TIME_CRIT - $MESSAGE"
    EXIT=$(( $EXIT | 2 ))
elif ! perl -e "exit( $PERF_TIME >= $TIME_WARN )" ; then
    MESSAGE="Response time $PERF_TIME>=$TIME_WARN - $MESSAGE"
    EXIT=$(( $EXIT | 1 ))
else
    MESSAGE="Response time ${PERF_TIME}s - $MESSAGE"
fi

case "$EXIT" in
    0) MESSAGE="OK: $MESSAGE" ;;
    1) MESSAGE="Warning: $MESSAGE" ;;
    2|3) MESSAGE="Critical: $MESSAGE" ; EXIT=2;;
esac

echo "$MESSAGE|time=${PERF_TIME}s;$TIME_WARN;$TIME_CRIT;0"
exit $EXIT
