Làm thế nào để bạn tạo một người dùng chỉ đọc trong PostgreSQL?


420

Tôi muốn tạo một người dùng trong PostgreSQL chỉ có thể thực hiện CHỌN từ một cơ sở dữ liệu cụ thể. Trong MySQL, lệnh sẽ là:

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

Lệnh hoặc chuỗi lệnh tương đương trong PostgreSQL là gì?

Tôi đã thử ...

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

Nhưng có vẻ như những thứ duy nhất bạn có thể cấp trên cơ sở dữ liệu là CREATE, CONNECT, TEMPORARY và TEMP.

Câu trả lời:


641

Cấp quyền sử dụng / chọn vào một bảng duy nhất

Nếu bạn chỉ cấp CONNECT cho cơ sở dữ liệu, người dùng có thể kết nối nhưng không có đặc quyền nào khác. Bạn phải cấp USAGE trên các không gian tên (lược đồ) và CHỌN trên các bảng và các khung nhìn riêng lẻ như vậy:

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;

Nhiều bảng / lượt xem (PostgreSQL 9.0+)

Trong các phiên bản mới nhất của PostgreSQL, bạn có thể cấp quyền trên tất cả các bảng / lượt xem / vv trong lược đồ bằng một lệnh duy nhất thay vì phải gõ từng cái một:

GRANT SELECT ON ALL TABLES IN SCHEMA public TO xxx;

Điều này chỉ ảnh hưởng đến các bảng đã được tạo. Mạnh mẽ hơn, bạn có thể tự động có các vai trò mặc định được gán cho các đối tượng mới trong tương lai:

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

Lưu ý rằng theo mặc định, điều này sẽ chỉ ảnh hưởng đến các đối tượng (bảng) được tạo bởi người dùng đã ban hành lệnh này: mặc dù nó cũng có thể được đặt trên bất kỳ vai trò nào mà người dùng phát hành là thành viên. Tuy nhiên, bạn không nhận các đặc quyền mặc định cho tất cả các vai trò mà bạn là thành viên khi tạo đối tượng mới ... vì vậy vẫn còn một số vấn đề xung quanh. Nếu bạn áp dụng cách tiếp cận mà cơ sở dữ liệu có vai trò sở hữu và các thay đổi lược đồ được thực hiện như vai trò sở hữu đó, thì bạn nên gán các đặc quyền mặc định cho vai trò sở hữu đó. IMHO điều này hơi khó hiểu và bạn có thể cần thử nghiệm để đưa ra quy trình làm việc chức năng.

Nhiều bảng / lượt xem (phiên bản PostgreSQL trước 9.0)

Để tránh các lỗi trong các thay đổi dài, nhiều bảng, nên sử dụng quy trình 'tự động' sau đây để tạo yêu cầu GRANT SELECTcho mỗi bảng / chế độ xem:

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

Điều này sẽ xuất các lệnh GRANT có liên quan thành GRANT CHỌN trên tất cả các bảng, dạng xem và trình tự ở chế độ công khai, cho tình yêu sao chép-dán. Đương nhiên, điều này sẽ chỉ được áp dụng cho các bảng đã được tạo.


22
Bạn nên đặt chỉnh sửa của mình liên quan đến PG9 ở đầu bài.
Danilo Bargen

5
Đẹp. Một điều tôi muốn nói thêm là bạn cũng có thể cần phải cho phép trình tự được đọc bởi người dùng này; vì vậy: GRANT CHỌN TRÊN TẤT CẢ CÁC YÊU CẦU TẠI SCHema công khai ĐẾN xxx;
JJC

26
Lưu ý rằng để ngăn người dùng này có thể tạo các bảng mới, tôi đã phải REVOKE CREATE ON SCHEMA public FROM PUBLIC;. Không có điều đó, người dùng "chỉ đọc" không thể sửa đổi các bảng hiện có, nhưng có thể tạo các bảng mới trong lược đồ và thêm / xóa dữ liệu khỏi các bảng đó.
Ajedi32

3
@ Ajedi32 Đây phải là một phần của câu trả lời được chấp nhận! Cảm ơn
Asfand Qazi

12
Đối với những người mới như tôi, tôi nghĩ rằng đáng để đề cập rằng bạn nên khởi động bàn điều khiển bằng cách psql mydbkhác, hầu hết các thao tác này sẽ không xảy ra. Cá nhân tôi đã mất một khoảng thời gian đáng kể để tự mình tìm ra nó. Hy vọng điều này sẽ giúp được ai đó.
Anass

41

Xin lưu ý rằng PostgreSQL 9.0 (ngày hôm nay trong bản thử nghiệm beta) sẽ có một cách đơn giản để làm điều đó :

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

3
Tôi đã phải ở trong cơ sở dữ liệu cụ thể để làm việc này. Postgresql 9.5.
dùng1158559

8
Điều này chỉ hoạt động cho các bảng hiện có trong lược đồ. Nếu người dùng ghi sau này tạo hoặc thay thế các bảng, người dùng chỉ đọc sẽ không có quyền truy cập vào chúng
anneb

33

Tham khảo lấy từ blog này:

Tập lệnh tạo người dùng chỉ đọc:

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

Gán quyền cho người dùng chỉ đọc này:

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;

Gán quyền để đọc tất cả các bảng mới được tạo trong tương lai

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

6
Đây là một câu trả lời rất hay trừ một điều còn thiếu: ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO Read_Only_User; cũng sẽ cho phép đọc tất cả các bảng được tạo trong cùng một DB trong tương lai.
Ravbaker

2
Thật bất thường khi cho phép người dùng chỉ đọc truy cập vào các chuỗi. Đọc trình tự cập nhật nó và chúng thường chỉ cần cho INSERTs.
jpmc26

Để đầy đủ, có thể thêm:GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA schema_name TO Read_Only_User;
Fabien Haddadi

@ jpmc26: điều đó có nghĩa là bạn khuyên dùng : GRANT ALL ON ALL SEQUENCES IN SCHEMA schema_name TO Read_Only_User?
Fabien Haddadi

@FabienHaddadi Điều đó có nghĩa là trừ khi bạn có một số yêu cầu thông thường, tôi không thấy cần phải cấp bất kỳ quyền nào trên chuỗi cho người dùng chỉ đọc.
jpmc26

24

Đây là cách tốt nhất mà tôi đã tìm thấy để thêm người dùng chỉ đọc (sử dụng PostgreSQL 9.0 trở lên):

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

Sau đó đăng nhập vào tất cả các máy liên quan (master + read-Slave (s) / hot-chờ (s), v.v.) và chạy:

$ 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
Tôi thích cách tiếp cận nhưng tôi cũng cần CẤP KẾT NỐI TRÊN CƠ SỞ [cơ sở dữ liệu] ĐẾN [người dùng hoặc vai trò]; và SỬ DỤNG GRANT TRÊN SCHema công khai ĐẾN [người dùng hoặc vai trò];
Ian Connor

1
Lược đồ công cộng vẫn cho phép người dùng như vậy tạo các bảng. Ngoài ra, các bảng mới không được bảo hiểm, cũng không phải là trình tự. Thật không may, điều này là khá phức tạp hơn một chút so với điều này. : - / Tôi sẽ đăng những gì tôi đã làm sau khi tôi xác nhận nó thêm một số.
JJC

Trong kịch bản trên của bạn, bạn đang cố gắng tạo vai trò hai lần. Tôi nghi ngờ rằng bạn có ý định sử dụng "ALTER ROLE ..." khi bật vai trò đăng nhập và đặt mật khẩu
Bogdan

Nếu bạn đã có người dùng, sau khi tạo vai trò chỉ đọc và cấp phép, hãy chọn perm cấp vai trò mới cho người dùng: GRANT chỉ đọc TO <USER>
gonz

18

Theo mặc định, người dùng mới sẽ có quyền tạo bảng. Nếu bạn đang dự định tạo một người dùng chỉ đọc, đây có thể không phải là điều bạn muốn.

Để tạo một người dùng chỉ đọc thực sự với PostgreSQL 9.0+, hãy chạy các bước sau:

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

Nếu người dùng chỉ đọc của bạn không có quyền liệt kê các bảng (nghĩa là \dkhông trả lại kết quả), thì đó có thể là do bạn không có USAGEquyền cho lược đồ. USAGElà một quyền cho phép người dùng thực sự sử dụng các quyền mà họ đã được chỉ định. Điểm này là gì? Tôi không chắc. Sửa chữa:

# 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

Tôi đã tạo một kịch bản thuận tiện cho việc đó; pg_grant_read_to_db.sh . Kịch bản lệnh này cấp các đặc quyền chỉ đọc cho một vai trò được chỉ định trên tất cả các bảng, dạng xem và chuỗi trong lược đồ cơ sở dữ liệu và đặt chúng làm mặc định.


4

Tôi đọc máng tất cả các giải pháp có thể, tất cả đều ổn, nếu bạn nhớ kết nối với cơ sở dữ liệu trước khi bạn cấp các thứ;) Dù sao cũng cảm ơn tất cả các giải pháp khác !!!

user@server:~$ sudo su - postgres

tạo người dùng 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

bắt đầu psql cli và đặt mật khẩu cho người dùng đã tạo:

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

kết nối với cơ sở dữ liệu đích:

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".

cấp tất cả các đặc quyền cần thiết:

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

thay đổi đặc quyền mặc định cho mục tiêu db shema công cộng:

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

3

Nếu cơ sở dữ liệu của bạn nằm trong lược đồ công khai, thật dễ dàng (điều này giả sử bạn đã tạo 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

Nếu cơ sở dữ liệu của bạn đang sử dụng customschema, hãy thực hiện như trên nhưng thêm một lệnh nữa:

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

1

Cách làm không đơn giản sẽ là cấp quyền chọn trên mỗi bảng của cơ sở dữ liệu:

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

Bạn có thể tự động hóa điều đó bằng cách tạo các báo cáo cấp của bạn từ siêu dữ liệu cơ sở dữ liệu.


1
CREATE USER username SUPERUSER  password 'userpass';
ALTER USER username set default_transaction_read_only = on;

0

Lấy từ một liên kết được đăng để phản hồi lại liên kết của despesz .

Postgres 9.x dường như có khả năng làm những gì được yêu cầu. Xem đoạn Grant On Database Object của:

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

Trong đó có ghi: "Ngoài ra còn có tùy chọn cấp đặc quyền cho tất cả các đối tượng cùng loại trong một hoặc nhiều lược đồ. Chức năng này hiện chỉ được hỗ trợ cho các bảng, trình tự và hàm (nhưng lưu ý rằng TABLES được coi là bao gồm các khung nhìn và bảng nước ngoài). "

Trang này cũng thảo luận về việc sử dụng ROLEs và RIÊNG TƯ gọi là "TẤT CẢ CÁC ƯU ĐÃI".

Cũng có mặt là thông tin về cách các chức năng GRANT so với các tiêu chuẩn SQL.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.