Каков охват политики Postgres? - PullRequest
0 голосов
/ 09 октября 2019

Я пытаюсь обернуть голову вокруг безопасности на уровне строк в Postgres. К сожалению, документация не очень многословна по этому вопросу. Моя проблема заключается в следующем:

У меня есть две таблицы: locations и locations_owners. Для местоположений установлено значение TRIGGER INSERT, которое автоматически добавит новую строку в таблицу locations_owners, включая переменную request.jwt.claim.sub .

. Хорошо, однако, когда я хочу создать политику для DELETE, например:

CREATE POLICY location_delete ON eventzimmer.locations FOR DELETE TO organizer USING(
    (SELECT EXISTS (SELECT name FROM protected.locations_owners AS owners WHERE owners.name = name AND owners.sub = (SELECT current_setting('request.jwt.claim.sub', true))))
);

Она всегда будет иметь значение true, независимо от фактического содержимого. Я знаю, что я могу вызвать пользовательскую процедуру с SELECT здесь, однако у меня возникли следующие вопросы:

  • какова область действия policy? Могу ли я получить доступ к таблицам? Могу ли я получить доступ к процедурам? Документация гласит «Любое условное выражение SQL» , поэтому SELECT EXISTS должно быть в порядке
  • как имена столбцов строк сопоставляются с политикой. В примерах просто волшебным образом используются имена столбцов (которые я принял, используя переменную name), однако я не нашел никакой документации о том, что это на самом деле делает
  • что такое магия user_name переменная. От куда это? Я полагаю, что текущий role выполняет запрос, но как я могу узнать?
  • Почему для DELETE нет выражения WITH CHECK? Если я правильно понимаю, WITH CHECK будет fail любой строкой с недопустимым ограничением, такое поведение я бы предпочел (потому что иначе PostgREST всегда будет возвращать 204)

Я немногосбит с толку поразительно отсутствующим количеством информации в (иначе) очень хорошей документации PostgreSQL. Где эта информация? Как я могу его найти?

Ради полноты я также приложил следующие определения столбцов:

CREATE TABLE eventzimmer.locations (
  name varchar PRIMARY KEY NOT NULL,
  latitude float NOT NULL,
  longitude float NOT NULL
);

CREATE TABLE IF NOT EXISTS protected.locations_owners (
    name varchar NOT NULL REFERENCES eventzimmer.locations(name) ON DELETE CASCADE,
    sub varchar NOT NULL
);

1 Ответ

0 голосов
/ 09 октября 2019

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

Используйте EXPLAIN, чтобы увидеть план запроса, и вы увидите там условия политики.

  • Таким образом, вы можете использовать любые столбцы из таблицы, для которой определена политика.

    По сути, вы можете использовать в определении политики все, что можно использовать в условиях WHERE: вызовы функций, подзапросы и т. Д.

    Вы также можете квалифицировать имя столбца с именем таблицыесли это требуется для устранения неоднозначности. Это можно использовать в политике из вашего примера: неквалифицированный name интерпретируется как owners.name, поэтому тест всегда проходит успешно. Чтобы исправить политику, используйте locations.name вместо name.

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

  • WITH CHECK - это условие добавления новой строкиINSERT или UPDATE должны выполнить. Поскольку DELETE не добавляет никаких данных, WITH CHECK не применяется к ним.

...