Query ให้สิทธิ์สำหรับตารางใน postgres


97

ฉันจะสืบค้น GRANTS ทั้งหมดที่มอบให้กับวัตถุใน postgres ได้อย่างไร

ตัวอย่างเช่นฉันมีตาราง "mytable":

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

ฉันต้องการบางสิ่งที่ให้ฉัน:

user1: SELECT, INSERT
user2: UPDATE

คำตอบ:



99

\z mytable จาก psql ช่วยให้คุณได้รับทุนทั้งหมดจากตาราง แต่คุณจะต้องแยกตามผู้ใช้แต่ละคน


คุณจะเรียกใช้สิ่งนี้โดยตรงจากบานหน้าต่าง sql หรือบรรทัดคำสั่ง pg หรือไม่?
Daniel L. VanDenBosch

2
@ DanielL.VanDenBosch: คำสั่งเมตาทั้งหมดเช่น\zใช้สำหรับ psql และ psql เป็นอินเทอร์เฟซบรรทัดคำสั่งสำหรับ PostgreSQL
Mike Sherrill '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), ...)เพื่อหลีกเลี่ยงความคลุมเครือ
Paul A Jungwirth

Plus One - นี่คือทองคำบริสุทธิ์!
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 |
...

สิ่งนี้ให้เฉพาะแถวที่ตรงกับผู้ใช้ที่ดำเนินการเท่านั้น ... ไม่ใช่ทุนทั้งหมด
Ricky Levi

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;

วิธีนี้ใช้ได้ดีโดยสมมติว่าคุณเข้าสู่ระบบในฐานะผู้ใช้ที่มีสิทธิ์ที่เหมาะสม Nitpick: ฉันแนะนำว่าควรเขียน cross join อย่างชัดเจนเช่นFROM pg_tables AS a CROSS JOIN pg_user AS bแทนที่จะใช้วิธี SQL 92 ด้วยลูกน้ำfrom pg_tables a, pg_user b
Davos

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;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.