Казалось бы, что может быть сложного в мониторинге сертификатов? Выдан сертификат – следите за его сроком действия. Многие по старинке используют календари, напоминания, иногда даже физические заметки. Но ручные методы неидеальны, ведь люди ошибаются, забывают и теряют информацию.
И если не автоматизировать такие моменты, то однажды можете проснуться и узнать, что сервис недоступен из-за протухшего сертификата. Давайте разберёмся, что к чему.
Глубже в технику: Grafana, Prometheus и наши экспортеры
Сначала запустим Grafana и Prometheus - это наши главные инструменты для мониторинга. Затем поболтаем об экспортерах и подключим один из них, добавим крутую панельку с графиками. Чтобы всё это дело не пропустить, научим Alertmanager слать нам уведомления в Telegram.
1. Начнем с основ: Grafana + Prometheus и Docker Compose
Для тех, кто в теме и уже тысячу раз слышал о awesome-compose/prometheus-grafana, шаг можно пропустить. Для остальных - вам понадобится compose.yml
файл:
services:
prometheus:
image: prom/prometheus
container_name: prometheus
command:
- "--config.file=/etc/prometheus/prometheus_config.yml"
ports:
- 9090:9090
restart: unless-stopped
volumes:
- ./prometheus:/etc/prometheus
- prom_data:/prometheus
grafana:
image: grafana/grafana
container_name: grafana
ports:
- 3000:3000
restart: unless-stopped
env_file: .env
environment:
- GF_SECURITY_ADMIN_USER=${GF_SECURITY_ADMIN_USER}
- GF_SECURITY_ADMIN_PASSWORD=${GF_SECURITY_ADMIN_PASSWORD}
volumes:
- ./grafana:/etc/grafana/provisioning/datasources
volumes:
prom_data:
Теперь создайте директорию prometheus
с файлом prometheus_config.yml
:
global:
scrape_interval: 15s
scrape_timeout: 10s
evaluation_interval: 15s
И то же самое для директории grafana
и файла datasource.yml
:
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
url: http://prometheus:9090
isDefault: true
access: proxy
editable: true
В примере будем хранить секреты в файле:
.env
. Но лучше так не делать, потому что файл может легко попасть в открытый доступ. Используйте для хранения секретов специальные инструменты, шифруйте файлы и все будет хорошо.
Создайте файл .env
и добавьте ИМЯ_ПОЛЬЗОВАТЕЛЯ_GRAFANA
и ПАРОЛЬ_ПОЛЬЗОВАТЕЛЯ_GRAFANA
:
GF_SECURITY_ADMIN_USER=<ИМЯ_ПОЛЬЗОВАТЕЛЯ_GRAFANA>
GF_SECURITY_ADMIN_PASSWORD=<ПАРОЛЬ_ПОЛЬЗОВАТЕЛЯ_GRAFANA>
Поднимаем всю эту красоту:
docker-compose up -d
Так, магия Docker сработала, и у нас есть Grafana на порту 3000 и Prometheus на 9090. Просто? Просто!
2. Погружаемся в мир экспортеров: выбор инструмента
Каждый экспортер имеет свои плюсы и минусы. Ведь как говорится, каждая кисть хороша
на своем холсте. Разберемся, какой из них лучше всего подойдет для вас:
ssl_exporter: его задача — сертификаты и только. Дает богатую информацию о сертификатах: даты истечения, алгоритмы, подписи и многое другое. Поддерживает различные моды для проверки: TCP, HTTPS, SMTP и так далее. Но если нужно больше, чем просто мониторинг SSL/TLS, придется искать дополнительные инструменты.
blackbox_exporter: умеет делать многое, он все проверит, в том числе и сертификаты. Если сравнивать с ssl_exporter, детализация данных и возможности могут показаться слабее. Избыточен, если нужен только мониторинг сертификатов, но отлично подойдет для комплексного мониторинга.
node-cert-exporter: если вам нужно отслеживать сертификаты на диске, это ваш выбор. Очень прост в использовании и не требует больших знаний.
x509-certificate-exporter: дает подробную информацию о сертификатах. Гибкий, может извлекать данные файлов или секретов Kubernetes. Сложнее в настройке и эксплуатации по сравнению с некоторыми другими инструментами.
cert_exporter: поддерживает множество источников сертификатов, включая файловую систему, Kubernetes и другие. Весьма универсален для разных сценариев использования.
Итак, какой инструмент выбрать? Выбор инструмента – это искусство, и, как и в любом искусстве, здесь есть свои тонкости и нюансы. Выбирайте то, что соответствует вашим потребностям и не бойтесь экспериментировать.
3. Работа с ssl_exporter
Мы уже обсудили, что представляет собой ssl_exporter. Следит за сертификатами хорошо
и по-разному. Давайте добавим его в compose.yml
:
ssl_exporter:
image: ribbybibby/ssl-exporter
ports:
- "9219:9219"
Сегодня нашей целью будет prometheus.io
. Добавляем scrape_configs
в prometheus_config.yml
:
scrape_configs:
- job_name: "ssl-exporter"
metrics_path: /probe
static_configs:
- targets:
- prometheus.io:443
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: ssl_exporter:9219
Так, перезапускаем наш compose.yml
:
docker-compose restart
В Prometheus выполняем PromQL запрос – ssl_probe_success
и если мы видим следующее, то значит настроили все верно:
ssl_probe_success{instance="prometheus.io:443", job="ssl-exporter"}
По умолчанию экспортер создает TCP-соединение с целью. В большинстве случаев этого хватает, но если вы хотите использовать проксирование через http, используйте модуль https
. Кроме того, можно с помощью file
следить за сертификатами на диске:
scrape_configs:
- job_name: "ssl-files"
metrics_path: /probe
params:
module: ["file"]
target: ["/etc/ssl/cert.pem"]
kubernetes_sd_configs:
- role: node
relabel_configs:
- source_labels: [__address__]
regex: ^(.*):(.*)$
target_label: __address__
replacement: ${1}:9219
Если сертификатов несколько, можно использовать глоб-поиск, что позволяет захватить сразу несколько файлов:
scrape_configs:
- job_name: "ssl-files"
metrics_path: /probe
params:
module: ["file"]
target: ["/etc/ssl/**/*.pem"]
kubernetes_sd_configs:
- role: node
relabel_configs:
- source_labels: [__address__]
regex: ^(.*):(.*)$
target_label: __address__
replacement: ${1}:9219
Также можно использовать в связке с Kubernetes, в документации больше информации.
4. Добавляем панель в Grafana
Велосипед изобретать не будем, а просто авторизовываемся и импортируем готовую панель из репозитория ssl_exporter:
Как не проспать проблемы
Что у нас в планах? Поднимем невероятно простой, но очень полезный сервис на Flask'е, который будет ловить уведомления от Alertmanager и пересылать их в Telegram. Создадим бот и настроим Alertmanager на отправку уведомлений.
1. Взлетаем с Flask
Ладно, не будем мелочиться, заводим директорию telegram
и кидаем туда файлик app.py
с элегантным, минималистичным и в стиле true pythonista кодом:
import os
import requests
from flask import Flask, request, jsonify
app = Flask(__name__)
TELEGRAM_TOKEN = os.environ["TELEGRAM_TOKEN"]
CHAT_ID = os.environ["TELEGRAM_CHAT_ID"]
TELEGRAM_URL = f"https://api.telegram.org/bot{TELEGRAM_TOKEN}/sendMessage"
@app.route("/alert", methods=["POST"])
def webhook():
data = request.json
alertname = data["alerts"][0]["labels"]["alertname"]
instance = data["alerts"][0]["labels"]["instance"]
summary = data["alerts"][0]["annotations"]["summary"]
text = f"⚠️ Alarm! {alertname} for {instance}. \n{summary}"
payload = {"chat_id": CHAT_ID, "text": text}
response = requests.post(TELEGRAM_URL, data=payload)
return jsonify(status="success"), 200
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000)
А еще пригодится Dockerfile
:
FROM python:3.10-alpine
WORKDIR /app
COPY . /app
RUN pip3 install -r requirements.txt
ENTRYPOINT ["python3"]
CMD ["app.py"]
Ну и, разумеется, незаменимый requirements.txt
:
flask
requests
2. Крафтим бота:
Запустим
@BotFather
в Telegram./newbot
, даем ему имя и вуаля! У вас в руках:ТОКЕН_БОТА
.Выясним свой chat_id, отправив
/start
своему боту и заглянув наhttps://api.telegram.org/bot<ТОКЕН_БОТА>/getUpdates
. Найдитеresult[0]message.chat.id
и запомните, это будет вашВАШ_ЧАТ_ID
.
Теперь добавьте всё это в compose.yml
:
telegram:
build:
context: telegram
stop_signal: SIGINT
env_file: .env
environment:
- TELEGRAM_TOKEN=${TELEGRAM_TOKEN}
- TELEGRAM_CHAT_ID=${TELEGRAM_CHAT_ID}
ports:
- "8000:8000"
А секреты ТОКЕН_БОТА
и ВАШ_ЧАТ_ID
в .env
:
TELEGRAM_TOKEN=<ТОКЕН_БОТА>
TELEGRAM_CHAT_ID=<ВАШ_ЧАТ_ID>
3. Дружим Alertmanager с Telegram
Пришло время разобраться, куда именно будем слать уведомления. Теоретически Alertmanager может отправлять сообщения куда угодно, но мы-то знаем, что сегодня наш выбор – Telegram.
Начнем с малого. Напишем правило, которое даст нам знать, когда у сертификата останется менее 90 дней жизни. Для желающих углубиться - в документации собраны разные запросы. В prometheus
создаем файл alert.rules.yml
и пишем туда:
groups:
- name: ssl-alerts
rules:
- alert: Expiry Soon
expr: ssl_cert_not_after - time() < 86400 * 90
for: 1m
labels:
severity: critical
annotations:
summary: "SSL certificate is expiring soon (less than 90 days)"
Допишем пару строк в prometheus_config.yml
:
rule_files:
- "/etc/prometheus/alert.rules.yml"
alerting:
alertmanagers:
- static_configs:
- targets:
- "alertmanager:9093"
Теперь давайте сделаем следующее: создадим директорию под названием alertmanager
и положим в нее файл alertmanager_config.yml
:
route:
group_by: ["instance"]
repeat_interval: 3h
receiver: "telegram-webhook"
receivers:
- name: "telegram-webhook"
webhook_configs:
- url: "http://telegram:8000/alert"
Что ж, наш compose.yml
тоже хочет внимания, добавляем контейнер alertmanager
:
alertmanager:
image: quay.io/prometheus/alertmanager
container_name: alertmanager
command:
- "--config.file=/etc/alertmanager/alertmanager_config.yml"
ports:
- "9093:9093"
volumes:
- ./alertmanager:/etc/alertmanager
А теперь — магия:
docker-compose down; docker-compose up -d
Итак, смотрим, что наш Alertmanager чувствует себя комфортно:
и правило в Prometheus заняло свою рабочую позицию:
Примерно через минуту Prometheus поймет, что есть какие-то проблемы:
И еще примерно через 30 секунд Alertmanager отправит уведомление в наш сервис:
Который перешлет его к вам в Telegram:
Вот и всё! Теперь у вас в арсенале есть бот, который держит руку на пульсе ваших сервисов и, в случае чего, моментально бьет тревогу! Ну что, вы ведь тоже чувствуете этот аромат возможностей?
Заключение
Мониторинг сертификатов — это не мания, это забота. Наслаждайтесь комфортом, технологичностью, не забывайте поливать свои растения и мониторить сертификаты.
Комментарии (12)
321785
25.09.2023 19:50-2А зачем мониторить то, что должно автоматически обновляться, например тем же certbot?
А вот отказ/просрочка обновления сертификата мониторить интересно.aborouhin
25.09.2023 19:50+2Ну так с тем же certbot / acme.sh что-то пойти не так может как минимум на трёх этапах:
не отработал сам certbot / acme.sh (используемый по умолчанию последним zerossl, скажем, в один прекрасный момент прекратил выдачу сертификатов для доменов ru);
не отработало преобразование сертификатов в форматы, необходимые разным сервисам (кому-то Java keystore подавай, кому-то что-то ещё);
не отработало копирование сертификатов с сервера, на котором мы обновляем сертификаты, на серверы, где они используются (Ansible playbook или что там для этого используется).
У меня это всё автоматизировано через тот самый Ansible, скажем, но всегда полезно заранее узнать, если что-то не так.
BugM
25.09.2023 19:50Мониторить нужно все работа чего для вас важна. Непротухшие сертификаты точно важны. Мало ли что пошло не так. Всякое бывает в этом мире.
saboteur_kiev
25.09.2023 19:50+2Капец, что только не наворотят, лишь бы скрипты на баше не писать. (шутка).
У меня несколько источников. Папка с сертификатами, секреты в опенщифте, сертификаты в роутах, наконец урл-ы. Секреты могут лежать в p12 или jks формате, с разными паролями.
Не знаю, зачем для мониторинга поднимать пачку компосов и сервисов. Скрипт на баше, который пробегает по всему, генерирует удобный html отчет, параллельно может скинуть статистику в инфлюкс для графаны, и отправить алерт на емайл.
Для тех, у кого автоматом цертбот - есть конторы, где сертификаты выдает корпоративный авторити. К нему может существовать какой-нить API, а может наоборот существовать только бюрократизированный подход с ручным аппрувалом. Поэтому мониторинг не равен автозамене, и может быть важен.
AzamatKomaev
25.09.2023 19:50У меня все TLS сертификаты от Let's Encrypt и алерты о том, что скоро один из них истечет приходят на почту которую я указал при создании.
Есть также сертификаты, созданные в Yandex Cloud, туда же можно добавить свои собственные. И через систему мониторинга облака накинуть алерт. Единственный минус - алерт будет приходить либо как push уведомление, либо как смс.
aborouhin
25.09.2023 19:50Только если сертификат успешно выпущен, но не встал или криво встал на сервер (а этот процесс иногда довольно замысловат, если это не просто nginx на публично доступном адресе, а какая-нибудь java, которой keystore подавай, в докере) - такой мониторинг Вам об этом не расскажет.
heroOfOurTime
25.09.2023 19:50+5Непонятно, зачем нужен отдельный питон-сервис, если алертменеджер сам умеет в телегу и в тексте даже есть прямая ссылка на <telegram_config>
znhv Автор
25.09.2023 19:50-1Здравствуйте, да, можно сделать сразу через Alertmanager. Отдельный сервис будет полезен, если захочется обработать какой-то случай по-особенному.
Inoriol
25.09.2023 19:50+1Если уж Grafan'у использовать, то лучше её внутренний Alertmanager, как по мне. Интерфейс почеловечнее, да и можно к дашборду прицепить проще
aborouhin
25.09.2023 19:50Да, удобнее. И алерты прямо из панелей создавать удобно, PromQL запрос сразу переносится и ссылка на дашборд прикрепляется. У меня у самого именно так.
Но вот если масштабироваться и Prometheus'ов будет уже несколько, а Grafana на них одна - то использование её встроенного алертинга снижает надёжность такой системы.
mr_zibit
на мой взгляд в заголовке ошибка: "Grafana: искусство мониторинга сертификатов" -> "Prometheus: искусство мониторинга сертификатов", т.к. МОНИТОРИНГ будет работать и без Grafana
а еще я бы использовал https://github.com/prometheus/blackbox_exporter/blob/master/CONFIGURATION.md#tls_config в качестве основы (более того, уже был материал на эту тему - https://habr.com/ru/companies/hostkey/articles/729898/)
znhv Автор
Здравствуйте, согласен, с заголовком промахнулся, уже поправил. Спасибо.