Пошук уроків, статей та іншого контенту
Налаштуєте автентифікацію, pg_hba.conf, шифрування з’єднань і базові практики захисту PostgreSQL.
Безпека PostgreSQL складається з кількох рівнів:
Автентифікація — перевірка, хто підключається до сервера.
Авторизація — визначення, що саме дозволено ролі.
Обмеження мережевого доступу — контроль адрес, баз даних і типів з’єднань.
Шифрування з’єднання — захист паролів і даних під час передавання мережею.
Захист конфігурації та секретів — правильні права на файли, паролі й резервні копії.
Автентифікація не замінює авторизацію. Навіть якщо користувач успішно ввійшов у PostgreSQL, це ще не означає, що він має доступ до всіх таблиць.
У PostgreSQL користувачі представлені ролями. Роль може мати право входу до сервера, бути власником об’єктів і отримувати окремі привілеї.
Для застосунку не варто використовувати суперкористувача. Створіть окрему роль із мінімально необхідними правами:
-- Створюємо роль, якій дозволено підключення за паролем
CREATE ROLE app_user
LOGIN
NOSUPERUSER
NOCREATEDB
NOCREATEROLE
NOINHERIT
PASSWORD 'замініть-цей-пароль';
-- Створюємо базу даних із власником app_user
CREATE DATABASE app_db OWNER app_user;
-- Підключіться до app_db перед виконанням наступних команд
-- У psql це можна зробити командою: \connect app_db
-- Забороняємо підключення до бази всім за замовчуванням
REVOKE CONNECT ON DATABASE app_db FROM PUBLIC;
-- Дозволяємо підключення лише ролі застосунку
GRANT CONNECT ON DATABASE app_db TO app_user;Пароль у прикладі потрібно замінити. У реальному проєкті не зберігайте його у файлах із кодом і не передавайте через відкриті канали.
Для читання й запису в конкретну схему можна видати лише потрібні права:
-- Дозволяємо використовувати схему
GRANT USAGE ON SCHEMA public TO app_user;
-- Дозволяємо працювати з наявними таблицями
GRANT SELECT, INSERT, UPDATE, DELETE
ON ALL TABLES IN SCHEMA public
TO app_user;
-- Дозволяємо використовувати послідовності для автоінкрементних ключів
GRANT USAGE, SELECT
ON ALL SEQUENCES IN SCHEMA public
TO app_user;Права на майбутні таблиці потрібно налаштувати окремо:
-- Застосовується до таблиць, які створить поточний власник схеми
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO app_user;
-- Застосовується до майбутніх послідовностей
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT USAGE, SELECT ON SEQUENCES TO app_user;Власник об’єкта має широкі права над цим об’єктом. Тому створення таблиць і виконання міграцій часто доручають окремій ролі, а роль застосунку залишають без права змінювати структуру бази.
Метод автентифікації визначається в конфігураційному файлі pg_hba.conf. Назва означає host-based authentication — автентифікацію на основі підключення, бази даних, користувача та адреси клієнта.
Розташування файлу можна перевірити SQL-запитом:
SHOW hba_file;Основні поля правила pg_hba.conf:
тип_з'єднання база_даних користувач адреса методДля локальних Unix-сокетів адреса не вказується:
local all all peerДля TCP-з’єднань адреса задається в CIDR-форматі:
host app_db app_user 192.168.1.0/24 scram-sha-256Правила перевіряються зверху вниз. PostgreSQL використовує перше правило, що підходить, і не переходить до наступного правила, якщо автентифікація за ним завершилася помилкою.
peerpeer працює для локальних Unix-сокетів. PostgreSQL перевіряє ім’я користувача операційної системи.
local all all peerНаприклад, користувач ОС postgres може підключитися як роль PostgreSQL postgres, якщо це дозволено відповідним правилом.
peer не використовує пароль і не працює для TCP-підключення.
scram-sha-256Сучасний рекомендований метод парольної автентифікації PostgreSQL. Він безпечніший за старий md5, але не замінює шифрування з’єднання.
Увімкніть зберігання нових паролів у форматі SCRAM:
-- Перевіряємо поточне налаштування
SHOW password_encryption;
-- У новіших версіях PostgreSQL значенням має бути scram-sha-256
SET password_encryption = 'scram-sha-256';
-- Встановлюємо пароль повторно, щоб він зберігався у форматі SCRAM
ALTER ROLE app_user PASSWORD 'новий-складний-пароль';Команда SET змінює параметр лише для поточного сеансу. Щоб задати його постійно, параметр можна встановити в конфігурації сервера:
password_encryption = 'scram-sha-256'Після зміни вже збережені паролі не перетворюються автоматично. Пароль ролі потрібно встановити повторно.
md5md5 — застарілий метод. Якщо в pg_hba.conf указано md5, а пароль ролі збережено у форматі SCRAM, сучасні версії PostgreSQL можуть виконати SCRAM-автентифікацію. Проте в новій конфігурації краще явно використовувати scram-sha-256.
trusttrust дозволяє підключення без перевірки пароля:
host all all 0.0.0.0/0 trustТаке правило фактично означає, що будь-хто з дозволеної мережі може ввійти як зазначений користувач. Не використовуйте trust для робочих баз даних.
pg_hba.confПриклад обмеженої конфігурації:
# Локальні адміністративні підключення через Unix-сокет
local all postgres peer
# Локальні підключення застосунку лише через TCP і SCRAM
hostssl app_db app_user 127.0.0.1/32 scram-sha-256
# Підключення застосунку з внутрішньої мережі
hostssl app_db app_user 192.168.1.0/24 scram-sha-256
# Усі інші TCP-підключення до цієї бази заборонені
host app_db all 0.0.0.0/0 rejectВажливі особливості:
local — підключення через Unix-сокет.
host — TCP-підключення, незалежно від використання TLS.
hostssl — лише TCP-підключення з TLS.
hostnossl — лише незашифровані TCP-підключення.
reject явно відхиляє підключення.
0.0.0.0/0 відповідає всім IPv4-адресам, тому його потрібно використовувати дуже обережно.
Правило reject має сенс лише після дозволених правил. Якщо поставити його на початок, воно заблокує всі наступні підключення до тієї самої бази.
Після зміни pg_hba.conf конфігурацію можна перечитати без повного перезапуску сервера:
SELECT pg_reload_conf();Перевірити синтаксис і проблеми з правилами допомагає подання pg_hba_file_rules:
SELECT
rule_number,
type,
database,
user_name,
address,
auth_method,
error
FROM pg_hba_file_rules
ORDER BY rule_number;Якщо поле error не порожнє, відповідне правило містить помилку.
Без TLS трафік між клієнтом і сервером може бути перехоплений у мережі. Це особливо небезпечно для:
паролів;
SQL-запитів;
результатів запитів;
персональних і фінансових даних.
PostgreSQL використовує TLS для шифрування TCP-з’єднань. Серверу потрібні сертифікат і приватний ключ.
Основні параметри сервера:
ssl = on
ssl_cert_file = 'server.crt'
ssl_key_file = 'server.key'Якщо шлях відносний, він розглядається відносно каталогу даних PostgreSQL. Шлях до каталогу даних можна перевірити так:
SHOW data_directory;Приватний ключ має бути доступний процесу PostgreSQL і захищений від читання іншими користувачами. Типові права для ключа:
chmod 600 server.keyВласником файла має бути користувач, від імені якого працює сервер PostgreSQL. Точні команди залежать від операційної системи та способу встановлення PostgreSQL.
Щоб перевірити, чи сервер підтримує TLS:
SHOW ssl;З’єднання з TLS потрібно вимагати в pg_hba.conf за допомогою hostssl:
hostssl app_db app_user 192.168.1.0/24 scram-sha-256Саме параметр ssl = on дозволяє TLS на сервері, а hostssl не дає конкретному правилу прийняти незашифроване TCP-з’єднання.
Після зміни параметрів сервера може знадобитися перезавантаження конфігурації:
SELECT pg_reload_conf();Якщо змінювали параметри, які читаються лише під час запуску сервера, потрібен повний перезапуск. Для перевірки конкретного клієнтського з’єднання в psql використовуйте:
\conninfoУ результаті має бути видно, що з’єднання використовує SSL/TLS.
Стан TLS можна перевірити і з SQL:
SELECT
pid,
usename,
datname,
client_addr,
ssl,
version,
cipher
FROM pg_stat_ssl
JOIN pg_stat_activity USING (pid)
WHERE pid = pg_backend_pid();Поле ssl має містити true, якщо поточне з’єднання зашифроване.
Шифрування захищає дані під час передавання, але клієнт також має переконатися, що підключається саме до правильного сервера. Для цього клієнт перевіряє сертифікат сервера та його ім’я.
У рядку підключення або параметрах клієнта зазвичай використовують режим перевірки сертифіката, наприклад:
sslmode=verify-fullТакий режим перевіряє:
що сертифікат підписаний довіреним центром сертифікації;
що ім’я сервера відповідає імені в сертифікаті.
Для перевірки потрібен кореневий сертифікат центру сертифікації, доступний клієнту. Режим require шифрує з’єднання, але не забезпечує повну перевірку імені сервера, тому для захисту від підміни сервера краще використовувати verify-full.
pg_hba.conf контролює правила PostgreSQL, але він не замінює мережевий екран.
Рекомендована схема:
не відкривати порт PostgreSQL для всього інтернету;
дозволити порт лише серверам застосунку або адміністративній мережі;
обмежити адреси в pg_hba.conf;
не використовувати 0.0.0.0/0, якщо немає чіткої потреби;
розділити адміністративний і прикладний доступ;
для зовнішнього адміністрування використовувати захищений канал, наприклад VPN або SSH-тунель.
За замовчуванням PostgreSQL часто слухає лише локальний інтерфейс. Якщо сервер має приймати з’єднання з мережі, параметр listen_addresses потрібно налаштувати свідомо:
listen_addresses = '192.168.1.10'Не встановлюйте listen_addresses = '*', якщо серверу не потрібно слухати всі мережеві інтерфейси.
Після зміни listen_addresses зазвичай потрібен перезапуск сервера, а не лише перечитування конфігурації.
Поточні значення важливих параметрів можна переглянути SQL-запитами:
SHOW listen_addresses;
SHOW port;
SHOW ssl;
SHOW password_encryption;
SHOW hba_file;
SHOW data_directory;Перевірте підключення саме з тієї машини, де працює застосунок. Наприклад, localhost і внутрішня IP-адреса можуть проходити за різними правилами pg_hba.conf.
Для тестування в psql:
psql "host=db.internal.example dbname=app_db user=app_user sslmode=verify-full"Не додавайте пароль до командного рядка: він може потрапити в історію оболонки або список процесів. Краще використати запит пароля psql, змінну середовища в контрольованому середовищі або спеціальний менеджер секретів.
Дотримуйтеся таких правил:
використовуйте окремі ролі для адміністрування, міграцій і роботи застосунку;
не запускайте застосунок під роллю postgres або іншим суперкористувачем;
використовуйте scram-sha-256 для парольної автентифікації;
вимагайте hostssl для мережевих підключень;
обмежуйте бази, ролі та IP-адреси в pg_hba.conf;
перевіряйте порядок правил, оскільки застосовується перше відповідне правило;
не використовуйте trust у робочому середовищі;
захищайте приватний ключ TLS правами файлової системи;
не зберігайте паролі в репозиторії;
регулярно відкликайте доступи, які більше не потрібні;
не відкривайте порт PostgreSQL без обмежень у мережевому екрані;
захищайте резервні копії, оскільки TLS не шифрує вже створені файли резервних копій.
pg_hba.conf стоїть не в тому місціhost all all 0.0.0.0/0 reject
hostssl app_db app_user 192.168.1.0/24 scram-sha-256Друге правило ніколи не спрацює, бо перше вже відхиляє всі підключення. Дозволені правила потрібно розміщувати перед загальними правилами блокування.
host замість hostsslhost app_db app_user 192.168.1.0/24 scram-sha-256Це правило дозволяє і зашифровані, і незашифровані TCP-з’єднання. Якщо TLS є обов’язковим, використовуйте hostssl.
hostssl all all 0.0.0.0/0 scram-sha-256Навіть із парольною автентифікацією це значно збільшує поверхню атаки. Краще вказати конкретну базу, роль і мережу.
SCRAM захищає процес перевірки пароля, але TLS потрібен для комплексного захисту всього сеансу. Без TLS запити та результати можуть передаватися мережею без шифрування.
Якщо ключ доступний іншим користувачам або недоступний процесу PostgreSQL, сервер може відмовитися запускати TLS. Перевіряйте власника та права файла.
pg_reload_conf() застосує всеПеречитування конфігурації підходить не для кожного параметра. listen_addresses та деякі інші параметри потребують повного перезапуску сервера.
Скомпрометований застосунок із правами суперкористувача може змінювати ролі, читати всі дані та змінювати конфігурацію. Роль застосунку повинна мати лише необхідні права.
pg_hba.conf визначає, хто, до якої бази, з якої адреси та яким методом може підключитися.
Правила pg_hba.conf обробляються зверху вниз, використовується перше відповідне правило.
Для парольної автентифікації використовуйте scram-sha-256.
Для мережевих підключень вимагайте TLS через hostssl.
Перевіряйте сертифікат клієнтом у режимі sslmode=verify-full.
Обмежуйте listen_addresses, IP-адреси та правила мережевого екрана.
Не використовуйте суперкористувача, trust і необмежені правила без чіткої потреби.
Захищайте не лише з’єднання, а й ролі, конфігураційні файли, приватні ключі та резервні копії.