CREATE POLICY — создать новую политику защиты на уровне строк для таблицы
CREATE POLICYимяONимя_таблицы[ AS { PERMISSIVE | RESTRICTIVE } ] [ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ] [ TO {имя_роли| PUBLIC | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...] ] [ USING (выражение_USING) ] [ WITH CHECK (выражение_CHECK) ]
Команда CREATE POLICY определяет для таблицы новую политику защиты на уровне строк. Заметьте, что для таблицы должна быть включена защита на уровне строк (используя ALTER TABLE ... ENABLE ROW LEVEL SECURITY), чтобы созданные политики действовали.
A policy grants the permission to select, insert, update, or delete rows
that match the relevant policy expression. Existing table rows are
checked against the expression specified in USING,
while new rows that would be created via INSERT
or UPDATE are checked against the expression specified
in WITH CHECK. When a USING
expression returns true for a given row then that row is visible to the
user, while if false or null is returned then the row is not visible.
Typically, no error occurs when a row is not visible, but see
Таблица 294 for exceptions.
When a WITH CHECK expression returns true for a row
then that row is inserted or updated, while if false or null is returned
then an error occurs.
Для операторов INSERT, UPDATE и MERGE выражения WITH CHECK применяются после срабатывания триггеров BEFORE, но до того, как будут собственно модифицированы данные. Таким образом, триггер BEFORE ROW может изменить данные, подлежащие добавлению, и повлиять на результат условия политики защиты. Выражения WITH CHECK обрабатываются до каких-либо других ограничений.
Имена политик задаются на уровне таблицы. Таким образом, одно имя политики можно использовать в нескольких разных таблицах и в каждой дать отдельное, подходящее этой таблице определение политики.
Политики могут применяться для определённых команд или для определённых ролей. По умолчанию создаваемые политики применяются для всех команд и ролей, если явно не задано другое. К одной команде могут применяться несколько политик; подробнее рассказывается ниже. В Таблице 294 показано, как к определённым командам применяются разные типы политик.
Для политик, которые могут иметь и выражения USING, и выражения WITH CHECK (ALL и UPDATE), в случае отсутствия выражения WITH CHECK выражение USING будет использоваться и для определения видимости строк (обычное назначение USING) и для определения, какие строки разрешено добавить (назначение WITH CHECK).
Если для таблицы включена защита на уровне строк, но применимые политики отсутствуют, предполагается политика «запрета по умолчанию», так что никакие строки нельзя будет увидеть или изменить.
имяИмя создаваемой политики. Оно должно отличаться от имён других политик для этой таблицы.
имя_таблицыИмя (возможно, дополненное схемой) существующей таблицы (или представления), к которой применяется эта политика.
PERMISSIVEУказывает, что создаваемая политика должна быть разрешительной. Все разрешительные политики, которые применяются к данному запросу, будут объединяться вместе логическим оператором «ИЛИ». Создавая разрешительные политики, администраторы могут расширять множество записей, к которым можно обращаться. Политики являются разрешительными по умолчанию.
RESTRICTIVEУказывает, что создаваемая политика должна быть ограничительной. Все ограничительные политики, которые применяются к данному запросу, будут объединяться вместе логическим оператором «И». Создавая ограничительные политики, администраторы могут сократить множество записей, к которым можно обращаться, так как для каждой записи должны удовлетворяться все ограничительные политики.
Заметьте, что для получения доступа к записям должна быть определена минимум одна разрешительная политика, и только в дополнение к ней могут быть определены имеющие смысл ограничительные политики, ограничивающие доступ. Если разрешительные политики отсутствуют, ни к каким записям обращаться нельзя. Когда определены и разрешительные, и ограничительные политики, запись будет доступна, если удовлетворяется минимум одна из разрешительных политик и все ограничительные.
командаКоманда, к которой применяется политика. Допустимые варианты: ALL, SELECT, INSERT, UPDATE и DELETE. ALL (все) подразумевается по умолчанию. Особенности их применения описаны ниже.
имя_ролиРоль (роли), к которой применяется политика. По умолчанию подразумевается PUBLIC, то есть политика применяется ко всем ролям.
выражение_USING
Any SQL conditional expression (returning
boolean). The conditional expression cannot contain
any aggregate or window functions. This expression will be added
to queries that refer to the table if row-level security is enabled.
Rows for which the expression returns true will be visible. Any
rows for which the expression returns false or null will not be
visible to the user (in a SELECT), and will not be
available for modification (in an UPDATE
or DELETE). Typically, such rows are silently
suppressed; no error is reported (but see
Таблица 294 for exceptions).
выражение_CHECKПроизвольное условное выражение SQL (возвращающее boolean). Это условное выражение не может содержать агрегатные или оконные функции. Когда включена защита на уровне строк, оно применяется в запросах INSERT и UPDATE к этой таблице, так что в них принимаются только те строки, для которых оно выдаёт true. Если это выражение выдаёт false или NULL для любой из добавляемых записей или записей, получаемых при изменении, выдаётся ошибка. Заметьте, что ограничение_проверки вычисляется для предлагаемого нового содержимого строки, а не для существующих данных.
ALL #Указание ALL для политики означает, что она применяется ко всем командам, вне зависимости от типа. Если существует политика ALL и другие более детализированные политики, тогда будет применяться и политика ALL, и более детализированная политика (или политики). Кроме того, политики ALL с выражением USING будут применяться и к стороне выборки, и к стороне изменения данных в запросе, если определено только выражение USING.
As an example, if an UPDATE is issued, then the
ALL policy will be applicable both to what the
UPDATE will be able to select as rows to be
updated (applying the USING expression),
and to the resulting updated rows, to check if they are permitted
to be added to the table (applying the WITH CHECK
expression, if defined, and the USING expression
otherwise). If an INSERT
or UPDATE command attempts to add rows to the
table that do not pass the ALL
policy's WITH CHECK expression (or its
USING expression, if it does not have a
WITH CHECK expression), the entire command will
be aborted.
SELECT #
Using SELECT for a policy means that it will apply
to SELECT queries and whenever
SELECT permissions are required on the relation the
policy is defined for. The result is that only those records from the
relation that pass the SELECT policy will be
returned during a SELECT query, and that queries
that require SELECT permissions, such as
UPDATE, DELETE, and
MERGE, will also only see those records
that are allowed by the SELECT policy.
A SELECT policy cannot have a WITH
CHECK expression, as it only applies in cases where
records are being retrieved from the relation, except as described
below.
If a data-modifying query has a RETURNING clause,
SELECT permissions are required on the relation,
and any newly inserted or updated rows from the relation must satisfy
the relation's SELECT policies in order to be
available to the RETURNING clause. If a newly
inserted or updated row does not satisfy the relation's
SELECT policies, an error will be thrown (inserted
or updated rows to be returned are never
silently ignored).
If an INSERT has an ON CONFLICT DO
NOTHING/UPDATE clause, SELECT
permissions are required on the relation, and the rows proposed for
insertion are checked using the relation's SELECT
policies. If a row proposed for insertion does not satisfy the
relation's SELECT policies, an error is thrown
(the INSERT is never silently
avoided). In addition, if the UPDATE path is
taken, the row to be updated and the new updated row are checked
against the relation's SELECT policies, and an
error is thrown if they are not satisfied (an auxiliary
UPDATE is never silently
avoided).
A MERGE command requires SELECT
permissions on both the source and target relations, and so each
relation's SELECT policies are applied before they
are joined, and the MERGE actions will only see
those records that are allowed by those policies. In addition, if
an UPDATE action is executed, the target relation's
SELECT policies are applied to the updated row, as
for a standalone UPDATE, except that an error is
thrown if they are not satisfied.
INSERT #Указание INSERT для политики означает, что она применяется к командам INSERT, а также к командам MERGE с действиями INSERT. Если вставляемые строки не проходят проверку политики, выдаётся ошибка нарушения политики и вся команда INSERT прерывается. Для политики INSERT не может задаваться выражение USING, так как она действует только когда в отношение добавляются записи.
Note that an INSERT with an ON CONFLICT
DO NOTHING/UPDATE clause will check the
INSERT policies' WITH CHECK
expressions for all rows proposed for insertion, regardless of
whether or not they end up being inserted.
UPDATE #
Using UPDATE for a policy means that it will apply
to UPDATE, SELECT FOR UPDATE,
and SELECT FOR SHARE commands, as well as
auxiliary ON CONFLICT DO UPDATE clauses of
INSERT commands, and MERGE
commands containing UPDATE actions.
Since an UPDATE command
involves pulling an existing record and replacing it with a new
modified record, UPDATE
policies accept both a USING expression and
a WITH CHECK expression.
The USING expression determines which records
the UPDATE command will see to operate against,
while the WITH CHECK expression defines which
modified rows are allowed to be stored back into the relation.
Если в какой-либо строке изменённые значения не будут удовлетворять выражению WITH CHECK, произойдёт ошибка и вся команда будет прервана. Если указывается только предложение USING, его выражение будет применяться и в качестве USING, и в качестве выражения WITH CHECK.
Обычно команде UPDATE также нужно прочитать данные из столбцов подлежащего изменению отношения (например, в предложении WHERE или RETURNING либо в выражении в правой части предложения SET). В этом случае также требуется иметь права SELECT в изменяемом отношении и в дополнение к политикам UPDATE будут применяться соответствующие политики SELECT или ALL. Таким образом, помимо того, что пользователю должны разрешать изменение строк политики UPDATE или ALL, ему также должны разрешать доступ к изменяемым строкам политики SELECT или ALL.
When an INSERT command has an auxiliary
ON CONFLICT DO UPDATE clause, if the
UPDATE path is taken, the row to be updated is
first checked against the USING expressions of
any UPDATE policies, and then the new updated row
is checked against the WITH CHECK expressions.
Note, however, that unlike a standalone UPDATE
command, if the existing row does not pass the
USING expressions, an error will be thrown (the
UPDATE path will never be silently
avoided). The same applies to an UPDATE action
of a MERGE command.
DELETE #
Using DELETE for a policy means that it will apply
to DELETE commands and MERGE
commands containing DELETE actions. For a
DELETE command, only rows that pass this policy
will be seen by the DELETE command. There can
be rows that are visible through a SELECT policy
that are not available for deletion, if they do not pass the
USING expression for the DELETE
policy. Note, however, that a DELETE action in a
MERGE command will see rows that are visible
through SELECT policies, and if the
DELETE policy does not pass for such a row, an
error will be thrown.
В большинстве случаев команде DELETE также нужно прочитать данные из столбцов в отношении, из которого осуществляется удаление (например, в предложении WHERE или RETURNING). В таких случаях необходимо также иметь право SELECT для этого отношения, и в дополнение к политикам DELETE будут применятся соответствующие политики SELECT или ALL. Таким образом, пользователь должен получить доступ к удаляемым строкам через политики SELECT или ALL, помимо того что удаление этих строк ему должны разрешить политики DELETE или ALL.
Для политики DELETE не может задаваться выражение WITH CHECK, так как она применяется только тогда, когда записи удаляются из отношения, а в этом случае новые строки, подлежащие проверке, отсутствуют.
Таблица 294 summarizes how the different types of policy apply to specific commands. In the table, «check» means that the policy expression is checked and an error is thrown if it returns false or null, whereas «filter» means that the row is silently ignored if the policy expression returns false or null.
Таблица 294. Политики, применяемые для разных команд
| Команда | Политика SELECT/ALL | Политика INSERT/ALL | Политика UPDATE/ALL | Политика DELETE/ALL | |
|---|---|---|---|---|---|
Выражение USING | Выражение WITH CHECK | Выражение USING | Выражение WITH CHECK | Выражение USING | |
SELECT / COPY ... TO | Filter existing row | — | — | — | — |
SELECT FOR UPDATE/SHARE | Filter existing row | — | Filter existing row | — | — |
INSERT | Check new row [a] | Check new row | — | — | — |
UPDATE | Filter existing row [a] & check new row [a] | — | Filter existing row | Check new row | — |
DELETE | Filter existing row [a] | — | — | — | Filter existing row |
INSERT ... ON CONFLICT | Check new row [b] | Check new row [b] | — | — | — |
ON CONFLICT DO UPDATE | Check existing & new rows [c] | — | Check existing row | Check new row [c] | — |
MERGE | Filter source & target rows | — | — | — | — |
MERGE ... THEN INSERT | — | Check new row | — | — | — |
MERGE ... THEN UPDATE | Check new row | — | Check existing row | Check new row | — |
MERGE ... THEN DELETE | — | — | — | — | Check existing row |
[a]
If read access is required to either the existing or new row (for
example, a [b] Row proposed for insertion is checked regardless of whether or not a conflict occurs. [c]
New row of the auxiliary | |||||
Когда к одной команде применяются несколько политик для различных типов команд (например, политики SELECT и UPDATE применяются к команде UPDATE), пользователь должен иметь разрешения всех этих типов (например, разрешение для выборки строк из отношения, а также разрешение на их изменение). Таким образом, выражения для одного типа политики комбинируются с выражениями для другого типа операцией И.
Когда к одной команде применяются несколько политик для одного типа команды, доступ к отношению должна дать как минимум одна разрешительная (PERMISSIVE) политика, а также должны удовлетворяться все ограничительные (RESTRICTIVE) политики. Таким образом выражения всех политик PERMISSIVE объединяются операцией ИЛИ, выражения всех политик RESTRICTIVE объединяются операцией И, а полученные результаты объединяются операцией И. Если политики PERMISSIVE отсутствуют, доступ запрещается.
Заметьте, что при объединении нескольких политик, политики ALL применяются как политики каждого применимого в данном случае типа.
Например, в команде UPDATE, требующей разрешений и для SELECT, и для UPDATE, в случае существования нескольких применимых политик каждого типа они будут объединяться следующим образом:
выражениеfrom RESTRICTIVE SELECT/ALL policy 1 ANDвыражениеfrom RESTRICTIVE SELECT/ALL policy 2 AND ... AND (выражениеfrom PERMISSIVE SELECT/ALL policy 1 ORвыражениеfrom PERMISSIVE SELECT/ALL policy 2 OR ... ) ANDвыражениеfrom RESTRICTIVE UPDATE/ALL policy 1 ANDвыражениеfrom RESTRICTIVE UPDATE/ALL policy 2 AND ... AND (выражениеfrom PERMISSIVE UPDATE/ALL policy 1 ORвыражениеfrom PERMISSIVE UPDATE/ALL policy 2 OR ... )
Чтобы создать или изменить политики для таблицы, нужно быть её владельцем.
Хотя политики применяются к явно выполняемым запросам к таблицам БД, они не применяются, когда система выполняет внутренние проверки ссылочной целостности или проверяет ограничения. Это означает, что существуют косвенные пути проверить существование заданного значения. Например, можно попытаться вставить повторяющееся значение в столбец, образующий первичный ключ или имеющую ограничение уникальности. Если при этом произойдёт ошибка, пользователь может заключить, что это значение уже существует. (В данном случае предполагается, что политика разрешает пользователю вставлять записи, которые он может не видеть.) Подобный приём также возможен, если пользователь может вставлять записи в таблицу, которая ссылается на другую, иным образом не видимую. Существование значения можно определить, вставив его в подчинённую таблицу, при этом успешный результат операции будет признаком того, что это значение есть в главной таблице. Эти изъяны можно устранить, либо тщательно разработав политики, которые вовсе не позволят пользователям выполнять операции добавления, изменения и удаления, по результатам которых можно узнать о значениях в таблицах, не видимых иным образом, либо используя генерируемые значения (например, суррогатные ключи).
Вообще система будет применять фильтры, устанавливаемые политиками безопасности, до условий в запросах пользователя, чтобы предотвратить нежелательную утечку защищаемых данных через пользовательские функции, которые могут быть недоверенными. Однако функции и операторы, помеченные системой (или системным администратором) как LEAKPROOF (герметичные) могут вычисляться до условий политики, так как они считаются доверенными.
Так как выражения политики добавляются непосредственно в запрос пользователя, они выполняются с правами пользователя, запускающего исходный запрос. Таким образом, пользователи, на которых распространяется заданная политика, должны иметь права для обращения ко всем таблицам и функциям, задействованным в выражении, иначе им просто будет отказано в доступе при попытке обращения к целевой таблице (если для неё включена защита на уровне строк). Однако это не влияет на работу представлений — как и с обычными запросами и представлениями, проверки разрешений и политики для нижележащих таблиц представления будут выполняться с правами владельца представления, и при этом будут действовать политики, распространяющиеся на этого владельца, за исключением случаев, когда представление определяется с характеристикой security_invoker (см. CREATE VIEW).
Для MERGE не существует отдельной политики. Когда выполняется MERGE, в зависимости от фактически выполняемых действий применяются политики, определённые для SELECT, INSERT, UPDATE и DELETE.
Дополнительное описание и практические примеры можно найти в Разделе 5.8.
CREATE POLICY является расширением PostgreSQL.