暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

小心 PostgreSQL 中的“public”

原创 刺史武都 2022-10-12
3259

默认情况下,PostgreSQL 带有“公共”模式,我们始终建议在 PostgreSQL 版本高达 14 时删除它。原因是,默认情况下,能够连接到数据库的每个人都可以在公共模式中创建对象。从 PostgreSQL 15 开始,这将不再可能。您可以查看该更改的发行说明,即:“Remove PUBLIC creation permission on the public schema (Noah Misch)”。

除了“public”模式之外,还有一个特殊的角色“public”。此角色可用于向所有其他角色授予某些内容,但这也带来了对默认情况下可能发生的一些误解。默认情况下,public 角色具有以下权限:

1

2

3

4

5

6

7

8

9

10

11

12

username | object_type |    object_name     |            array           

----------+-------------+--------------------+-----------------------------

 public   | DATABASE    | postgres           | {CONNECT,TEMPORARY}

 public   | DATABASE    | template1          | {CONNECT}

 public   | LANGUAGE    | internal           | {USAGE}

 public   | LANGUAGE    | c                  | {USAGE}

 public   | LANGUAGE    | sql                | {USAGE}

 public   | LANGUAGE    | plpgsql            | {USAGE}

 public   | SCHEMA      | pg_catalog         | {USAGE}

 public   | SCHEMA      | public             | {USAGE}

 public   | SCHEMA      | information_schema | {USAGE}

(9 rows)

有一些“使用”权限,看起来不错,但也有针对“postgres”和“template1”数据库的“连接”权限(如果您想知道如何从系统中获取这些权限,那么您应该检查文档中的各种“has_***”函数)。

上周,一位遇到此问题的客户联系了我们:

1

2

3

4

5

6

postgres=# create database d;

CREATE DATABASE

postgres=# create user u with login password 'u';

CREATE ROLE

postgres=# revoke connect on database d from u;

REVOKE

简单设置:一个数据库,一个用户,并从该用户撤销该数据库的连接权限。该用户是否能够连接到数据库?从数据库主机外部进行简单测试:

1

2

3

4

5

6

7

dwe@ltdwe:~$ psql -h 192.168.100.241 -p 5432 -U u d

psql (14.5, server 16devel)

WARNING: psql major version 14, server major version 16.

         Some psql features might not work.

Type "help" for help.

 

d=>

工作得很好,即使连接权限被撤销(当然我之前修改过pg_hba.conf)。这是为什么?原因在于“公共”角色。如果我们再次检查该角色的权限,我们可以看到:

1

2

3

4

5

6

7

8

9

10

11

12

13

username | object_type |    object_name     |            array

----------+-------------+--------------------+-----------------------------

 public   | DATABASE    | postgres           | {CONNECT,TEMPORARY}

 public   | DATABASE    | template1          | {CONNECT}

 public   | DATABASE    | d                  | {CONNECT,TEMPORARY}

 public   | LANGUAGE    | internal           | {USAGE}

 public   | LANGUAGE    | c                  | {USAGE}

 public   | LANGUAGE    | sql                | {USAGE}

 public   | LANGUAGE    | plpgsql            | {USAGE}

 public   | SCHEMA      | pg_catalog         | {USAGE}

 public   | SCHEMA      | public             | {USAGE}

 public   | SCHEMA      | information_schema | {USAGE}

(10 rows)

由于“public”角色默认具有连接权限,因此所有其他用户都可以自动使用,这就是它仍然有效的原因。你应该做的是:

1

2

postgres=# revoke connect on database d from public;

REVOKE

一旦从公共撤销连接,用户将无法再连接:

1

2

3

dwe@ltdwe:~$ psql -h 192.168.100.241 -p 5432 -U u d

psql: error: connection to server at "192.168.100.241", port 5432 failed: FATAL:  permission denied for database "d"

DETAIL:  User does not have CONNECT privilege.

请记住,授予“public”的权限对所有用户都有效。

原文标题:Be careful with “public” in PostgreSQL

原文作者:Daniel Westermann

原文链接:https://www.dbi-services.com/blog/be-careful-with-public-in-postgresql/

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论