Я хотел бы написать запрос, который выводит права для каждого пользователя по таблице доступности. Причина такого поиска заключается в том, что я могу сделать снимок прав на таблицу и затем сравнить их на разных серверах или до и после запуска большого сценария сброса GRANTS. Я ищу вывод, который легко сравнить, поэтому что-то вроде этого:
schema_name table_name qualified_name owner_name privilege setting
api base4 api.base4 postgres delete TRUE
api bucket_test api.bucket_test postgres delete TRUE
Я написал запрос, который помогает мне в этом, но с именами привилегий и настройками в виде столбцапар. Я мог бы разрезать столбцы пополам, назвав их после привилегии, но я придерживаюсь более узкого формата строки выше. Это делает сравнения, которые я буду выполнять, гранулярными для таблицы + пользователь + привилегия.
schema_name table_name qualified_name owner_name privilege delete privilege insert privilege references privilege setting privilege trigger privilege truncate privilege update
api base4 api.base4 postgres delete TRUE insert TRUE references TRUE select TRUE trigger TRUE truncate TRUE update TRUE
api bucket_test api.bucket_test postgres delete TRUE insert TRUE references TRUE select TRUE trigger TRUE truncate TRUE update TRUE
Может кто-нибудь предложить правильное соединение или отменить вкладку + соединение, чтобы переделать запрос, который я получил сейчас?
И, да, этот запрос будет генерировать много строк результатов. Это нормально, это то, что я ищу.
with
table_list as
( select schemaname as schema_name,
tablename as table_name,
quote_ident(schemaname) || '.' || quote_ident(tablename) as qualified_name,
tableowner as owner_name
from pg_tables
where schemaname in ('data','api')
order by 3),
user_list as
( select usename as user_name
from pg_user
order by 1)
select table_list.schema_name,
table_list.table_name,
table_list.qualified_name,
table_list.owner_name,
'delete' as privilege, has_table_privilege(user_list.user_name, concat(table_list.qualified_name), 'delete') as delete,
'insert' as privilege, has_table_privilege(user_list.user_name, concat(table_list.qualified_name), 'insert') as insert,
'references' as privilege, has_table_privilege(user_list.user_name, concat(table_list.qualified_name), 'references') as references,
'select' as privilege, has_table_privilege(user_list.user_name, concat(table_list.qualified_name), 'select') as select,
'trigger' as privilege, has_table_privilege(user_list.user_name, concat(table_list.qualified_name), 'trigger') as trigger,
'truncate' as privilege, has_table_privilege(user_list.user_name, concat(table_list.qualified_name), 'truncate') as truncate,
'update' as privilege, has_table_privilege(user_list.user_name, concat(table_list.qualified_name), 'update') as update
from table_list
cross join user_list
Я на Postgres 11.4 на RDS.
Последующие действия
Для тех, кто найдет этот вопрос позже,Вот версия окончательного запроса в виде представления:
DROP VIEW IF EXISTS data.table_grants;
CREATE OR REPLACE VIEW data.table_grants AS
with
table_list as
( select schemaname as schema_name,
tablename as table_name,
schemaname::text || '.' || tablename::text as qualified_name,
tableowner as owner_name
from pg_tables
where schemaname in ('data','api')
order by 3),
user_list as
( select usename as user_name
from pg_user
order by 1)
select
table_list.*,
user_list.user_name,
privilege,
has_table_privilege(user_name, qualified_name, privilege) as setting
from
table_list
cross join user_list
cross join (values
('delete'), ('insert'), ('references'), ('select'), ('trigger'), ('truncate'), ('update')
) as p(privilege);
ALTER TABLE data.table_grants
OWNER TO user_change_structure;
Это упрощает поиск по грантам таблицы, как этот, чтобы увидеть права, предоставленные для таблицы с именем item
select *
from table_grants
where table_name = 'item'
order by user_name,
privilege;
Или этот запрос для получения обобщенного представления прав пользователя для определенной таблицы:
select qualified_name,
owner_name,
user_name,
array_agg(privilege) as rights
from table_grants
where table_name = 'item' and
setting = true
group by qualified_name,
owner_name,
user_name;
Приведенные выше запросы не обязательно являются оптимально эффективными, и продуктом представления являются таблицы * users * 8. ... но для меня все это мгновенно, с менее чем 100 столами и примерно 15 ролями.