22.3. Членство в роли #

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

Для настройки групповой роли сначала нужно создать саму роль:

CREATE ROLE имя;

Обычно групповая роль не имеет атрибута LOGIN, хотя при желании его можно установить.

После того как групповая роль создана, в неё можно добавлять или удалять членов, используя команды GRANT и REVOKE:

GRANT групповая_роль TO роль1, ... ;
REVOKE групповая_роль FROM роль1, ... ;

Членом роли может быть и другая групповая роль (потому что в действительности нет никаких различий между групповыми и не групповыми ролями). При этом база данных не допускает замыкания членства по кругу. Также не допускается управление членством роли PUBLIC в других ролях.

Члены групповой роли могут использовать её права двумя способами. Во-первых, члены группы, которым было предоставлено членство с атрибутом SET, могут выполнить команду SET ROLE, чтобы временно «стать» групповой ролью. В этом состоянии сеанс базы данных имеет доступ к правам групповой роли вместо исходной роли, от имени которой был выполнен вход в систему. При этом для всех создаваемых объектов базы данных владельцем считается групповая, а не исходная роль. Во-вторых, члены группы, которым было предоставлено членство с атрибутом INHERIT, автоматически используют права ролей, членами которых они являются прямо или косвенно, вплоть до роли без атрибута INHERIT. Например:

CREATE ROLE joe LOGIN;
CREATE ROLE admin;
CREATE ROLE wheel;
CREATE ROLE island;
GRANT admin TO joe WITH INHERIT TRUE;
GRANT wheel TO admin WITH INHERIT FALSE;
GRANT island TO joe WITH INHERIT TRUE, SET FALSE;

После подключения с ролью joe сеанс базы данных будет использовать права, выданные напрямую joe, и права, выданные ролям admin и island, так как joe «наследует» эти права. Однако права, выданные wheel, будут недоступны, потому что, хотя joe косвенно является членом wheel, это членство получено через роль admin, которая была выдана с атрибутом WITH INHERIT FALSE. После выполнения команды:

SET ROLE admin;

сеанс будет использовать только права, выданные admin, а не права, выданные роли joe или island. После выполнения команды:

SET ROLE wheel;

сеанс будет использовать только права, выданные wheel, а не права, выданные joe или admin. Начальный набор прав можно восстановить любой из команд:

SET ROLE joe;
SET ROLE NONE;
RESET ROLE;

Примечание

Команда SET ROLE в любой момент разрешает выбрать любую роль, прямым или косвенным членом которой является оригинальная роль, под которой был выполнен вход в систему, при условии, что существует цепочка членства в ролях, каждая из которых имеет атрибут SET TRUE (установленный по умолчанию). Поэтому в примере выше не обязательно сначала становиться admin перед тем как стать wheel. С другой стороны, стать island не получится вовсе, а joe может получить доступ к правам только через механизм наследования.

Примечание

В стандарте SQL есть чёткое различие между пользователями и ролями. При этом пользователи, в отличие от ролей, не наследуют права автоматически. Такое поведение может быть получено в PostgreSQL, если для ролей, используемых как роли в стандарте SQL, устанавливать атрибут INHERIT, а для ролей-пользователей в стандарте SQL — атрибут NOINHERIT. Однако в PostgreSQL все роли по умолчанию имеют атрибут INHERIT. Это сделано для обратной совместимости с версиями до 8.1, в которых пользователи всегда могли использовать права групп, членами которых они являются.

Атрибуты роли LOGIN, SUPERUSER, CREATEDB и CREATEROLE можно рассматривать как особые права, но они никогда не наследуются как обычные права на объекты базы данных. Чтобы ими воспользоваться, необходимо переключиться на роль, имеющую этот атрибут, с помощью команды SET ROLE. Продолжая предыдущий пример, можно установить атрибуты CREATEDB и CREATEROLE для роли admin. Затем при входе с ролью joe, получить доступ к этим правам будет возможно только после выполнения SET ROLE admin.

Для удаления групповой роли используется DROP ROLE:

DROP ROLE имя;

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