Tại sao người dùng mới được phép tạo bảng?


41

Tôi đang tự hỏi tại sao một người dùng mới được tạo lại được phép tạo bảng sau khi kết nối với cơ sở dữ liệu. Tôi có một cơ sở dữ liệu , project2_core:

postgres=# \l
                                          List of databases
     Name      |    Owner     | Encoding  |   Collate   |    Ctype    |       Access privileges       
---------------+--------------+-----------+-------------+-------------+-------------------------------
 postgres      | postgres     | SQL_ASCII | C           | C           | 
 project2_core | atm_project2 | UTF8      | de_DE.UTF-8 | de_DE.UTF-8 | project2=CTc/project2
 template0     | postgres     | SQL_ASCII | C           | C           | =c/postgres                  +
               |              |           |             |             | postgres=CTc/postgres
 template1     | postgres     | SQL_ASCII | C           | C           | =c/postgres                  +
               |              |           |             |             | postgres=CTc/postgres
(5 rows)

Càng xa càng tốt. Bây giờ tôi tạo một người dùng:

postgres=# CREATE ROLE dietrich ENCRYPTED PASSWORD 'md5XXX' LOGIN NOCREATEROLE NOCREATEDB NOSUPERUSER

Được chứ. Khi tôi cố gắng kết nối với cơ sở dữ liệu, người dùng không được phép làm như vậy:

$ psql -h localhost -p 5432 -U dietrich -W project2_core
Password for user dietrich: 
psql: FATAL:  permission denied for database "project2_core"
DETAIL:  User does not have CONNECT privilege.

Đây là những gì tôi mong đợi. Bây giờ những thứ kỳ lạ bắt đầu. Tôi cấp cho người dùng CONNECT:

postgres=# GRANT CONNECT ON DATABASE project2_core TO dietrich;
GRANT
postgres=# \l
                                          List of databases
     Name      |    Owner     | Encoding  |   Collate   |    Ctype    |       Access privileges       
---------------+--------------+-----------+-------------+-------------+-------------------------------
 postgres      | postgres     | SQL_ASCII | C           | C           | 
 project2_core | atm_project2 | UTF8      | de_DE.UTF-8 | de_DE.UTF-8 | project2=CTc/project2+
               |              |           |             |             | dietrich=c/project2
 template0     | postgres     | SQL_ASCII | C           | C           | =c/postgres                  +
               |              |           |             |             | postgres=CTc/postgres
 template1     | postgres     | SQL_ASCII | C           | C           | =c/postgres                  +
               |              |           |             |             | postgres=CTc/postgres
(5 rows)

Và không cần thêm bất kỳ khoản tài trợ nào, người dùng được phép tạo bảng:

$ psql -h localhost -p 5432 -U dietrich -W project2_core
Password for user dietrich: 
psql (9.2.3)
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)
Type "help" for help.

project2_core=> create table adsf ();
CREATE TABLE
project2_core=> \d
        List of relations
 Schema | Name | Type  |  Owner   
--------+------+-------+----------
 public | adsf | table | dietrich
(1 row)

Tôi đã dự kiến ​​rằng người dùng không được phép làm bất cứ điều gì trước khi tôi làm rõ ràng GRANT USAGEtrên lược đồ và sau đó GRANT SELECTtrên các bảng.

Lỗi của tôi ở đâu? Tôi đang làm gì sai? Làm cách nào tôi có thể đạt được những gì tôi muốn (rằng người dùng mới không được phép làm bất cứ điều gì trước khi cấp cho cô ấy các quyền thích hợp một cách rõ ràng.

Tôi bị lạc, và sự giúp đỡ của bạn được đánh giá rất cao :)

EDIT Theo lời khuyên của @ daniel-verite, bây giờ tôi sẽ thu hồi tất cả ngay sau khi tạo cơ sở dữ liệu. Người ăn kiêng không được phép tạo bảng nữa. Tốt NHƯNG : Bây giờ, cũng là chủ sở hữu của cơ sở dữ liệu, project2 , không được phép tạo bảng. Ngay cả sau khi phát hành GRANT ALL PRIVILEGES ON DATABASE project2_core TO project2GRANT ALL PRIVILEGES ON SCHEMA public TO project2, tôi vẫn gặp lỗi LRI: không có lược đồ nào được chọn để tạo và khi tôi cố gắng cụ thể CREATE TABLE public.WHATEVER ();, tôi nhận được ERROR: quyền bị từ chối đối với lược đồ công khai . Tôi đang làm gì sai?

Câu trả lời:


38

Khi bạn tạo một cơ sở dữ liệu mới, bất kỳ vai trò nào cũng được phép tạo các đối tượng trong publiclược đồ. Để loại bỏ khả năng này, bạn có thể phát hành ngay sau khi tạo cơ sở dữ liệu:

REVOKE ALL ON schema public FROM public;

Chỉnh sửa: sau lệnh trên, chỉ một siêu người dùng có thể tạo các đối tượng mới bên trong publiclược đồ, điều này không thực tế. Giả sử một người không phải là siêu người dùng foo_usernên được cấp đặc quyền này, điều này nên được thực hiện với:

GRANT ALL ON schema public TO foo_user;

Để biết ý ALLnghĩa của lược đồ, chúng ta phải tham khảo GRANT trong tài liệu , (trong PG 9.2, có không dưới 14 dạng câu lệnh GRANT áp dụng cho những thứ khác nhau ...). Dường như đối với một lược đồ có nghĩa là CREATEUSAGE.

Mặt khác, GRANT ALL PRIVILEGES ON DATABASE...sẽ cấp CONNECTCREATETEMP, nhưng CREATEtrong bối cảnh này liên quan đến schemas, không bảng vĩnh viễn.

Liên quan đến lỗi này : ERROR: no schema has been selected to create in, nó xảy ra khi cố gắng tạo một đối tượng không có đủ điều kiện lược đồ (như trong create table foo(...)) trong khi thiếu quyền tạo nó trong bất kỳ lược đồ nào của search_path.


hoạt động :) Nhưng tôi vẫn không hiểu: Tôi đã thử REVOKE ALL ON DATABASE project2_core FROM PUBLIC;. Tại sao điều này không có tác dụng?
andreas-h

mhh bây giờ chủ sở hữu của cơ sở dữ liệu không được phép CREATE TABLEnữa. xem chỉnh sửa của tôi ở trên.
andreas-h

@ andreas-h: chỉnh sửa câu trả lời với nhiều chi tiết hơn
Daniel Vérité

Liên quan đến lỗi, có thể dễ dàng sao chép bằng cách đưa ra các lệnh từ câu hỏi và REVOKE của bạn theo thứ tự :)
dezso

@ DanielVérité Tôi đã xây dựng các khái niệm đằng sau câu trả lời mới này để bổ sung cho bạn. Một kiểm tra vệ sinh sẽ có giá trị.
Craig Ringer

19

Điều cốt yếu cần hiểu ở đây là các đặc quyền không phải là gia truyềnkhông được kế thừa từ việc chứa các đối tượng . ALLcó nghĩa là tất cả các đặc quyền cho đối tượng này không phải tất cả các đặc quyền cho đối tượng này và tất cả các đối tượng được chứa .

Khi bạn cấp ALLtrên cơ sở dữ liệu, bạn đang cấp CREATE, CONNECT, TEMP. Đây là những hành động trên cơ sở dữ liệu đối tượng tự:

  • CONNECT: Kết nối với DB
  • CREATE: Tạo một lược đồ ( không phải bảng)
  • TEMP: Tạo các đối tượng tạm thời, bao gồm nhưng không giới hạn ở các bảng tạm thời

Bây giờ, mỗi cơ sở dữ liệu PostgreQuery theo mặc định có một publiclược đồ được tạo khi cơ sở dữ liệu được tạo. Lược đồ này có tất cả các quyền được cấp cho vai trò public, trong đó mọi người đều mặc nhiên là thành viên. Đối với một lược đồ, ALLcó nghĩa là CREATE, USAGE:

  • CREATE: Tạo các đối tượng (bao gồm các bảng) trong lược đồ này
  • USAGE: Liệt kê các đối tượng trong lược đồ và truy cập chúng nếu quyền của chúng cho phép

Nếu bạn không chỉ định lược đồ để tạo một đối tượng như bảng, thì công cụ cơ sở dữ liệu sẽ sử dụng search_pathvà theo mặc định, publiclược đồ là đầu tiên trên bảng search_pathđể bảng được tạo ở đó. Mọi người đều có quyền publictheo mặc định, vì vậy việc tạo được cho phép. Tại thời điểm này, quyền của người dùng không liên quan, vì người dùng không cố gắng làm bất cứ điều gì với đối tượng cơ sở dữ liệu, chỉ là một lược đồ trong đó.

Không có vấn đề gì khi bạn không cấp cho người dùng bất kỳ quyền nào ngoài việc cấp CONNECTtrên cơ sở dữ liệu, vì publiclược đồ cho phép tất cả người dùng tạo các bảng trong đó theo mặc định. Daniel đã giải thích làm thế nào để thu hồi quyền đó nếu muốn.

Nếu bạn muốn ủy quyền mọi quyền một cách rõ ràng, hãy thu hồi tất cả từ công khai hoặc đơn giản là bỏ lược đồ công khai. Bạn có thể tạo cơ sở dữ liệu mẫu mới với thay đổi này được áp dụng nếu bạn muốn. Thay phiên, bạn có thể áp dụng nó template1, nhưng điều đó có thể sẽ phá vỡ rất nhiều mã của bên thứ 3 giả định rằng nó publictồn tại và có thể ghi được.


Điều này có thể có ý nghĩa hơn nếu bạn nhìn vào một sự tương tự hệ thống tập tin.

Nếu tôi có cấu trúc thư mục (chế độ được đơn giản hóa để chỉ hiển thị chế độ áp dụng cho người dùng hiện tại):

/dir1           mode=r-x
/dir1/dir2      mode=rwx

sau đó tôi không thể tạo bất cứ thứ gì trong đó /dir1, vì tôi không có quyền viết. Vì vậy, nếu tôi touch /dir1/somefilesẽ nhận được một quyền từ chối lỗi.

Tuy nhiên, tôi làm được phép nhìn vào bên trong /dir1và truy cập chứa các file và thư mục, bao gồm /dir1/dir2. Tôi có quyền viết trên dir2. Vì vậy, touch /dir1/dir2/somefilesẽ thành công , mặc dù tôi không có quyền viết thư dir1.

Điều tương tự với cơ sở dữ liệu và lược đồ.


7

Nếu bạn chỉ muốn ngăn người dùng mới tạo bảng, bạn cần chạy lệnh sau:

REVOKE CREATE ON SCHEMA public FROM public;

Nếu bạn REVOKE ALL(như các câu trả lời khác đề xuất), bạn cũng sẽ ngăn người dùng có USAGEquyền. USAGEcó nghĩa là người dùng có thể sử dụng các quyền được gán cho họ, vì vậy nếu bạn xóa điều đó thì người dùng của bạn sẽ không thể liệt kê hoặc truy cập các bảng mà họ có quyền truy cập.

Ngoài ra, bạn cũng có thể REVOKE CREATEcho một người dùng cụ thể:

REVOKE CREATE ON schema public FROM myuser;

Xem thêm: Cách tạo người dùng chỉ đọc với PostgreSQL .

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.