Сегодня напишем скрипт для мониторинга срока действия SSL сертификатов наших сайтов.
Этот мониторинг пригодится многим:
- Системным администраторам в крупных компаниях, чтобы не пропустить момент перевыпуска сертификатов. Особенно, если количество сайтов — сотни.
- Владельцам собственных сайтов. Многие пользуются сервисом Let's Encrypt, особенностью сертификатов которого является короткий срок жизни. Если автоматика обновления сертификатов выйдет из строя, то мониторинг SSL сертификатов поможет выявить проблему до того, как она себя проявит.
Это уже вторая модификация скриптов мониторинга. Главная особенность — низкая нагрузка на заббикс.
Доступна третья версия для Zabbix 5.0: Zabbix — мониторинг SSL сертификатов
Ссылки
IIS - SSL сертификат Let's Encrypt
Подготовка
Для работы с SSL нам потребуется утилита openssl:
apt-get install openssl
Весь мониторинг основан на команде:
echo | openssl s_client -servername internet-lab.ru -connect internet-lab.ru:443 2>/dev/null | openssl x509 -noout -dates | grep "notAfter" | cut -d'=' -f2
Команда выводит дату завершения срока действия SSL сертификата.
Скрипты
Мониторинг у меня будет находиться на самом заббикс-сервере. Создаём следующую структуру каталогов:
В директории /usr/lib/zabbix/externalscripts создадим папку ssl_expire с содержимым:
- data — директория, пока пустая. Наполняться будет автоматически.
- domain_list.txt — файл содержит список сайтов, для которых нужно проверять срок действия SSL сертификата. В одной строке один домен, например:
domain1.ru domain2.com www.domain3.ru internet-lab.ru xn----7sbabo2beumogg8p.xn--p1ai
- ssl_check.sh — этот скрипт вызывается из заббикс-агента пользовательскими переменными. Без параметра он выводит JSON со списком доменов для автообнаружения. С доменом в качестве параметра возвращает количество дней до окончания срока действия SSL сертификата, домен должен быть в списке domain_list.txt.
- ssl_cron.sh — этот скрипт вызывается в cron раз в шесть часов и обновляет информацию о всех SSL для доменов из списка.
- ssl_miss.sh — этот скрипт вызывается из заббикс-агента пользовательскими переменными. С доменом в качестве параметра возвращает количество дней, прошедших с момента последнего обновления данных кроном. Помогает вызвать триггер с предупреждением, если crontab перестанет работать или по какой-то причине перестанет обрабатываться домен в скрипте.
Содержимое ssl_check.sh:
#!/bin/bash
# сколько дней осталось до истечения срока действия SSL сертификата
# получаем имя домена
DOMAIN=$1
#если домен не передан - выводим массив для автообнаружения
if [[ $DOMAIN = "" ]]; then
# список доменов
LISTPATH="/usr/lib/zabbix/externalscripts/ssl_expire/domain_list.txt"
#заполняем массив из файла и выводим в JSON
readarray DOMAINLIST < $LISTPATH
if ((${#DOMAINLIST[*]}>0)); then
echo "{"
echo " \"data\": ["
for ((a=0; a < ${#DOMAINLIST[*]}; a++))
do
x=${DOMAINLIST[$a]};
x=${x//[[:space:]]/};
echo " {"
echo " \"{#DOMAIN}\": \"${x}\""
if ((a+1 < ${#DOMAINLIST[*]})); then
echo " },"
else
echo " }"
fi
done
echo " ]"
echo "}"
fi
else
#если домен передан - работаем
#файл
DATAPATH="/usr/lib/zabbix/externalscripts/ssl_expire/data/"
FILEPATH="${DATAPATH}${DOMAIN}"
if [ -e $FILEPATH ]; then
CURRENTDATE=`LANG=en_EN TZ=GMT date +"%b %d %R:%S %Y %Z"`
NOTAFTER=`cat $FILEPATH | grep "NotAfter" | cut -d'=' -f2`
if [[ $NOTAFTER == "" ]]; then
echo "-1"
else
DIFFDAYS=`echo $(( ($(date -d "$NOTAFTER" +"%s")-$(date -d "$CURRENTDATE" +"%s"))/86400 ))`
echo "$DIFFDAYS"
fi
else
echo "-1"
fi
fi
Содержимое ssl_cron.sh:
#!/bin/bash
# Создаёт файлы доменов с текущей датой и датой истечения сертификата (для crontab)
# переменные
LISTPATH="/usr/lib/zabbix/externalscripts/ssl_expire/domain_list.txt"
DATAPATH="/usr/lib/zabbix/externalscripts/ssl_expire/data/"
CURRENTDATE=`LANG=en_EN TZ=GMT date +"%b %d %R:%S %Y %Z"`
#заполняем массив из файла
readarray DOMAINLIST < $LISTPATH
if ((${#DOMAINLIST[*]}>0)); then
for ((a=0; a < ${#DOMAINLIST[*]}; a++))
do
DOMAIN=${DOMAINLIST[$a]};
DOMAIN=${DOMAIN//[[:space:]]/};
#получаем данные о ssl сертификате...
NOTAFTER=`echo | openssl s_client -servername $DOMAIN -connect $DOMAIN:443 2>/dev/null | openssl x509 -noout -dates | grep "notAfter" | cut -d'=' -f2`
VALIDNOTAFTER=`date -d "$NOTAFTER" > /dev/null 2>&1; echo $?`
#если получили дату
if [[ $VALIDNOTAFTER == 0 ]]; then
FILEPATH="${DATAPATH}${DOMAIN}"
touch $FILEPATH
echo "CheckDate=$CURRENTDATE" > $FILEPATH
if [[ $NOTAFTER != "" ]]; then
echo "NotAfter=$NOTAFTER" >> $FILEPATH
fi
fi
done
fi
Содержимое ssl_miss.sh:
#!/bin/bash
# выводит сколько дней назад проверялся сертификат
# получаем имя домена
DOMAIN=$1
#если домен передан - работаем
if [ $DOMAIN != "" ]; then
#файл
DATAPATH="/usr/lib/zabbix/externalscripts/ssl_expire/data/"
FILEPATH="${DATAPATH}${DOMAIN}"
if [ -f $FILEPATH ]; then
CURRENTDATE=`LANG=en_EN TZ=GMT date +"%b %d %R:%S %Y %Z"`
CHECKDATE=`cat $FILEPATH | grep "CheckDate" | cut -d'=' -f2`
DIFFDAYS=`echo $(( ($(date -d "$CURRENTDATE" +"%s")-$(date -d "$CHECKDATE" +"%s"))/86400 ))`
echo "$DIFFDAYS"
else
echo "-1"
fi
else
#ошибка
echo "-1"
fi
Примечания к скриптам
В коде скриптов есть путь вида usr/lib/zabbix/externalscripts/, если у вас другие пути - нужно будет изменить.
CURRENTDATE=`LANG=en_EN TZ=GMT date +"%b %d %R:%S %Y %Z"`
Это получение текущей даты. На самом деле формат даты практического применения не имеет, просто привожу дату к такому же формату, как у сертификата.
- TZ=GMT — переводит дату в формат GMT
- LANG=en_EN — устанавливает язык
- "%b %d %R:%S %Y %Z" — формат даты вида: Jun 14 03:59:01 2019 GMT
Crontab
В крон добавляем расписание, срабатывает раз в шесть часов:
0 */6 * * * /usr/lib/zabbix/externalscripts/ssl_expire/ssl_cron.sh >/dev/null 2>&1
Перезапускаем крон:
service cron restart
По идее скрипт должен выполниться и папка data заполнится файлами с названиями доменов. Если не выполнится - запустите ssl_cron.sh сами, а потом разбирайтесь, что там с кроном.
Пример содержимого файлов на примере домена internet-lab.ru.
root@zabbix:/usr/lib/zabbix/externalscripts/ssl_expire/data# pwd
/usr/lib/zabbix/externalscripts/ssl_expire/data
root@zabbix:/usr/lib/zabbix/externalscripts/ssl_expire/data# ll | grep internet
-rw-r--r-- 1 root root 69 июн 14 06:59 internet-lab.ru
root@zabbix:/usr/lib/zabbix/externalscripts/ssl_expire/data# cat internet-lab.ru
CheckDate=Jun 14 03:59:01 2019 GMT
NotAfter=Jul 23 13:00:33 2019 GMT
Внутри файлов пишется две даты. Дата проверки в формате GMT.
CheckDate=Jun 14 03:59:01 2019 GMT
Дата истечения сертификата (если удалось определить) в формате GMT:
NotAfter=Jul 23 13:00:33 2019 GMT
Zabbix агент
Теперь нужно настроить заббикс-агент, чтобы он отдавал данные серверу. Убеждаемся, что в /etc/zabbix/zabbix_agentd.conf есть настройка:
Include=/etc/zabbix/zabbix_agentd.conf.d/
Переходим в папку /etc/zabbix/zabbix_agentd.conf.d/, создаём файл ssl_expire.conf с содержимым:
UserParameter=ssl_expire.check[*],/usr/lib/zabbix/externalscripts/ssl_expire/ssl_check.sh $1
UserParameter=ssl_expire.miss[*],/usr/lib/zabbix/externalscripts/ssl_expire/ssl_miss.sh $1
UserParameter=ssl_expire.list,/usr/lib/zabbix/externalscripts/ssl_expire/ssl_check.sh
- ssl_expire.list — список доменов в JSON для автообнаружения.
- ssl_expire.check[*] — дней до окончания срока действия сертификата (float, потому как может возвращать "-1").
- ssl_expire.miss[*] — сколько дней назад была проверка. В идеале должно быть 0, иначе нужно разбираться.
Перезапускаем агент:
service zabbix-agent restart
Zabbix шаблон
Ставим на сервер шаблон и привязываем к заббикс-серверу. Шаблон я уже набросал.
Скачать шаблон: zbx_ssl_expire.xml
В шаблоне одно приложение:
Одно правило автообнаружения, срабатывает раз в час для обновления списка доменов:
Два прототипа элементов данных:
Семь прототипов триггеров:
Примечание
Не стал делать модификацию скрипта. Понадобился мне как-то мониторинг срока действия сертификата на FTP. Методом научного тыка была разработана конструкция:
openssl s_client -servername example.com -connect example.com:21 -port 21 -tls1_2 -starttls ftp 2>/dev/null | openssl x509 -noout -dates | grep "notAfter" | cut -d'=' -f2