暂时跳过 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
函数时。
我有 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
函数时。