Поширена практика «застосунок підключається як postgres» означає, що SQL-ін'єкція чи помилка в коді може видалити будь-яку таблицю, прочитати будь-які дані, змінити налаштування сервера. Принцип найменших привілеїв: кожна роль має лише ті права, які їй потрібні.
Типова схема ролей:
-- Власник схеми: від його імені ганяють міграції
CREATE ROLE app_owner LOGIN PASSWORD '...';
CREATE SCHEMA app AUTHORIZATION app_owner;
-- Застосунок: лише робота з даними
CREATE ROLE app_user LOGIN PASSWORD '...';
GRANT USAGE ON SCHEMA app TO app_user;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA app TO app_user;
GRANT USAGE ON ALL SEQUENCES IN SCHEMA app TO app_user;
-- Права на таблиці, які створять пізніше міграції
ALTER DEFAULT PRIVILEGES FOR ROLE app_owner IN SCHEMA app
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO app_user;
ALTER DEFAULT PRIVILEGES FOR ROLE app_owner IN SCHEMA app
GRANT USAGE ON SEQUENCES TO app_user;
-- Аналітика й розслідування: лише читання
CREATE ROLE readonly LOGIN PASSWORD '...';
GRANT pg_read_all_data TO readonly; -- PostgreSQL 14+
Що це дає:
- Застосунок не може
DROP TABLE,ALTER, створювати ролі чи читати системні налаштування. - Міграції виконуються окремою роллю - її пароль не живе в змінних середовища вебсерверів.
- Аналітики й розробники на проді працюють від ролі лише для читання.
Деталі, про які забувають:
- Права за замовчуванням (
ALTER DEFAULT PRIVILEGES) - без них нова таблиця з міграції буде недоступна застосунку. - Схема
public: з PostgreSQL 15 звичайні ролі за замовчуванням не можуть створювати в ній об'єкти - на старіших версіях це право варто забрати (REVOKE CREATE ON SCHEMA public FROM PUBLIC). - Послідовності потребують окремого
USAGE, інакше вставка з автоінкрементом впаде. - Підключення обмежують ще й на рівні
pg_hba.conf: з яких адрес, до яких баз, яким методом автентифікації (scram-sha-256).