暂时跳过 RLS 检查

Skip RLS checks temporarily

我有 table 启用了行级安全和相关策略 - 工作得非常好。

我的问题是有时,基于某些条件,我想在函数执行期间绕过特定语句的策略。

类似于:

...
statement 1
statement 2
if (some cond) then
   disable rls temporarily 
   statement 3 -- mostly delete rows the user can't normally see
   enable rls
else
   statement 3
end if

我实现它的方法是创建一个函数 check_cond,其中 returns 是一个计算 some cond 的布尔值,并创建了一个额外的 select 策略,调用此 check_cond.

有效 - 但实际问题是查询 select * from tab 现在看起来像这样: select * from tab where <original policy condition> or check_cond()

or check_cond() 导致 postges 总是进行完整的 table 扫描,因为它无法评估预先计划的结果。

如果我能够在策略中编写 "dynamic" 代码,我将能够根据 check_cond() 的值 add/remove 条件,但据我所知它不是可能。

有什么聪明的方法可以让我在不牺牲性能的情况下暂时禁用 rls 或动态添加条件?

谢谢。

最简单的方法是让超级用户拥有一个 SECURITY DEFINER 函数,该函数运行:

ALTER ROLE someuser BYPASSRLS;

其中 someuser 是运行 SQL 语句的用户。

之后,您可以用同样的方法重新启用它。

但这很不安全,因为没有什么能阻止用户在其他时间调用这些函数。

更好的方法是定义一个由 BYPASSRLS 用户拥有的安全定义器函数,它会为您执行删除操作。

注意:出于安全原因,总是 SET search_path当你定义一个SECURITY DEFINER函数时。