Недавно на одном из проектов для телекоммуникационной компании нам пришлось дополнительно (не без помощи коллег из ИБ) проработать вопрос безопасного использования паролей для подключения к базе данных PostgreSQL кластера Zabbix.
Прописывать пароль для доступа к базе данных в явном виде в конфигурационном файле небезопасно. В таких случаях обычно ограничиваются возможностями разграничения прав к конфигурационным файлам Zabbix на уровне операционных систем.
Но вернемся к нашей задаче. Изучив входные данные об инфраструктуре заказчика, мы сразу обратили внимание, что коллеги в сегменте ИБ уже используют решение от HashiCorp — Vault, что и стало для нас отправной точкой:
во-первых, Zabbix отлично интегрируется с решениями от HashiCorp;
во-вторых, у нас есть опыт работы с HashiCorp Vault.
Основной целью было обезопасить конфигурацию HA Zabbix, убрав указываемые в явном виде логины и пароли для подключения к базе данных PostgreSQL. Сделать это нужно было так, чтобы наше решение было совместимо с уже применяемым стеком на стороне заказчика.
Итак, в этом посте пройдемся по нескольким шагам:
Рассмотрим нашу схему работы HA Zabbix и дадим краткую характеристику данному стеку.
Рассмотрим предполагаемый вариант использования Vault в связке с HA Zabbix.
Предложим конфигурацию для данного решения.
Схема работы HA Zabbix
В части сбора, хранения и анализа метрик от сервисов мы достаточно часто используем связку HA Zabbix и Patroni (рис. 1).
Почему выбрана именно такая технология? Patroni позволяет создавать высокодоступный кластер PostgreSQL на основе потоковой репликации. Учитывая наличие автоматического контролируемого и аварийного переключения между нодами (master-standby-replica) Patroni PostgreSQL, использование Zabbix в связке с PostgreSQL позволяет нам, по большей степени, не беспокоиться о доступности базы данных.
Не будем углубленно рассматривать схему реализации HA Zabbix, она немало изучена в других статьях, а лишь напомним, что Zabbix, начиная с версии 6.0, под «капотом» имеет механизм кластеризации. В нашей мониторинговой «теме» принципиально важно иметь высокодоступный «монитор» — в нашем случае это HA Zabbix 6.0
Включается режим HA в zabbix_server.conf в переменных HANodeName и NodeAddress и для zabbix_agentd.conf в переменных Server и ServerActive. Получится что-то наподобие такой схемы, как на рис. 2.
Здесь у нас есть два хоста в статусе Active и Standby. Учитывая наличие в нашей схеме HAProxy и keepalived (рис. 1), мы имеем VIP IP 10.125.140.90. Именно по этому IP мы и подключаемся к Active ноде нашего Zabbix. Пример конфигурации для балансировки HA Zabbix:
listen Zabbix
bind 10.125.140.90:8118
default_backend zabbix_server
option httpchk OPTIONS /zabbix
backend zabbix_server
balance roundrobin
server zbx01 10.125.140.80:80 check #port 80
server zbx02 10.125.140.81:80 check #port 80
где server zbx01 и server zbx02 — ноды Zabbix, bind 10.125.140.90 — VIP IP.
Балансировка кластера Patroni также настраивается в HAProxy.
Напомним, что для доступа к PostgreSQL в конфигурационном файле Zabbix — zabbix_server.conf — нужно заполнить две переменные: DBUser и DBPassword, соответственно, логин и пароль от базы данных Zabbix в PostgreSQL. Важно не забыть это сделать не только на Active ноде, но и на Standby (рис. 1).
Используем Vault в связке с HA Zabbix
К нашим входным данным мы добавим Vault и остановимся на составляющих (рис. 3).
Для работы Vault используется key-value хранилище Consul.
В нашем мониторинговом решении также присутствовала одна база данных по типу key-value — etcd (рис. 1). Patroni вполне хорошо работает и с Consul, но мы учитываем требование коллег из ИБ не смешивать две системы Consul/HA Vault и Zabbix/Patroni.
Глубокий анализ настроек Consul и Vault в этом посте мы разбирать не будем (как и с HA Zabbix/Patroni, этот вопрос неоднократно уже изучался на Хабр), выделим лишь составные хосты HashiCorp Consul и HA Vault.
У нас есть две ноды Vault в статусах Active и StandBy (рис. 4) и три ноды Consul, одна из которых в статусе Leader (рис. 5).
После этого краткого обзора кластера HashiCorp Consul и HA Vault предполагаемая схема приобретает вид, показанный на рис. 6.
Обратим внимание, что кластер HashiCorp Consul и HA Vault пока никак не связан с нашими сервисами (HAproxy – Zabbix/Patroni), поэтому перейдем к основной части нашей работы.
Настраиваем конфигурацию
Для включения Vault в Zabbix переменные DBUser и DBPassword в конфигурационном файле zabbix_server.conf необходимо выключить (что мы и сделаем):
#DBUser=*****
#DBPassword=*****
Переменные VaultToken, VaultURL, VaultDBPath — включить.
VaultURL — внимание! — это адрес нашей Active ноды Vault (см. выше), ну и VaultDBPath — путь к нашим секретам. Все эти данные нам предоставлены.
Но если с VaultToken и VaultDBPath всё понятно (на всякий случай можно почитать тут), то по VaultURL требуется уточнение.
Переменная VaultURL в zabbix_server.conf принимает только один сетевой адрес, но, как мы помним, у нас две ноды HA Vault (Active-StandBy). Если указать Active, всё хорошо до тех пор, пока она активна, а если потребуется ноду вывести из обслуживания, что тогда? Выход — наш балансировшик HAProxy.
Вспомним, что у нас решение по балансировке HA Zabbix уже есть, мы ходим на одну из нод Zabbix (Active) по VIP IP (10.125.140.90), так почему бы не воспользоваться схожей конфигурацией и не «забалансить» наш HA Vault?
Решаем!
Конфигурация на первом и на втором узле HAProxy идентична:
frontend vault
mode tcp
bind *:8200
bind *:443 ssl cert /etc/haproxy/cert
redirect scheme https code 301 if !{ ssl_fc }
log global
option tcplog
default_backend ha_vault
backend ha_vault
mode tcp
timeout check 5000
timeout server 30000
timeout connect 5000
option httpchk GET /v1/sys/health
http-check expect status 200
server node5 ***.***.***.***:8200check ssl check-ssl verify none
server node6 ***.***.***.***:8200check ssl check-ssl verify none
где в server node5 и server node6 указываем IP наших нод Vault.
Для наглядности заглянем в Web HAProxy (рис. 7).
Видим, что у нас сейчас активна node6 — нода Vault в статусе Active. Теперь осталось вернуться в конфигурацию Zabbix — zabbix_server.conf (у нас две ноды Zabbix, поэтому настройки должны быть идентичны):
VaultToken=s.*****************************
VaultURL=https://10.125.140.90:8200
VaultDBPath=secret/zabbix/database
где VaultURL — VIP IP.
Ну и напоследок, для принятия конфигурации:
systemctl restart zabbix-server.service
На этом настройка HA Vault / HAProxy для нашего кластера Zabbix закончена. Теперь и Zabbix, и Vault доступны по IP 10.125.140.90, и общая схема имеет следующий вид, показанный на рис. 8.
Цель нашей работы достигнута — в нашем конфигурационном файле zabbix_server.conf не содержится пароля к БД в явном виде, мы получили в конфигурации Zabbix единую точку доступа в HA Vault кластер.
Автор: Иван Подстольный, инженер-проектировщик отдела систем мониторинга "Инфосистемы Джет"
Abyss777
В чем принципиальное отличие пароля в явном виде в конфиге zabbix от токена в явном виде в этом же конфиге, с которым можно получить этот пароль?
Одним дополнительным curl можно превратить одно в другое...
JetHabr Автор
Бесспорно, так и есть, но тут скорее было требования по явному виду пароля в конфигурации
Ign0r
Объясните, пожалуйста, почему в качестве хранилища выбран Consul? Встроенный функционал Service Discovery и его интеграцию с HAProxy вы не используете, объем хранимых данных - ничтожен. Не проще ли ограничиться внутренним хранилищем Vault?
JetHabr Автор
Да, Consul уже используется активно в решении у заказчика, поэтому было принято решение задействовать его, об этом упомянули в статье. Спасибо за вопрос!
Ign0r
И ещё - Vault не балансируется. Все запросы перенаправляются на активный узел и выполняются там. А результат реплицируется. Так что - ваше решение немного надуманное.
Ign0r
Пардон. Вы используете HA. Я пропустил что у вас данные статичны.
JetHabr Автор
Добавлю, что нет стопроцентно безопасных решений. В данной заметке мы использовали решение из документации по настройке секретов в Zabbix (ссылка в тексте есть), или вот тут еще раз: https://www.zabbix.com/documentation/6.0/en/manual/config/secrets [Configuration parameters] На наш взгляд это вполне рабочее решение в данном конкретном случае.
Abyss777
Дак мы тоже его используем. Но оно не помогает скрывать пароль от БД zabbix. Оно для других вещей:
Один источник правды о паролях, сменили пароль на базу - занесли его в Vault (вручную или автоматически) все инстансы zabbix его будут знать, не нужно обходить и править конфиг. Я думаю когда придумывали HA zabbix, тогда и задались вопросом, как нескольким инстансам его безопасно сообщить.
Ну и самое главное, пароли из Vault можно использовать как значения макросов. Вот в этом случае это позволяет их скрыть от пользователей Zabbix. Инженер настраивающий хост должен знать только его путь в Vault.
Ну или когда одна автоматизация создала пользователя например в базе для мониторинга, а другая автоматизация настроила хост в zabbix. Пароль в открытом виде нигде не передаётся, и пользователи его не увидят.
Но если узнают токен, то это эквивалентно знанию всех паролей.
JetHabr Автор
Мы говорим о явном прописывании паролей в конфигурации. Написали об этом в начале.