CREATE POLICY

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).

Политика предоставляет разрешение на выборку, добавление, обновление или удаление строк, удовлетворяющих соответствующему выражению политики. Существующие строки таблицы сравниваются с выражением, указанным в в USING, в то время как новые строки, которые будут созданы с помощью INSERT или UPDATE, проверяются на соответствие выражению, указанному в WITH CHECK. Когда выражение USING возвращает для данной строки true, эта строка видна пользователю, а если возвращается false или NULL, то не видна. Когда выражение WITH CHECK возвращает для строки значение true, эта строка добавляется или обновляется, а если возвращается значение false или NULL, то возникает ошибка.

Для операторов INSERT и UPDATE выражения WITH CHECK применяются после того, как срабатывают триггеры BEFORE, но до того, как будут сделаны какие-либо фактические изменения данных. Таким образом, триггер BEFORE ROW может изменять добавляемые данные, влияя на результат проверки политики защиты. Выражения WITH CHECK применяются перед любыми другими ограничениями.

Имена политик указаны на уровне таблицы. Поэтому одно имя политики может использоваться для нескольких разных таблиц и в каждой дать отдельное определение политики, подходящее этой конкретной таблице.

Политики могут применяться для определенных команд или для определенных ролей. По умолчанию вновь созданные политики применяются для всех команд и ролей, если не указано иное. К одной команде может применяться несколько политик; дополнительную информацию см. ниже. В таблице Политики, применяемые по типу команды показано, как различные типы политик применяются к определенным командам.

Для политик, которые могут иметь и выражения USING, и выражения WITH CHECK (ALL и UPDATE), в случае отсутствия выражения WITH CHECK выражение USING будет использоваться и для определения того, какие строки будут видимыми (обычное назначение USING), и для определения того, какие новые строки будет разрешено добавить (назначение WITH CHECK)

Если для таблицы включена защита на уровне строк, но применимые политики отсутствуют, то предполагается политика «по умолчанию запретить», чтобы никакие строки не были видны или доступны для обновления.


Параметры

имя

Имя создаваемой политики. Должно отличаться от имени любой другой политики для таблицы.

имя_таблицы

Имя таблицы, к которой применяется политика (может быть дополнено схемой).

PERMISSIVE

Указывает, что политика должна быть создана как разрешительная. Все разрешительные политики, применимые к данному запросу, будут объединены с помощью логического оператора «ИЛИ». Создавая разрешительные политики, администраторы могут расширить множество записей, к которым можно обращаться. По умолчанию политики являются разрешительными.

RESTRICTIVE

Указывает, что политика должна быть создана как ограничительная. Все ограничительные политики, применимые к данному запросу, будут объединены с помощью логического оператора «И». Создавая ограничительные политики, администраторы могут сократить множество записей, к которым можно обращаться, так как для каждой записи должны удовлетворяться все ограничительные политики.

Обратите внимание, что для предоставления доступа к записям необходима хотя бы одна разрешительная политика, и только после этого возможно успешное использование ограничительных политик для сокращения этого доступа. Если существуют только ограничительные политики, то никакие записи не будут доступны. При наличии сочетания разрешительных и ограничительных политик запись доступна только в том случае, если кроме всех ограничительных политик удовлетворяется как минимум одна из разрешительных.

команда

Команда, к которой применяется политика. Допустимые варианты: ALL, SELECT, INSERT, UPDATE и DELETE. По умолчанию подразумевается ALL (все). Особенности их применения описаны ниже.

имя_роли

Роль (или роли), к которой будет применяться политика. Значение по умолчанию равно PUBLIC, то есть политика применяется ко всем ролям.

выражение_USING

Произвольное условное выражение SQL (возвращающее boolean). Условное выражение не может содержать никаких агрегатных или оконных функций. Это выражение будет добавлено в запросы, обращающиеся к данной таблице, если включена защита на уровне строк. Строки, для которых выражение возвращает true, будут видны. Любые строки, для которых выражение возвращает значение false или NULL, не будут видны пользователю (в запросе SELECT) и не будут доступны для изменения (в запросе UPDATE или DELETE). Такая строка просто пропускается; ошибка при этом не выдается.

выражение_CHECK

Произвольное условное выражение SQL (возвращающее boolean). Условное выражение не может содержать никаких агрегатных или оконных функций. Это выражение будет использоваться в запросах INSERT и UPDATE к таблице, если включена защита на уровне строк, так что в них принимаются только те строки, для которых оно выдает true. Если это выражение выдает false или NULL для любой из добавляемых записей или записей, получаемых при изменении, выдается ошибка. Обратите внимание, что выражение_CHECK вычисляется для предлагаемого нового содержимого строки, а не для существующих данных.


Политики по командам

ALL

Указание ALL для политики означает, что она будет применяться ко всем командам, независимо от типа последних. Если существует политика ALL и другие более детализированные политики, то будут применяться и политика ALL, и более детализированная политика (или политики). Вдобавок политики ALL будут применяться как к стороне выборки, так и к стороне изменения данных в запросе, используя в обоих случаях выражение USING, если было определено только оно.

Например, когда выполняется UPDATE, политика ALL будет фильтровать и строки, которые UPDATE сможет выбрать для изменения (применяя выражение USING), и итоговые измененные строки, проверяя, разрешено ли записать их в таблицу (применяя выражение WITH CHECK, если оно определено, или, в противном случае, USING). Если команда INSERT или UPDATE пытается добавить в таблицу строки, не удовлетворяющие выражению WITH CHECK политики ALL, вся команда будет прервана.

SELECT

Указание SELECT для политики означает, что она будет применяться к запросам SELECT всякий раз, когда при обращении к отношению, для которого определена политика, требуется право SELECT. Результатом является то, что запрос SELECT выдаст только те записи из отношения, которые удовлетворят политике SELECT, и запросы, использующие право SELECT, например запрос UPDATE, увидят только записи, разрешенные политикой SELECT. Для политики SELECT не может задаваться выражение WITH CHECK, так как оно действует, только когда записи читаются из отношения.

INSERT

Указание INSERT для политики означает, что она будет применяться к командам INSERT. Попытка добавления строк, которые не удовлетворят этой политике, приведет к ошибке нарушения политики, и вся команда INSERT будет прервана. Для политики INSERT не может задаваться выражение USING, так как она действует, только когда в отношение добавляются записи.

Обратите внимание, что INSERT с указанием ON CONFLICT DO UPDATE проверяет выражения WITH CHECK политик INSERT только для строк, добавляемых в отношение по пути INSERT.

UPDATE

Указание UPDATE для политики означает, что она будет применяться к командам UPDATE, SELECT FOR UPDATE и SELECT FOR SHARE, а также к дополнительным предложениям ON CONFLICT DO UPDATE команд INSERT. Так как UPDATE подразумевает извлечение существующей записи и замену ее новой измененной записью, политики UPDATE принимают оба выражения: и USING, и WITH CHECK. Выражение USING определяет, какие записи команда UPDATE будет видеть для работы с ними, в то время как выражение WITH CHECK определяет, какие измененные строки могут быть сохранены в отношении.

Любые строки, измененные значения которых не будут удовлетворять выражению WITH CHECK, вызовут ошибку, и вся команда будет прервана. Если указывается только предложение USING, оно будет применяться и в качестве, собственно, USING, и в качестве выражения WITH CHECK.

Как правило, команда UPDATE также должна считывать данные из столбцов подлежащего изменению отношения (например, в предложении WHERE или RETURNING либо в выражении в правой части предложения SET). В этом случае также требуется иметь права SELECT в изменяемом отношении, а в дополнение к политикам UPDATE будут применяться соответствующие политики SELECT или ALL. Таким образом, пользователь должен иметь доступ к изменяемой строке (или строкам) через политику UPDATE или ALL, а также разрешение на изменение этой строки (или строк) от политики SELECT или ALL.

Если команда INSERT указана со вспомогательным предложением ON CONFLICT DO UPDATE, то при выборе пути UPDATE сначала подлежащая изменению строка проверяется по выражениям USING всех политик UPDATE, а затем новая обновленная строка проверяется по выражениям WITH CHECK. Обратите внимание, однако, что, в отличие от отдельной команды UPDATE, если существующая строка не удовлетворяет выражениям USING, будет выдаваться ошибка (путь UPDATE никогда не пропускается неявно).

DELETE

Указание DELETE для политики означает, что она будет применяться к командам DELETE. Команде DELETE будут видны только те строки, которые разрешит эта команда. При этом среди них могут быть строки, которые видны через SELECT, но если они не удовлетворяют выражению USING политики DELETE, то удалить их будет нельзя.

В большинстве случаев команде DELETE также требуется считывать данные из столбцов в отношении, из которого осуществляется удаление (например, в предложении WHERE или RETURNING). В этом случае также требуются права SELECT для отношения, и в дополнение к политикам DELETE будут применяться соответствующие политики SELECT или ALL. Таким образом, пользователь должен иметь доступ к удаляемой строке (или строкам) через политику SELECT или ALL, а также разрешение на удаление этой строки (или строк) от политики DELETE или ALL.

Для политики DELETE не может задаваться выражение WITH CHECK, так как она применяется только тогда, когда записи удаляются из отношения, а в этом случае новые строки, подлежащие проверке, отсутствуют.

Таблица. Политики, применяемые по типу команды

КомандаПолитика SELECT/ALL
Выражение USING
Политика INSERT/ALL
Выражение WITH CHECK
Политика UPDATE/ALL
Выражение USING
Политика UPDATE/ALL
Выражение WITH CHECK
Политика DELETE/ALL
Выражение USING
SELECTСуществующая строка--
SELECT FOR UPDATE/SHAREСуществующая строка-Существующая строка-
INSERTНовая строка-
INSERT ... RETURNINGНовая строка 1Новая строка-
UPDATEСуществующие и новые строки 1-Существующая строкаНовая строка
DELETEСуществующая строка 1--Существующая строка
ON CONFLICT DO UPDATEСуществующие и новые строки-Существующая строкаНовая строка
1

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


Применение нескольких политик

Когда к одной команде применяются несколько политик различных типов команд (например, политики 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, могут вычисляться до условий политики, так как они считаются доверенными.

Поскольку выражения политики добавляются непосредственно в запрос пользователя, они будут выполняться с правами пользователя, выполняющего запрос. Таким образом, пользователи, на которых распространяется заданная политика, должны иметь доступ ко всем таблицам или функциям, на которые ссылается выражение, иначе при попытке обращения к таблице, у которой включена защита на уровне строк, они просто получат ошибку «отказано в доступе». Однако это не меняет способ работы представлений. Как и с обычными запросами и представлениями, проверки разрешений и политики для таблиц, на которые ссылается представление, будут использовать права владельца представления и все политики, распространяющиеся на этого владельца.

Дополнительное описание и практические примеры можно найти в разделе Политики безопасности строк.


Совместимость

Команда CREATE POLICY является расширением QHB.


См. также

ALTER POLICY, DROP POLICY, ALTER TABLE