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