Определяет новую политику безопасности на уровне строк для таблицы.
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
RESTRICTIVE
Указывает, что политика должна быть создана как ограничивающая. Все применимые ограничивающие политики объединяются с помощью логического оператора AND. Создавая ограничивающие политики, администраторы могут сужать набор записей, к которым возможен доступ, поскольку все ограничивающие политики должны выполняться для каждой записи.
Чтобы полезно использовать ограничивающие политики для сужения доступа, необходимо определить хотя бы одну разрешающую политику, предоставляющую доступ к записям. Если существуют только ограничивающие политики, то доступ к записям невозможен. При наличии смешанных разрешающих и ограничивающих политик запись доступна только в том случае, если проходит хотя бы одна разрешающая политика и все ограничивающие политики.
command
role_name
using_expression
check_expression
ALL
Использование ALL для политики означает, что она будет применяться ко всем командам независимо от их типа. Если существует политика ALL и более специфичные политики, то применяются как политика ALL, так и более специфичная(ые) политика(и). Кроме того, политики ALL применяются как к части выборки запроса, так и к части модификации, используя выражение USING в обоих случаях, если определено только выражение USING.
Например, при выполнении UPDATE политика ALL будет применяться как к тому, какие строки UPDATE сможет выбрать для обновления (применяя выражение USING), так и к результирующим обновлённым строкам, чтобы проверить, разрешено ли их добавление в таблицу (применяя выражение WITH CHECK, если оно определено, или USING в противном случае). Если команда INSERT или UPDATE пытается добавить строки, не проходящие выражение WITH CHECK политики ALL, вся команда будет прервана.
SELECT
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.