如何在数据库和架构上管理用户的默认权限?

Jim*_*nis 59 postgresql database-design permissions

我想将一个相当简单的、内部的、数据库驱动的应用程序从 SQLite3 迁移到 PostgreSQL 9.3,并在执行过程中收紧数据库中的权限。

该应用程序当前包含一个用于更新数据的命令;和一个查询它。当然,我还需要以其他方式维护数据库(创建新表、视图、触发器等)。

虽然此应用程序一开始将是唯一托管在服务器上的应用程序,但我更愿意假设它将来可能会托管在具有其他数据库的服务器上,而不是在以后有必要时进行争夺未来。

我认为这些将是一组相当常见的要求,但我很难找到一个简单的教程来解释如何在 PostgreSQL 中设置一个新数据库,并使用这种用户/权限分离。参考资料详细介绍了组、用户、角色、数据库、模式和域;但我觉得他们很困惑。

这是我到目前为止尝试过的(从内部psql作为“postgres”):

CREATE DATABASE hostdb;
REVOKE ALL ON DATABASE hostdb FROM public;
\connect hostdb
CREATE SCHEMA hostdb;
CREATE USER hostdb_admin WITH PASSWORD 'youwish';
CREATE USER hostdb_mgr   WITH PASSWORD 'youwish2';
CREATE USER hostdb_usr WITH PASSWORD 'youwish3';

GRANT ALL PRIVILEGES ON DATABASE hostdb TO hostdb_admin;
GRANT CONNECT ON DATABASE hostdb TO hostdb_mgr, hostdb_usr;
ALTER DEFAULT PRIVILEGES IN SCHEMA hostdb GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO hostdb_mgr;
ALTER DEFAULT PRIVILEGES IN SCHEMA hostdb GRANT SELECT ON TABLES TO hostdb_usr;
Run Code Online (Sandbox Code Playgroud)

但我没有得到预期的语义。我想对其进行配置,以便只有hostdb_admin可以创建(以及删除和更改)表;在hostdb_mgr可以读取,插入,更新和删除默认情况下,所有表; 并且hostdb_usr只能读取所有表(和视图)。

当我尝试这个时,我发现我能够以hostdb这些用户中的任何一个创建表;但是,对于每个用户,我只能读取或修改该用户创建的表 - 除非我使用显式GRANT.

我猜有什么东西之间缺少CREATE DATABASECREATE SCHEMA,东西应用SCHEMADATABASE

(随着事情变得更先进,我也会有问题要对TRIGGERS、存储过程VIEWS和其他对象应用类似的限制)。

我在哪里可以找到有关这方面的体面指南、教程或视频系列?

Erw*_*ter 111

我在哪里可以找到有关这方面的体面指南、教程或视频系列?

您会在手册中找到所有内容。链接如下。
当然,这件事并非微不足道,有时甚至令人困惑。这是用例的配方:

食谱

我想对其进行配置,以便只有hostdb_admin可以创建(以及删除和更改)表;
hostdb_mgr可以读取,插入,更新和删除默认情况下,所有表;
并且hostdb_usr只能读取所有表(和视图)。

作为超级用户postgres

CREATE USER schma_admin WITH PASSWORD 'youwish';
-- CREATE USER schma_admin WITH PASSWORD 'youwish' CREATEDB CREATEROLE; -- see below
CREATE USER schma_mgr   WITH PASSWORD 'youwish2';
CREATE USER schma_usr   WITH PASSWORD 'youwish3';
Run Code Online (Sandbox Code Playgroud)

如果你想要一个更强大的管理员,也可以管理数据库和角色,添加角色属性CREATEDBCREATEROLE以上。

将每个角色授予下一个更高级别,因此所有级别至少从下一个较低级别(级联)“继承”一组特权:

GRANT schma_usr TO schma_mgr;
GRANT schma_mgr TO schma_admin;

CREATE DATABASE hostdb;
REVOKE ALL ON DATABASE hostdb FROM public;  -- see notes below!

GRANT CONNECT ON DATABASE hostdb TO schma_usr;  -- others inherit

\connect hostdb  -- psql syntax
Run Code Online (Sandbox Code Playgroud)

我正在命名模式schma(不会hostdb令人困惑)。随便选一个名字。(可选)使schma_admin架构的所有者:

CREATE SCHEMA schma AUTHORIZATION schma_admin;

SET search_path = schma;  -- see notes

ALTER ROLE schma_admin IN DATABASE hostdb SET search_path = schma; -- not inherited
ALTER ROLE schma_mgr   IN DATABASE hostdb SET search_path = schma;
ALTER ROLE schma_usr   IN DATABASE hostdb SET search_path = schma;

GRANT USAGE  ON SCHEMA schma TO schma_usr;
GRANT CREATE ON SCHEMA schma TO schma_admin;

ALTER DEFAULT PRIVILEGES FOR ROLE schma_admin
GRANT SELECT                           ON TABLES TO schma_usr;  -- only read

ALTER DEFAULT PRIVILEGES FOR ROLE schma_admin
GRANT INSERT, UPDATE, DELETE, TRUNCATE ON TABLES TO schma_mgr;  -- + write, TRUNCATE optional

ALTER DEFAULT PRIVILEGES FOR ROLE schma_admin
GRANT USAGE, SELECT, UPDATE ON SEQUENCES TO schma_mgr;  -- SELECT, UPDATE are optional 
Run Code Online (Sandbox Code Playgroud)

对于and drop and alter下面笔记。

Postgres 14添加了预定义的非登录角色,pg_read_all_datapg_write_all_data为所有模式中的所有对象提供只读/只写访问权限。这超出了这里的要求,但可能有用。看:


随着事情变得更先进,我也会有问题要对TRIGGERS、存储过程VIEWS和其他对象应用类似的限制。

景色很特别。其中之一:

...(但请注意,这ALL TABLES被认为包括视图和外部表)。

对于可更新视图

请注意,对视图执行插入、更新或删除操作的用户必须对视图具有相应的插入、更新或删除权限。此外,视图的所有者必须具有底层基础关系的相关权限,但执行更新的用户不需要底层基础关系的任何权限(参见 第 38.5 节)。

触发器也很特别。您需要在TRIGGER桌子上的特权,并且:

But we are already over-expanding the scope of this question ...

Important Notes

Ownership

If you want to allow schma_admin (alone) to drop and alter tables, make the role own all objects. The documentation:

The right to drop an object, or to alter its definition in any way, is not treated as a grantable privilege; it is inherent in the owner, and cannot be granted or revoked. (However, a similar effect can be obtained by granting or revoking membership in the role that owns the object; see below.) The owner implicitly has all grant options for the object, too.

ALTER TABLE some_tbl OWNER TO schma_admin;
Run Code Online (Sandbox Code Playgroud)

Or create all objects with the role schma_admin to begin with, then you need not set the owner explicitly. It also simplifies default privileges, which you then only have to set for the one role:

Pre-existing objects

Default privileges only apply for newly created objects and only for the particular role they are created with. You'll want to adapt permissions for existing objects, too:

The same applies if you create objects with a role that does not have DEFAULT PRIVILEGES set, like the superuser postgres. Reassign ownership to schma_admin and set privileges manually - or set DEFAULT PRIVILEGES for postgres as well (while connected to the right DB!):

ALTER DEFAULT PRIVILEGES FOR ROLE postgres GRANT ...  -- etc.
Run Code Online (Sandbox Code Playgroud)

Default privileges

You were missing an important aspect of the ALTER DEFAULT PRIVILEGES command. It applies to the current role unless specified otherwise:

Default privileges only apply to the current database. So you don't mess with other databases in the DB cluster. The documentation:

for all objects created in the current database

You may also want to set default privileges for FUNCTIONS and TYPES (not just TABLES and SEQUENCES), but those might not be needed.

Default privileges for PUBLIC

Default privileges granted to PUBLIC are rudimentary and overestimated by some. The documentation:

PostgreSQL grants default privileges on some types of objects to PUBLIC. No privileges are granted to PUBLIC by default on tables, columns, schemas or tablespaces. For other types, the default privileges granted to PUBLIC are as follows: CONNECT and CREATE TEMP TABLE for databases; EXECUTE privilege for functions; and USAGE privilege for languages.

Bold emphasis mine. typically the one command above is enough to cover everything:

REVOKE ALL ON DATABASE hostdb FROM public;
Run Code Online (Sandbox Code Playgroud)

In particular, no default privileges are granted to PUBLIC for new schemas. It may be confusing that the default schema named "public" starts with ALL privileges for PUBLIC. That's just a convenience feature to ease the start with newly created databases. It does not affect other schemas in any way. You can revoke these privileges in the template database template1, then all newly created databases in this cluster start without them:

\connect template1
REVOKE ALL ON SCHEMA public FROM public;
Run Code Online (Sandbox Code Playgroud)

The privilege TEMP

Since we revoked all privileges on hostdb from PUBLIC, regular users cannot create temporary tables unless we explicitly allow it. You may or may not want to add this:

GRANT TEMP ON DATABASE hostdb TO schma_mgr;
Run Code Online (Sandbox Code Playgroud)

search_path

不要忘记设置search_path. 如果集群中只有一个数据库,则只需在postgresql.conf. 否则(更有可能)将其设置为数据库的属性,或者仅用于涉及的角色,甚至是两者的组合。细节:

schma, public如果您也使用公共模式,您可能希望将其设置为,或者甚至(不太可能)$user, schma, public...

另一种方法是使用默认模式“public”,search_path除非您更改它,否则该模式应该与默认设置一起使用。PUBLIC在这种情况下,请记住撤销权限。

有关的