Отслеживание срока действия сертификата с помощью Zabbix

Случился на моей практике интересный инцидент из серии «умная мысля приходит опосля»: хостер(да и сам владелец тоже) профукал срок действия SSL сертификата на сайте. Не сказать, что ситуация критичная, но всё равно неприятный осадок остался. Было решено написать скрипт мониторинга срока действия сертификатов и мониторить это дело zabbix-ом.
Система позволяет значительно расширять базовый функционал, используя для этого любые языки программирования.
Хочу заметить, что везде, где планируется мониторить больше 3 инстансов я использую полюбившееся мне решение low level discovery(LLD) — возможность автоматического создания элементов данных, триггеров и графиков для разных(любых) ресурсов операционной системы. Не буду вдаваться в подробности, почитать об этом можно по вышеприведённой ссылке.
Для работы этого мониторинга потребуется несколько скриптов:
— первый будет генерировать ответ для discovery в JSON-формате
— второй будет парсить дату окончания сертификата и считать сколько дней осталось
— третий файл(не исполняемый) будет содержать список хостов, для которых будут сниматься данные

Наглядно:

# ls -l /etc/zabbix/scripts/sslcheck/
-rw-r--r--. 1 zabbix zabbix   49 Aug 31 20:43 list.txt
-rwxr-xr-x. 1 zabbix zabbix  548 Aug 31 20:11 ssl_check.sh
-rwxr-xr-x. 1 zabbix zabbix  185 Aug 31 20:45 ssl_discovery.sh

Начнём с самого простого — список хостов.
Располагаются они по одному в строке, ничего сложного. Как только необходимо добавить сайт в систему отслеживания нужно всего то дописать его в конец файла. Через пару минут данные появятся.

# cat /etc/zabbix/scripts/sslcheck/list.txt
ukraine.com.ua
google.com.ua
vk.com
facebook.com

Дальше составляющая обнаружения. Данные должны быть в определённом формате для того, что бы zabbix сумел их принять
Листинг файла следующий:

# cat /etc/zabbix/scripts/sslcheck/ssl_discovery.sh
#!/bin/bash
JSON=$(for i in `cat /etc/zabbix/scripts/sslcheck/list.txt`; do printf "{\"{#SSL}\":\"$i\"},"; done | sed 's/^\(.*\).$/\1/')
printf "{\"data\":["
printf "$JSON"
printf "]}"

При выполнении получаем вот такой результат:

# /etc/zabbix/scripts/sslcheck/ssl_discovery.sh
{"data":[{"{#SSL}":"ukraine.com.ua"},{"{#SSL}":"google.com.ua"},{"{#SSL}":"vk.com"},{"{#SSL}":"facebook.com"}]}

Имя макроса {#SSL} можно заменить на своё, но тогда его нужно будет сменить и в шаблоне (файл прилагается в конце статьи)
В действительности как раз {#SERVER} или {#HOSTNAME} подойдут больше, но существенной разницы нет.

Далее главный скрипт, который получает информацию о сертификате сайта, парсит необходимое поле и высчитывает разницу

# cat /etc/zabbix/scripts/sslcheck/ssl_check.sh
#!/bin/sh
SERVER=$1
TIMEOUT=25
RETVAL=0
TIMESTAMP=`echo | date`
if [ -z "$2" ]
then
PORT=443;
else
PORT=$2;
fi
EXPIRE_DATE=`echo | openssl s_client -connect $SERVER:$PORT 2>/dev/null | openssl x509 -noout -dates 2>/dev/null | grep notAfter | cut -d'=' -f2`
EXPIRE_SECS=`date -d "${EXPIRE_DATE}" +%s`
EXPIRE_TIME=$(( ${EXPIRE_SECS} - `date +%s` ))
if test $EXPIRE_TIME -lt 0
then
RETVAL=0
else
RETVAL=$(( ${EXPIRE_TIME} / 24 / 3600 ))
fi

echo ${RETVAL}

Не думаю, что очень нужны пояснения, но всё же:
1) EXPIRE_DATE — дата окончания действия сертификата в формате Sep 16 11:56:55 2015 GMT
2) EXPIRE_SECS — перевод полученного результата в Unix-timestamp (количество секунд до этого момента, начиная с полуночи 1 января 1970 года)
3) EXPIRE_TIME — высчитываем разницу между текущим временем и временем действия SSL
4) RETVAL — перевод секунд в сутки для наглядности

Делаем файлы исполнительными и на всякий случай указываем пользователя zabbix в качестве владельца:

# chmod +x /etc/zabbix/scripts/sslcheck/ssl_check.sh
# chmod +x /etc/zabbix/scripts/sslcheck/ssl_discovery.sh
# chown zabbix:zabbix /etc/zabbix/scripts/sslcheck/ssl_check.sh
# chown zabbix:zabbix /etc/zabbix/scripts/sslcheck/ssl_discovery.sh

Сам вывод крайне прост:

# /etc/zabbix/scripts/sslcheck/ssl_check.sh vk.com
15
# /etc/zabbix/scripts/sslcheck/ssl_check.sh google.com
70

так же можно проверить как будет вести себя скрипты, если запускаться они будут от пользователя zabbix:

# sudo -u zabbix /etc/zabbix/scripts/sslcheck/ssl_check.sh google.com
# sudo -u zabbix /etc/zabbix/scripts/sslcheck/ssl_discovery.sh

Если всё ок — можно переходить к завершающей стадии: внедрению этого функционала в наш zabbix-сервер
Проверим, сконфигурирован ли агент на создание пользовательских параметров

# cat /etc/zabbix/zabbix_agentd.conf | grep Include | grep -v "#"
Include=/etc/zabbix/zabbix_agentd.d/*.conf

Отлично, теперь создадим файл, в котором укажем новые ключи:

# cat /etc/zabbix/zabbix_agentd.d/ssl.conf
UserParameter=ssl.discovery[*],/etc/zabbix/scripts/sslcheck/ssl_discovery.sh
UserParameter=ssl.expire[*],/etc/zabbix/scripts/sslcheck/ssl_check.sh $1

После всего нужно перезапустить агент что бы он перечитал новенькие ключи

# service zabbix-agent restart

Что бы не дожидаться данных, которые появятся в соответствии с указанным в шаблоне интервалом, можно проверить работоспособность новых ключей следующим образом:

# zabbix_agentd -t 'ssl.discovery'
ssl.discovery                                 [t|{"data":[{"{#SSL}":"ukraine.com.ua"},{"{#SSL}":"google.com.ua"},{"{#SSL}":"vk.com"},{"{#SSL}":"facebook.com"}]}]
# zabbix_agentd -t 'ssl.expire[telegram.org]'
ssl.expire[telegram.org]                      [t|1134]

Работает, отлично. Значит и данные скоро пойдут
А вот так они выглядят, если немного подождать. Ну и обновляться будут в зависимости от ваших таймеров.
Так как счет ведётся на сутки, то не вижу смысла обновлять данные чаще, чем раз в час.
Если, к примеру, сертификат истекает через 27 дней, то сколько бы раз в день мы не проверяли данные — это число так и будет 27.
Однако, каждому своё. Устанавливайте интервал обновления рассудительно

zabbix_SSL

А так выглядит отработанный триггер
zabbix_SSL_expire_trigger

Скачать XML-шаблон абсолютно бесплатно! 🙂

Файлы для фряхи можно забрать с гита. На здоровье

Отслеживание срока действия сертификата с помощью Zabbix: 16 комментариев

  1. Tazman

    Приветствую. Почитал про LLD, но так и не смог победить Value should be a JSON object в настройках обнаружения. Посоветуете решение?

  2. Tazman

    Добрый день.
    1. /etc/zabbix/scripts/sslcheck/ssl_check.sh vk.com
    578
    2. у второй команды какой-то очень большой вывод, что именно мы там ищем?
    3. zabbix_agentd -t ‘ssl.discovery’
    ‘ssl.discovery’ [m|ZBX_NOTSUPPORTED] [Invalid item key format.]

    1. Tazman

      в третьей команде по-моему некорректные символы ‘
      если так zabbix_agentd -t ‘ssl.discovery’, то вывод:
      «}{«{#SSL}»:»имя_хоста1″]}] [t|{«data»:[{«{#SSL}»:»имя_хоста2

      1. Воронов Глеб Автор записи

        У вас некорректно отрабатывает скрипт /etc/zabbix/scripts/sslcheck/ssl_discovery.sh
        какой вывод при его запуске?
        А так же укажите вашу операционку

        Вот мой вывод

        {"data":[{"{#SSL}":"www.domain.com"},{"{#SSL}":"www.domain2.com"},{"{#SSL}":"www.domain3.com"},{"{#SSL}":"www.domain4.com"}]}
        1. Tazman

          Debian jessie
          uname -a (Linux zabbix 3.16.0-4-amd64 #1 SMP Debian 3.16.39-1 (2016-12-30) x86_64 GNU/Linux)
          вывод скрипта:
          root@zabbix:~# cd /etc/zabbix/scripts/sslcheck/
          root@zabbix:/etc/zabbix/scripts/sslcheck# ./ssl_discovery.sh
          «]}root@zabbix:/etc/zabbix/scripts/sslcheck#
          Вот прям так, со смещением последний строки. синтаксическая ошибка?

          1. Воронов Глеб Автор записи

            Смотрите, код скрипта:

            #!/bin/bash
            JSON=$(for i in `cat /etc/zabbix/scripts/sslcheck/list.txt`; do printf "{\"{#SSL}\":\"$i\"},"; done | sed 's/^\(.*\).$/\1/')
            printf "{\"data\":["
            printf "$JSON"
            printf "]}"

            Ваш вывод

            «]}

            Смешение строки даёт printf. Это не проблема.
            У меня подозрение, что вы где то упустили кавычки.
            Обрабатывается только последняя строка из скрипта.
            Проверьте синтаксис внимательнее. Рекомендую использовать vim с подсветкой синтаксиса

              1. Tazman

                Появился прогресс. в строке `cat /etc/zabbix/scripts/sslcheck/list.txt` заменил «`» гравис на апостраф «‘».
                Теперь скрипт отдает так
                root@zabbix:/etc/zabbix/scripts/sslcheck# ./ssl_discovery.sh
                {«data»:[{«{#SSL}»:»cat /etc/zabbix/scripts/sslcheck/list.txt»}]}root@zabbix:/etc/zabbix/scripts/sslcheck#
                но не читает домены из list.txt

                  1. Tazman

                    не буду спорить с автором. но при использовании обратного апострофа результат хуже. быть может у вас есть возможность выложить скрипты скажем в архиве?

  3. Tazman

    Глеб, благодарю за познавательную и полезную статью, все завелось и полетело. Уверен, косяк был с моей стороны. tradenark.com.ua однозначно в закладки)

Добавить комментарий