写点什么

你应该知道的数仓安全:都是同名 Schema 惹的祸

  • 2022-10-24
    中国香港
  • 本文字数:2495 字

    阅读完需:约 8 分钟

本文分享自华为云社区《你应该知道的数仓安全——都是同名Schema惹的祸》,作者: zhangkunhn 。

典型场景


经常遇到小伙伴问到:


  • 我是管理员账号,怎么还没有权限?

  • 管理员给我赋权了啊,怎么还没有权限?


当小伙伴询问的时候,我第一时间就会想到都是用户同名 Schema 惹的祸。


同名 Schema 是私有 Schema


我们知道,CREATE USER 语法在创建用户的同时会在当前数据库中创建一个与用户同名的 SCHEMA。这个 Schema 很特殊,只有两种用户能在这个 Schema 下面创建表、视图、函数等对象:


  1. 用户自己

  2. 管理员


然而,不管谁创建的,对象的所有者(Owner)都是用户自己。基于这个事实,我们可以称用户同名 Schema 为私有 Schema。私有表明了当前 Schema 的特殊性,在这个 Schema 下面的所有对象都是这个用户自己的,不管是谁创建的。


我们来看一个例子。数据库中有三个用户,如表所示。



使用管理员 dbadmin 执行以下 SQL:


 gaussdb=# create table ua.ta (c1 int); CREATE TABLE gaussdb =# select relname, relowner, rolname from pg_class c, pg_authid a where relname = 'ta' and c.relowner= a.oid;  relname | relowner | rolname  ---------+----------+---------  t1      |    16546 | ua(不是dbadmin) (1 row)
复制代码


可以看到:


系统管理员在普通用户同名 schema 下创建的对象,所有者为 schema 的同名用户


让我们来总结第一点:同名 Schema 是私有 Schema,这个 Schema 下面的所有对象的所有者都是用户自己,不管是谁创建的。管理员在私有 Schema 下创建的表等对象会发生 Owner 切换

视图规则:按照 view 的 owner 做权限检查


再来谈视图和视图封装的基表的权限。视图对基表的权限检查是按照视图的 Owner 做权限检查。例如

create view v1 as select * from t1;


用户执行 select * from v1 时做权限检查分为两步:


  1. 首先检查当前用户对视图 v1 的 SELECT 权限;

  2. 然后检查视图 v1 的 owner 对基表 t1 的 SELECT 权限。


不是直接检查当前用户对基表 t1 的 SELECT 权限。


总结第二点:视图会按照视图的 Owner 对基表做权限检查

私有 Schema 与视图规则导致莫名其妙的权限报错


由于私有 Schema 会造成 Owner 切换,而视图规则要求对基表按照视图 Owner 做权限检查。那么在私有 Schema 下面创建视图就会导致莫名其妙的现象:


私有 Schema + view 规则 --> 管理员无权限访问自己创建的视图。


 gaussdb =# set role dbadmin password ‘*******’;      -- 切换到管理员用户 SET gaussdb => create table ua.ta (c1 int);              -- 表ta的owner是??? CREATE TABLE gaussdb => create view ub.vb as select * from ua.ta; -- 视图vb的owner是??? CREATE VIEW gaussdb => select * from ub.vb;                      -- 管理员创建的view,他竟然无权限!!! ERROR: SELECT permission denied to user “ub” for relation “ua.ta“  
复制代码


我们以管理员用户在用户 ua 的私有 schema 下创建表 ta, 之后在用户 ub 的 schema 下创建了视图 vb, 视图 vb 的基表是 ua.ta。管理员执行对视图 vb 的查询,报错无权限。


对于这个莫名其妙的现象,我们仔细捋一捋其中的来龙去脉。


  1. 根据私有 Schema 切换 Owner 的法则,尽管是管理员创建的,ta 的 owner 切换到 ua, 同样 vb 的 owner 应该是 u2.

  2. 结合 view 规则,对基表按照视图 Owner 做权限检查,视图 vb 的 owner 对基表 ua.ta 是否具有 select 权限。视图 vb 的 owner 是 ub,而 ub 对 ua.ta 无 select 权限,因此查询报错。

权限报错消除


如何解决这种权限报错呢?从上述梳理中,其实已经明白了如何赋权来消除这种报错。那就是给视图的 owner 用户 ub 赋予基表 ua.ta 的 SELCT 权限:管理员或者用户 ua 执行下面的赋权语句即可。


 GRANT SELECT on ua.ta to ub; 
复制代码


有小伙伴 问了,我每次都这么仔细捋一捋,感觉很浪费时间,有没有简单的方法。答案是有的,只需从查询的权限报错着手,不需要每次都捋一捋。


我们当前的权限报错有着非常完备的提醒,会给用户显示如下提示:


SELECT permission denied to user “user_name” for relation “ schema_name.table_name

可以看到,权限报错包括哪个权限、哪个用户、哪个 schema 的哪个对象。那么看到这个之后,可以直接找管理员或者 Owner 来执行授予操作就可以了。


对于上述报错,直接就对应到赋权语句:


grant SELECT on schema_name.table_name to user_name;


当然这个赋权跟我们前面的分析是殊途同归的。


现在来回想下,是不是一切都清晰了。那么我们再来看一遍示例。以管理员 dbadmin 执行以下 SQL 语句。


 gaussdb => create table ua.ta (c1 int);              -- ta的owner是ua CREATE TABLE gaussdb => create view ub.vb as select * from ua.ta; -- vb的owner是ub CREATE VIEW postgres=# select * from ub.vb;                      -- 按照报错的指引来 ERROR: SELECT permission denied to user “ub” for relation “ua.ta“  gaussdb =# grant usage on schema ua to ub;           -- 将schema ua和基表ta的权限给ub GRANT gaussdb =# grant select on ua.ta to ub; GRANT postgres=# select * from ub.vb;                      -- 权限检查通过,可以正常查询  c1  ---- (0 rows)
复制代码


补充知识:


  1. CREATE USER 语法在创建用户的同时会在当前数据库中,为该用户创建一个同名的 SCHEMA;其他数据库中,则不会创建同名的 SCHEMA;如果需要,可使用 create schema authorization user_name 语法,该语法会根据用户名来创建同名 schema。

  2. 为什么用户同名 Schema 这么特殊,别的 Schema 没有这些特点?因为:a) 在创建用户时同时创建了与用户同名的 Schema,并将 Schema 的 owner 设置为同名用户;b) 在创建对象时,如果创建对象的 schema 是用户同名 Schema,就会将对象的 Owner 切换为同名用户,而不是执行 SQL 语句的当前用户。

总结


遇到权限报错第一时间想到是否涉及同名 schema。同名 Schema 是用户的私有 Schema。私有 Schema 中所有的对象 Owner 都是用户自己,不管是谁创建的。在私有 Schema 中创建对象,对象 Owner 会切换到同名用户。视图规则是按照视图 Owner 来检查对基表的权限。由于私有 Schema 的 Owner 切换机制和视图规则导致了同名 Schema 的权限报错。根据报错的提示,授予用户相应的权限就可以解决权限报错问题。


点击关注,第一时间了解华为云新鲜技术~

发布于: 刚刚阅读数: 3
用户头像

提供全面深入的云计算技术干货 2020-07-14 加入

华为云开发者社区,提供全面深入的云计算前景分析、丰富的技术干货、程序样例,分享华为云前沿资讯动态,方便开发者快速成长与发展,欢迎提问、互动,多方位了解云计算! 传送门:https://bbs.huaweicloud.com/

评论

发布
暂无评论
你应该知道的数仓安全:都是同名Schema惹的祸_数据库_华为云开发者联盟_InfoQ写作社区