คุณจะสร้างผู้ใช้แบบอ่านอย่างเดียวใน PostgreSQL ได้อย่างไร


419

ฉันต้องการสร้างผู้ใช้ใน PostgreSQL ที่สามารถเลือกได้จากฐานข้อมูลเฉพาะเท่านั้น ใน MySQL คำสั่งจะเป็น:

GRANT SELECT ON mydb.* TO 'xxx'@'%' IDENTIFIED BY 'yyy';

คำสั่งหรือชุดคำสั่งที่เทียบเท่าใน PostgreSQL คืออะไร

ฉันเหนื่อย...

postgres=# CREATE ROLE xxx LOGIN PASSWORD 'yyy';
postgres=# GRANT SELECT ON DATABASE mydb TO xxx;

แต่ปรากฏว่าสิ่งเดียวที่คุณสามารถให้สิทธิ์ในฐานข้อมูลคือ CREATE, CONNECT, TEMPORARY และ TEMP

คำตอบ:


641

ให้สิทธิ์การใช้งาน / เลือกไปยังตารางเดียว

หากคุณให้สิทธิ์ CONNECT กับฐานข้อมูลผู้ใช้สามารถเชื่อมต่อ แต่ไม่มีสิทธิ์อื่น คุณต้องให้สิทธิ์การใช้งานกับเนมสเปซ (สกีมา) และเลือกบนตารางและมุมมองแต่ละรายการเช่น:

GRANT CONNECT ON DATABASE mydb TO xxx;
-- This assumes you're actually connected to mydb..
GRANT USAGE ON SCHEMA public TO xxx;
GRANT SELECT ON mytable TO xxx;

หลายตาราง / มุมมอง (PostgreSQL 9.0+)

ในเวอร์ชันล่าสุดของ PostgreSQL คุณสามารถให้สิทธิ์ในทุกตาราง / จำนวนการดู / ฯลฯ ในสคีมาโดยใช้คำสั่งเดียวแทนที่จะต้องพิมพ์ทีละรายการ:

GRANT SELECT ON ALL TABLES IN SCHEMA public TO xxx;

สิ่งนี้จะมีผลกับตารางที่สร้างขึ้นแล้วเท่านั้น มีพลังมากขึ้นคุณสามารถกำหนดบทบาทเริ่มต้นให้กับวัตถุใหม่ในอนาคตโดยอัตโนมัติ:

ALTER DEFAULT PRIVILEGES IN SCHEMA public
   GRANT SELECT ON TABLES TO xxx;

โปรดทราบว่าโดยค่าเริ่มต้นการดำเนินการนี้จะมีผลกับวัตถุ (ตาราง) ที่สร้างโดยผู้ใช้ที่ออกคำสั่งนี้: แม้ว่าจะสามารถกำหนดบทบาทใดก็ได้ที่ผู้ใช้ที่ออกเป็นสมาชิก อย่างไรก็ตามคุณไม่ได้รับสิทธิพิเศษเริ่มต้นสำหรับบทบาททั้งหมดที่คุณเป็นสมาชิกเมื่อสร้างวัตถุใหม่ ... ดังนั้นยังมีบางสิ่งที่น่าประหลาดใจ หากคุณใช้วิธีการที่ฐานข้อมูลมีบทบาทการเป็นเจ้าของและการเปลี่ยนแปลงแบบแผนจะดำเนินการตามบทบาทการเป็นเจ้าของนั้นคุณควรกำหนดสิทธิ์เริ่มต้นให้กับบทบาทการเป็นเจ้าของนั้น IMHO นี่เป็นเรื่องที่ค่อนข้างสับสนและคุณอาจต้องทำการทดลองเพื่อสร้างเวิร์กโฟลว์การทำงาน

หลายตาราง / มุมมอง (รุ่น PostgreSQL ก่อน 9.0)

เพื่อหลีกเลี่ยงข้อผิดพลาดในการเปลี่ยนแปลงที่มีความยาวและหลายตารางขอแนะนำให้ใช้กระบวนการ 'อัตโนมัติ' ต่อไปนี้เพื่อสร้างสิ่งที่จำเป็นGRANT SELECTสำหรับแต่ละตาราง / มุมมอง:

SELECT 'GRANT SELECT ON ' || relname || ' TO xxx;'
FROM pg_class JOIN pg_namespace ON pg_namespace.oid = pg_class.relnamespace
WHERE nspname = 'public' AND relkind IN ('r', 'v', 'S');

สิ่งนี้ควรส่งออกคำสั่ง GRANT ที่เกี่ยวข้องไปยัง GRANT SELECT ในทุกตารางมุมมองและลำดับในที่สาธารณะสำหรับความรักการคัดลอกและวาง โดยปกติจะใช้กับตารางที่สร้างขึ้นแล้วเท่านั้น


22
คุณควรแก้ไขที่เกี่ยวข้องกับ PG9 ที่ด้านบนของโพสต์
Danilo Bargen

5
ดี สิ่งหนึ่งที่ฉันเพิ่มคือคุณอาจต้องอนุญาตให้ผู้ใช้อ่านลำดับนี้ ดังนั้น: ให้สิทธิ์เลือกตามลำดับทั้งหมดในสคีมาสาธารณะถึง xxx;
JJC

26
REVOKE CREATE ON SCHEMA public FROM PUBLIC;โปรดทราบว่าเพื่อป้องกันไม่ให้ผู้ใช้นี้จากความสามารถในการสร้างตารางใหม่ผมต้อง หากไม่มีสิ่งนั้นผู้ใช้ "อ่านอย่างเดียว" จะไม่สามารถแก้ไขตารางที่มีอยู่ได้ แต่สามารถสร้างตารางใหม่ในสคีมาและเพิ่ม / ลบข้อมูลออกจากตารางเหล่านั้น
Ajedi32

3
@ Ajedi32 นี่ควรเป็นส่วนหนึ่งของคำตอบที่ยอมรับ! ขอบคุณ
Asfand Qazi

12
สำหรับมือใหม่อย่างฉันฉันคิดว่ามันคุ้มค่าที่จะกล่าวถึงว่าคุณควรเริ่มใช้งานคอนโซลโดยpsql mydbที่ไม่ต้องทำสิ่งเหล่านี้ โดยส่วนตัวแล้วฉันใช้เวลาพอสมควรในการคิดออกเอง หวังว่านี่จะช่วยใครซักคน
Anass

41

โปรดทราบว่า PostgreSQL 9.0 (วันนี้ในการทดสอบเบต้า) จะมีวิธีง่าย ๆดังนี้:

test=> GRANT SELECT ON ALL TABLES IN SCHEMA public TO joeuser;

3
ฉันต้องอยู่ในฐานข้อมูลเฉพาะเพื่อให้สามารถทำงานได้ Postgresql 9.5
user1158559

8
ใช้งานได้กับตารางที่มีอยู่ในสคีมาเท่านั้น หากผู้ใช้เขียนในภายหลังสร้างหรือแทนที่ตารางผู้ใช้แบบอ่านอย่างเดียวจะไม่สามารถเข้าถึงได้
anneb

32

การอ้างอิงที่นำมาจากบล็อกนี้:

สคริปต์เพื่อสร้างผู้ใช้แบบอ่านอย่างเดียว:

CREATE ROLE Read_Only_User WITH LOGIN PASSWORD 'Test1234' 
NOSUPERUSER INHERIT NOCREATEDB NOCREATEROLE NOREPLICATION VALID UNTIL 'infinity';

กำหนดสิทธิ์ให้กับผู้ใช้แบบอ่านอย่างเดียวนี้:

GRANT CONNECT ON DATABASE YourDatabaseName TO Read_Only_User;
GRANT USAGE ON SCHEMA public TO Read_Only_User;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO Read_Only_User;
GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO Read_Only_User;

6
นี่เป็นคำตอบที่ดีมากยกเว้นสิ่งหนึ่งที่ขาดหายไป: ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO Read_Only_User; ซึ่งจะอนุญาตให้อ่านตารางทั้งหมดที่สร้างในฐานข้อมูลเดียวกันในอนาคต
Ravbaker

2
เป็นเรื่องผิดปกติที่จะอนุญาตให้ผู้ใช้เข้าถึงลำดับอย่างอ่านได้อย่างเดียว การอ่านลำดับจะทำการอัปเดตและโดยทั่วไปแล้วพวกเขาจำเป็นต้องใช้สำหรับINSERTs เท่านั้น
jpmc26

เพื่อความสมบูรณ์อาจเพิ่ม:GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA schema_name TO Read_Only_User;
Fabien Haddadi

@ jpmc26: นั่นหมายความว่าคุณแนะนำ: GRANT ALL ON ALL SEQUENCES IN SCHEMA schema_name TO Read_Only_User?
Fabien Haddadi

@FabienHaddadi นั่นหมายความว่าถ้าคุณไม่มีข้อกำหนดบางอย่างฉันไม่เห็นว่าจำเป็นต้องให้สิทธิ์ใด ๆ ในลำดับต่อผู้ใช้แบบอ่านอย่างเดียว
jpmc26

24

นี่เป็นวิธีที่ดีที่สุดที่ฉันพบว่าเพิ่มผู้ใช้แบบอ่านอย่างเดียว (โดยใช้ PostgreSQL 9.0 หรือใหม่กว่า):

$ sudo -upostgres psql postgres
postgres=# CREATE ROLE readonly WITH LOGIN ENCRYPTED PASSWORD '<USE_A_NICE_STRONG_PASSWORD_PLEASE';
postgres=# GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;

จากนั้นล็อกอินเข้าสู่เครื่องที่เกี่ยวข้องทั้งหมด (master + read-slave (s) / hot-standby (s), ฯลฯ .)) และเรียกใช้:

$ echo "hostssl <PUT_DBNAME_HERE> <PUT_READONLY_USERNAME_HERE> 0.0.0.0/0 md5" | sudo tee -a /etc/postgresql/9.2/main/pg_hba.conf
$ sudo service postgresql reload

2
ฉันชอบวิธีการ แต่ฉันก็ต้องให้การเชื่อมต่อกับฐานข้อมูล [ฐานข้อมูล] ถึง [ผู้ใช้หรือบทบาท]; และมอบสิทธิ์การใช้งานให้กับสาธารณะใน SCHEMA ถึง [theuser or role];
Ian Connor

1
สคีมาสาธารณะยังคงอนุญาตให้ผู้ใช้ดังกล่าวสร้างตาราง นอกจากนี้ตารางใหม่จะไม่ครอบคลุมและไม่มีการเรียงลำดับ น่าเสียดายที่นี่ซับซ้อนกว่านี้เล็กน้อย : - / ฉันจะโพสต์สิ่งที่ฉันทำไปเมื่อฉันตรวจสอบแล้วอีกครั้ง
JJC

ในสคริปต์ข้างต้นของคุณคุณพยายามสร้างบทบาทสองครั้ง ฉันสงสัยว่าคุณตั้งใจจะใช้ "การเปลี่ยนแปลงบทบาท ..." เมื่อเปิดใช้งานบทบาทสำหรับการเข้าสู่ระบบและการตั้งค่ารหัสผ่าน
Bogdan

หากคุณมีผู้ใช้อยู่แล้วหลังจากสร้างบทบาทแบบอ่านอย่างเดียวและให้สิทธิ์ในการเลือก perms ให้บทบาทใหม่แก่ผู้ใช้: GRANT อ่านได้อย่างเดียวถึง <USER>
gonz

18

โดยค่าเริ่มต้นผู้ใช้ใหม่จะได้รับอนุญาตให้สร้างตาราง หากคุณวางแผนที่จะสร้างผู้ใช้แบบอ่านอย่างเดียวนี่อาจไม่ใช่สิ่งที่คุณต้องการ

ในการสร้างผู้ใช้แบบอ่านอย่างเดียวอย่างแท้จริงด้วย PostgreSQL 9.0+ ให้รันขั้นตอนต่อไปนี้:

# This will prevent default users from creating tables
REVOKE CREATE ON SCHEMA public FROM public;

# If you want to grant a write user permission to create tables
# note that superusers will always be able to create tables anyway
GRANT CREATE ON SCHEMA public to writeuser;

# Now create the read-only user
CREATE ROLE readonlyuser WITH LOGIN ENCRYPTED PASSWORD 'strongpassword';
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonlyuser;

หากผู้ใช้แบบอ่านอย่างเดียวของคุณไม่มีสิทธิ์ในการแสดงรายการตาราง (เช่น\dไม่มีผลลัพธ์) อาจเป็นเพราะคุณไม่มีUSAGEสิทธิ์สำหรับสคีมา USAGEเป็นสิทธิ์ที่อนุญาตให้ผู้ใช้ใช้สิทธิ์ที่ได้รับมอบหมาย ประเด็นนี้คืออะไร? ฉันไม่แน่ใจ. เพื่อแก้ไข:

# You can either grant USAGE to everyone
GRANT USAGE ON SCHEMA public TO public;

# Or grant it just to your read only user
GRANT USAGE ON SCHEMA public TO readonlyuser;

8

ฉันได้สร้างสคริปต์ที่สะดวกสำหรับสิ่งนั้น pg_grant_read_to_db.sh สคริปต์นี้ให้สิทธิ์แบบอ่านอย่างเดียวแก่บทบาทที่ระบุในตารางมุมมองและลำดับทั้งหมดในสคีมาฐานข้อมูลและตั้งค่าให้เป็นค่าเริ่มต้น


4

ฉันอ่านวิธีแก้ปัญหาที่เป็นไปได้ทั้งหมดซึ่งเป็นเรื่องปกติถ้าคุณจำการเชื่อมต่อกับฐานข้อมูลก่อนที่คุณจะให้สิ่งต่าง ๆ ;) ขอบคุณไปยังโซลูชันอื่น ๆ ทั้งหมด !!!

user@server:~$ sudo su - postgres

สร้างผู้ใช้ psql:

postgres@server:~$ createuser --interactive 
Enter name of role to add: readonly
Shall the new role be a superuser? (y/n) n
Shall the new role be allowed to create databases? (y/n) n
Shall the new role be allowed to create more new roles? (y/n) n

เริ่ม psql cli และตั้งรหัสผ่านสำหรับผู้ใช้ที่สร้าง:

postgres@server:~$ psql
psql (10.6 (Ubuntu 10.6-0ubuntu0.18.04.1), server 9.5.14)
Type "help" for help.

postgres=# alter user readonly with password 'readonly';
ALTER ROLE

เชื่อมต่อกับฐานข้อมูลเป้าหมาย:

postgres=# \c target_database 
psql (10.6 (Ubuntu 10.6-0ubuntu0.18.04.1), server 9.5.14)
You are now connected to database "target_database" as user "postgres".

ให้สิทธิ์ที่จำเป็นทั้งหมด:

target_database=# GRANT CONNECT ON DATABASE target_database TO readonly;
GRANT

target_database=# GRANT USAGE ON SCHEMA public TO readonly ;
GRANT

target_database=# GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly ;
GRANT

เปลี่ยนสิทธิ์เริ่มต้นสำหรับเป้าหมาย db public shema:

target_database=# ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO readonly;
ALTER DEFAULT PRIVILEGES

3

หากฐานข้อมูลของคุณอยู่ในสคีมาสาธารณะจะเป็นเรื่องง่าย (ถือว่าคุณได้สร้างไว้แล้วreadonlyuser)

db=> GRANT SELECT ON ALL TABLES IN SCHEMA public to readonlyuser;
GRANT
db=> GRANT CONNECT ON DATABASE mydatabase to readonlyuser;
GRANT
db=> GRANT SELECT ON ALL SEQUENCES IN SCHEMA public to readonlyuser;
GRANT

หากฐานข้อมูลของคุณกำลังใช้งานcustomschemaให้ดำเนินการด้านบน แต่เพิ่มคำสั่งอีกหนึ่งคำสั่ง:

db=> ALTER USER readonlyuser SET search_path=customschema, public;
ALTER ROLE

1

วิธีที่ไม่ตรงไปตรงมาในการทำคือเลือกให้กับแต่ละตารางของฐานข้อมูล:

postgres=# grant select on db_name.table_name to read_only_user;

คุณสามารถทำให้เป็นแบบอัตโนมัติได้โดยสร้างคำสั่งการอนุญาตจาก metadata ฐานข้อมูล



0

นำมาจากลิงก์ที่โพสต์เพื่อตอบสนองต่อdespesz 'ลิงก์

Postgres 9.x มีความสามารถในการทำสิ่งที่ร้องขอ ดูย่อหน้า Grant On Database Objects ของ:

http://www.postgresql.org/docs/current/interactive/sql-grant.html

ที่กล่าวว่า: "นอกจากนี้ยังมีตัวเลือกในการให้สิทธิ์กับวัตถุทั้งหมดที่เป็นประเภทเดียวกันภายในหนึ่งหรือมากกว่า schemas ขณะนี้ฟังก์ชั่นนี้ได้รับการสนับสนุนเฉพาะสำหรับตารางลำดับและฟังก์ชั่น (แต่โปรดทราบว่าตารางทั้งหมด และตารางต่างประเทศ) "

หน้านี้ยังกล่าวถึงการใช้บทบาทและสิทธิพิเศษที่เรียกว่า "สิทธิพิเศษทั้งหมด"

นอกจากนี้ยังมีข้อมูลเกี่ยวกับฟังก์ชัน GRANT ที่เปรียบเทียบกับมาตรฐาน SQL

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