Как вставить в таблицу с безопасностью на уровне строк? - PullRequest
0 голосов
/ 27 апреля 2018

У меня есть следующая таблица:

            Table "api_v1.person"
    Column     |  Type  |      Modifiers
---------------+--------+-------------------------------------------------------
 person_id     | bigint | not null default...
 name          | text   | not null
 date_of_birth | date   |
 api_user      | text   | not null default "current_user"()

Это имеет следующую политику:

POLICY "api_user_only" FOR ALL
  USING ((api_user = ("current_user"())::text))
  WITH CHECK ((api_user = ("current_user"())::text))

Насколько я понимаю, часть политики FOR ALL означает, что она охватывает вставки, а WITH CHECK гарантирует, что значение, вставленное в api_user, совпадает с текущим пользователем, например, именем роли. Предложение USING должно влиять только на SELECTS или другие возвращаемые данные. Однако, когда я пытаюсь вставить, я получаю следующие результаты:

demo=> INSERT INTO api_v1.person (name, api_user) VALUES ('Greg', current_user);
ERROR:  query would be affected by row-level security policy for table "person"

Как мне сделать эту вставку?

Я использую PostgreSQL 9.6.8.

Вот SQL, необходимый для воспроизведения:

BEGIN;

CREATE SCHEMA api_v1;

CREATE TABLE api_v1.person (
    person_id BIGSERIAL PRIMARY KEY,
    "name" TEXT NOT NULL,
    date_of_birth DATE,
    api_user TEXT NOT NULL DEFAULT current_user
);

ALTER TABLE api_v1.person ENABLE ROW LEVEL SECURITY;

CREATE POLICY
api_user_only
ON
    api_v1.person
USING
    (api_user = CURRENT_USER)
WITH CHECK
    (api_user = CURRENT_USER)
;

CREATE ROLE test_role;

GRANT USAGE ON SCHEMA api_v1 TO test_role;
GRANT ALL ON api_v1.person TO test_role;
GRANT USAGE ON SEQUENCE api_v1.person_person_id_seq TO test_role;

COMMIT;

SET ROLE test_role;

INSERT INTO api_v1.person ("name") VALUES ('Greg');

1 Ответ

0 голосов
/ 29 апреля 2018

В postgresql.conf есть настройка, row_security. Если этот параметр отключен, то любой запрос, который будет выполняться политикой безопасности на уровне строк, завершается с ошибкой: ERROR: query would be affected by row-level security policy for table "table_name". Однако запросы от суперпользователей, владельца таблицы (если вы не форсируете RLS) и ролей с помощью bypassrls будут работать.

Для параметра row_security необходимо установить значение on, а затем необходимо перезапустить PostgreSQL, чтобы обычные операторы пользователя обрабатывались для таблиц с политиками безопасности на уровне строк.

Из исходного кода:

/*
 * We should apply RLS.  However, the user may turn off the row_security
 * GUC to get a forced error instead.
 */
if (!row_security && !noError)
    ereport(ERROR,
            (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
             errmsg("query would be affected by row-level security policy for table \"%s\"",
                    get_rel_name(relid)),
             amowner ? errhint("To disable the policy for the table's owner, use ALTER TABLE NO FORCE ROW LEVEL SECURITY.") : 0));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...