1
0
Fork 0
mirror of https://github.com/munin-monitoring/contrib.git synced 2025-07-21 18:41:03 +00:00
Munin-Contrib/plugins/ssl/ssl-certificate-expiry
Olivier Mehani 0b4725d69d [ssl/ssl-certificate-expiry] Fix unset starttls parameter
Signed-off-by: Olivier Mehani <shtrom@ssji.net>
2019-10-03 17:28:04 +02:00

174 lines
4.9 KiB
Bash
Executable file

#!/bin/sh -u
# -*- sh -*-
# shellcheck disable=SC2039
: << =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 foo.example.net_PORT_STARTTLS
PORT is the TCP port number
STARTTLS is passed to openssl as "-starttls" argument. Useful for services like SMTP or IMAP implementing StartTLS.
Current known values are ftp, imap, pop3 and smtp
PORT is mandatory if STARTTLS is used.
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
ssl-certificate-expiry_mail.example.net_25_smtp
=head2 Cron setup
To avoid having to run the SSL checks during the munin-update, it is possible
to run it from cron, and save a cachefile to be read during the update, This is
particularly useful when checking a large number of certificates, or when some
of the hosts are slow.
To do so, add a cron job running the plugin with cron as the argument:
<minute> * * * <user> /usr/sbin/munin-run/ssl-certificate-expiry cron
<user> should be the user that has write permission to the MUNIN_PLUGSTATE.
<minute> should be a number between 0 and 59 when the check should run every hour.
If, for any reason, the cron script stops running, the script will revert to
uncached updates after the cache file is older than an hour.
=head1 AUTHORS
* Pactrick Domack (ssl_)
* Olivier Mehani (ssl-certificate-expiry)
* Copyright (C) 2013 Patrick Domack <patrickdk@patrickdk.com>
* Copyright (C) 2017, 2019 Olivier Mehani <shtrom+munin@ssji.net>
=head1 LICENSE
=cut
# shellcheck disable=SC1090
. "${MUNIN_LIBDIR}/plugins/plugin.sh"
if [ "${MUNIN_DEBUG:-0}" = 1 ]; then
set -x
fi
HOSTPORT=${0##*ssl-certificate-expiry_}
CACHEFILE="${MUNIN_PLUGSTATE}/$(basename "${0}").cache"
if [ "${HOSTPORT}" != "${0}" ] \
&& [ -n "${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"
local starttls="$3"
# Wrap IPv6 addresses in square brackets
echo "$host" | grep -q ':' && host="[$host]"
local s_client_args=
[ -n "$starttls" ] && s_client_args="-starttls $starttls"
# shellcheck disable=SC2086
echo "" | openssl s_client -CApath /etc/ssl/certs \
-servername "$host" -connect "${host}:${port}" \
$s_client_args 2>/dev/null \
| parse_valid_days_from_certificate
}
main() {
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 "_")
starttls=$(echo "$service" | cut -f 3 -d "_")
else
host=$service
port=443
starttls=""
fi
fieldname="$(clean_fieldname "$service")"
valid_days=$(print_expire_days "$host" "$port" "$starttls")
[ -z "$valid_days" ] && valid_days="U"
printf "%s.value %s\\n" "$fieldname" "$valid_days"
echo "${fieldname}.extinfo Last checked: $(date)"
done
}
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 numbers of days before certificate expiry"
for service in $services; do
fieldname=$(clean_fieldname "$service")
echo "${fieldname}.label $(echo "${service}" | sed 's/_/:/')"
print_thresholds "${fieldname}" warning critical
done
exit 0
;;
cron)
UPDATE="$(main)"
echo "${UPDATE}" > "${CACHEFILE}"
chmod 0644 "${CACHEFILE}"
exit 0
;;
esac
if [ -n "$(find "${CACHEFILE}" -mmin -60 2>/dev/null)" ]; then
cat "${CACHEFILE}"
exit 0
fi
main