Роли, атрибуты, привилегии, и подключения

PostgreSQLВ курсе Администрирование PostgreSQL 10. Базовый курс есть большой раздел про управление доступом (роли, атрибуты, привилегии, и подключения). Информации много, она очень интересная, разнообразная. В курсе есть практика по каждому из занятий.

Я для себя сделал небольшую дополнительную пракитку, в которой хотел зафиксировать некоторые моменты из курса. Готовил это параллельно с изучением курса. Потом еще поделился этими черновиками. И вот уже решил что пусть будет в открытом доступе, может кому ещё пригодиться.

Использовать буду 13-ю версию PostgreSQL.

Если вкратце — ниже я создам несколько ролей и объектов БД (схема, таблица), настрою роли так, чтобы можно было пользоваться этими объектами и еще с групповыми ролями поработаю. Но подробно ничего говорить об этом не буду — всё есть в курсе.

А вот и оглавление:

Создание ролей

Сначала посмотрим сколько ролей в системе уже есть (команда \du):

postgres=# \du
                               	List of roles
 Role name |                     	Attributes                     	| Member of
-----------+------------------------------------------------------------+-----------
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}

 

Имеется только одна предопределенная роль (postgres), это суперпользователь (это тот, кто может переопределять любые ограничения доступа в базе данных). В статье документации Роли базы данных есть информация об этом (и еще много о чем).

Для демонстрации создам четыре роли (после названия роли перечислены её атрибуты):

CREATE ROLE mainrole LOGIN;
CREATE ROLE grouprole CREATEDB;
CREATE ROLE slaverole LOGIN;
CREATE ROLE weakrole NOINHERIT LOGIN;

Проверим результат:

postgres=# \du
                               	List of roles
 Role name |                     	Attributes                     	| Member of
-----------+------------------------------------------------------------+-----------
 grouprole | Create DB, Cannot login                                	| {}
 mainrole  |                                                        	| {}
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
 slaverole |                                                        	| {}
 weakrole  | No inheritance                                         	| {}

.

Замечания про именования объектов в PostgreSQL

Информация ниже относится не только к названию ролей, но и к наименованию других пользовательских идентификаторов в PostgreSQL.

Названия ролей (по умолчанию) переводятся в нижний регистр. Если хотите чтобы роль была написана в верхнем (или часть названия роли) — нужно помещать название в двойные кавычки. То же относится к названиям, начинающимся с цифр. И вообще, в названии роли нужно использовать правила именования идентификаторов SQL:

postgres=# CREATE ROLE UPPERROLE LOGIN;
CREATE ROLE
postgres=# \du
                               	List of roles
 Role name |                     	Attributes                     	| Member of
-----------+------------------------------------------------------------+-----------
 grouprole | Create DB, Cannot login                                	| {}
 mainrole  |                                                        	| {}
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
 slaverole |                                                        	| {}
 upperrole |                                                        	| {}
 weakrole  | No inheritance                                         	| {}

postgres=# create role "UPPERROLE" login;
CREATE ROLE
postgres=# \du
                               	List of roles
 Role name |                     	Attributes                     	| Member of
-----------+------------------------------------------------------------+-----------
 UPPERROLE |                                                        	| {}
 grouprole | Create DB, Cannot login                                	| {}
 mainrole  |                                                        	| {}
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
 slaverole |                                                        	| {}
 upperrole |                                                        	| {}
 weakrole  | No inheritance                                         	| {}

И, как можно догадаться, роли upperrole и UPPERROLE — это разные роли.

Про начальные цифры в названии:

postgres=# CREATE ROLE 000 LOGIN;
2021-12-20 21:57:40.104 MSK [71143] ERROR:  syntax error at or near "000" at character 13
2021-12-20 21:57:40.104 MSK [71143] STATEMENT:  CREATE ROLE 000 LOGIN;
ERROR:  syntax error at or near "000"
LINE 1: CREATE ROLE 000 LOGIN;

postgres=# CREATE ROLE "000" LOGIN;
CREATE ROLE
postgres=# \du
                               	List of roles
 Role name |                     	Attributes                     		| Member of
-----------+------------------------------------------------------------+-----------
 000  	   |                                                        	| {}
 UPPERROLE |                                                        	| {}
 grouprole | Create DB, Cannot login                                	| {}
 mainrole  |                                                        	| {}
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
 slaverole |                                                        	| {}
 upperrole |                                                        	| {}
 weakrole  | No inheritance                                         	| {}

Про удаление ролей аналогично:

postgres=# DROP ROLE 000;
2021-12-20 21:59:57.188 MSK [71143] ERROR:  syntax error at or near "000" at character 11
2021-12-20 21:59:57.188 MSK [71143] STATEMENT:  DROP ROLE 000;
ERROR:  syntax error at or near "000"
LINE 1: DROP ROLE 000;
              	^
postgres=# DROP ROLE "000";
DROP ROLE
postgres=# DROP ROLE "UPPERROLE";
DROP ROLE
postgres=# DROP ROLE UPPERROLE;
DROP ROLE
postgres=# \du
                               	List of roles
 Role name |                     	Attributes                     	| Member of
-----------+------------------------------------------------------------+-----------
 grouprole | Create DB, Cannot login                                	| {}
 mainrole  |                                                        	| {}
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
 slaverole |                                                        	| {}
 weakrole  | No inheritance                                         	| {}

.

Создание базы данных и схемы

Создаю БД для дальнейшей демонстрации:

postgres=# CREATE DATABASE maindb;

Список ролей можно посмотреть с помощью команды \l:

postgres=# \l
                              	List of databases
   Name		|  Owner   | Encoding |   Collate   |	Ctype	|   Access privileges   
-----------+----------+----------+-------------+-------------+-----------------------
 maindb		| postgres | UTF8 	| en_US.UTF-8 | en_US.UTF-8 |
 postgres   | postgres | UTF8 	| en_US.UTF-8 | en_US.UTF-8 |
 template0  | postgres | UTF8 	| en_US.UTF-8 | en_US.UTF-8 | =c/postgres      	+
       		| 		   |      	|             |         	| postgres=CTc/postgres
 template1	| postgres | UTF8 	| en_US.UTF-8 | en_US.UTF-8 | =c/postgres      	+
            |          |      	|         	  |         	| postgres=CTc/postgres
(4 rows)

Подключаюсь к этой БД и создаю схему:

postgres=# \c maindb
You are now connected to database "maindb" as user "postgres".
maindb=# CREATE SCHEMA mainschema;
CREATE SCHEMA

Посмотрим созданные схемы (\dn) и созданные таблицы (\dp):

maindb=# \dn
	List of schemas
	Name	|  Owner   
------------+----------
 mainschema | postgres
 public 	| postgres
(2 rows)

maindb=# \dp
                        	Access privileges
 Schema | Name | Type | Access privileges | Column privileges | Policies
--------+------+------+-------------------+-------------------+----------
(0 rows)

.

Включение схемы в путь поиска

Чтобы не было проблем в дальнейшем, нужно созданную схему включить в путь поиска:

maindb=# SHOW search_path;
   search_path   
-----------------
 "$user", public
(1 row)

maindb=# SET search_path = mainschema, public;
SET
maindb=# SHOW search_path;
	search_path	 
--------------------
 mainschema, public
(1 row)

maindb=# SELECT current_schemas(true);
    	current_schemas    	 
--------------------------------
 {pg_catalog,mainschema,public}
(1 row)

Последний запрос выводит фактически использованный путь поиска.

Создание таблицы

Создаю тестовую таблицу, заполняю данными:

maindb=# CREATE TABLE maintable (id integer);
CREATE TABLE
maindb=# INSERT INTO maintable VALUES (1),(2),(3);
INSERT 0 3
maindb=# SELECT * FROM maintable;
 id
----
  1
  2
  3
(3 rows)

Посмотрим список таблиц (\dp), там же выводятся их права доступа:

maindb=# \dp
                             	Access privileges
   Schema   |   Name	| Type  | Access privileges | Column privileges | Policies
------------+-----------+-------+-------------------+-------------------+----------
 mainschema | maintable | table |               	|               	|
(1 row)

 

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

Выдача привилегий

Выдаю гранты:

maindb=# GRANT SELECT ON mainschema.maintable TO grouprole;
GRANT
maindb=# GRANT USAGE ON SCHEMA mainschema TO grouprole;
GRANT
maindb=# \dp
                                 	Access privileges
   Schema   |   Name	| Type  | 	Access privileges 	| Column privileges | Policies
------------+-----------+-------+---------------------------+-------------------+----------
 mainschema | maintable | table | postgres=arwdDxt/postgres+|               	|
        	|       	|   	| grouprole=r/postgres  	|               	|
(1 row)

.

Включение в групповую роль

Включаем slaverole в групповую grouprole (можно запись читать справа-налево: включаем slaverole в grouprole):

maindb=# GRANT grouprole TO slaverole;
GRANT ROLE
maindb=# \du
                                 List of roles
 Role name |                     Attributes                     |  Member of  
-----------+------------------------------------------------------------+-------------
 grouprole | Create DB, Cannot login                                | {}
 mainrole  |                                                        | {}
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
 slaverole |                                                        | {grouprole}
 weakrole  | No inheritance                                         | {}
--REVOKE grouprole FROM slaverole;

Включаем weakrole в групповую grouprole

maindb=# GRANT grouprole TO weakrole;
GRANT ROLE
maindb=# \du
                                	List of roles
 Role name |                     	Attributes                     	|  Member of  
-----------+------------------------------------------------------------+-------------
 grouprole | Create DB, Cannot login                                	| {}
 mainrole  |                                                        	| {}
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
 slaverole |                                                        	| {grouprole}
 weakrole  | No inheritance                                         	| {grouprole}

.

Проверка групповых ролей

Заходим под пользователем slaverole (хотя явного атрибута login у этой роли нет):

maindb=# \c - slaverole
You are now connected to database "maindb" as user "slaverole".
maindb=> SELECT * FROM mainschema.maintable;
 id
----
  1
  2
  3
(3 rows)

Содержимое таблицы отображается.

Заходим под пользователем weakrole:

maindb=> \c - weakrole
You are now connected to database "maindb" as user "weakrole".
maindb=> SELECT * FROM mainschema.maintable;
2021-12-20 22:31:57.983 MSK [110069] ERROR:  permission denied for schema mainschema at character 15
2021-12-20 22:31:57.983 MSK [110069] STATEMENT:  SELECT * FROM mainschema.maintable;
ERROR:  permission denied for schema mainschema
LINE 1: SELECT * FROM mainschema.maintable;

Нет доступа, потому что роль без наследования привилегий.

Переключаемся на пользователя postgres, возвращаем наследование для weakrole:

maindb=> \c - postgres
You are now connected to database "maindb" as user "postgres".
maindb=# ALTER ROLE weakrole INHERIT;
ALTER ROLE
maindb=# \c - weakrole
You are now connected to database "maindb" as user "weakrole".
maindb=> SELECT * FROM mainschema.maintable;
 id
----
  1
  2
  3
(3 rows)

Содержимое таблицы отображается.

Теперь проверим доступ к атрибутам групповой роли. Под пользователем weakrole попробуем создать БД:

maindb=> CREATE DATABASE db;
2021-12-20 22:40:34.860 MSK [110129] ERROR:  permission denied to create database
2021-12-20 22:40:34.860 MSK [110129] STATEMENT:  CREATE DATABASE db;
ERROR:  permission denied to create database

.

Переключение SET ROLE

Нужно явно переключиться на grouprole:

maindb=> SELECT session_user, current_user;
 session_user | current_user
--------------+--------------
 weakrole 	| weakrole
(1 row)

maindb=> SET ROLE grouprole;
SET
maindb=> SELECT session_user, current_user;
 session_user | current_user
--------------+--------------
 weakrole 	| grouprole
(1 row)

Снова пробую создать базу данных:

maindb=> CREATE DATABASE db;
CREATE DATABASE

База данных создана успешно.

Возвращаемся в роль weakrole:

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

И пробую удалить созданную БД:

maindb=> DROP DATABASE db;
DROP DATABASE

Получилось 🙂

Код команд без вывода

\du
CREATE ROLE mainrole LOGIN;
CREATE ROLE grouprole CREATEDB;
CREATE ROLE slaverole LOGIN;
CREATE ROLE weakrole NOINHERIT LOGIN;
\du
CREATE DATABASE maindb;
\l
\c maindb
CREATE SCHEMA mainschema;
\dn
\dp
SHOW search_path;
SET search_path = mainschema, public;
SHOW search_path;
SELECT current_schemas(true);
CREATE TABLE maintable (id integer);
INSERT INTO maintable VALUES (1),(2),(3);
SELECT * FROM maintable;
\dp
GRANT SELECT ON mainschema.maintable TO grouprole;
GRANT USAGE ON SCHEMA mainschema TO grouprole;
\dp
GRANT grouprole TO slaverole;
\du
--REVOKE grouprole FROM slaverole;
GRANT grouprole TO weakrole;
\du
\c - slaverole
SELECT * FROM mainschema.maintable;
\c - weakrole
SELECT * FROM mainschema.maintable;
\c - postgres
ALTER ROLE weakrole INHERIT;
\c - weakrole
SELECT * FROM mainschema.maintable;
CREATE DATABASE db;
SELECT session_user, current_user;
SET ROLE grouprole;
SELECT session_user, current_user;
CREATE DATABASE db;
RESET ROLE;
SELECT session_user, current_user;
DROP DATABASE db;

 


Be the first to comment

Leave a Reply

Ваш Mail не будет опубликован.


*