Requête octroyée pour une table dans postgres

92

Comment puis-je interroger tous les GRANTS accordés à un objet dans postgres?

Par exemple j'ai la table "ma table":

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

J'ai besoin de quelque chose qui me donne:

user1: SELECT, INSERT
user2: UPDATE
Markus
la source

Réponses:

108

Je l'ai déjà trouvé:

SELECT grantee, privilege_type 
FROM information_schema.role_table_grants 
WHERE table_name='mytable'
Markus
la source
97

\z mytable de psql vous donne toutes les subventions d'une table, mais vous devrez ensuite la diviser par utilisateur individuel.

CPJ
la source
l'exécuteriez-vous directement à partir du volet sql ou de la ligne de commande pg?
Daniel L. VanDenBosch
2
@ DanielL.VanDenBosch: toutes les méta-commandes, comme \z, sont pour psql. Et psql est l'interface de ligne de commande de PostgreSQL.
Mike Sherrill 'Cat Recall'
29

Si vous voulez vraiment une ligne par utilisateur, vous pouvez grouper par bénéficiaire (nécessite PG9 + pour string_agg)

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

Cela devrait générer quelque chose comme:

 grantee |   privileges   
---------+----------------
 user1   | INSERT, SELECT
 user2   | UPDATE
(2 rows)
Nicolas Payart
la source
1
Presque ce que je veux, puis-je avoir les GRANTsorties exactes comme pg_dump?
brauliobo
26

La requête ci-dessous vous donnera une liste de tous les utilisateurs et leurs autorisations sur la table dans un schéma.

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';

Plus de détails sur has_table_privilagespeuvent être trouvés ici .

shruti
la source
4
C'est la seule réponse ici qui calcule les autorisations obtenues à partir de l'appartenance à d'autres rôles, donc il obtient mon vote. D'un autre côté, je dirais has_table_privilege(usename, contact(schemaname, '.', tablename), ...)d'éviter toute ambiguïté.
Paul A Jungwirth
Plus One - C'EST DE L'OR PUR!
Daniel
9

Cette requête répertorie toutes les tables de toutes les bases de données et schémas (décommentez la ou les lignes dans la WHEREclause pour filtrer des bases de données, des schémas ou des tables spécifiques), avec les privilèges affichés dans l'ordre afin qu'il soit facile de voir si un privilège spécifique est accordé ou non:

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;

Exemple de sortie:

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
la source
cela ne donne que les lignes correspondant à l'utilisateur qui l'a exécuté ... pas toutes les subventions
Ricky Levi
2

Ajout de la réponse de @ shruti

Pour interroger les octrois pour toutes les tables d'un schéma pour un utilisateur donné

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;
vishnu narayanan
la source
Cela fonctionne bien, en supposant que vous vous connectez en tant qu'utilisateur avec les autorisations appropriées. Nitpick: Je conseille qu'une jointure croisée soit écrite explicitement, par exemple FROM pg_tables AS a CROSS JOIN pg_user AS bplutôt que la manière SQL 92 de le faire avec une virgulefrom pg_tables a, pg_user b
Davos
1

Voici un script qui génère des requêtes d'octroi pour une table particulière. Il omet les privilèges du propriétaire.

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;
Sahap Asci
la source