PostgreSQL -public schema

Overview

上一篇文章中,介绍了理解 PostgreSQL schema的基础知识、创建和删除机制,并回顾了几个用例。本文将扩展这些基础知识并探讨与schema相关的权限管理。
但有一个需要澄清的初步事项。在上一篇文章中,讨论了一个可能的混淆点,涉及到“schema”一词的多重使用。在PostgreSQL数据库上下文中,该术语的专门含义与其在关系数据库管理系统中通常的使用方式不同。对于当前主题,有另一个类似的术语混乱,涉及“public”一词。

在初始创建数据库时,新创建的PostgreSQL数据库包括一个预定义的名为“public”的schema。它是一个和其他schema一样的schema,但同一个词也用作一个关键字,在本应使用实际role name的上下文中表示“all users”,例如schema权限管理。下面的例子将澄清这一术语的重要性及其两种不同用法。

查询Schema权限

在使用示例代码来授予和撤销schema权限之前,需要回顾一下如何检查schema的权限。使用 psql 命令行界面,我们使用 dn+ 命令列出schema和相关权限。对于新创建的 sampledb 数据库,我们会看到public schema的以下內容:

sampledb=# dn+ 
                          List of schemas
  Name  |  Owner   |  Access privileges   |      Description      
--------+----------+----------------------+------------------------
 public | postgres | postgres=UC/postgres+| standard public schema
        |          | =UC/postgres         |
(1 row)

前两列和第四列非常简单:如前所述,显示默认创建的schema名为“public”,描述为“standard public schema”,由角色“postgres”拥有。(除非另有指定,否则schema所有权设置为创建schema的角色。)第三列列出了访问权限,这是这里感兴趣的内容。权限信息的格式提供了三个项目:privlileges grantee(权限被授予者)、privilege(权限)和privilege grantor(权限授予者),格式为“grantee=privileges/grantor”,即等号左侧是接收权限的角色,等号右侧是一组指定特定权限的字母,最后在斜线后面是授予权限的角色。可能会有多个此类权限信息规范,以"+"号分隔列出,因为权限是累加的。
对于schema,有两种可能的权限可以分别授予:U 代表“USAGE”(使用)和 C 代表“CREATE”(创建)。前者是一个角色查找schema中包含的数据库对象(如表和视图)所必需的权限;后者允许一个角色在schema中创建数据库对象。其他类型的数据库对象还有其他权限字母,但对于schema,只适用于 U 和 C。
因此,为了解释上面的权限列表,第一个规范告诉我们,postgres 用户被授予在public schema上update和create的权限。

请注意,对于上面的第二个规范,等号左侧会出现一个空字符串。这就是通过前面提到的 PUBLIC 关键字授予all users的权限的表示方式。

后一种在public schema上授予"all users" usage和create权限的规范,被一些人视为可能违背了通用安全原则的最佳实践,因为最佳实践通常倾向于从默认限制访问开始,要求数据库管理员明确授予适当且最低必要的访问权限。这些在public schema上的宽松权限是有意在系统中配置的,目的是为了方便和兼容旧系统。
还要注意,除了宽松的权限设置外,public schema唯一特别之处在于它也列在了search_path中,正如我们在上一篇文章中讨论的那样。这同样是为了方便:search_path配置和宽松的权限设置共同使新数据库的使用变得像是没有schema这个概念一样。

public schema的历史背景

这种兼容性问题起源于大约十五年前(在 PostgreSQL 7.3 版之前,参见 7.3 版发布说明),当时 PostgreSQL 还没有schema 特征。在 7.3 版引入schema功能时,通过配置public schema的宽松权限和 search_path,使得旧版应用程序(这些应用程序不支持schema)能够在升级后的数据库功能中无需修改地运行,从而确保了兼容性。
除此之外,public schema没有什么特别之处:如果用例不需要它,一些 DBA 会删除它;其他人则通过撤销默认权限来锁定它。

撤销权限

schema权限通过 GRANT 和 REVOKE 命令进行管理,分别用于添加和撤销权限。我们将尝试一些限制public schema的权限具体示例,但一般语法是:

REVOKE [ GRANT OPTION FOR ]
    { { CREATE | USAGE } [, ...] | ALL [ PRIVILEGES ] }
    ON SCHEMA schema_name [, ...]
    FROM { [ GROUP ] role_name | PUBLIC } [, ...]
    [ CASCADE | RESTRICT ]

因此,作为初始的示例,我们从public schema中移除create权限。请注意,在这些示例中,小写单词“public”指的是schema,可以替换为数据库中存在的任何其他有效schema名称。大写的“PUBLIC”是一个特殊关键字,表示“所有用户”,可以用特定角色名称或逗号分隔的角色名称列表替换,以实现更精细的访问控制。

sampledb=# REVOKE CREATE ON SCHEMA public FROM PUBLIC;
REVOKE
sampledb=# dn+
                          List of schemas
  Name  |  Owner   |  Access privileges   |      Description       
--------+----------+----------------------+------------------------
 public | postgres | postgres=UC/postgres+| standard public schema
        |          | =U/postgres          | 
(1 row)

在这个schema权限列表中,与第一个列表唯一的区别是第二个权限规范中缺少了“C”,这证实了我们的命令已经生效:除了postgres用户之外的用户不再能在public schema中创建表、视图或其他对象。

请注意,上述从public schema中撤销create权限的命令是针对之前公布的漏洞CVE-2018-1058的建议缓解措施,该漏洞源于public schema上的默认权限设置。

进一步的限制可能需要通过删除使用权限来完全拒绝对此schema的查找访问:

sampledb=# REVOKE USAGE ON SCHEMA public FROM PUBLIC;
REVOKE
sampledb=# dn+
                          List of schemas
  Name  |  Owner   |  Access privileges   |      Description       
--------+----------+----------------------+------------------------
 public | postgres | postgres=UC/postgres | standard public schema
(1 row)

由于非所有者用户的所有可用的schema权限均已被撤销,因此整个第二个权限规范在上面的列表中消失。

我们使用两个单独的命令执行的操作可以通过一个指定所有权限的命令简洁地完成,如下所示:

sampledb=# REVOKE ALL PRIVILEGES ON SCHEMA public FROM PUBLIC;
REVOKE

此外,还可以撤销schema所有者的权限:

sampledb=# REVOKE ALL PRIVILEGES ON SCHEMA public FROM postgres;
REVOKE
sampledb=# dn+
                        List of schemas
  Name  |  Owner   | Access privileges |      Description       
--------+----------+-------------------+------------------------
 public | postgres |                   | standard public schema
(1 row)

但这实际上并没有实现任何实际效果,因为schema所有者仅凭所有权就保留了对其所拥有schema的全部权限,而不管明确分配与否。
public schema的宽松权限分配是与初始数据库创建相关的特殊产物。后续在现有数据库中创建的schema遵循了最佳实践,即开始时不分配任何权限。。例如,在创建名为“private”的新schema后检查schema权限,显示新schema没有权限:

sampledb=# create schema private;
CREATE SCHEMA
sampledb=# dn+
                          List of schemas
  Name   |  Owner   |  Access privileges   |      Description       
---------+----------+----------------------+------------------------
 private | postgres |                      | 
 public  | postgres |                      | standard public schema
(2 rows)

Granting Privileges

添加权限的命令的一般形式为:

GRANT { { CREATE | USAGE } [, ...] | ALL [ PRIVILEGES ] }
    ON SCHEMA schema_name [, ...]
    TO role_specification [, ...] [ WITH GRANT OPTION ]
where role_specification can be:
  [ GROUP ] role_name
  | PUBLIC
  | CURRENT_USER
  | SESSION_USER

例如,使用此命令,我们可以允许所有角色通过添加usage权限来查找private schema的数据库对象

sampledb=# GRANT USAGE ON SCHEMA private TO PUBLIC;
GRANT
sampledb=# dn+
                          List of schemas
  Name   |  Owner   |  Access privileges   |      Description       
---------+----------+----------------------+------------------------
 private | postgres | postgres=UC/postgres+| 
         |          | =U/postgres          | 
 public  | postgres |                      | standard public schema
(2 rows)

请注意,现在我们已经为schema分配了非默认权限,UC权限以postgres所有者作为第一规范出现。第二个规范,=U/postgres,对应于我们刚刚作为postgres用户调用的GRANT命令,授予所"all users"使用权限(回想一下,等号左侧的空字符串表示“all users”)。

例如,可以为名为“user1”的特定角色授予private schema的create和usage权限:

sampledb=# GRANT ALL PRIVILEGES ON SCHEMA private TO user1;
GRANT
sampledb=# dn+
                          List of schemas
  Name   |  Owner   |  Access privileges   |      Description       
---------+----------+----------------------+------------------------
 private | postgres | postgres=UC/postgres+| 
         |          | =U/postgres         +| 
         |          | user1=UC/postgres    | 
 public  | postgres |                      | standard public schema
(2 rows)

我们还未提及一般命令形式中的“WITH GRANT OPTION”子句。正如其字面意思,此子句允许授予的角色将指定的权限授予其他用户,它在权限列表中以附加到特定权限的星号表示。

sampledb=# GRANT ALL PRIVILEGES ON SCHEMA private TO user1 WITH GRANT OPTION;
GRANT
sampledb=# dn+
                          List of schemas
  Name   |  Owner   |  Access privileges   |      Description       
---------+----------+----------------------+------------------------
 private | postgres | postgres=UC/postgres+| 
         |          | =U/postgres         +| 
         |          | user1=U*C*/postgres  | 
 public  | postgres |                      | standard public schema
(2 rows)

结论

最后,请记住,我们只讨论了schema访问权限。虽然 USAGE 权限允许查找schema中的数据库对象,但要实际访问对象以执行特定操作(例如读取、写入、执行等),角色还必须具有对这些特定数据库对象执行这些操作的适当权限。

  • 18
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值