CREATE POLICY

Определяет новую политику безопасности на уровне строк для таблицы.

Обзор

CREATE POLICY <name> ON <table_name>
    [ AS { PERMISSIVE | RESTRICTIVE } ]
    [ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ]
    [ TO { <role_name> | PUBLIC | CURRENT_USER | SESSION_USER } [, ...] ]
    [ USING ( <using_expression> ) ]
    [ WITH CHECK ( <check_expression> ) ]

Описание

Команда CREATE POLICY определяет новую политику безопасности на уровне строк для таблицы. Обратите внимание, что безопасность на уровне строк должна быть включена для таблицы (с помощью ALTER TABLE ... ENABLE ROW LEVEL SECURITY), чтобы Database применял созданные политики.

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

Для операторов INSERT и UPDATE выражения WITH CHECK применяются до внесения фактических изменений в данные и до проверки любых других ограничений.

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

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

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

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

Параметры

  • name

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

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

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

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

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

  • command

    • Команда, к которой применяется политика. Допустимые значения: 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 для любой из вставляемых строк или строк, полученных в результате обновления. Обратите внимание, что check_expression оценивается по предполагаемому новому содержимому строки, а не по исходному содержимому.

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

  • ALL

    • Использование ALL для политики означает, что она будет применяться ко всем командам независимо от их типа. Если существует политика ALL и более специфичные политики, то применяются как политика ALL, так и более специфичная(ые) политика(и). Кроме того, политики ALL применяются как к части выборки запроса, так и к части модификации, используя выражение USING в обоих случаях, если определено только выражение 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. Таким образом, пользователь должен иметь доступ к строкам, подлежащим обновлению, через политику SELECT или ALL, а также разрешение на их обновление через политику UPDATE или 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 Новая строка[a] Новая строка -- -- --
UPDATE Существующие и новые строки[a] -- Существующая строка Новая строка --
DELETE Существующая строка[a] -- -- -- Существующая строка
ON CONFLICT DO UPDATE Существующие и новые строки -- Существующая строка Новая строка --

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

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

Когда к одной команде применяются несколько политик разных типов (например, политики SELECT и UPDATE к команде UPDATE), пользователь должен иметь оба типа разрешений (например, право выбирать строки из отношения и право их обновлять). Таким образом, выражения одного типа политики объединяются с выражениями другого типа политики с помощью оператора AND.

Когда к одной команде применяются несколько политик одного типа, должна существовать хотя бы одна разрешающая политика, предоставляющая доступ к отношению, и все ограничивающие политики должны выполняться. Таким образом, все выражения разрешающих политик объединяются с помощью OR, все выражения ограничивающих политик — с помощью 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
  ...
)

Замечания

Вы должны быть владельцем таблицы, чтобы создавать или изменять политики для неё.

Хотя политики применяются к явным запросам к таблицам в базе данных, они не применяются, когда система выполняет внутренние проверки ссылочной целостности или проверку ограничений. Это означает, что существуют косвенные способы определить наличие определённого значения. Например, попытка вставить дублирующее значение в столбец, являющийся первичным ключом или имеющий уникальное ограничение. Если вставка завершится ошибкой, пользователь может сделать вывод, что такое значение уже существует. (Этот пример предполагает, что пользователю разрешено вставлять записи, которые он не имеет права видеть.) Другой пример — когда пользователю разрешено вставлять в таблицу, ссылающуюся на другую, скрытую таблицу. Существование можно определить, вставляя значения в ссылающуюся таблицу: успех будет означать, что значение существует в связанной таблице. Эти проблемы можно решить тщательным проектированием политик, чтобы предотвратить возможность вставки, удаления или обновления записей, которые могут указывать на значения, которые пользователь не должен видеть, либо путём использования генерируемых значений (например, суррогатных ключей) вместо ключей с внешним смыслом.

Как правило, система будет применять условия фильтрации, заданные с помощью политик безопасности, до условий, указанных в пользовательских запросах, чтобы предотвратить случайное раскрытие защищённых данных пользовательским функциям, которые могут быть ненадёжными. Однако функции и операторы, помеченные системой (или системным администратором) как LEAKPROOF, могут оцениваться до выражений политик, поскольку предполагается, что они надёжны.

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

См. раздел «О настройке политик безопасности на уровне строк» для получения дополнительной информации и практических примеров.

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

CREATE POLICY является расширением Database стандарта SQL.

Смотрите также

ALTER POLICY, DROP POLICY, ALTER TABLE