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

[译] 在 POSTGRESQL 中查看权限和行级安全性

原创 Bigbig 2022-06-17
505

image.png

查看权限如何检查的细节一直让我感到困惑。PostgreSQL v15 引入了“安全调用者”视图,它改变了检查权限的方式。新的安全调用程序视图可以有效地使用行级安全性。我将借此机会解释查看权限的工作原理以及您如何从新功能中受益。

为什么以特殊方式检查查看权限?

从根本上说,视图是具有名称和所有者的 SQL 语句。当 PostgreSQL 处理一条 SQL 语句时,它会用它们的定义替换视图。替换发生在查询重写步骤中,在优化器计算最佳执行计划之前。PostgreSQL 将视图实现为查询重写规则。

但除了作为子查询的简写之外,视图还可以用作安全工具。SELECT用户可以在她拥有权限 的表上创建一个视图,并将SELECT该视图授予另一个用户。然后,其他用户可以访问该视图以仅查看部分基础数据,即使他对基础表没有权限。但是请注意,只有在视图上设置了视图选项时,以这种方式使用视图才是安全security_barrier的。PostgreSQL 文档包含对由此避免的安全问题的详细描述。

有关 PostgreSQL 如何检查查看权限的详细信息

为了允许使用上一段中描述的视图,PostgreSQL 以一种特殊的方式检查视图权限。

它使用视图的所有者来检查对视图定义中引用的所有关系的访问。在这里,“关系”是存储在系统目录中的任何内容的 PostgreSQL 术语pg_class:(分区)表、视图、(分区)索引、序列、复合类型、物化视图和外部表。通常,视图所有者拥有所有必需的权限。否则,她一开始就不会被允许创建视图。

请注意,上述内容并未扩展到其他对象。 例如,在视图中调用的函数的权限被检查为访问视图的用户(调用者)。

此外,虽然 PostgreSQL 使用视图所有者来检查权限,但调用者是current_user在执行查询期间。因此,PostgreSQL执行所有未SECURITY DEFINER在视图调用者的安全上下文中定义的函数。换句话说,视图的所有权导致与SECURITY DEFINER函数的所有权不同的行为。

视图和行级安全性

行级安全性 (RLS) 确定哪些行对用户可见。用户只能看到满足行级安全策略强加的条件的行。由于 PostgreSQL 使用视图所有者来检查基础表的权限,因此它也使用视图所有者来检查这些表的行级安全策略是有意义的。

虽然使用视图所有者来检查权限和 RLS 策略是有意义的,但它会对有效的用例造成严重破坏。具体来说,如果能够查询视图并仅查看您(作为调用用户)通过策略可以看到的基础表中的那些数据,那就太好了。

查看权限示例

以下示例是上述内容的展示:

\connect - laurenz
 
-- joe has no SELECT privileges
CREATE TABLE rls (rls_user text);
 
INSERT INTO rls VALUES ('laurenz'), ('joe');
 
-- does not apply to the table owner!
ALTER TABLE rls ENABLE ROW LEVEL SECURITY;
 
-- everybody can see their own row
CREATE POLICY u ON rls TO PUBLIC USING (rls_user = user);
 
-- shows the current user
-- everybody has the EXECUTE privilege
CREATE FUNCTION whoami() RETURNS text RETURN user;
 
CREATE VIEW v 
   AS SELECT rls_user, whoami() FROM rls;
 
GRANT SELECT ON v TO joe;
 
\connect - joe
 
TABLE v;
 
 rls_user │ whoami 
══════════╪════════
 laurenz  │ joe
 joe      │ joe
(2 rows)

joerls即使他对表没有权限,也可以查看数据,因为视图所有者的权限laurenz适用。joe看到这两行,因为 PostgreSQL 检查表 owner 的行级安全性,表 ownerlaurenz不受行级安全性的约束。但请注意,该函数user(以及因此whoami)返回运行查询的用户,而不是视图所有者!如果使用了策略,这同样适用user于策略定义中的调用。当视图所有者决定应用哪个行级安全策略时,PostgreSQLUSING作为视图调用者评估条件。

security_invoker在视图中查看权限

PostgreSQL v15 引入了 view 选项security_invoker来改变它检查权限的方式。如果该选项设置为onon 视图,PostgreSQL 将检查所有权限作为调用用户。本质上,以下代码:

CREATE VIEW v AS SELECT /* whatever */;
GRANT SELECT ON v TO joe;
\connect - joe
SELECT * FROM v;

各方面的行为

\connect - joe
SELECT * FROM (SELECT /* whatever */) AS v;

让我们看看我们的原始示例如何处理security_invoker视图:

\connect - laurenz
 
ALTER VIEW v SET (security_invoker = on);
 
-- necessary with "security_invoker"
GRANT SELECT ON rls TO joe;
 
\connect - joe
 
TABLE laurenz.v;
 
 rls_user │ whoami 
══════════╪════════
 joe      │ joe
(1 row)

现在使用了行级安全策略joe,我们只得到一个结果行。

security_invoker视图用例

主要用例(以及启发该功能的用例)是能够使用视图并仍然作为调用者检查基础表上的行级安全策略。但是视图的其他用例也可以更好地使用带有security_invoker = on. 例如,为经常使用的子查询提供“代码重用”的视图。security_invoker = on是大多数不用于安全目的的视图的适当设置。

##3 结论
您可以将视图用作一种工具,以允许特权较低的用户部分访问特权数据。为了促进这一点,PostgreSQL 通常以视图所有者的身份检查基础表的权限。view 选项改为检查访问视图的用户的security_invoker权限。这使得视图和行级安全性可以很好地交互,并且是大多数用例中的适当设置。

如果您想获得有关如何最好地使用视图的建议,请阅读我关于视图依赖项的文章,该文章还告诉您如何跟踪嵌套视图。
文章地址:https://www.cybertec-postgresql.com/en/tracking-view-dependencies-in-postgresql/

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

评论