Перейти к основному содержимому

Членство в групповых ролях

Главное предназначение групповых ролей в упрощении администрирования прав, имеющихся у обычных ролей. Так, привилегии проще назначать конкретным ролям, которым эти права потребовались. Если этих ролей тысячи, управлять таким коллективом крайне затруднительно. Гораздо проще классифицировать все роли по видам выполняемых ими действий и сгруппировать в групповые роли.

Предоставление членства в группе​

Членством в групповых ролях управляют уже известные нам команды: GRANT и REVOKE. Для добавления роли в другую роль используется команда GRANT <группа> TO <роль>. Похожим образом роль лишается членства — REVOKE <группа> FROM <роль>.

примечание

Вплоть до 15-й версии PostgreSQL членство роли в группах отображала метакоманда \du.

Создадим от имени postgres новую роль abiturient с правом подключения к базе данных.

postgres@my_db=# CREATE USER abiturient NOINHERIT;
CREATE ROLE

Для удобства создания роли с разрешением на подключение было снова использовано ключевое слово USER. После указания имени роли идет ключевое слово NOINHERIT. Оно влияет на наследование привилегий, об этом будет рассказано далее.

Добавим новую роль в групповую grp_students.

postgres@my_db=# GRANT grp_students TO abiturient;
GRANT ROLE

Проверим, что роль вошла в группу. Чтобы сократить список выводимых ролей, используем шаблон на имя роли.

postgres@my_db=# \du *ent*
List of roles
Role name | Attributes | Member of
--------------+-------------------------+----------------
abiturient | No inheritance | {grp_students}
grp_students | Create DB, Cannot login | {}
student | | {grp_students}

Как видим, теперь в групповой роли grp_students состоят student и abiturient.

Привилегии групповых ролей​

Удобство групповых ролей в возможности наследования привилегий: достаточно назначить группе необходимые привилегии, и все члены данной роли могут эти привилегии наследовать. За наследование отвечает атрибут INHERIT/NOINHERIT. Первый позволяет наследовать (устанавливается по умолчанию новой роли), второй — запрещает (устанавливается вручную, как в случае с ролью abiturient). Роль с атрибутом NOINHERIT хоть и не наследует привилегии групповой роли, но может пользоваться ее правами с помощью команды SET ROLE.

примечание

С 16-й версии PostgreSQL возможность выполнения команды SET ROLE членом групповой роли контролируется более жестко.

В СУБД Pangolin же имеется собственная ролевая модель, скрипты для реализации которой имеются в составе дистрибутива. При наличии установленной документации СУБД Pangolin в ней можно получить подробности о ролевой модели.

Наследование привилегий​

Поскольку роль student имеет атрибут INHERIT по умолчанию и состоит в групповой роли grp_students, на ее примере покажем наследование привилегий.

Выдадим групповой роли grp_students разрешение на вставку данных в таблицу suptab от имени postgres.

postgres@my_db=# GRANT INSERT ON suptab TO grp_students;
GRANT

Теперь переключимся на роль student и проверим привилегии на таблицу.

postgres@my_db=# \c - student
You are now connected to database "my_db" as user "student".
student@my_db=> \dp suptab
Access privileges
Schema | Name | Type | Access privileges | Column privileges | Policies
--------+--------+---------+---------------------------+--------------------+----------
public | suptab | table | postgres=arwdDxt/postgres+| |
| | | student=r/postgres +| |
| | | grp_students=a/postgres | |
(1 row)

Как видим, появилась запись для роли grp_students. Но запись ACL с привилегиями роли student не изменилась. Попробуем вставить в таблицу suptab строку.

student@my_db=> INSERT INTO suptab VALUES (now());
INSERT 0 1

Вставка прошла успешно. Проверим содержимое таблицы.

student@my_db=> SELECT * FROM suptab;
s
------------
2024-10-26
(1 row)

Запись ACL для student не изменилась, поскольку в метаданные объекта записываются только привилегии, которые выдаются явно. Привилегия INSERT, которая позволила student выполнить вставку данных в suptab, не принадлежит student, а лишь наследуется им за счет членства в grp_students и атрибута INHERIT.

Без наследования привилегий​

Теперь попробуем выполнить ту же вставку данных от имени abiturient.

student@my_db=> \c - abiturient
You are now connected to database "my_db" as user "abiturient".
abiturient@my_db=> INSERT INTO suptab VALUES (now());
ERROR: permission denied for table suptab

Вставка данных завершилась ошибкой, так как напрямую роли abiturient разрешений на взаимодействие с таблицей suptab не выдавали, и наследовать их от групповой роли она не может из-за атрибута NOINHERIT, который был указан при ее создании.

Чтобы выполнить вставку данных, нужно переключиться на роль с привилегией INSERT внутри сессии с помощью команды SET ROLE.

abiturient@my_db=> SET ROLE grp_students;
SET

Повторим попытку на вставку данных.

abiturient@my_db=> INSERT INTO suptab VALUES (now());
INSERT 0 1

Вставка прошла успешно, так как текущим пользователем считается grp_students, а не abiturient. Проверить это можно, выведя значения session_user и current_user().

abiturient@my_db=> SELECT session_user, current_user;
session_user | current_user
-------------+--------------
abiturient | grp_students
(1 row)

Предопределенные роли​

PostgreSQL кроме обычных содержит также несколько предопределенных ролей, предоставляющих доступ к некоторым возможностям суперпользователя. Они необходимы для ограничения круга задач, требующих применения привилегии суперпользователя.

  • pg_read_all_data/pg_write_all_data — чтение/изменение любых данных;
  • pg_read_all_settings — чтение любых параметров настройки;
  • pg_read_all_stats — чтение любых представлений pg_stat_*;
  • pg_stat_scan_tables — возможность выполнения длительной блокировки функциями мониторинга;
  • pg_monitor — чтение представлений и выполнение функций мониторинга;
  • pg_database_owner — роль владельца базы данных;
  • pg_signal_backend — передача сигналов серверам экземпляра;
  • pg_read_server_files/pg_write_server_files — чтение/запись файлов на стороне сервера;
  • pg_execute_server_program — выполнение программного кода на стороне сервера;
  • pg_checkpoint — право выполнять контрольную точку.

Предоставлять доступ к этим ролям могут (помимо суперпользователя) административные роли с атрибутом CREATEROLE.

Роли pg_monitor, pg_read_all_settings, pg_read_all_stats и pg_stat_scan_tables предназначены для легкой настройки мониторинга сервера базы данных. Они предоставляют набор общих привилегий, позволяющие читать различные настройки конфигурации, статистику и другую системную информацию.

Предопределенная роль pg_database_owner относится к владельцу текущей базы данных и может владеть объектами в ней, а также этой роли можно предоставлять привилегии с помощью команды GRANT. Однако есть и ограничения: она не может входить ни в какую другую роль и не может включать в себя другие роли. Исходно эта роль владеет особой схемой PUBLIC, о которой будет рассказано далее.

примечание

В СУБД Pangolin в скриптах автоматизации существует ролевая модель для обеспечения контроля доступа к защищаемым элементам системы. Также при использовании утилиты initprotection включается механизм защиты данных от привилегированных пользователей со своими специфическими ролями.

Псевдороль public и схема public​

Могут быть ситуации, когда нужно настроить базовые права для какого-то объекта в базе данных для всех ее пользователей. На такой случай есть псевдороль public, которая является псевдонимом для всех ролей (неявным образом включает их в себя). Несмотря на то, что зарегистрированной роли public не существует, ей можно назначать и отзывать привилегии командами GRANT и REVOKE. Выданные привилегии роли public будут доступны всем пользователям, которые могут подключиться к базе данных. Поэтому такой способ управления правами считается небезопасным.

В каждой базе данных есть схема public для общего размещения объектов. Если при создании объекта, не была явно указана схема, новый объект помещается в общую схему — public. В ранних версиях PostgreSQL права на создание объектов (C) в схеме public были у псевдороли public, но сейчас осталось только право на использование объектов (U).

примечание

Вплоть до 14-й версии PostgreSQL схема public принадлежала псевдороли public, что давало возможность любому пользователю создавать объекты в этой схеме. Исходя из требований безопасности предлагалось удалять привилегию создания объектов:

REVOKE CREATE ON SCHEMA public FROM PUBLIC;

Начиная с 15-й версии PostgreSQL схема public принадлежит роли pg_database_owner. Но в унаследованных с более ранних версий PostgreSQL базах данных права на схему public до сих пор могут принадлежать псевдороли public, что нельзя признать безопасным.

Важно

Одной из особенностей ролевой модели в СУБД Pangolin является отключение роли public.

Переключимся на роль postgres и посмотрим на привилегии для схем с помощью метакоманды \dn+. За счет указанного символа +, будет также выведено описание для каждой схемы, у которой оно есть.

abiturient@my_db=> \c - postgres
You are now connected to database "my_db" as user "postgres".
postgres@my_db=# \dn+
List of schemas
Name | Owner | Access privileges | Description
-----------+-------------------+----------------------------------------+------------------------
def_sch | student | |
my_schema | student | student=UC/student +|
| | aspirant=U/student |
public | pg_database_owner | pg_database_owner=UC/pg_database_owner+| standard public schema
| | =U/pg_database_owner |
(3 rows)

В списке схем нас интересует схема public. Первая строчка в записи привилегий отдана под роль, владеющую базой данных и ее максимальные привилегии. А вот пустое место перед символом = указывает на псевдороль public, которая получила привилегию на использование объектов от предопределенной роли pg_database_owner.

В качестве примера выдадим роли public привилегию на создание объектов в схеме public.

postgres@my_db=# GRANT CREATE ON SCHEMA public TO public;
GRANT

Снова проверим привилегии на схемы.

postgres@my_db=# \dn+
List of schemas
Name | Owner | Access privileges | Description
-----------+-------------------+----------------------------------------+------------------------
def_sch | student | |
my_schema | student | student=UC/student +|
| | aspirant=U/student |
public | pg_database_owner | pg_database_owner=UC/pg_database_owner+| standard public schema
| | =UC/pg_database_owner |
(3 rows)

Список привилегий псевдороли public пополнился, и при этом источником привилегии указана предопределенная роль pg_database_owner. Поскольку выдача привилегии выполнялась от имени суперпользователя postgres, PostgreSQL в процессе выполнения запроса подставил вместо него роль, которая может выдавать такие права — pg_database_owner.

В целях безопасности лишим роль public данной привилегии.

postgres@my_db=# REVOKE CREATE ON SCHEMA public FROM PUBLIC;
REVOKE

Проверим привилегии.

postgres@my_db=# \dn+
List of schemas
Name | Owner | Access privileges | Description
-----------+-------------------+----------------------------------------+------------------------
def_sch | student | |
my_schema | student | student=UC/student +|
| | aspirant=U/student |
public | pg_database_owner | pg_database_owner=UC/pg_database_owner+| standard public schema
| | =U/pg_database_owner |
(3 rows)

Итоги​

  • Членство управляется командами GRANT <группа> TO <роль> и REVOKE <группа> FROM <роль>;
  • Атрибут INHERIT (по умолчанию) позволяет роли наследовать привилегии групповой роли;
  • Атрибут NOINHERIT запрещает наследование — роль может использовать права группы только через SET ROLE;
  • Команда SET ROLE устанавливает групповую роль в качестве current_user внутри текущей сессии;
  • Функции session_user и current_user возвращают роль, начавшую сессию, и текущую роль соответственно;
  • Команда RESET ROLE возвращает значение current_user к значению session_user;
  • Предопределенные роли (pg_read_all_data, pg_monitor и др.) предоставляют ограниченный доступ к функциям суперпользователя;
  • Псевдороль public — псевдоним всех ролей, ей можно назначать и отзывать привилегии командами GRANT и REVOKE;
  • Схема public принадлежит предопределенной роли pg_database_owner и содержит привилегию USAGE для псевдороли public.

Самопроверка​

Вопрос 1

Какая команда добавляет роль abiturient в групповую роль grp_students?

Вопрос 2

Роль abiturient создана с атрибутом NOINHERIT и входит в grp_students. Групповой роли выдана привилегия INSERT. Что произойдет при попытке вставки от имени abiturient?

abiturient@my_db=> INSERT INTO suptab VALUES (now());

Вопрос 3

Роль abiturient с атрибутом NOINHERIT хочет использовать привилегии группы grp_students. Что нужно сделать?

Вопрос 4

Какие из перечисленных являются предопределенными ролями PostgreSQL? Выберите все верные варианты.