Гранты запросов для таблицы в postgres

97

Как я могу запросить все ГРАНТЫ, предоставленные объекту в postgres?

Например, у меня есть таблица "mytable":

GRANT SELECT, INSERT ON mytable TO user1
GRANT UPDATE ON mytable TO user2 

Мне нужно что-то, что дает мне:

user1: SELECT, INSERT
user2: UPDATE
Маркус
источник

Ответы:

113

Я уже нашел:

SELECT grantee, privilege_type 
FROM information_schema.role_table_grants 
WHERE table_name='mytable'
Маркус
источник
99

\z mytable from psql предоставляет вам все гранты из таблицы, но затем вам придется разделить их по отдельным пользователям.

CPJ
источник
вы бы запустили это прямо из панели sql или командной строки pg?
Дэниел Л. ВанДенБош,
2
@ DanielL.VanDenBosch: все мета-команды, например \z, предназначены для psql. А psql - это интерфейс командной строки для PostgreSQL.
Майк Шерилл 'Cat Recall'
31

Если вам действительно нужна одна строка для каждого пользователя, вы можете сгруппировать по получателю (требуется PG9 + для string_agg)

SELECT grantee, string_agg(privilege_type, ', ') AS privileges
FROM information_schema.role_table_grants 
WHERE table_name='mytable'   
GROUP BY grantee;

Это должно вывести что-то вроде:

 grantee |   privileges   
---------+----------------
 user1   | INSERT, SELECT
 user2   | UPDATE
(2 rows)
Николя Пайяр
источник
1
Почти то, что я хочу, могу ли я получить точные результаты, GRANTтакие как pg_dump?
brauliobo
28

Приведенный ниже запрос предоставит вам список всех пользователей и их разрешения для таблицы в схеме.

select a.schemaname, a.tablename, b.usename,
  HAS_TABLE_PRIVILEGE(usename, quote_ident(schemaname) || '.' || quote_ident(tablename), 'select') as has_select,
  HAS_TABLE_PRIVILEGE(usename, quote_ident(schemaname) || '.' || quote_ident(tablename), 'insert') as has_insert,
  HAS_TABLE_PRIVILEGE(usename, quote_ident(schemaname) || '.' || quote_ident(tablename), 'update') as has_update,
  HAS_TABLE_PRIVILEGE(usename, quote_ident(schemaname) || '.' || quote_ident(tablename), 'delete') as has_delete, 
  HAS_TABLE_PRIVILEGE(usename, quote_ident(schemaname) || '.' || quote_ident(tablename), 'references') as has_references 
from pg_tables a, pg_user b 
where a.schemaname = 'your_schema_name' and a.tablename='your_table_name';

Более подробную информацию has_table_privilagesможно найти здесь .

шрути
источник
4
Это единственный ответ, который вычисляет разрешения, полученные от членства в других ролях, поэтому он получает мой голос. С другой стороны, я бы сказал, has_table_privilege(usename, contact(schemaname, '.', tablename), ...)чтобы избежать двусмысленности.
Пол А Юнгвирт
Плюс один - ЭТО ЧИСТОЕ ЗОЛОТО!
Daniel
9

В этом запросе будут перечислены все таблицы во всех базах данных и схемах (раскомментируйте строки в WHEREпредложении, чтобы отфильтровать определенные базы данных, схемы или таблицы), с привилегиями, показанными в порядке, чтобы было легко увидеть, если предоставлена ​​конкретная привилегия или нет:

SELECT grantee
      ,table_catalog
      ,table_schema
      ,table_name
      ,string_agg(privilege_type, ', ' ORDER BY privilege_type) AS privileges
FROM information_schema.role_table_grants 
WHERE grantee != 'postgres' 
--  and table_catalog = 'somedatabase' /* uncomment line to filter database */
--  and table_schema  = 'someschema'   /* uncomment line to filter schema  */
--  and table_name    = 'sometable'    /* uncomment line to filter table  */
GROUP BY 1, 2, 3, 4;

Пример вывода:

grantee |table_catalog   |table_schema  |table_name     |privileges     |
--------|----------------|--------------|---------------|---------------|
PUBLIC  |adventure_works |pg_catalog    |pg_sequence    |SELECT         |
PUBLIC  |adventure_works |pg_catalog    |pg_sequences   |SELECT         |
PUBLIC  |adventure_works |pg_catalog    |pg_settings    |SELECT, UPDATE |
...
Isapir
источник
это дает только строки, соответствующие пользователю, который его выполнил ... не все гранты
Рики Леви
2

Добавление к ответу @shruti

Запросить гранты для всех таблиц в схеме для данного пользователя

select a.tablename, 
       b.usename, 
       HAS_TABLE_PRIVILEGE(usename,tablename, 'select') as select,
       HAS_TABLE_PRIVILEGE(usename,tablename, 'insert') as insert, 
       HAS_TABLE_PRIVILEGE(usename,tablename, 'update') as update, 
       HAS_TABLE_PRIVILEGE(usename,tablename, 'delete') as delete, 
       HAS_TABLE_PRIVILEGE(usename,tablename, 'references') as references 
from pg_tables a, 
     pg_user b 
where schemaname='your_schema_name' 
      and b.usename='your_user_name' 
order by tablename;
Вишну Нараянан
источник
Это хорошо работает, если вы входите в систему как пользователь с соответствующими разрешениями. Нитпик: Я советую, чтобы перекрестное соединение было написано явно, например, FROM pg_tables AS a CROSS JOIN pg_user AS bа не SQL 92, как это делается с запятойfrom pg_tables a, pg_user b
Давос
1

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

SELECT 
    format (
      'GRANT %s ON TABLE %I.%I TO %I%s;',
      string_agg(tg.privilege_type, ', '),
      tg.table_schema,
      tg.table_name,
      tg.grantee,
      CASE
        WHEN tg.is_grantable = 'YES' 
        THEN ' WITH GRANT OPTION' 
        ELSE '' 
      END
    )
  FROM information_schema.role_table_grants tg
  JOIN pg_tables t ON t.schemaname = tg.table_schema AND t.tablename = tg.table_name
  WHERE
    tg.table_schema = 'myschema' AND
    tg.table_name='mytable' AND
    t.tableowner <> tg.grantee
  GROUP BY tg.table_schema, tg.table_name, tg.grantee, tg.is_grantable;
Сахап Аски
источник