Временно пропустить проверки RLS

У меня есть таблицы с включенной безопасностью на уровне строк и соответствующими политиками — они работают очень хорошо.

Моя проблема в том, что иногда, исходя из некоторых условий, я хочу обойти политику для определенного оператора во время выполнения функции.

что-то вроде:

...
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, которая возвращает логическое значение, оценивающее some cond, и создал дополнительную политику выбора, которая вызывает это check_cond.

Это работает, но проблема в том, что запрос select * from tab теперь выглядит так: select * from tab where <original policy condition> or check_cond()

Этот or check_cond() заставляет postges всегда выполнять полное сканирование таблицы, поскольку он не может заранее оценить результат.

Если бы я мог написать «динамический» код в политике, я бы смог добавлять/удалять условия на основе значения check_cond(), но, насколько я знаю, это невозможно.

Какой-нибудь умный способ, который позволил бы мне временно отключить rls или динамически добавлять условия без ущерба для производительности?

Спасибо.


person Pyrocks    schedule 19.02.2020    source источник


Ответы (1)


Проще всего было бы иметь функцию SECURITY DEFINER, принадлежащую суперпользователю, которая запускается:

ALTER ROLE someuser BYPASSRLS;

где someuser — это пользователь, запускающий операторы SQL.

После этого вы можете снова включить его таким же образом.

Но это довольно небезопасно, потому что ничто не мешает пользователю вызывать эти функции в другое время.

Лучшим способом было бы определить функцию определения безопасности, принадлежащую пользователю с BYPASSRLS, который будет выполнять удаление за вас.

Примечание. из соображений безопасности всегда SET search_path при определении функции SECURITY DEFINER.

person Laurenz Albe    schedule 19.02.2020
comment
Лучшим способом было бы определить функцию определения безопасности, принадлежащую пользователю с BYPASSRLS, который выполняет удаление за вас. - определитель безопасности - это волшебное слово, которое я искал - это должно помочь - спасибо! Приму, как только заработаю - person Pyrocks; 19.02.2020