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

02 Занятие 02: Управление доступом / Членство в ролях

Исходная страница в нативном Markdown: Управление доступом / Членство в ролях
Примечание

Эта страница извлечена из официального PDF в нативный Markdown. Текст слайдов, код и комментарии сохранены в порядке чтения; исходные PDF и HTML остаются эталоном макета. HTML source: dbs_02_access_membership.html Archive: DBS-handouts-16.zip Страниц PDF: 24

Page 1: Управление доступом / Членство в ролях

Авторские права

© Postgres Professional, 2017–2026 Авторы: Егор Рогов, Павел Лузанов, Илья Баштанов, Алексей Береснев Фото: Олег Бартунов (монастырь Пху и пик Бхрикути, Непал)

Использование материалов курса

Некоммерческое использование материалов курса (презентации, демонстрации) разрешается без ограничений. Коммерческое использование возможно только с письменного разрешения компании Postgres Professional. Запрещается внесение изменений в материалы курса.

Обратная связь

Отзывы, замечания и предложения направляйте по адресу: edu@postgrespro.ru

Отказ от ответственности

Компания Postgres Professional не несет никакой ответственности за любые повреждения и убытки, включая потерю дохода, нанесенные прямым или непрямым, специальным или случайным использованием материалов курса. Компания Postgres Professional не предоставляет каких-либо гарантий на материалы курса. Материалы курса предоставляются на основе принципа «как есть» и компания Postgres Professional не обязана предоставлять сопровождение, поддержку, обновления, расширения и изменения.

Page 2: Темы

  • Включение роли в роль
  • Способы получения прав на объект
  • Наследование
  • Переключение на роль
  • Управление включением ролей

Page 3: Включение роли в роль

Source slide page 3: Включение роли в роль{#source-figure-003 caption=“Source slide page 3: Включение роли в роль”}

Включение в роль Исключение из роли

student=# GRANT dba TO alice;
student=# REVOKE dba FROM alice;
  • dba
  • alice
  • Псевдороль PUBLIC неявно включает остальные роли

Комментарии преподавателя

Роль можно включить в другую роль. В таком случае вторая роль выступает в качестве группы и говорят, что первая роль становится членом второй. Роль может быть включена в несколько ролей; включенная роль может, в свою очередь, включать в себя третьи роли и т. д., но циклы при этом не допускаются.

Роль может быть одновременно «пользовательской» (иметь атрибут LOGIN) и «групповой» (включать другие роли).

В кластере существует также псевдороль PUBLIC, которая неявно включает в себя все остальные роли.

https://postgrespro.ru/docs/postgresql/16/role-membership

Page 4: Получение прав на объект

Суперпользовательский доступ

  • суперпользователи не ограничены в действиях, за исключением удаления начального суперпользователя Владение
  • Обладание привилегией
  • Членство в группе
    • INHERIT
    • наследование прав групповой роли
    • SET
    • переключение на групповую роль
    • ADMIN
    • управление членством в групповой роли

Комментарии преподавателя

В целом у роли есть несколько вариантов получить право на действия с определенным объектом.

Суперпользователи (роли с атрибутом SUPERUSER) — особый случай, для них проверки прав доступа не выполняются. При этом нельзя удалить начальную суперпользовательскую роль или лишить ее атрибута SUPERUSER. Начальный суперпользователь (bootstrap superuser) создается при создании кластера баз данных.

Становясь владельцем объекта, роль получает право выполнять с ним практически любые действия.

Помимо этого, у роли может возникнуть право на действие с объектом, если она получит привилегию на объект (автоматически при создании объекта или явно).

И наконец, роль может получить дополнительные права при включении в другую роль. При включении можно указать любую комбинацию параметров членства:

● INHERIT включает наследование прав групповой роли на действия с объектами;

● SET позволяет переключаться на групповую роль;

● ADMIN дает право включать в группу другие роли, изменять атрибуты членства в группе и исключать роли из группы.

Параметры INHERIT и SET появились в PostgreSQL 16.

Page 5: Наследование

Source slide page 5: Наследование{#source-figure-005 caption=“Source slide page 5: Наследование”}

Атрибуты не наследуются

  • Права на объекты наследуются
    • если роль входит в группу с параметром членства INHERIT
    • grp1
    • grp2
    • grp3

Комментарии преподавателя

Если роль включена в другую роль, она может наследовать права на объекты, которыми обладает группа благодаря привилегиям или владению. Атрибуты ролей никогда не наследуются.

Роль может наследовать права на объекты от нескольких ролей, как при непосредственном включении в несколько групп, так и по цепочке включений. Наследуются не только права, которыми непосредственно обладает группа, но и права, которые она сама унаследовала.

Наследование срабатывает, когда роль включена в группу с параметром членства INHERIT. По умолчанию именно так и происходит, поскольку команда GRANT берет значение параметра INHERIT из одноименного атрибута включаемой роли, а при создании роли этот атрибут по умолчанию устанавливается. Однако параметр можно установить и явно, переопределив атрибут. Для этого надо указать в команде GRANT предложение WITH INHERIT.

Page 6: Наследование

Зарегистрируем роли Алисы и Боба.

student=# CREATE ROLE alice LOGIN;
CREATE ROLE
student=# CREATE ROLE bob LOGIN;
CREATE ROLE

Алиса будет владельцем базы данных:

student=# CREATE DATABASE access_membership OWNER alice;
CREATE DATABASE

Алиса подключается к БД и создает таблицу в схеме public.

student$ psql -d access_membership -U alice
alice=> CREATE TABLE t (id int);
CREATE TABLE

Включим Боба в роль Алисы:

student=# GRANT alice TO bob;
GRANT ROLE

Параметры членства ролей в группах можно увидеть в системном каталоге:

student=# SELECT roleid::regrole AS group,
  member::regrole,
  grantor::regrole,
  inherit_option
FROM pg_auth_members
WHERE member = 'bob'::regrole;
 group | member | grantor  | inherit_option
-------+--------+----------+----------------
 alice | bob    | postgres | t
(1 row)

Заметьте, что в сеансе student включение в роль выполнено от имени начального суперпользователя postgres. В этом случае не возникает зависимость от роли student, которая затруднит ее удаление. Последний столбец показывает параметр членства INHERIT. Он унаследован от атрибута INHERIT роли bob, который у нее включен по умолчанию. Поэтому Боб, подключившись, сможет прочитать таблицу.

student$ psql -d access_membership -U bob
bob=> SELECT * FROM t;
 id
----
(0 rows)

Убедиться, что привилегии Алисы унаследованы Бобом, можно и с помощью системной функции. Ее вызов с параметром USAGE показывает, наследует ли текущий пользователь привилегии роли alice:

bob=> SELECT pg_has_role(CURRENT_ROLE, 'alice', 'USAGE');
 pg_has_role
-------------
 t
(1 row)

Можно задать параметр членства явно:

student=# GRANT alice TO bob WITH INHERIT OPTION; -- или INHERIT TRUE
NOTICE:  role "bob" has already been granted membership in role "alice" by role "postgres"
GRANT ROLE

Что будет, если лишить роль Боба атрибута INHERIT?

Page 7: Page 7

Source slide page 7: Page 7{#source-figure-007 caption=“Source slide page 7: Page 7”}

student=# ALTER ROLE bob NOINHERIT;
ALTER ROLE
bob=> SELECT pg_has_role(CURRENT_ROLE, 'alice', 'USAGE');
 pg_has_role
-------------
 t
(1 row)

Наследование обеспечивается параметром членства INHERIT, поэтому Боб по-прежнему может читать содержимое таблицы:

bob=> SELECT * FROM t;
 id
----
(0 rows)

Параметр появился в PostgreSQL 16, в более ранних версиях отмена атрибута привела бы к потере наследования. Заметьте, что наследуются и права, которые дает владение, поэтому Боб может, например, изменить таблицу:

bob=> ALTER TABLE t SET (fillfactor=10);
ALTER TABLE

Page 8: Переключение на роль

Source slide page 8: Переключение на роль{#source-figure-008 caption=“Source slide page 8: Переключение на роль”}

Параметр членства SET

  • Переключение на роль Возврат к исходной роли
alice=> SET ROLE dba;
alice=> RESET ROLE;
session_user

Комментарии преподавателя

Параметр членства SET позволяет выполнить команду SET ROLE и (временно) переключиться на групповую роль со всеми ее атрибутами и привилегиями на объекты. Все действия будут выполняться от имени групповой роли и создаваемые объекты будут принадлежать групповой роли. Права исходной роли при этом недоступны. Параметр появился в PostgreSQL 16, до этого переключение на групповую роль разрешалось всегда.

Имя пользователя, подключившегося к серверу, возвращает функция session_user. А имя текущей роли можно узнать с помощью функции current_user (или current_role, что одно и то же).

https://postgrespro.ru/docs/postgresql/16/functions-info#FUNCTIONS-INFO-SESSION

Page 9: Переключение на роль

Source slide page 9: Переключение на роль{#source-figure-009 caption=“Source slide page 9: Переключение на роль”}

Удалим параметр INHERIT членства роли bob в группе alice:

student=# REVOKE INHERIT OPTION FOR alice FROM bob;
REVOKE ROLE

Членство ролей в группах и параметры членства удобно проверять с помощью метакоманды \drg:

student=# \drg bob
            List of role grants
 Role name | Member of | Options | Grantor
-----------+-----------+---------+----------
 bob       | alice     | SET     | postgres
(1 row)

Привилегии отозваны немедленно:

bob=> SELECT * FROM t;
ERROR:  permission denied for table t

Оставшийся параметр членства SET позволяет члену группы переключиться на групповую роль:

bob=> SET ROLE alice;
SET
bob=> SELECT * FROM t;
 id
----
(0 rows)

Теперь все действия в сеансе Боба происходят от имени Алисы. Узнать имена текущей роли и роли, начавшей сеанс, можно с помощью функций:

bob=> SELECT current_user, session_user;
 current_user | session_user
--------------+--------------
 alice        | bob
(1 row)

Боб может, например, от имени Алисы выдать себе все привилегии на таблицу:

bob=> GRANT ALL ON t TO bob;
GRANT
bob=> \dp t
                             Access privileges
 Schema | Name | Type  |  Access privileges  | Column privileges | Policies
--------+------+-------+---------------------+-------------------+----------
 public | t    | table | alice=arwdDxt/alice+|                   |
        |      |       | bob=arwdDxt/alice   |                   |
(1 row)

При переключении роль также получает атрибуты групповой роли. Добавим роли alice атрибут, разрешающий создавать базы данных:

student=# ALTER ROLE alice CREATEDB;
ALTER ROLE

Обладает ли теперь Боб, переключивший свой сеанс на роль Алисы, правом создавать базы данных?

bob=> SELECT has_database_privilege(current_catalog, 'CREATE');
 has_database_privilege
------------------------
 t
(1 row)

Page 10: Page 10

Да, право есть. Вернемся к исходной роли сеанса:

bob=> RESET ROLE;
RESET
bob=> SELECT current_user, session_user;
 current_user | session_user
--------------+--------------
 bob          | bob
(1 row)

Суперпользователь может использовать другую команду для переключения на любую роль:

student=# SET SESSION AUTHORIZATION bob;
SET

Такой подход позволяет, например, тестировать работу под разными пользователями без необходимости подключаться к серверу под каждым из них (подробнее об этом пойдет речь в модуле «Методы аутентификации»). Обратите внимание, что имя пользователя, начавшего сеанс, скрыто:

student=# SELECT current_user, session_user;
 current_user | session_user
--------------+--------------
 bob          | bob
(1 row)

Вернем сеанс суперпользователя к исходной роли:

student=# RESET SESSION AUTHORIZATION;
RESET
student=# SELECT current_user, session_user;
 current_user | session_user
--------------+--------------
 student      | student
(1 row)

Page 11: Управление членством

Source slide page 11: Управление членством{#source-figure-011 caption=“Source slide page 11: Управление членством”}

Параметр членства ADMIN

  • включение в группу
  • исключение из группы
  • изменение параметров членства
alice=> GRANT dba TO bob;
alice=> REVOKE dba FROM bob;
  • alice

Комментарии преподавателя

Управлять включением ролей в группу (а также исключением ролей из группы и изменением параметров членства ролей в группе) могут те члены группы, которые имеют в ней параметр членства ADMIN.

Роль не может иметь параметр членства ADMIN сама в себе, поэтому не может управлять включением в себя других ролей.

Суперпользователи могут управлять включением любых ролей в любые.

Page 12: Управление включением

Source slide page 12: Управление включением{#source-figure-012 caption=“Source slide page 12: Управление включением”}

Зарегистрируем еще роль для Чарли:

student=# CREATE ROLE charlie;
CREATE ROLE

Если роль входит в группу с параметром ADMIN, она может добавлять в группу другие роли:

student=# GRANT alice TO bob WITH ADMIN OPTION; -- или ADMIN TRUE
GRANT ROLE
student=# \drg bob
              List of role grants
 Role name | Member of |  Options   | Grantor
-----------+-----------+------------+----------
 bob       | alice     | ADMIN, SET | postgres
(1 row)

Обладая параметром членства ADMIN в группе Алисы, Боб теперь может включить Чарли в эту группу:

bob=> GRANT alice TO charlie;
GRANT ROLE
bob=> \drg charlie
              List of role grants
 Role name | Member of |   Options    | Grantor
-----------+-----------+--------------+---------
 charlie   | alice     | INHERIT, SET | bob
(1 row)

По умолчанию параметр SET устанавливается, а параметр INHERIT, как мы уже видели, наследуется от атрибута INHERIT включаемой роли. Параметр членства ADMIN в группе Алисы дает Бобу право изменять параметры членства других ролей в этой группе:

bob=> REVOKE INHERIT OPTION FOR alice FROM charlie;
REVOKE ROLE
bob=> \drg charlie
            List of role grants
 Role name | Member of | Options | Grantor
-----------+-----------+---------+---------
 charlie   | alice     | SET     | bob
(1 row)

Включать в свою группу другие роли Боб не может:

bob=> GRANT bob TO charlie;
ERROR:  permission denied to grant role "bob"
DETAIL:  Only roles with the ADMIN option on role "bob" may grant this role.

Page 13: Каскадное исключение

Source slide page 13: Каскадное исключение{#source-figure-013 caption=“Source slide page 13: Каскадное исключение”}

Лишение членства в роли с параметром ADMIN

student=# REVOKE alice FROM bob CASCADE;
  • bob

Комментарии преподавателя

Когда пользователь лишается членства в роли, которым он обладал с параметром ADMIN, членства должны лишиться и другие роли, которым оно было предоставлено этим пользователем. В этом случае в команде REVOKE необходимо указать ключевое слово CASCADE, иначе будет зафиксирована ошибка.

Такое лишение членства действует рекурсивно, точно так же, как при отзыве права передачи привилегии GRANT OPTION, которое рассматривалось в предыдущей теме.

https://postgrespro.ru/docs/postgresql/16/sql-revoke

Page 14: Каскадное исключение

Боб был включен в группу Алисы с правом управления и воспользовался им:

student=# \drg bob|charlie
              List of role grants
 Role name | Member of |  Options   | Grantor
-----------+-----------+------------+----------
 bob       | alice     | ADMIN, SET | postgres
 charlie   | alice     | SET        | bob
(2 rows)

Поэтому нельзя просто так исключить его из группы:

student=# REVOKE alice FROM bob;
ERROR:  dependent privileges exist
HINT:  Use CASCADE to revoke them too.

Но можно, используя ключевое слово CASCADE, удалить Боба из группы вместе со всеми, кого тот успел включить в группу Алисы:

student=# REVOKE alice FROM bob CASCADE;
REVOKE ROLE
student=# \drg bob|charlie
            List of role grants
 Role name | Member of | Options | Grantor
-----------+-----------+---------+---------
(0 rows)

Можно было бы отозвать у Боба право управления, не исключая его из группы Алисы, но при этом все равно пришлось бы указать CASCADE. Роль можно удалить, если она не владеет объектами. Просто так удалить Алису и Боба не получится:

student=# DROP ROLE alice;
ERROR:  role "alice" cannot be dropped because some objects depend on it
DETAIL:  owner of database access_membership
1 object in database access_membership
student=# DROP ROLE bob;
ERROR:  role "bob" cannot be dropped because some objects depend on it
DETAIL:  1 object in database access_membership

Можно удалить объекты, принадлежащие роли, если они не нужны:

student=# \c access_membership
You are now connected to database "access_membership" as user "student".
student=# DROP OWNED BY bob;
DROP OWNED

Если же удалить объекты нельзя, можно передать их другому владельцу:

student=# REASSIGN OWNED BY alice TO student;
REASSIGN OWNED

В общем случае (без прав суперпользователя) для смены владельца командой REASSIGN OWNED BY или ALTER … OWNER TO нужен параметр членства SET в роли нового владельца.

student=# DROP ROLE alice, bob, charlie;
DROP ROLE

Page 15: Итоги

Роли можно включать друг в друга

  • Права на объекты приобретаются за счет привилегий, владения и членства в группах
  • Параметры членства определяют порядок передачи прав при включении

Page 16: Практика

  1. Создайте роль для Алисы, включив ее в суперпользователь-скую роль с параметром SET. Все дальнейшие действия выполняются в сеансе Алисы.
    1. Создайте пользователя Боб — члена группы readers — и пользователя Чарли — члена группы writers. Оба включения выполнены с параметром INHERIT (без SET).
    1. Создайте таблицу в отдельной схеме, выдайте роли readers привилегию на ее чтение, а роли writers — на изменение.
    1. Проверьте, могут ли Алиса, Боб и Чарли читать и менять строки таблицы.

Page 17: 1. Роль Алисы

student=# CREATE USER alice NOINHERIT IN ROLE student;
CREATE ROLE

Эта команда эквивалентна двум следующим:

CREATE ROLE alice LOGIN NOINHERIT;
GRANT student TO alice;
student=# \c - alice
You are now connected to database "student" as user "alice".
alice=> SET ROLE student;
SET

2. Пользователи и группы

Создадим группы readers и writers.

alice=> CREATE ROLE readers;
CREATE ROLE
alice=> CREATE ROLE writers;
CREATE ROLE

Боб — читатель.

alice=> CREATE USER bob;
CREATE ROLE
alice=> GRANT readers TO bob WITH SET FALSE;
GRANT ROLE

Чарли — писатель.

alice=> CREATE USER charlie;
CREATE ROLE
alice=> GRANT writers TO charlie WITH SET FALSE;
GRANT ROLE

Вот что получилось:

alice=> \drg
            List of role grants
 Role name | Member of | Options | Grantor
-----------+-----------+---------+----------
 alice     | student   | SET     | postgres
 bob       | readers   | INHERIT | postgres
 charlie   | writers   | INHERIT | postgres
(3 rows)

3. База данных, схема и таблица

alice=> CREATE DATABASE access_membership OWNER alice;
CREATE DATABASE
alice=> \c access_membership
You are now connected to database "access_membership" as user "alice".
alice=> CREATE SCHEMA app;
CREATE SCHEMA
alice=> CREATE TABLE app.tab(who text DEFAULT current_user);

Page 18: Page 18

CREATE TABLE

Привилегии:

alice=> GRANT USAGE ON SCHEMA app TO readers, writers;
GRANT
alice=> GRANT SELECT ON TABLE app.tab TO readers;
GRANT
alice=> GRANT INSERT, UPDATE, DELETE ON TABLE app.tab TO writers;
GRANT

4. Права на таблицу

alice=> \dp app.tab
                             Access privileges
 Schema | Name | Type  |  Access privileges  | Column privileges | Policies
--------+------+-------+---------------------+-------------------+----------
 app    | tab  | table | alice=arwdDxt/alice+|                   |
        |      |       | readers=r/alice    +|                   |
        |      |       | writers=awd/alice   |                   |
(1 row)

Алиса может читать и менять строки, поскольку является владельцем:

alice=> INSERT INTO app.tab DEFAULT VALUES;
INSERT 0 1
alice=> SELECT * FROM app.tab;
  who
-------
 alice
(1 row)
alice=> \c - bob
You are now connected to database "access_membership" as user "bob".

Боб может читать:

bob=> SELECT * FROM app.tab;
  who
-------
 alice
(1 row)

Но не может менять:

bob=> INSERT INTO app.tab DEFAULT VALUES;
ERROR:  permission denied for table tab
bob=> \c - charlie
You are now connected to database "access_membership" as user "charlie".

Чарли может менять строки:

charlie=> INSERT INTO app.tab DEFAULT VALUES;
INSERT 0 1

Но не читать их:

charlie=> SELECT * FROM app.tab;
ERROR:  permission denied for table tab

Уборка

charlie=> \c student student

Page 19: Page 19

You are now connected to database "student" as user "student".
student=# DROP DATABASE access_membership WITH (FORCE);
DROP DATABASE
student=# DROP ROLE alice, bob, charlie, readers, writers;
DROP ROLE

Page 20: Практика+

Изучите способы получения метаинформации.

    1. Создайте роли, схему и таблицу, как это сделано в Практике.
    1. Получите: список объектов Алисы; права пользователей на эти объекты; список ролей, имеющих право чтения таблицы; информацию о включении ролей в группы.
    1. Может ли пользователь Дейв, не имеющий доступа к объектам, увидеть эту метаинформацию?

Комментарии преподавателя

2, 3. Для получения метаинформации можно использовать следующие источники:

● системный каталог https://postgrespro.ru/docs/postgresql/16/catalogs;

● системные информационные функции https://postgrespro.ru/docs/postgresql/16/functions-info;

● метакоманды psql https://postgrespro.ru/docs/postgresql/16/app-psql#:~:text=удаляет%20п еред%20отправкой.-,Метакоманды,-Всё%2C%20что%20вводится

● информационную схему https://postgrespro.ru/docs/postgresql/16/information-schema.

Page 21: 1. Роли, схема, таблица

Роль Алисы.

student=# CREATE USER alice NOINHERIT IN ROLE student;
CREATE ROLE
student=# \c - alice
You are now connected to database "student" as user "alice".
alice=> SET ROLE student;
SET

Группы readers и writers.

alice=> CREATE ROLE readers;
CREATE ROLE
alice=> CREATE ROLE writers;
CREATE ROLE

Боб — читатель.

alice=> CREATE USER bob;
CREATE ROLE
alice=> GRANT readers TO bob WITH SET FALSE;
GRANT ROLE

Чарли — писатель.

alice=> CREATE USER charlie;
CREATE ROLE
alice=> GRANT writers TO charlie WITH SET FALSE;
GRANT ROLE

Вот что получилось:

alice=> \drg
            List of role grants
 Role name | Member of | Options | Grantor
-----------+-----------+---------+----------
 alice     | student   | SET     | postgres
 bob       | readers   | INHERIT | postgres
 charlie   | writers   | INHERIT | postgres
(3 rows)

База данных и таблица.

alice=> CREATE DATABASE access_membership OWNER alice;
CREATE DATABASE
alice=> \c access_membership
You are now connected to database "access_membership" as user "alice".
alice=> CREATE SCHEMA app;
CREATE SCHEMA
alice=> CREATE TABLE app.tab(who text DEFAULT current_user);
CREATE TABLE

Привилегии.

alice=> GRANT USAGE ON SCHEMA app TO readers, writers;
GRANT

Page 22: 2. Метаинформация

alice=> GRANT SELECT ON TABLE app.tab TO readers;
GRANT
alice=> GRANT INSERT, UPDATE, DELETE ON TABLE app.tab TO writers;
GRANT

Получим информацию от имени суперпользователя.

alice=> \c - student
You are now connected to database "access_membership" as user "student".

В системном каталоге можно увидеть список схем:

student=# SELECT * FROM pg_namespace;
  oid  |      nspname       | nspowner |                            nspacl
-------+--------------------+----------+--------------------------------------------------
-------------
    99 | pg_toast           |       10 |
    11 | pg_catalog         |       10 | {postgres=UC/postgres,=U/postgres}
  2200 | public             |     6171 |
{pg_database_owner=UC/pg_database_owner,=U/pg_database_owner}
 13296 | information_schema |       10 | {postgres=UC/postgres,=U/postgres}
 16395 | app                |    16386 | {alice=UC/alice,readers=U/alice,writers=U/alice}
(5 rows)

А также список объектов Алисы с привилегиями на них:

student=# SELECT oid, relname, relacl
FROM pg_class
WHERE relowner = 'alice'::regrole;
  oid  |       relname        |                         relacl
-------+----------------------+---------------------------------------------------------
 16400 | pg_toast_16396       |
 16401 | pg_toast_16396_index |
 16396 | tab                  | {alice=arwdDxt/alice,readers=r/alice,writers=awd/alice}
(3 rows)

Получить список ролей, имеющих право чтения таблицы, можно с помощью функции:

student=# SELECT rolname
FROM pg_roles
WHERE has_table_privilege(rolname, 'app.tab', 'SELECT');
     rolname
------------------
 pg_read_all_data
 student
 postgres
 alice
 readers
 bob
(6 rows)

А сведения о включении ролей — используя другую функцию:

student=# SELECT rolname
FROM pg_roles
WHERE pg_has_role('bob', rolname, 'MEMBER,USAGE');
 rolname
---------
 readers
 bob
(2 rows)

Более подробную информацию о включении дает метакоманда psql:

student=# \drg

Page 23: Page 23

            List of role grants
 Role name | Member of | Options | Grantor
-----------+-----------+---------+----------
 alice     | student   | SET     | postgres
 bob       | readers   | INHERIT | postgres
 charlie   | writers   | INHERIT | postgres
(3 rows)

В некоторых случаях полезна информационной схема: например, доступные текущему пользователю таблицы показывает представление tables.

student=# SELECT table_schema, table_name, string_agg(privilege_type,',') AS privs
FROM information_schema.tables
  NATURAL JOIN information_schema.table_privileges
WHERE table_schema = 'app'
GROUP BY 1,2
ORDER BY 1,2 \gx
-[ RECORD 1
]+------------------------------------------------------------------------------------
table_schema | app
table_name   | tab
privs        |
INSERT,SELECT,UPDATE,DELETE,TRUNCATE,REFERENCES,TRIGGER,SELECT,INSERT,UPDATE,DELETE

3. Обычный пользователь

student=# CREATE USER dave;
CREATE ROLE
student=# \c - dave
You are now connected to database "access_membership" as user "dave".

Дейв не имеет доступа к схеме и таблице:

dave=> SELECT * FROM app.tab;
ERROR:  permission denied for schema app
LINE 1: SELECT * FROM app.tab;
                      ^

Однако он видит список всех таблиц:

dave=> SELECT oid, relname, relacl
FROM pg_class
WHERE relowner = 'alice'::regrole;
  oid  |       relname        |                         relacl
-------+----------------------+---------------------------------------------------------
 16400 | pg_toast_16396       |
 16401 | pg_toast_16396_index |
 16396 | tab                  | {alice=arwdDxt/alice,readers=r/alice,writers=awd/alice}
(3 rows)

Список ролей, имеющих право чтения таблицы, тоже доступен (используем oid вместо имени, так как доступа к схеме нет):

dave=> SELECT rolname
FROM pg_roles
WHERE has_table_privilege(rolname, 16396::regclass, 'SELECT');
     rolname
------------------
 pg_read_all_data
 student
 postgres
 alice
 readers
 bob
(6 rows)

Пользователь может получить и информацию о включении ролей:

dave=> SELECT rolname
FROM pg_roles
WHERE pg_has_role('bob', rolname, 'MEMBER,USAGE');

Page 24: Page 24

 rolname
---------
 readers
 bob
(2 rows)
dave=> \drg
            List of role grants
 Role name | Member of | Options | Grantor
-----------+-----------+---------+----------
 alice     | student   | SET     | postgres
 bob       | readers   | INHERIT | postgres
 charlie   | writers   | INHERIT | postgres
(3 rows)

Уборка

dave=> \c student student
You are now connected to database "student" as user "student".
student=# DROP DATABASE access_membership WITH (FORCE);
DROP DATABASE
student=# DROP ROLE alice, bob, charlie, dave, readers, writers;
DROP ROLE