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

我猜测GRANTCREATE DATABASE之间缺少某些内容,可以应用CREATE SCHEMASCHEMA吗?

(随着事情的发展,我也将对DATABASE,存储过程,TRIGGERS以及其他对象施加类似的限制)。

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

评论

我认为(至少是一部分)问题在于公共伪角色。可以将所有其他角色(用户,组-这些都是相同的)视为成员。尝试从中删除特权,例如,通过public撤销对SCHEMA hostdb的创建。与您一样,撤销数据库级别的权限只会禁用某些数据库级别的权限,而不会影响架构或表。

@dezso:关于模式的默认特权,可能存在误解。只有默认模式public恰好带有PUBLIC的特权。除此之外,新架构没有默认权限。因此,这不会影响演示的用例。请参阅答案中的章节。

#1 楼


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


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

食谱


我想要对其进行配置,以便只有hostdb_admin可以创建
(并删除和alter)表;
默认情况下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特权,并且:


在PostgreSQL 8.4中执行触发器函数需要什么特权?

但是我们已经结束了-扩大此问题的范围...

重要说明

所有权

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


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


ALTER TABLE some_tbl OWNER TO schma_admin;


或创建所有角色为schma_admin的对象,那么您无需设置明确的所有者。它还简化了默认特权,您只需为一个角色设置即可:

预先存在的对象

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


关系

的权限被拒绝如果您创建具有角色的对象,则同样适用没有设置DEFAULT PRIVILEGES的用户,例如超级用户postgres。将所有权重新分配给schma_admin并手动设置权限-或也为DEFAULT PRIVILEGES设置postgres(在连接到正确的DB时!): br />您错过了ALTER DEFAULT PRIVILEGES命令的重要方面。除非另有说明,否则它适用于当前角色:


不能更改默认特权

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




您可能还希望为FUNCTIONSTYPES(不仅是TABLESSEQUENCES)设置默认特权,但要设置这些特权可能不需要。

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


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


我的字体加粗。通常,上面的一个命令足以覆盖所有内容:

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


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

REVOKE ALL ON DATABASE hostdb FROM public;


特权template1


由于我们从TEMP撤消了对hostdb的所有特权,因此除非我们明确允许,否则普通用户无法创建临时表。您可能想要也可能不想添加:

\connect template1
REVOKE ALL ON SCHEMA public FROM public;


PUBLIC

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


search_path对标识符解析和“当前模式”有何影响?

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

替代方法是使用默认模式“公共”,该模式应与$user, schma, public的默认设置一起使用,除非您进行了更改。在这种情况下,请记住撤销search_path的特权。

相关的


PostgreSQL中特定数据库的授予特权
PostgreSQL-DB用户仅应允许调用函数


评论


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

–丹尼斯·马塔福诺夫(Denis Matafonov)
18年2月18日在14:26

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

–欧文·布兰德斯特(Erwin Brandstetter)
18年2月18日在14:30

是的,超级用户拥有所有访问权限,但是您不能概括其默认权限。为架构中的角色设置默认特权,并让这些默认设置应用于该角色的所有成员在他们在架构中创建表时,将非常好。例如,要说“确保由工程团队中的任何人在此架构中创建的任何表都可以被报告团队中的任何人读取”。简而言之,我希望表创建角色的成员继承其默认权限。

–组合主义者
19-09-19在21:25

最近发表