授予 PostgreSQL 中特定数据库的权限

Posted

技术标签:

【中文标题】授予 PostgreSQL 中特定数据库的权限【英文标题】:Grant privileges for a particular database in PostgreSQL 【发布时间】:2014-09-15 02:28:00 【问题描述】:

我正在从 mysql 迁移到 PostgreSQL,并且遇到了用户权限问题。我习惯于使用以下命令为用户分配数据库的所有表的所有权限:

# MySQL
grant all privileges on mydatabase.* to 'myuser'@'localhost' identified by 'mypassword';

在我看来,PostgreSQL 9.x 解决方案涉及将权限分配给“模式”,但我需要努力弄清楚要发出什么 SQL 证明是多余的。我知道再花几个小时的研究会得出一个答案,但我认为每个从 MySQL 迁移到 PostgreSQL 的人都可以受益于在 Web 上至少有一个页面提供简单而完整的配方。这是我需要为用户发出的唯一命令。我宁愿不必为每个新表发出命令。

我不知道在 PostgreSQL 中必须以不同的方式处理哪些场景,所以我将列出一些我过去通常必须处理的场景。假设我们只是想修改已经创建的单个数据库的权限。

(1a) 尚未创建所有表,或 (1b) 已创建表。

(2a) 用户尚未创建,或 (2b) 用户已创建。

(3a) 权限尚未分配给用户,或 (3b) 权限之前已分配给用户。

(4a) 用户只需要插入、更新、选择和删除行,或者 (4b) 用户还需要能够创建和删除表。

我已经看到了授予所有数据库所有权限的答案,但这不是我想要的。拜托,我正在寻找一个简单的食谱,虽然我也不介意解释。

我不想向所有用户和所有数据库授予权限,这似乎是传统的捷径,因为当任何一个用户受到威胁时,这种方法会危及所有数据库。我托管多个数据库客户端并为每个客户端分配不同的登录名。

看起来我还需要USAGE 权限来获取serial 列的递增值,但我必须按某种顺序授予它。我的问题变得更复杂了。

【问题讨论】:

我怀疑 PostgresQL 上用户权限的复杂性可能会严重阻碍更广泛的采用。 以下页面似乎授予用户对所有数据库的所有表的必要权限,而我只想授予对单个数据库的权限。 dba.stackexchange.com/questions/36870/… 【参考方案1】:

Postgres 中的基本概念

角色是可以访问数据库集群中所有数据库的全局对象 - 给定所需的权限。

一个集群包含许多数据库,其中包含许多模式。不同数据库中的模式(即使名称相同)是不相关的。为架构授予权限仅适用于当前数据库(授予时的当前数据库)中的此特定架构。

默认情况下,每个数据库都以架构 public 开头。这是一个约定,许多设置都是从​​它开始的。除此之外,架构public 只是一个和其他架构一样的架构。

来自 MySQL,您可能希望从单个架构 public 开始,有效地完全忽略架构层。我经常在每个数据库中使用几十个模式。 Schema 有点(但不完全)像文件系统中的目录。

一旦你使用了多个模式,一定要了解search_path设置:

How does the search_path influence identifier resolution and the "current schema"

默认权限

Per documentation on GRANT:

PostgreSQL 在某些类型的对象上授予默认权限以 PUBLICPUBLIC 默认不会在表上授予任何权限, 列、模式或表空间。对于其他类型,默认 授予PUBLIC 的权限如下:CONNECTCREATE TEMP TABLE 用于数据库; EXECUTE 函数特权;和USAGE 语言特权。

所有这些默认值都可以通过ALTER DEFAULT PRIVILEGES 进行更改:

Grant all on a specific schema in the db to a group role in PostgreSQL

组角色

Like @Craig commented,最好将GRANT 权限赋予一个组角色,然后使特定用户成为该角色的成员(GRANT 将组角色赋予用户角色)。这种方式更容易处理和撤销某些任务所需的特权包。

组角色只是另一个无需登录的角色。添加登录以将其转换为用户角色。更多:

Why did PostgreSQL merge users and groups into roles?

预定义角色

更新: Postgres 14 或更高版本添加了新的predefined roles(正式为“默认角色”)pg_read_all_datapg_write_all_data 以简化以下部分内容。见:

Grant access to all tables of a database

食谱

说,我们有一个新数据库mydb,一个组mygrp,和一个用户myusr ...

以超级用户身份连接到相关数据库时(例如postgres):

REVOKE ALL ON DATABASE mydb FROM public;  -- shut out the general public
GRANT CONNECT ON DATABASE mydb TO mygrp;  -- since we revoked from public

GRANT USAGE ON SCHEMA public TO mygrp;

像你写的那样分配“一个用户对所有表的所有权限”(我可能更严格):

GRANT ALL ON ALL TABLES IN SCHEMA public TO mygrp;
GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO mygrp; -- don't forget those

要为未来的对象设置默认权限,请为在此架构中创建对象的每个角色运行:

ALTER DEFAULT PRIVILEGES FOR ROLE myusr IN SCHEMA public
GRANT ALL ON TABLES TO mygrp;

ALTER DEFAULT PRIVILEGES FOR ROLE myusr IN SCHEMA public
GRANT ALL ON SEQUENCES TO mygrp;

-- more roles?

现在,将组授予用户:

GRANT mygrp TO myusr;

相关答案:

PostgreSQL - DB user should only be allowed to call functions

替代(非标准)设置

来自 MySQL,并且由于您希望将数据库的权限分开,您可能会喜欢这种非标准设置 db_user_namespace。 Per documentation:

此参数启用每个数据库的用户名。默认关闭。

仔细阅读手册。我不使用这个设置。它不会使上述内容无效。

【讨论】:

不值得单独回答,但我还想补充一点,一般来说,您不应该对个人用户使用GRANTing。而是创建角色(组)并授予他们对表的权限。创建用户时将用户添加到角色。这将为您节省很多管理上的痛苦。 @CraigRinger:没错。这是与演示代码相关的答案:***.com/questions/15867175/… @ErwinBrandstetter,您的修订接近于澄清我的另一个问题。为什么在“ALTER DEFAULT PRIVILEGES”查询中提到“myusr”?在我看来,“GRANT mygrp TO myusr”应该足以授予 myusr mygrp 的权限。 @JoeLapp:只要只有一个用户,你就根本不需要ALTER DEFAULT PRIVILEGES。如果有多个,并且每个都可以创建对象,并且您希望其他用户共享新对象的权限,请自动授予组角色权限。 只是想添加一个说明。默认情况下,在数据库中创建资源的用户拥有对该资源的所有权限。 ALTER DEFAULT PRIVILEGES 的目的是让其他用户也可以访问该资源。在此示例中,这是通过向mygrp 授予myusr 创建的所有资源的权限来完成的。 AWS 文档有一句话让我很清楚:“定义一组默认访问权限,以应用于将来由指定用户创建的对象”(我的重点)。 docs.aws.amazon.com/redshift/latest/dg/…【参考方案2】:

我不想向所有用户和所有数据库授予权限,这似乎是传统的捷径,因为当任何一个用户受到威胁时,这种方法会危及所有数据库。我托管多个数据库客户端并为每个客户端分配不同的登录名。

好的。当您将表分配给正确的角色时,授予的权限将是特定于角色的,而不是针对所有用户的!然后您可以决定将roles 提供给谁。

    为每个数据库创建一个role。一个角色可以拥有多个用户。 然后将client-username 分配给正确的角色。 如果需要,还可以将 your-username 分配给每个角色。

(1a) 尚未创建所有表,或 (1b) 已创建表。

好的。您可以稍后创建表格。 准备好后,将表分配给正确的客户端 role

CREATE TABLE tablename();
CREATE ROLE rolename;
ALTER TABLE tablename OWNER TO rolename;

(2a) 用户尚未创建,或 (2b) 用户已创建。

好的。准备好后创建用户名。如果您的客户需要多个用户名,只需创建第二个 client-username

CREATE USER username1;
CREATE USER username2;

(3a) 权限尚未分配给用户,或 (3b) 权限之前已分配给用户。

好的。当您准备好授予权限时,创建用户并为她分配正确的角色。 使用 GRANT-TO 命令为用户分配角色。

GRANT rolename TO username1;
GRANT rolename TO username2;

(4a) 用户只需要插入、更新、选择和删除行,或者 (4b) 用户还需要能够创建和删除表。

好的。您可以运行这些命令来为您的用户添加权限。

GRANT SELECT, UPDATE, INSERT, DELETE ON dbname TO role-or-user-name;
ALTER USER username1 CREATEDB;

【讨论】:

【参考方案3】:

也许您可以给我一个授予特定用户的示例 在所有表上选择/插入/更新/删除——那些现有的和不存在的 尚未创建——特定数据库?

您在 MySQL 中所称的数据库更类似于 PostgreSQL 架构,而不是 PostgreSQL 数据库。

以超级用户身份连接到数据库“test”。这里是

$ psql -U postgres test

Change the default privileges 用于现有用户“tester”。

ALTER DEFAULT PRIVILEGES IN SCHEMA public
    GRANT INSERT, SELECT, UPDATE, DELETE ON TABLES
    TO tester;

更改默认权限对现有表没有影响。这是设计使然。对于现有表,请使用标准 GRANT 和 REVOKE 语法。

您不能为不存在的用户分配权限。

【讨论】:

我认为这是我的问题之一:假设 MySQL 和 PostgreSQL 数据库是类似的实体。您的解释与 Erwin 的解释相结合,纠正了这种误解。谢谢!【参考方案4】:

如果您只使用 PUBLIC,您可能会忘记架构。 然后你做这样的事情:(see doc here)

GRANT   SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER 
    [, ...] | ALL [ PRIVILEGES ] 
    ON  [ TABLE ] table_name [, ...]
         | ALL TABLES IN SCHEMA schema_name [, ...] 
    TO  [ GROUP ] role_name | PUBLIC  [, ...] [ WITH GRANT OPTION ]

【讨论】:

谢谢,但是如果我使用 PUBLIC,我不是授予所有用户对所有数据库的特定权限吗?我希望授予单个用户对单个数据库的所有表的权限,甚至是尚未创建的表。 我说的是公共架构,而不是公共角色。 对不起,我想我不明白您的回复。也许您可以给我一个示例,该示例授予特定用户对特定数据库的所有表(现有但尚未创建的表)的选择/插入/更新/删除?谢谢!

以上是关于授予 PostgreSQL 中特定数据库的权限的主要内容,如果未能解决你的问题,请参考以下文章

授予对 PostgreSQL 中未来表的权限?

PostgreSQL 授予对表的访问权限

PostgreSQL:将所有权限授予 PostgreSQL 数据库上的用户

授予对 PostgreSQL 中未来创建的模式的使用和特权

在 PostgreSQL 中撤销另一个用户授予的权限

PostgreSQL 和 Django 的权限被拒绝错误。授予 PostgreSQL 用户管理员权限