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' без необходимости: запросы могут содержать персональные данные и пароли.
Порядок внедрения
- Снимите текущее состояние:
SELECT * FROM pg_hba_file_rules;, список ролей\du, права баз. - Сделайте резервную копию базы и конфигурации, проверьте восстановление.
- Создайте роли приложения и чтения, переведите приложения на них, суперпользователя оставьте только администраторам.
- Отзовите права PUBLIC и выдайте нужные явно.
- Обновите pg_hba.conf, проверьте через
pg_hba_file_rules, затемpg_reload_conf(). Держите открытой вторую сессию администратора на случай ошибки. - Включите SSL и переведите клиентов на
sslmode=verify-full. - Включите журналирование и подключите его к мониторингу.
Диагностика
| Симптом | Причина и что делать |
|---|---|
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 требует, чтобы доступ к данным был ограничен и подотчётен: правила входа, роли с минимальными правами, шифрование и журнал дают проверяемый минимум. Если в базе персональные данные, это же закрывает часть организационных и технических мер: самопроверка по ПДн.
Как проверить
- В
pg_hba_file_rulesнет строк сtrustи ошибок, последние строки —reject. - Приложения работают под отдельными ролями без суперправ, роль чтения не может изменять данные.
- Подключение к служебным базам обычными ролями даёт отказ.
- Подключение без SSL отклоняется, с SSL проходит.
- В журнале видны подключения, неудачные входы и DDL, события доходят до мониторинга.
Источники
- Методика оценки уровня зрелости кибербезопасности компании, Группа Сбер: sberbank.ru.
- Документация PostgreSQL: pg_hba.conf, SSL, права.






















