PostgreSQL: безопасная настройка pg_hba.conf, ролей и SSL

0
10
Обложка статьи: PostgreSQL: безопасная настройка pg_hba.conf, ролей и SSL

Свежеустановленный PostgreSQL обычно «работает из коробки», а значит, и пускает лишнее: любая роль может подключиться к любой базе, а в схеме public часто разрешено создавать объекты. В официальном образе Docker к тому же включён вход без пароля с локального адреса, а шифрование выключено. Ниже порядок, который закрывает эти места: правила входа, роли, права, SSL и журнал. Каждый шаг проверен на тестовом контейнере postgres:16-alpine.

Статья опирается на логику направления «Безопасность данных» из методики зрелости Группы Сбер (источник); это методика для крупных компаний, мы используем её как ориентир и пересказываем своими словами.

Что должно получиться

Уровень Что это значит на практике
2. Гигиенический Доступ к базам данных ограничен по адресам и ролям, права выданы по необходимости, соединения шифруются, подключения журналируются

Критерии сформулированы нами по мотивам методики, это ориентир, а не оценка соответствия.

pg_hba.conf: правила входа

Файл pg_hba.conf читается сверху вниз, срабатывает первая подходящая строка. Поэтому порядок такой: узкие разрешения, затем явный отказ для всего остального. Пример для базы appdb, к которой ходят приложения из docker-сети 172.17.0.0/16:

# TYPE   DATABASE   USER        ADDRESS          METHOD
# локальные подключения: администратор по системному пользователю, остальные по паролю
local    all        postgres                     peer
local    all        all                          scram-sha-256
# приложение: только своя база, только с адреса приложений и только по TLS
hostssl  appdb      app_owner   172.17.0.0/16    scram-sha-256
hostssl  appdb      app_ro      172.17.0.0/16    scram-sha-256
# всё остальное отклоняется явно (и по IPv4, и по IPv6)
host     all        all         0.0.0.0/0        reject
host     all        all         ::/0             reject
  • local ... peer для postgres — администратор входит только с сервера под своей системной учётной записью.
  • scram-sha-256 вместо md5 и trust: пароль не передаётся в слабом виде и не обходится.
  • hostssl принимает только соединения с шифрованием; подключение без SSL получает отказ.
  • Последние две строки reject закрывают всё, что не разрешено выше, для IPv4 и IPv6.

Изменения применяются без перезапуска: SELECT pg_reload_conf();. Перед этим проверьте файл запросом к представлению pg_hba_file_rules: колонка error показывает ошибочные строки. В тесте опечатка scram-sha-257 дала запись invalid authentication method "scram-sha-257", при этом перезагрузка конфигурации вернула t и ошибочная строка была просто пропущена, поэтому смотреть нужно именно представление.

SELECT line_number, error FROM pg_hba_file_rules WHERE error IS NOT NULL;

Роли и права

Приложению не нужен суперпользователь. Нужны две роли: владелец схемы (для миграций) и роль только для чтения (отчёты, аналитики). Отдельно убираем права группы PUBLIC, которые действуют на всех:

-- Роли и права для базы appdb (выполнять от суперпользователя postgres)
-- владелец приложения: может менять структуру, но не суперпользователь
CREATE ROLE app_owner LOGIN PASSWORD 'ЗАДАЙТЕ_ДЛИННЫЙ_ПАРОЛЬ' NOSUPERUSER NOCREATEDB NOCREATEROLE;
-- пользователь только для чтения (отчёты, аналитика)
CREATE ROLE app_ro LOGIN PASSWORD 'ЗАДАЙТЕ_ДРУГОЙ_ПАРОЛЬ' NOSUPERUSER NOCREATEDB NOCREATEROLE;

ALTER DATABASE appdb OWNER TO app_owner;
-- по умолчанию подключаться к базе может любая роль (право PUBLIC): убираем и выдаём явно
REVOKE ALL ON DATABASE appdb FROM PUBLIC;
GRANT CONNECT ON DATABASE appdb TO app_ro;
-- чужие базы (в том числе служебную postgres) тоже закрываем
REVOKE CONNECT ON DATABASE postgres FROM PUBLIC;
REVOKE CONNECT ON DATABASE template1 FROM PUBLIC;

\c appdb
-- в схеме public нельзя создавать объекты всем подряд
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
GRANT USAGE ON SCHEMA public TO app_ro;
-- права на уже созданные и будущие таблицы владельца
GRANT SELECT ON ALL TABLES IN SCHEMA public TO app_ro;
ALTER DEFAULT PRIVILEGES FOR ROLE app_owner IN SCHEMA public GRANT SELECT ON TABLES TO app_ro;

Что показала проверка. До отзыва прав роль только для чтения подключалась к служебным базам postgres и template1; после REVOKE CONNECT ... FROM PUBLIC получаем FATAL: permission denied for database "postgres". С ролью app_ro в базе appdb SELECT работает, INSERT даёт permission denied for table orders, а CREATE TABLE — permission denied for schema public. Проверить права всех баз сразу можно так:

SELECT datname, has_database_privilege('app_ro', datname, 'CONNECT') FROM pg_database;

Шифрование соединений

В параметрах сервера задайте ssl = on, пути ssl_cert_file и ssl_key_file. Файл ключа должен принадлежать пользователю postgres с правами 600. Важно: если включить ssl = on без файла сертификата, сервер не запустится (could not load server certificate file), поэтому сначала положите сертификат, потом включайте параметр, и не на единственном рабочем экземпляре без окна работ. В тесте с сертификатом show ssl вернул on, строка hostssl отклонила подключение с sslmode=disable, а с sslmode=require соединение прошло по TLSv1.3. Для клиентов лучше sslmode=verify-full с корневым сертификатом: так проверяется и подлинность сервера.

Сервер не должен слушать лишнего: если база нужна только приложениям на этом хосте, задайте listen_addresses на нужный адрес, а порт 5432 закройте на файрволе для остальных (правила файрвола).

Журнал подключений и DDL

Чтобы видеть, кто и когда подключался, и ловить изменения структуры, включите в postgresql.conf:

log_connections = on
log_disconnections = on
log_statement = 'ddl'
log_min_duration_statement = 500

В тесте в журнале появились строки connection authorized, statement: create table, duration: 501 ms для медленного запроса, disconnection и FATAL: password authentication failed для неверного пароля. Отправляйте журнал в общую систему: правила обнаружения в Wazuh могут реагировать на серию неудачных входов. Не включайте log_statement = 'all' без необходимости: запросы могут содержать персональные данные и пароли.

Порядок внедрения

  1. Снимите текущее состояние: SELECT * FROM pg_hba_file_rules;, список ролей \du, права баз.
  2. Сделайте резервную копию базы и конфигурации, проверьте восстановление.
  3. Создайте роли приложения и чтения, переведите приложения на них, суперпользователя оставьте только администраторам.
  4. Отзовите права PUBLIC и выдайте нужные явно.
  5. Обновите pg_hba.conf, проверьте через pg_hba_file_rules, затем pg_reload_conf(). Держите открытой вторую сессию администратора на случай ошибки.
  6. Включите SSL и переведите клиентов на sslmode=verify-full.
  7. Включите журналирование и подключите его к мониторингу.

Диагностика

Симптом Причина и что делать
pg_hba.conf rejects connection ... no encryption Клиент подключается без SSL, а правило hostssl. Включите sslmode=require или выше
password authentication failed Неверный пароль или роль создана с другим методом хранения. Задайте пароль заново при password_encryption = scram-sha-256
pg_hba.conf rejects connection для нужного адреса Адрес приложения не входит в подсеть правила, либо выше стоит правило reject. Проверьте порядок строк
Сервер не стартует после ssl = on Нет или недоступен файл сертификата или ключа. Проверьте пути, владельца и права 600
Через docker exec не работает вход peer Команда выполняется от root. Используйте docker exec -u postgres
Не меняются параметры через ALTER SYSTEM Несколько команд в одном вызове -c не выполняются. Выполняйте по одной

Где это в модели зрелости

Материал относится к направлению «Безопасность данных» (материалы направления, карта зрелости). Уровень 2 требует, чтобы доступ к данным был ограничен и подотчётен: правила входа, роли с минимальными правами, шифрование и журнал дают проверяемый минимум. Если в базе персональные данные, это же закрывает часть организационных и технических мер: самопроверка по ПДн.

Как проверить

  1. В pg_hba_file_rules нет строк с trust и ошибок, последние строки — reject.
  2. Приложения работают под отдельными ролями без суперправ, роль чтения не может изменять данные.
  3. Подключение к служебным базам обычными ролями даёт отказ.
  4. Подключение без SSL отклоняется, с SSL проходит.
  5. В журнале видны подключения, неудачные входы и DDL, события доходят до мониторинга.

Источники

  • Методика оценки уровня зрелости кибербезопасности компании, Группа Сбер: sberbank.ru.
  • Документация PostgreSQL: pg_hba.conf, SSL, права.

Оставьте свой ответ