До сих пор ты работал под ролью postgres, суперпользователем, которому можно всё. В уроке про установку мы обещали, что приложению в бою такую роль не дают. Сегодня выполняем обещание: заводим роли с ограниченными правами, а во второй половине урока учимся делать резервную копию базы. Это две стороны одной заботы: чтобы данные никто не испортил и чтобы их можно было вернуть, если испортили. Этим уроком кластер заканчивается. Примеры работают на учебной базе магазина.
Ключи от офиса
В офисе у директора ключ от всех дверей. У бухгалтера ключ от бухгалтерии и архива, у курьера от входа и склада. Курьеру незачем открывать сейф, и если он потеряет свой ключ, сейф останется закрытым.
В базе так же. Если приложение работает под суперпользователем, любая ошибка в коде или удачная атака открывает всю базу: можно удалить таблицы, прочитать чужие данные, создать новые роли. Поэтому каждому клиенту дают ровно те права, которые нужны для его работы. Это называют принципом наименьших привилегий.
Роль
В PostgreSQL и пользователь, и группа называются одним словом, роль. Создадим роль для бэкенда магазина:
CREATE ROLE shop_app LOGIN PASSWORD 'change-me';
LOGINразрешает с этой ролью подключаться. Роль безLOGINподключиться не может, такие используют как группы.PASSWORDзадаёт пароль. В настоящем проекте его генерируют длинным и случайным, а в код кладут только через переменную окружения, как строку подключения.
SELECT rolname, rolsuper, rolcanlogin
FROM pg_roles
WHERE rolname IN ('postgres', 'shop_app')
ORDER BY rolname;
rolname | rolsuper | rolcanlogin
----------+----------+-------------
postgres | t | t
shop_app | f | t
(2 rows)
Новая роль не суперпользователь и пока не может ничего, кроме как подключиться. Роли общие для всего кластера: одна и та же shop_app видна из всех баз.
GRANT: выдаём права
Права выдаёт команда GRANT. Подумаем, что нужно бэкенду магазина: показывать каталог, значит читать authors и books, и оформлять заказы, значит читать и добавлять строки в orders и order_items.
GRANT SELECT ON authors, books TO shop_app;
GRANT SELECT, INSERT ON orders, order_items TO shop_app;
Права перечисляются через запятую. Основные права на таблицу:
| Право | Что разрешает |
|---|---|
SELECT | читать строки |
INSERT | добавлять строки |
UPDATE | менять строки |
DELETE | удалять строки |
TRUNCATE | очищать таблицу целиком |
Проверяем под чужой ролью
Подключаться заново под shop_app не обязательно. Суперпользователь может временно надеть чужую роль командой SET ROLE и посмотреть на базу её глазами:
SET ROLE shop_app;
SELECT current_user, count(*) AS books FROM books;
current_user | books
--------------+-------
shop_app | 9
(1 row)
Книги читаются. А теперь то, чего мы не разрешали:
SELECT * FROM customers;
ERROR: permission denied for table customers
DELETE FROM orders WHERE id = 5;
ERROR: permission denied for table orders
UPDATE books SET price = 1 WHERE id = 1;
ERROR: permission denied for table books
Покупателей не видно, удалить заказ нельзя, поменять цену тоже. А добавить заказ можно, это мы разрешили:
INSERT INTO orders VALUES (6, 1, '2026-10-09', 'new');
Даже создать свою таблицу роль не может:
CREATE TABLE notes (id integer);
ERROR: permission denied for schema public
С 15-й версии PostgreSQL создавать таблицы в схеме public может только владелец базы. В старых версиях это разрешалось всем, так что на старом сервере проверь права схемы сам.
Снимаем чужую роль и возвращаемся к себе:
RESET ROLE;
SELECT current_user;
current_user
--------------
postgres
(1 row)
урок из курса
Урок из курса «PostgreSQL с нуля». Курс покупается один раз и остаётся навсегда: 500 ₽.
Оплата пока не подключена: премиум и курсы открываются промокодом.