Запрос на возврат прав пользователя для каждой таблицы с одним правом на строку результатов - PullRequest
0 голосов
/ 01 октября 2019

Я хотел бы написать запрос, который выводит права для каждого пользователя по таблице доступности. Причина такого поиска заключается в том, что я могу сделать снимок прав на таблицу и затем сравнить их на разных серверах или до и после запуска большого сценария сброса 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 ролями.

1 Ответ

0 голосов
/ 01 октября 2019

Как Ислингр уже предлагал в комментариях, вы можете использовать

select
  table_list.*,
  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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...