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).
Политика предоставляет разрешение на выборку, вставку, обновление или удаление строк, соответствующих соответствующему выражению политики. Существующие строки таблицы проверяются по выражению, указанному в USING, тогда как новые строки, создаваемые с помощью INSERT или UPDATE, проверяются по выражению, указанному в WITH CHECK. Если выражение USING возвращает true для данной строки, эта строка видна пользователю; если возвращается false или null, строка не видна. Как правило, ошибка не возникает, если строка не видна, но исключения смотрите в таблице 300. Если выражение WITH CHECK возвращает true для строки, эта строка вставляется или обновляется; если возвращается false или null, возникает ошибка.
Для операторов INSERT, UPDATE и MERGE выражения WITH CHECK применяются после срабатывания триггеров BEFORE и до фактического изменения данных. Таким образом, триггер BEFORE ROW может изменить данные, подлежащие вставке, что повлияет на результат проверки политики безопасности. Выражения WITH CHECK применяются до любых других ограничений.
Имена политик задаются отдельно для каждой таблицы. Следовательно, одно и то же имя политики может использоваться для множества разных таблиц, имея свое определение для каждой из них, соответствующее этой таблице.
Политики могут применяться для конкретных команд или конкретных ролей. По умолчанию вновь созданные политики применяются ко всем командам и ролям, если не указано иное. К одной команде могут применяться несколько политик; подробнее смотрите ниже. В таблице 300 обобщено, как различные типы политик применяются к конкретным командам.
Для политик, которые могут иметь как выражение USING, так и WITH CHECK (ALL и UPDATE), если выражение WITH CHECK не определено, то выражение USING будет использоваться как для определения видимости строк (обычный случай USING), так и для определения того, какие новые строки разрешено добавлять (случай WITH CHECK).
Если для таблицы включена безопасность на уровне строк, но не существует применимых политик, подразумевается политика «запрет по умолчанию» (default deny), в результате чего ни одна строка не будет видна или доступна для обновления.
Параметры
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 вернет только те записи из отношения, которые проходят проверку политики SELECT, а запросы, требующие разрешений SELECT (например, UPDATE, DELETE и MERGE), также будут «видеть» только те записи, которые разрешены политикой SELECT. Политика SELECT не может содержать выражение WITH CHECK, так как она применяется только в случаях извлечения записей из отношения, за исключением описанных ниже.
Если запрос, изменяющий данные, содержит предложение RETURNING, требуются разрешения SELECT на отношении, и любые вновь вставленные или обновленные строки должны удовлетворять политикам SELECT этого отношения, чтобы быть доступными для предложения RETURNING. Если вновь вставленная или обновленная строка не удовлетворяет политикам SELECT отношения, будет вызвана ошибка (вставленные или обновленные строки, подлежащие возврату, никогда не игнорируются без генерации ошибки).
Если команда INSERT содержит предложение ON CONFLICT DO UPDATE или предложение ON CONFLICT DO NOTHING с указанием арбитражного индекса или ограничения, требуются разрешения SELECT на отношении, и строки, предлагаемые для вставки, проверяются с использованием политик SELECT этого отношения. Если строка, предлагаемая для вставки, не удовлетворяет политикам SELECT отношения, возникает ошибка (команда INSERT никогда не пропускается без генерации ошибки). Кроме того, если выполняется ветвь UPDATE, строка, подлежащая обновлению, и новая обновленная строка проверяются на соответствие политикам SELECT отношения, и при несоответствии возникает ошибка (вспомогательное обновление никогда не отменяется без генерации ошибки).
Команда MERGE требует разрешений SELECT как на исходном, так и на целевом отношении, поэтому политики SELECT каждого отношения применяются до их соединения, и действия MERGE будут «видеть» только те записи, которые разрешены этими политиками. Кроме того, если выполняется действие UPDATE, к обновленной строке применяются политики SELECT целевого отношения (как для самостоятельного UPDATE), за исключением того, что при несоответствии возникает ошибка.
INSERT
Использование INSERT в качестве политики означает, что она будет применяться к командам INSERT и MERGE, содержащим действия INSERT. Вставка строк, не соответствующих этой политике, приведет к ошибке нарушения политики, и вся команда INSERT будет прервана. Политика INSERT не может содержать выражение USING, поскольку она применяется только в случаях добавления записей в отношение.
Обратите внимание, что INSERT с предложением ON CONFLICT DO NOTHING/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 и командам MERGE, содержащим действия DELETE. Для команды DELETE только те строки, которые проходят проверку этой политики, будут видны команде DELETE. Могут существовать строки, видимые через политику SELECT, которые недоступны для удаления, если они не проходят проверку выражения USING для политики DELETE. Обратите внимание, однако, что действие DELETE в команде MERGE будет видеть строки, видимые через политики SELECT, и если для такой строки не проходит проверка политики DELETE, будет вызвана ошибка.
В большинстве случаев команде DELETE также требуется читать данные из столбцов отношения, из которого выполняется удаление (например, в предложении WHERE или RETURNING). В этом случае также требуются разрешения SELECT на отношении, и соответствующие политики SELECT или ALL будут применяться дополнительно к политикам DELETE. Таким образом, пользователь должен иметь доступ к удаляемой строке (строкам) через политику SELECT или ALL в дополнение к разрешению на удаление строки (строк) через политику DELETE или ALL.
Политика DELETE не может содержать выражение WITH CHECK, так как она применяется только в случаях удаления записей из отношения, где новая строка для проверки отсутствует.
В таблице ниже приведено краткое описание того, как различные типы политик применяются к конкретным командам. В таблице «check» означает, что выражение политики проверяется, и если оно возвращает false или null, генерируется ошибка, тогда как «filter» означает, что строка молча игнорируется, если выражение политики возвращает false или null.
Политики, применяемые по типу команд:
| Команда | Политика SELECT/ALL | Политика INSERT/ALL | Политика UPDATE/ALL | Политика DELETE/ALL | |
|---|---|---|---|---|---|
Выражение USING | Выражение WITH CHECK | Выражение USING | Выражение WITH CHECK | Выражение USING | |
SELECT / COPY ... TO | Отбор существующей строки | — | — | — | — |
SELECT FOR UPDATE/SHARE | Отбор существующей строки | — | Отбор существующей строки | — | — |
INSERT | Проверка новой строки [a] | Проверка новой строки | — | — | — |
UPDATE | Отбор существующей строки [a] и проверка новой строки [a] | — | Отбор существующей строки | Проверка новой строки | — |
DELETE | Отбор существующей строки [a] | — | — | — | Отбор существующей строки |
INSERT ... ON CONFLICT | Проверка новой строки [b][c] | Проверка новой строки [c] | — | — | — |
ON CONFLICT DO UPDATE | Проверка существующей и новой строк [d] | — | Отбор существующей строки | Проверка новой строки [d] | — |
MERGE | Отбор исходных и целевых строк | — | — | — | — |
MERGE ... THEN INSERT | Проверка новой строки [a] | Проверка новой строки | — | — | — |
MERGE ... THEN UPDATE | Проверка новой строки | — | Отбор существующей строки | Проверка новой строки | — |
MERGE ... THEN DELETE | — | — | — | — | Отбор существующей строки |
[a] Если требуется доступ на чтение к существующей или новой строке (например, предложение WHERE или RETURNING, ссылающееся на столбцы из отношения).
[b] Если указан индекс арбитра или ограничение.
[c] Строка, предлагаемая для вставки, проверяется независимо от того, возникает ли конфликт.
[d] Новая строка вспомогательной команды UPDATE, которая может отличаться от новой строки исходной команды INSERT.
Применение нескольких политик
Если при выполнении одной команды задействованы политики разных типов (например, и 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.