如何在DATABASE vs SCHEMA上为用户管理默认特权?


48

我想将一个相当简单的内部数据库驱动的应用程序从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;

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

当我尝试此操作时,我发现我可以hostdb像这些用户一样创建表。但是,对于每个用户,我只能读取或修改该用户创建的表-除非我使用explicit GRANT

我猜,还有的之间失去了一些东西CREATE DATABASECREATE SCHEMA,东西应用SCHEMADATABASE

(随着事情的发展,我还将对将类似的限制应用于TRIGGERS,存储过程VIEWS以及其他对象提出疑问)。

在哪里可以找到合适的指南,教程或视频系列?


2
我认为(至少是一部分)问题在于public假角色。可以将所有其他角色(用户,组-这些都是相同的)视为成员。尝试通过例如删除特权REVOKE CREATE ON SCHEMA hostdb FROM public。与您一样,撤销数据库级别的权限仅会禁用某些数据库级别的权限,而不会影响架构或表。
dezso 2015年

@dezso:关于模式的默认特权,可能会有误解。只有默认模式public与一起提供PUBLIC。除此之外,新架构没有默认权限。因此,这不会影响演示的用例。请参阅我的答案中的章节。
Erwin Brandstetter,2015年

Answers:


86

在哪里可以找到合适的指南,教程或视频系列?

您将在手册中找到所有内容。下面的链接。
当然,这不是一件小事,有时会造成混乱。这是用例的配方:

食谱

我想对其进行配置,以便只有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';

如果您想要一个功能更强大的管理员,该管理员还可以管理数据库和角色,请添加角色属性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

我正在命名架构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 

有关详细信息,and drop and alter请参见以下注释。

随着事情的发展,我还将对在TRIGGERS,存储过程VIEWS以及其他对象上施加类似的限制提出疑问。

意见很特别。对于一个:

...(但请注意,该ALL TABLES视图包括视图和外部表)。

对于可更新的视图

请注意,在视图上执行插入,更新或删除的用户必须在视图上具有相应的插入,更新或删除特权。另外,视图的所有者必须对基础基本关系具有相关的特权,但是执行更新的用户不需要对基础基本关系的任何许可(请参阅 第38.5节)。

触发器也很特殊。您需要TRIGGER表上的特权,并且:

但是我们已经过度扩大了这个问题的范围...

重要笔记

所有权

如果要允许schma_admin(单独)删除和更改表,请让角色拥有所有对象。文档:

删除对象或以任何方式更改其定义的权利不视为可授予的特权;它是所有者固有的,不能被授予或撤销。(但是,通过授予或撤消拥有对象的角色的成员资格,可以获得类似的效果;请参见下文。)所有者也隐式拥有该对象的所有授予选项。

ALTER TABLE some_tbl OWNER TO schma_admin;

以角色schma_admin开始创建所有对象,然后无需显式设置所有者。它还简化了默认权限,您只需为一个角色设置即可:

预先存在的对象

默认特权仅适用于新创建的对象,并且仅适用于使用它们创建的特定角色。您还需要调整现有对象的权限:

如果创建的对象没有DEFAULT PRIVILEGES设置角色(例如superuser),则同样适用postgres。重新分配所有权schma_admin,并手动设置权限-或者设置DEFAULT PRIVILEGESpostgres和:(同时连接到正确的DB!)

ALTER DEFAULT PRIVILEGES FOR ROLE postgres GRANT ...  -- etc.

默认权限

您缺少该ALTER DEFAULT PRIVILEGES命令的重要方面。除非另有说明,否则它适用于当前角色:

默认特权仅适用于当前数据库。因此,您不会与数据库集群中的其他数据库混淆。文档:

对于当前数据库中创建的所有对象

可能还想为FUNCTIONS和设置默认特权TYPES(不只是TABLESSEQUENCES),但是可能不需要这些特权。

的默认权限 PUBLIC

授予的默认特权PUBLIC是基本的,并且被某些人高估了。文档:

PostgreSQL授予某些对象类型的默认特权 PUBLIC默认情况下,对表,列,模式或表空间不授予任何特权PUBLIC对于其他类型,默认权限授予PUBLIC如下:CONNECTCREATE TEMP TABLE为数据库; EXECUTE功能特权;和USAGE 语言特权。

大胆强调我的。通常,上面的一个命令足以覆盖所有内容:

REVOKE ALL ON DATABASE hostdb FROM public;

特别是,不会PUBLIC为新架构授予默认权限。名为“ public”的默认模式以的ALL特权开头可能会造成混淆PUBLIC。这只是一个便利功能,可以简化新创建数据库的入门。它不会以任何方式影响其他架构。您可以在模板数据库中撤消这些特权template1,然后在没有它们的情况下启动该集群中所有新创建的数据库:

\connect template1
REVOKE ALL ON SCHEMA public FROM public;

特权 TEMP

由于我们对撤销所有权限hostdbPUBLIC,普通用户无法创建临时表,除非我们明确地允许它。您可能想要也可能不想添加:

GRANT TEMP ON DATABASE hostdb TO schma_mgr;

search_path

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

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

另一种选择是使用默认模式“ public”,该模式应与默认设置一起使用,search_path除非您更改了默认设置。PUBLIC在这种情况下,请记住撤销特权。

有关


我正在搜索如何向新创建的超级用户添加默认管理权限,因此无需在每个表上都给他附加权限。我发现了这个。而且this看起来确实像是太空飞船的指令...
Denis Matafonov

@DenisMatafonov:超级用户自动拥有所有特权。我建议您以案情开始一个新的问题。评论不是地方。您可以始终链接到相关问题/答案以获取上下文。
Erwin Brandstetter

是的,超级用户具有所有访问权限,但是您不能概括其默认权限。为架构中的角色设置默认特权,并让这些默认设置应用于该角色的所有成员在架构中创建表时,将非常好。例如,说“确保由工程团队中的任何人在此架构中创建的任何表都可以被报告团队中的任何人读取”。简而言之,我希望表创建角色的成员继承其默认权限。
combinatorist
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.