CREATE POLICY#

Примечание

Эта страница переведена при помощи нейросети GigaChat.

CREATE POLICY — создание новой политики безопасности уровня строки для таблицы.

Синтаксис#

CREATE POLICY name ON table_name
  [ AS { PERMISSIVE | RESTRICTIVE } ]
  [ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ]
  [ TO { role_name | PUBLIC | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...] ]
  [ USING ( using_expression ) ]
  [ WITH CHECK ( check_expression ) ]

Описание#

CREATE POLICY предназначена для создания новой политики безопасности на уровне строк для заданной таблицы. Однако для того чтобы такие политики начали применяться, необходимо предварительно включить строковую безопасность с помощью ALTER TABLE ... ENABLE ROW LEVEL SECURITY.

Политика управляет доступом к строкам таблицы для операций SELECT, INSERT, UPDATE и DELETE. При этом:

  • выражение USING проверяет уже существующие строки — если результат true, строка становится видимой для пользователя. Если false или NULL, то строка скрыта;

  • выражение WITH CHECK проверяет новые данные, поступающие при вставке (INSERT) или изменении (UPDATE) — строка принимается, только если условие возвращает true, в противном случае происходит ошибка.

Проверка выражения WITH CHECK выполняется:

  • после выполнения триггеров BEFORE ROW;

  • до фактического изменения данных;

  • до любых других ограничений.

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

Политика может быть ограничена по команде (SELECT, INSERT, UPDATE, DELETE или ALL) и по ролям (например, конкретным пользователям).

По умолчанию политика применяется ко всем командам и всем ролям, если не указано иное. К одной команде может применяться несколько политик (смотрите ниже более подробную информацию). Политики, применяемые по типу команды описаны в разделе «Политики для каждой команды».

Если выражение WITH CHECK не задано, используется USING как для проверки видимости, так и для проверки новых данных.

При включенной безопасности на уровне строки, но отсутствии политик, действует «запрет по умолчанию» — доступ к строкам полностью блокируется.

Параметры#

name

Имя политики, которая должна быть создана. Оно должно отличаться от имени любой другой политики для этой таблицы.

table_name

Имя таблицы, при необходимости дополненное схемой, к которой применяется политика.

PERMISSIVE

Указывает, что политика создается как разрешающая. Все разрешающие политики, которые применимы к конкретному запросу, объединяются логическим оператором OR. Это означает, что если хотя бы одна из таких политик разрешает доступ к строке, доступ будет предоставлен. Использование разрешающих политик позволяет администраторам расширить набор строк, к которым может быть получен доступ. По умолчанию создаваемые политики являются разрешающими.

RESTRICTIVE

Указывает, что политика создается как ограничивающая. Все ограничивающие политики, применимые к конкретному запросу, объединяются логическим оператором AND. Это означает, что строка будет доступна только в том случае, если она соответствует всем таким политикам одновременно. Использование ограничивающих политик позволяет администраторам сужать доступ к данным.

Для того чтобы ограничивающие политики имели эффект, как минимум одна разрешающая политика должна разрешать доступ к строкам. Если заданы только ограничивающие политики, то никакие строки не будут доступны. В случае, когда присутствуют и разрешающие, и ограничивающие политики, строка будет доступна только при выполнении условия: хотя бы одна разрешающая политика должна возвращать true, и все ограничивающие — тоже true.

command

Указывает команду SQL, к которой применяется политика. Возможные значения: ALL, SELECT, INSERT, UPDATE, DELETE. По умолчанию используется ALL. Смотрите ниже информацию о том, как они применяются.

role_name

Указывает одну или несколько ролей, к которым применяется политика. Если не указано явно, по умолчанию используется PUBLIC, что означает применение политики ко всем ролям.

using_expression

Задает любое SQL-выражение, возвращающее логическое значение (boolean). Это выражение не должно содержать агрегатные или оконные функции. При включенной безопасности на уровне строк данное условие будет автоматически добавлено ко всем запросам, обращающимся к таблице. Строки, для которых выражение возвращает true, становятся видимыми пользователю. Если результат false или NULL, такие строки не отображаются в выборках (SELECT) и не могут быть изменены (UPDATE, DELETE). Эти строки исключаются без ошибок — система просто скрывает их от пользователя.

check_expression

Задает любое SQL-выражение, возвращающее логическое значение (boolean). Это выражение не должно содержать агрегатные или оконные функции. Выражение используется при выполнении команд INSERT и UPDATE, если включена безопасность на уровне строк. Только те строки, для которых выражение возвращает true, будут вставлены или обновлены. Если выражение вернет false или NULL хотя бы для одной строки, будет выдана ошибка. Обратите внимание: проверка производится не на исходных данных строки, а на предполагаемом новом содержимом после вставки или обновления.

Политики для каждой команды#

ALL

Если для политики указано ALL, это означает, что она применяется ко всем командам — SELECT, INSERT, UPDATE и DELETE. Если одновременно присутствуют как политика ALL, так и более специфичная (например, только для UPDATE), то обе будут применяться.

Кроме того, политика ALL используется как для чтения строк, так и для их изменения. Если задано только выражение USING, оно применяется в обоих случаях.

Например, при выполнении команды UPDATE:

  • выражение USING определяет, какие строки можно выбрать для обновления;

  • выражение WITH CHECK (если задано) проверяет, допустимы ли обновленные строки для сохранения в таблице. Если WITH CHECK не задано — используется USING.

Если попытка вставки или обновления приводит к строкам, не соответствующим выражению WITH CHECK в политике ALL, выполнение команды будет прервано с ошибкой.

SELECT

Использование SELECT для политики означает, что она будет применяться к запросам SELECT, а также ко всем операциям, где требуется право чтения данных из таблицы.

В результате возвращаются только те строки, которые соответствуют политики SELECT, и запрос, использующий право SELECT, например, запрос UPDATE, увидит только записи, разрешенные политикой SELECT.

Политика SELECT не может содержать выражение WITH CHECK, поскольку не применяется к операциям записи.

INSERT

Политика INSERT применяется к командам INSERT, а также к MERGE, если в нем есть действия INSERT.

Если строка, которую пытаются вставить, не проходит проверку выражением WITH CHECK, произойдет ошибка, и вся операция будет отменена. Политика INSERT не поддерживает выражение USING, так как она не используется для фильтрации уже существующих строк, а применяется только к новым.

Если используется INSERT ... ON CONFLICT DO UPDATE, проверка WITH CHECK выражения для политики INSERT выполняется только для строк, фактически вставляемых, а не для обновляемых.

UPDATE

Политика UPDATE применяется к следующим командам:

  • UPDATE;

  • SELECT FOR UPDATE;

  • SELECT FOR SHARE;

  • MERGE с действием UPDATE;

  • к конструкции ON CONFLICT DO UPDATE в INSERT.

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

  • USING определяет, какие строки можно выбрать для обновления;

  • WITH CHECK проверяет допустимость обновленной строки.

Если хотя бы одна строка после изменения не соответствует WITH CHECK, вся команда прерывается ошибкой. Если указано только USING, оно применяется в обоих случаях — и как фильтр, и как проверка.

Также часто UPDATE требует прав на чтение (например, для WHERE, RETURNING, или вычислений в SET). В таком случае дополнительно применяются политики SELECT или ALL. Таким образом, пользователь должен иметь доступ к строке(ам), которая(ые) обновляется через политику SELECT или ALL, в дополнение к предоставлению разрешения на обновление строки(ок) посредством политики UPDATE или ALL.

При INSERT ... ON CONFLICT DO UPDATE сначала строка проверяется по USING выражениям политики UPDATE, затем результат обновления проверяется через WITH CHECK.

Если строка не проходит USING, возникает ошибка, в отличие от обычного UPDATE, обновление никогда не пропускается, а прерывается.

DELETE

Политика DELETE применяется к команде DELETE. Только те строки, которые проходят проверку USING, могут быть удалены. Может возникнуть ситуация, когда строка видна через SELECT, но ее нельзя удалить, потому что она не проходит USING в политике DELETE.

В большинстве случаев DELETE требует чтения данных из таблицы (например, в WHERE или RETURNING). Поэтому применяются также соответствующие политики SELECT или ALL. Таким образом, пользователь должен иметь доступ к удаляемым строкам через политику SELECT или ALL, помимо того, что ему предоставлено разрешение на удаление строк через политику DELETE или ALL.

Политика DELETE не может содержать выражение WITH CHECK, поскольку при удалении нет новой строки, которую нужно проверять.

Политики, применяемые по типу команд:

  • SELECT

    Выражение

    Политика SELECT/ALL

    Политика INSERT/ALL

    Политика UPDATE/ALL

    Политика DELETE/ALL

    USING

    Существующая строка

    Х

    WITH CHECK

    Х

    Х

  • SELECT FOR UPDATE/SHARE

    Выражение

    Политика SELECT/ALL

    Политика INSERT/ALL

    Политика UPDATE/ALL

    Политика DELETE/ALL

    USING

    Существующая строка

    Х

    Существующая строка

    WITH CHECK

    Х

    Х

  • INSERT/MERGE ... THEN INSERT

    Выражение

    Политика SELECT/ALL

    Политика INSERT/ALL

    Политика UPDATE/ALL

    Политика DELETE/ALL

    USING

    Х

    WITH CHECK

    Х

    Новая строка

    Х

  • INSERT ... RETURNING

    Выражение

    Политика SELECT/ALL

    Политика INSERT/ALL

    ПолитикUPDATE/ALL

    Политика DELETE/ALL

    USING

    Новая строка [1]

    Х

    WITH CHECK

    Х

    Новая строка

    Х

  • INSERT/MERGE ... THEN UPDATE

    Выражение

    Политика SELECT/ALL

    Политика INSERT/ALL

    ПолитикUPDATE/ ALL

    Политика DELETE/ALL

    USING

    Существующие и новые строки [1]

    Х

    Существующая строка

    WITH CHECK

    Х

    Новая строка

    Х

  • DELETE

    Выражение

    Политика SELECT/ALL

    Политика INSERT/ALL

    Политика UPDATE/ALL

    Политика DELETE/ALL

    USING

    Существующая строка [1]

    Х

    Существующая строка

    WITH CHECK

    Х

    Х

  • ON CONFLICT DO UPDATE

    Выражение

    Политика SELECT/ALL

    Политика INSERT/ALL

    Политика UPDATE/ALL

    Политика DELETE/ALL

    USING

    Существующие и новые строки

    Х

    Существующая строка

    WITH CHECK

    Х

    Новая строка

    Х

Применение нескольких политик#

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

Если для одной команды задействованы несколько политик одного и того же типа (например, несколько политик UPDATE), они обрабатываются следующим образом:

  • должно быть хотя бы одно разрешающее правило (PERMISSIVE) — без него доступ будет полностью запрещен;

  • все разрешающие выражения (PERMISSIVE) объединяются между собой оператором OR;

  • все ограничивающие выражения (RESTRICTIVE) объединяются оператором AND;

  • затем оба результата объединяются оператором AND.

При объединении нескольких политик, политики ALL применяются как политики каждого применимого в данном случае типа.

Например, в команде UPDATE, требующей разрешений и для SELECT, и для UPDATE, в случае существования нескольких применимых политик каждого типа они будут объеденины следующим образом:

expression from RESTRICTIVE SELECT/ALL policy 1
AND
expression from RESTRICTIVE SELECT/ALL policy 2
AND
...
AND
(
  expression from PERMISSIVE SELECT/ALL policy 1
  OR
  expression from PERMISSIVE SELECT/ALL policy 2
  OR
  ...
)
AND
expression from RESTRICTIVE UPDATE/ALL policy 1
AND
expression from RESTRICTIVE UPDATE/ALL policy 2
AND
...
AND
(
  expression from PERMISSIVE UPDATE/ALL policy 1
  OR
  expression from PERMISSIVE UPDATE/ALL policy 2
  OR
  ...
)

Примечания#

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

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

Например, если пользователь вставляет значение в столбец с ограничением уникальности или первичным ключом, и произойдет ошибка (дублирование), можно сделать вывод, что такое значение уже существует в таблице — даже если напрямую видеть эту строку пользователю не разрешено политиками. Подобный способ может использоваться и при вставке в таблицу, содержащую внешний ключ на другую таблицу, которая иначе для пользователя недоступна: успешная вставка означает, что соответствующее значение присутствует в связанной таблице.

Чтобы исключить такие утечки, политики безопасности следует разрабатывать особенно тщательно: можно либо полностью запретить пользователям выполнять операции INSERT, UPDATE и DELETE, которые могут выдать существование скрытых данных, либо использовать суррогатные ключи (генерируемые значения, не несущие смысловой нагрузки), чтобы минимизировать вероятность такой утечки.

Условия фильтрации, заданные в политиках безопасности, применяются раньше, чем условия, указанные в пользовательских запросах (WHERE, RETURNING и другие). Это делается для защиты данных от потенциально недоверенных пользовательских функций, которые могли бы раскрыть конфиденциальную информацию. Однако функции и операторы, помеченные как LEAKPROOF, могут быть выполнены до применения политик, поскольку они считаются безопасными.

Так как выражения политик встраиваются напрямую в пользовательские запросы, они выполняются от имени пользователя, инициировавшего запрос. Поэтому пользователь должен иметь соответствующие права доступа ко всем таблицам и функциям, упомянутым в выражении политики. В противном случае он получит ошибку permission denied при попытке обращения к защищенной таблице.

Однако при работе с представлениями (VIEW) действует другая логика: как и в обычных случаях, разрешения и политики для таблиц, на которые ссылается представление, проверяются от имени владельца представления. Исключение составляют представления, созданные с параметром security_invoker (смотрите CREATE VIEW).

Для команды MERGE не существует отдельного типа политики. Вместо этого при выполнении MERGE применяются соответствующие политики SELECT, INSERT, UPDATE и DELETE — в зависимости от конкретных действий, выполняемых внутри команды.

Совместимость#

CREATE POLICY является расширением PostgreSQL.

Смотрите также#

ALTER POLICY, DROP POLICY, ALTER TABLE