Раздел 33 · PostgreSQL с нуля

Роли, права и резервные копии

junior~25 мин

без входаВойди, чтобы отмечать прогресс, вести заметки и решать задачи в редакторе. войти

До сих пор ты работал под ролью 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 ₽.

Оплата пока не подключена: премиум и курсы открываются промокодом.