root / plugins / ssl / ssl-certificate-expiry @ 793b75b9
Historique | Voir | Annoter | Télécharger (4,1 ko)
| 1 | 59f057f8 | Olivier Mehani | #!/bin/sh -u |
|---|---|---|---|
| 2 | a4c30808 | Olivier Mehani | # -*- sh -*- |
| 3 | 793b75b9 | Olivier Mehani | # shellcheck disable=SC2039 |
| 4 | a4c30808 | Olivier Mehani | |
| 5 | : << =cut |
||
| 6 | |||
| 7 | =head1 NAME |
||
| 8 | |||
| 9 | 59f057f8 | Olivier Mehani | ssl-certificate-expiry - Plugin to monitor Certificate expiration on multiple services and ports |
| 10 | a4c30808 | Olivier Mehani | |
| 11 | =head1 CONFIGURATION |
||
| 12 | |||
| 13 | 81e19668 | Olivier Mehani | [ssl-certificate-expiry] |
| 14 | 33239697 | Olivier Mehani | env.services www.service.tld blah.example.net_PORT |
| 15 | a4c30808 | Olivier Mehani | |
| 16 | To set warning and critical levels do like this: |
||
| 17 | |||
| 18 | 81e19668 | Olivier Mehani | [ssl-certificate-expiry] |
| 19 | a4c30808 | Olivier Mehani | env.services ... |
| 20 | env.warning 30: |
||
| 21 | |||
| 22 | 47ef2182 | Olivier Mehani | Alternatively, if you want to monitor hosts separately, you can create multiple symlinks named as follows. |
| 23 | |||
| 24 | 81e19668 | Olivier Mehani | ssl-certificate-expiry_HOST_PORT |
| 25 | 47ef2182 | Olivier Mehani | |
| 26 | For example: |
||
| 27 | |||
| 28 | 81e19668 | Olivier Mehani | ssl-certificate-expiry_www.example.net |
| 29 | ssl-certificate-expiry_www.example.org_443 |
||
| 30 | ssl-certificate-expiry_192.0.2.42_636 |
||
| 31 | ssl-certificate-expiry_2001:0DB8::badc:0fee_485 |
||
| 32 | 47ef2182 | Olivier Mehani | |
| 33 | 59f057f8 | Olivier Mehani | =head2 Cron setup |
| 34 | a4c30808 | Olivier Mehani | |
| 35 | 59f057f8 | Olivier Mehani | To avoid having to run the SSL checks during the munin-update, it is possible |
| 36 | to run it from cron, and save a cachefile to be read during the update, This is |
||
| 37 | particularly useful when checking a large number of certificates, or when some |
||
| 38 | of the hosts are slow. |
||
| 39 | a4c30808 | Olivier Mehani | |
| 40 | 59f057f8 | Olivier Mehani | To do so, add a cron job running the plugin with cron as the argument: |
| 41 | |||
| 42 | */5 * * * * <user> /usr/sbin/munin-run/ssl-certificate-expiry cron |
||
| 43 | |||
| 44 | <user> should be the user that has write permission to the MUNIN_PLUGSTATE. |
||
| 45 | |||
| 46 | =head1 AUTHORS |
||
| 47 | |||
| 48 | * Pactrick Domack (ssl_) |
||
| 49 | * Olivier Mehani (ssl-certificate-expiry) |
||
| 50 | |||
| 51 | * Copyright (C) 2013 Patrick Domack <patrickdk@patrickdk.com> |
||
| 52 | * Copyright (C) 2017, 2019 Olivier Mehani <shtrom+munin@ssji.net> |
||
| 53 | a4c30808 | Olivier Mehani | |
| 54 | =head1 LICENSE |
||
| 55 | |||
| 56 | =cut |
||
| 57 | |||
| 58 | e7eb2886 | Lars Kruse | # shellcheck disable=SC1090 |
| 59 | a4c30808 | Olivier Mehani | . "${MUNIN_LIBDIR}/plugins/plugin.sh"
|
| 60 | |||
| 61 | 59f057f8 | Olivier Mehani | if [ "${MUNIN_DEBUG:-0}" = 1 ]; then
|
| 62 | a4c30808 | Olivier Mehani | set -x |
| 63 | fi |
||
| 64 | |||
| 65 | 81e19668 | Olivier Mehani | HOSTPORT=${0##*ssl-certificate-expiry_}
|
| 66 | 59f057f8 | Olivier Mehani | CACHEFILE="${MUNIN_PLUGSTATE}/$(basename "${0}").cache"
|
| 67 | 47ef2182 | Olivier Mehani | |
| 68 | if [ "${HOSTPORT}" != "${0}" ] \
|
||
| 69 | && [ ! -z "${HOSTPORT}" ]; then
|
||
| 70 | services="${HOSTPORT}"
|
||
| 71 | fi |
||
| 72 | |||
| 73 | e7eb2886 | Lars Kruse | |
| 74 | # Read data including a certificate from stdin and output the (fractional) number of days left |
||
| 75 | # until the expiry of this certificate. The output is empty if parsing failed. |
||
| 76 | parse_valid_days_from_certificate() {
|
||
| 77 | 793b75b9 | Olivier Mehani | local input_data |
| 78 | local valid_until_string |
||
| 79 | local valid_until_epoch |
||
| 80 | local now_epoch |
||
| 81 | local input_data |
||
| 82 | e7eb2886 | Lars Kruse | input_data=$(cat) |
| 83 | if echo "$input_data" | grep -q -- "-----BEGIN CERTIFICATE-----"; then |
||
| 84 | valid_until_string=$(echo "$input_data" | openssl x509 -noout -enddate \ |
||
| 85 | | grep "^notAfter=" | cut -f 2 -d "=") |
||
| 86 | if [ -n "$valid_until_string" ]; then |
||
| 87 | valid_until_epoch=$(date --date="$valid_until_string" +%s) |
||
| 88 | if [ -n "$valid_until_epoch" ]; then |
||
| 89 | now_epoch=$(date +%s) |
||
| 90 | # calculate the number of days left |
||
| 91 | echo "$valid_until_epoch" "$now_epoch" | awk '{ print(($1 - $2) / (24 * 3600)); }'
|
||
| 92 | fi |
||
| 93 | fi |
||
| 94 | fi |
||
| 95 | } |
||
| 96 | |||
| 97 | |||
| 98 | print_expire_days() {
|
||
| 99 | 793b75b9 | Olivier Mehani | local host="$1" |
| 100 | local port="$2" |
||
| 101 | e7eb2886 | Lars Kruse | |
| 102 | # Wrap IPv6 addresses in square brackets |
||
| 103 | echo "$host" | grep -q ':' && host="[$host]" |
||
| 104 | |||
| 105 | echo "" | openssl s_client -CApath /etc/ssl/certs \ |
||
| 106 | -servername "$host" -connect "${host}:${port}" 2>/dev/null \
|
||
| 107 | | parse_valid_days_from_certificate |
||
| 108 | } |
||
| 109 | |||
| 110 | 59f057f8 | Olivier Mehani | main() {
|
| 111 | for service in $services; do |
||
| 112 | if echo "$service" | grep -q "_"; then |
||
| 113 | host=$(echo "$service" | cut -f 1 -d "_") |
||
| 114 | port=$(echo "$service" | cut -f 2 -d "_") |
||
| 115 | else |
||
| 116 | host=$service |
||
| 117 | port=443 |
||
| 118 | fi |
||
| 119 | fieldname="$(clean_fieldname "$service")" |
||
| 120 | valid_days=$(print_expire_days "$host" "$port") |
||
| 121 | [ -z "$valid_days" ] && valid_days="U" |
||
| 122 | printf "%s.value %s\\n" "$fieldname" "$valid_days" |
||
| 123 | done |
||
| 124 | } |
||
| 125 | e7eb2886 | Lars Kruse | |
| 126 | 59f057f8 | Olivier Mehani | case ${1:-} in
|
| 127 | a4c30808 | Olivier Mehani | config) |
| 128 | echo "graph_title SSL Certificates Expiration" |
||
| 129 | echo 'graph_args --base 1000' |
||
| 130 | echo 'graph_vlabel days left' |
||
| 131 | echo 'graph_category security' |
||
| 132 | 59f057f8 | Olivier Mehani | echo "graph_info This graph shows the numbers of days before certificate expiry" |
| 133 | a4c30808 | Olivier Mehani | for service in $services; do |
| 134 | fieldname=$(clean_fieldname "$service") |
||
| 135 | 47ef2182 | Olivier Mehani | echo "${fieldname}.label $(echo "${service}" | sed 's/_/:/')"
|
| 136 | 59f057f8 | Olivier Mehani | print_thresholds "${fieldname}" warning critical
|
| 137 | a4c30808 | Olivier Mehani | done |
| 138 | |||
| 139 | exit 0 |
||
| 140 | ;; |
||
| 141 | 59f057f8 | Olivier Mehani | cron) |
| 142 | TMP=$(mktemp "${CACHEFILE}.XXXXXXXX")
|
||
| 143 | trap 'rm -f "${TMP}"' EXIT
|
||
| 144 | main > "${TMP}"
|
||
| 145 | chmod 0644 "${TMP}"
|
||
| 146 | mv "${TMP}" "${CACHEFILE}"
|
||
| 147 | |||
| 148 | exit 0 |
||
| 149 | ;; |
||
| 150 | a4c30808 | Olivier Mehani | esac |
| 151 | |||
| 152 | 59f057f8 | Olivier Mehani | if [ -e "${CACHEFILE}" ]; then
|
| 153 | cat "${CACHEFILE}"
|
||
| 154 | rm "${CACHEFILE}"
|
||
| 155 | exit 0 |
||
| 156 | fi |
||
| 157 | a4c30808 | Olivier Mehani | |
| 158 | 59f057f8 | Olivier Mehani | main |
