CREATE POLICY
- :::{note} Эта страница переведена при помощи нейросети 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/ALLUSINGСуществующая строка Х — — WITH CHECKХ — — Х -
SELECT FOR UPDATE/SHAREВыражение Политика SELECT/ALLПолитика INSERT/ALLПолитика UPDATE/ALLПолитика DELETE/ALLUSINGСуществующая строка Х Существующая строка — WITH CHECKХ — — Х -
INSERT/MERGE ... THEN INSERTВыражение Политика SELECT/ALLПолитика INSERT/ALLПолитика UPDATE/ALLПолитика DELETE/ALLUSING— Х — — WITH CHECKХ Новая строка — Х -
INSERT ... RETURNINGВыражение Политика SELECT/ALLПолитика INSERT/ALLПолитик UPDATE/ALLПолитика DELETE/ALLUSINGНовая строка 1 Х — — WITH CHECKХ Новая строка — Х -
INSERT/MERGE ... THEN UPDATEВыражение Политика SELECT/ALLПолитика INSERT/ALLПолитик UPDATE/ALLПолитика DELETE/ALLUSINGСуществующие и новые строки 1 Х Существующая строка — WITH CHECKХ — Новая строка Х -
DELETEВыражение Политика SELECT/ALLПолитика INSERT/ALLПолитика UPDATE/ALLПолитика DELETE/ALLUSINGСуществующая строка 1 Х — Существующая строка WITH CHECKХ — — Х -
ON CONFLICT DO UPDATEВыражение Политика SELECT/ALLПолитика INSERT/ALLПолитика UPDATE/ALLПолитика DELETE/ALLUSINGСуществующие и новые строки Х Существующая строка — 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