Перейти к основному содержимому

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

Footnotes

  1. если для существующей или новой строки требуется доступ на чтение (например, предложение WHERE или RETURNING, обращающееся к столбцам отношения). 2 3