具有单个数据库用户和连接池的行级安全性

Mad*_*ist 5 postgresql row-level-security

我正在使用node-postgres连接到启用了连接池的 PostgreSQL 9.6 数据库。所有连接都使用同一个数据库用户。我不能使用多个数据库用户的一个原因是,据我所知,在这种情况下,行级安全性和视图不能很好地协同工作,因为视图的所有者用于 RLS。

我现在正在考虑在 Postgres 中使用行级安全性,我想确保我这样做是正确的。

我正在使用SET LOCAL设置当前应用程序用户 ID,然后由行级安全性 USING 子句使用。我能想到通过连接池实现这一点的唯一方法是使用 node-postgres 将每个查询包装在一个事务中,并SET LOCAL在每个事务中执行如下命令。

SET LOCAL postgres.my_user = 20;
Run Code Online (Sandbox Code Playgroud)

以下代码是我想如何定义行级安全性的简化示例,真实版本还有一些条件:

CREATE POLICY table_a_read_policy ON table_a FOR SELECT
USING (
    EXISTS (
    SELECT * 
    FROM permissions 
    WHERE 
        user_id = current_setting('postgres.my_user')::int AND 
        permission_type = 'read'
    )
);
Run Code Online (Sandbox Code Playgroud)

我的理解是,在这种情况下,任何 SQL 注入也会使攻击者能够以这种方式设置任何用户 ID 并规避行级安全性。但是我没有看到任何方法可以避免这种情况,因为我连接的数据库用户必须能够查看整个应用程序的所有数据。

有几点我不完全确定:

  • 使用SET LOCAL作为存储当前应用程序用户身份以实现行级安全的方式是否安全?尤其是在连接池的上下文中?
  • 有没有比在 node-postgres 中的事务中包装每个查询并SET LOCAL每次执行命令更好的方法?
  • 有没有办法以一种 SQL 注入不会自动提供规避行级安全性的能力的方式来构造它(限制使用单个数据库用户建立数据库连接)?

小智 2

我也想做一些类似于你所说的事情。偶然发现这篇博文并发现它很有用。希望这可以帮助。

\n\n

blog.2ndquadrant.com/application-users-vs-row-level-security

\n\n
\n

签名会话变量

\n\n

第一个解决方案是对会话变量\xe2\x80\x93的简单改进,我们可以\xe2\x80\x99真正阻止用户设置任意值,但是如果我们可以验证该值没有被破坏呢?使用简单的数字签名就可以很容易地做到这一点。可信部分(连接池、应用程序)不仅可以存储用户名,还可以执行以下操作:

\n\n

signature = sha256(username + timestamp + SECRET)

\n\n

然后将值和签名存储到会话变量中:

\n\n

SET my.username = \'username:timestamp:signature\'

\n\n

假设用户不知道 SECRET 字符串(例如 128B 的随机数据),则\xe2\x80\x99 不可能在不使签名无效的情况下修改该值。

\n
\n

  • 由于链接来来去去,您应该总结博客文章,以便将关键信息保留在此处。 (3认同)