Политика PostgreSQL RLS для конкретного пользователя работает не так, как ожидалось, и применяется ко всем пользователям.

У меня есть 2 пользователя в моей БД, один "сильный", а другой "слабый". Я хочу применить политику RLS только для одного из них, слабого пользователя. Это означает, что когда сильный пользователь запрашивает таблицу, он должен получить все строки. Но когда слабый пользователь запрашивает таблицу, политика будет применена и вернет только разрешенные строки.

Я создал таблицу и применил политику RLS только к слабому пользователю. Но даже при запросе с сильным пользователем политика выполняется и не позволяет мне получить все строки. Я использую PostgreSQL версии 11.4.

Вот как я создал политику (я создал политику с другим третьим пользователем, который является администратором и владельцем таблицы)

CREATE TABLE account_test
(
    id bigserial not null,
    description varchar(200),
    tenant_id UUID not null
);
ALTER TABLE account_test ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_policy ON account_test TO weak_user
                        USING (tenant_id = current_setting('rls.tenant_id')::uuid);

account =# выберите * из pg_policies;

schemaname | tablename | полицина | разрешительный | роли | cmd | qual | with_check ------------+--------------+---------------+------------+---------------+-----+--------------------------------------------------------------+------------ счет | account_test | tenant_policy | РАЗРЕШЕНИЕ | {weak_user} | ВСЕ | (tenant_id = (current_setting('rls.tenant_id'::text))::uuid) |

Теперь вставка и выбор с администратором всегда работает, потому что он владелец:

insert into account_test (description, tenant_id) VALUES ('desc111', '11111111-c929-462e-ade4-074c81643191');
select * from account_test;  

здесь нет проблем, и все строки возвращены.

При попытке войти в систему с помощью weak_user и выбрать, я не получаю ожидаемых строк:

select * from account_test; 
-- returns 0 rows as expected (weak_user).

Если я устанавливаю параметр, применяется политика, и я получаю данные, как ожидалось:

select set_config('rls.tenant_id', '11111111-c929-462e-ade4-074c81643191',true);
select * from account_test; 
-- returns 1 row as expected

Теперь, когда я вхожу в систему с помощью strong_user и выполняю запрос "select * from account_test", я ожидаю, что все строки будут возвращены, потому что политика применяется только для weak_user. Однако я получаю то же поведение, что и для weak_user, и строки не возвращаются. Также запрос с set_config ничего не возвращает.

Что мне не хватает? Это ожидаемое поведение? Кто-нибудь может объяснить?

0 ответов

В тот момент, когда вы включите RLS на столе с ALTER TABLE account_test ENABLE ROW LEVEL SECURITYдля всех пользователей используется политика по умолчанию - запретить все.

Когда [RLS] включен для таблицы, любой нормальный доступ к таблице для выбора строк или изменения строк должен быть разрешен политикой безопасности строк. (Однако владелец таблицы обычно не подчиняется политикам безопасности строк.) Если для таблицы не существует политики, используется политика запрета по умолчанию, что означает, что никакие строки не видны или могут быть изменены.

- https://www.postgresql.org/docs/current/ddl-rowsecurity.html

У каждой политики есть имя, и для таблицы можно определить несколько политик. Поскольку политики зависят от таблицы, каждая политика для таблицы должна иметь уникальное имя. В разных таблицах могут быть политики с одинаковыми именами.

Для того чтобы strong_user чтобы получить доступ, вам нужно будет добавить еще одно правило, например

CREATE POLICY tenant_policy ON account_test TO strong_user USING (true);

Когда к данному запросу применяется несколько политик, они объединяются либо с использованием ИЛИ (для разрешающих политик, которые используются по умолчанию), либо с использованием И (для ограничительных политик). Это похоже на правило, согласно которому данная роль имеет привилегии всех ролей, членом которых она является. Разрешительные и ограничительные политики обсуждаются ниже.

Другие вопросы по тегам