#!/bin/sh # -*- sh -*- : << =cut =head1 NAME ssl-certificate-expiry - Plugin to monitor CERTificate expiration on multiple services and ports =head1 CONFIGURATION [ssl-certificate-expiry] env.services www.service.tld blah.example.net_PORT To set warning and critical levels do like this: [ssl-certificate-expiry] env.services ... env.warning 30: Alternatively, if you want to monitor hosts separately, you can create multiple symlinks named as follows. ssl-certificate-expiry_HOST_PORT For example: ssl-certificate-expiry_www.example.net ssl-certificate-expiry_www.example.org_443 ssl-certificate-expiry_192.0.2.42_636 ssl-certificate-expiry_2001:0DB8::badc:0fee_485 =head1 AUTHOR Pactrick Domack (ssl_) Olivier Mehani (ssl-certificate-expiry) Copyright (C) 2013 Patrick Domack Copyright (C) 2017 Olivier Mehani =head1 LICENSE =cut # shellcheck disable=SC1090 . "${MUNIN_LIBDIR}/plugins/plugin.sh" if [ "${MUNIN_DEBUG}" = 1 ]; then set -x fi HOSTPORT=${0##*ssl-certificate-expiry_} if [ "${HOSTPORT}" != "${0}" ] \ && [ ! -z "${HOSTPORT}" ]; then services="${HOSTPORT}" fi # Read data including a certificate from stdin and output the (fractional) number of days left # until the expiry of this certificate. The output is empty if parsing failed. parse_valid_days_from_certificate() { local input_data local valid_until_string local valid_until_epoch local now_epoch local input_data input_data=$(cat) if echo "$input_data" | grep -q -- "-----BEGIN CERTIFICATE-----"; then valid_until_string=$(echo "$input_data" | openssl x509 -noout -enddate \ | grep "^notAfter=" | cut -f 2 -d "=") if [ -n "$valid_until_string" ]; then valid_until_epoch=$(date --date="$valid_until_string" +%s) if [ -n "$valid_until_epoch" ]; then now_epoch=$(date +%s) # calculate the number of days left echo "$valid_until_epoch" "$now_epoch" | awk '{ print(($1 - $2) / (24 * 3600)); }' fi fi fi } print_expire_days() { local host="$1" local port="$2" # Wrap IPv6 addresses in square brackets echo "$host" | grep -q ':' && host="[$host]" echo "" | openssl s_client -CApath /etc/ssl/certs \ -servername "$host" -connect "${host}:${port}" 2>/dev/null \ | parse_valid_days_from_certificate } case $1 in config) echo "graph_title SSL Certificates Expiration" echo 'graph_args --base 1000' echo 'graph_vlabel days left' echo 'graph_category security' echo "graph_info This graph shows the days left for the certificate" for service in $services; do fieldname=$(clean_fieldname "$service") echo "${fieldname}.label $(echo "${service}" | sed 's/_/:/')" print_thresholds "${fieldname}" done exit 0 ;; esac for service in $services; do if echo "$service" | grep -q "_"; then host=$(echo "$service" | cut -f 1 -d "_") port=$(echo "$service" | cut -f 2 -d "_") else host=$service port=443 fi fieldname="$(clean_fieldname "$service")" valid_days=$(print_expire_days "$host" "$port") [ -z "$valid_days" ] && valid_days="U" printf "%s.value %s\n" "$fieldname" "$valid_days" done