2008 г.
Базы данных. Вводный курс
Сергей Кузнецов
Назад Содержание Вперёд
22.2.4. Передача привилегий и ролей
Для передачи привилегий и ролей от одних authID
другим поддерживается оператор GRANT
, который мы обсудим отдельно для случаев передачи привилегий и передачи ролей.
Передача привилегий
В случае передачи привилегий используется следующий синтаксис оператора GRANT
:
GRANT { ALL PRIVILEGES | privilege_commalist }
ON privilege_object
TO { PUBLIC | authID_commalist } [ WITH GRANT OPTION ]
[ GRANTED BY { CURRENT_USER | CURRENT_ROLE } ]
privilege ::= SELECT [ column_name_commalist ]
| DELETE
| INSERT [ column_name_commalist ]
| UPDATE [ column_name_commalist ]
| REFERENCES [ column_name_commalist ]
| USAGE
| TRIGGER
| EXECUTE
privilege_object ::= [ TABLE ] table_name
| DOMAIN domain_name
| CHARACTER SET character_set_name
| COLLATION collation_name
| TRANSLATION translation_name
Поскольку authID
может являться идентификатором пользователя или именем роли, привилегии могут передаваться от пользователей пользователям, от пользователей ролям, от ролей ролям и от ролей пользователям.
В списке привилегий можно использовать SELECT
, DELETE
, INSERT
, UPDATE
, REFERENCES
и TRIGGER
только в том случае, когда в качестве объекта привилегий указывается таблица. Соответственно, список привилегий может состоять из единственной привилегии USAGE
только в том случае, когда объектом является домен, набор символов, порядок сортировки или трансляция. Если в списке привилегий указывается более одной привилегии, то они все передаются указанным authID
, но для этого текущий authID
SQL-сессии должен обладать привилегией на передачу привилегий.
Использование ключевого слова ALL PRIVILEGES
вместо явного задания списка привилегий означает, что передаются все привилегии доступа к соответствующему объекту базы данных, которыми обладает текущий authID
SQL-сессии.
Как показывает синтаксис, один оператор GRANT
позволяет передавать привилегии доступа только к одному объекту, но в том случае, когда объектом является таблица, разные привилегии могут передаваться по отношению к одному и тому же набору столбцов или к разным наборам. Если при указании привилегий SELECT
, DELETE
, UPDATE
и REFERENCES
список имен столбцов не задается, передаются привилегии по отношению ко всем столбцам таблицы. Заметим, что эти привилегии касаются всех существующих столбов данной таблицы, а также всех столбцов, которые когда-либо будут к ней добавлены.
Включение в оператор необязательного раздела WITH GRANT OPTION
означает, что получателям передаваемых привилегий дается также привилегия на дальнейшую передачу полученных привилегий, включая привилегию на передачу привилегий. Включение в оператор раздела GRANTED BY
позволяет явно указать, передаются ли привилегии от имени текущего идентификатора пользователя или же текущего имени роли.
При проверке возможности выполнения операции в SQL-сессии учитываются привилегии текущего authID
SQL-сессии, а также привилегии всех ролей, которые переданы данному authID
. Поскольку этим ролям могли быть переданы другие роли, обладающие собственными привилегиями, анализ возможности выполнения операции является рекурсивной процедурой.
Если одна и та же привилегия передается более одного раза одному и тому же authID2
от имени одного и того же authID1
, то возникает ситуация, называемая избыточной дублирующей привилегией. Эта ситуация не вызывает дополнительных проблем, поскольку избыточная передача привилегии игнорируется. Для аннулирования данной привилегии у authID2
от имени authID2
требуется выполнение всего лишь одной операции REVOKE
(см. ниже в этом разделе). Если привилегия была один раз передана authID2
от имени authID1
вместе с привилегией на передачу этой привилегии (WITH GRANT OPTION
), а в другой раз – без этой опции (порядок действий не является существенным), то authID2
обладает данной привилегией и привилегией на ее передачу.
Если предпринимается попытка передачи нескольких привилегий, но соответствующий authID
не обладает ни одной из них, то фиксируется ошибка. Аналогично, если производится попытка передачи нескольких привилегий с передачей привилегии на передачу привилегий, но соответствующий authID
не обладает привилегией WITH GRANT OPTION
ни для одной из передаваемых привилегий, то фиксируется ошибка. Наконец, если производится попытка передачи нескольких привилегий с передачей привилегии на передачу привилегий и соответствующий authID
обладает привилегией на передачу только части этих привилегий, то в результате выполнения операции вырабатывается предупреждение, но соответствующая часть привилегий передается с привилегией WITH GRANT OPTION
.
Привилегии и представления
При определении представлений действуют специальные правила определения привилегий над этими представлениями. Если при создании обычных объектов базы данных, таких, как таблица или домен, текущий authID
автоматически получает все возможные привилегии доступа к соответствующему объекту, включая привилегию на передачу привилегий, то для представлений ситуация иная. Поскольку создаваемое представление всегда основывается на одной или нескольких базовых таблицах (или представлениях), привилегии, которые получает создатель представления, должны основываться на привилегиях, которыми располагает текущий authID
по отношению к этим базовым таблицам или представлениям.
Например, чтобы операция создания представления была выполнена успешно, текущий authID
должен обладать привилегией SELECT
по отношению ко всем базовым таблицам и представлениям, на которых основывается новое представление. Тогда текущий authID
автоматически получит привилегию SELECT
для нового представления. Но текущий authID
сможет передавать эту привилегию другим authID
только тогда, когда обладает соответствующей привилегией для всех базовых таблиц и представлений, на которых основывается новое представление. Аналогичным образом на представление распространяются привилегии DELETE
, INSERT
, UPDATE
и REFERENCES
. Поскольку триггеры над представлениями создавать не разрешается, привилегия TRIGGER
представлениям не передается.
Наконец, посмотрим, что происходит при смене привилегий владельца представления по отношению к таблицам, на которых основано это представление. Для простоты предположим, что представление V
основано на базовой таблице T
. Если во время создания V
текущий authID
(будущий владелец представления) обладал по отношению к T
привилегиями SELECT
и INSERT
, то он будет обладать этими привилегиями и по отношению к V
174). Если впоследствии владелец представления получит по отношению к T
дополнительные привилегии, то он (и все authID
, которым передавались все привилегии – ALL PRIVILEGES
для V
) получит те же привилегии для V
. Должно быть понятно, каким образом обобщается этот подход на случай, когда представление определяется над несколькими таблицами или представлениями.
Передача ролей
Для передачи ролей используется следующий вариант оператора GRANT:
GRANT role_name_commalist
TO { PUBLIC | authID_commalist } [ WITH ADMIN OPTION ]
[ GRANTED BY { CURRENT_USER | CURRENT_ROLE } ]
Как показывает синтаксис, оператор позволяет передавать произвольное число ролей произвольному числу authID
(которые могут представлять собой идентификаторы пользователей или имена ролей). Как и в случае передачи привилегий, от данного authID
можно передавать только те роли, которые были получены этим authID
с привилегией на дальнейшую передачу (WITH ADMIN OPTION
). При включении в состав оператора GRANT
раздела GRANTED BY
можно явно указать, что роли передаются от имени текущего идентификатора пользователя или же текущего имени роли.
22.2.5. Изменение текущих идентификаторов пользователей и имен ролей
Как мы отмечали ранее в этом разделе, в SQL:1999 специфицированы некоторые операторы, позволяющие изменять текущий идентификатор пользователя и текущее имя роли SQL-сессии.
Оператор SET SESSION AUTHORIZATION
Для изменения текущего идентификатора пользователя SQL-сессии может использоваться оператор
SET SESSION AUTHORIZATION value_specification
Как указывалось в лекции 17, value_specification
может быть либо литералом (в данном случае литералом типа символьных строк), либо вызовом ниладической функции, такой, как CURRENT_USER
, SESSION_USER
и т. д. Если указанная спецификация значения не соответствует требованиям, предъявляемым в реализации к представлению идентификатора пользователя, операция изменения текущего идентификатора пользователя аварийно завершается.
В стандарте также говорится, что если спецификация значения, заданная в операции, формально соответствует требованиям, предъявляемым к формату идентификатора пользователя конкретной системы, но в действительности не представляет известный системе идентификатор пользователя, то опять же фиксируется ошибка, и операция не выполняется. Допускается, чтобы в реализации принималось решение о смене идентификатора пользователя сессии одновременно с регистрацией нового идентификатора пользователя. Ограничения на регистрацию таким способом нового пользователя тоже определяются на уровне реализации. После успешного выполнения оператора SET SESSION AUTHORIZATION
текущее имя роли соответствующей сессии принимает значение NULL
, так что текущим authID
этой сессии становится заданное значение идентификатора пользователя.
Опять по необходимости забегая вперед, заметим, что операцию смены текущего идентификатора пользователя SQL-сессии не разрешается выполнять внутри какой-либо транзакции этой сессии. Иначе терялся бы смысл привилегий доступа, которыми руководствуется система при выполнении операций внутри транзакции.
Оператор SET ROLE
Для смены текущего имени роли SQL-сессии можно использовать оператор
SET ROLE { value_specification | NONE }
Ограничения на выполнение операции SET ROLE
почти совпадают с определенными в стандарте ограничениями на выполнение операции SET SESSION AUTHORIZATION
. Наиболее важные отличия состоят в том, что эту операцию от имени текущего authID
сессии всегда разрешается выполнять для ролей, которые переданы «пользователю» PUBLIC
или данному текущему authID
, а также в том, что всегда разрешается применение конструкции SET ROLE NONE
. Выполнение последней конструкции приводит к тому, что значение текущего имени роли сессии становится неопределенным.
Заметим, что при смене текущего имени роли SQL-сессии значение текущего пользовательского идентификатора сессии не меняется, так что вполне вероятно, что после выполнения операции и текущий идентификатор, и текущее имя роли будут иметь значения, отличные от неопределенного значения. И конечно, операция SET ROLE NONE
будет выполнена успешно только в том случае, когда значение текущего пользовательского идентификатора не является неопределенным175).
22.2.6. Аннулирование привилегий и ролей
Если от имени некоторого authID
некоторые привилегии или роли были переданы одному или нескольким другим authID
, то впоследствии первый authID
(в сессии, где этот authID
является текущим) можно изъять, или аннулировать, переданные привилегии или роли путем применения оператора REVOKE
. Как и в случае передачи привилегий и ролей, способы аннулирования привилегий и ролей похожи, но между ними имеются некоторые отличия. Поэтому мы снова обсудим эти способы в отдельности.
Аннулирование привилегий
Для аннулирования привилегий используется оператор REVOKE
, определяемый следующим синтаксическим правилом:
REVOKE [ GRANT OPTION FOR] privilege_commalist
ON privilege_object
FROM { PUBLIC | authID_commalist }
[ GRANTED BY { CURRENT_USER | CURRENT_ROLE } ]
{ RESTRICT | CASCADE }
Синтаксис конструкций privilege
и privilege_object
такой же, как для оператора GRANT
. Общий смысл операции должен быть понятен из синтаксиса: у указанных authID
аннулируются указанные привилегии доступа к указанному объекту базы данных.
Первой важной особенностью оператора аннулирования привилегий является обязательность указания одного из ключевых слов RESTRICT
или CASCADE
. Если в операторе содержится RESTRICT
, то при выполнении операции система проверит, не передавалась ли какая-либо из указанных привилегий каким-либо authID
от того authID
, у которого привилегия должна быть аннулирована (это вполне возможно, если ранее привилегия была передана с правом передачи). Если это действительно так, операция не выполняется; в противном случае указанные привилегии у указанных authID
аннулируются. Иначе говоря, при наличии ключевого слова RESTRICT
не допускается, например, ситуация, показанная на рис. 22.2.
Рис. 22.2. Передача полученной привилегии
На этом рисунке authID1
является владельцем объекта базы данных с именем object
и, следовательно, обладает всеми привилегиями над этим объектом. Пунктирной стрелкой обозначена одна из подобных привилегий pr1
. От имени authID1
привилегия pr1
была передана authID2
вместе с привилегией на ее дальнейшую передачу. Наконец, от имени authID2
привилегия pr1
была передана authID3
. Тогда операция аннулирования этой привилегии от имени authID1
у authID2
при наличии ключевого слова RESTRICT
не будет выполнена успешно.
В той же ситуации привилегия была бы аннулирована для authID2
(и для authID3
), если бы в операторе GRANT
присутствовало ключевое слово CASCADE
. В общем случае если выполняется операция REVOKE
... CASCADE
, то указанные привилегии аннулируются у всех authID
, прямо или косвенно (через промежуточные authID
) получивших привилегии от текущего authID
SQL-сессии, в которой выполняется данная операция.
Если в операторе содержится раздел GRANT OPTION FOR
, но имеется ключевое слово RESTRICT
, то указанные привилегии для указанных authID
не аннулируются, но у указанных authID
аннулируется привилегия передачи данных привилегий (операция должна успешно выполняться только при соблюдении обсуждавшихся ранее условий). Однако если в операторе одновременно содержатся и GRANT OPTION FOR
, и CASCADE
, то указанные привилегии аннулируются у всех authID
, которые прямо или косвенно (через промежуточные authID
) получили привилегии от текущего authID
SQL-сессии, в которой выполняется данная операция.
Задание в операторе необязательного раздела GRANTED BY
позволяет явно указать, что должно использоваться в качестве текущего authID
– текущий пользовательский идентификатор или текущее имя роли SQL-сессии. Если раздел GRANTED BY
в операторе REVOKE
не содержится, то действия производятся от имени текущего authID
SQL-сессии (о том, как он определяется, см. выше).
Если текущий (или указанный) authID
не обладает ни одной из указанных в операторе REVOKE
привилегий, то выполнение операции не производится (фиксируется ошибка). Если authID
обладает некоторыми, но не всеми, привилегиями из числа указанных, то операция выполняется по отношению к этим некоторым привилегиям, но выдается предупреждение.
Возможны ситуации, когда у некоторого authID
остается некоторая привилегия после выполнения операции аннулирования у этого authID
этой привилегии. Одна из таких ситуаций проиллюстрирована на рис. 22.3.
Рис. 22.3. Косвенная и прямая передача привилегий
Здесь привилегия pr1
передана от authID1
к authID2
вместе с правом на дальнейшую передачу этой привилегии. Далее, привилегия pr1
передается от authID2
к authID3
. И затем выполняется прямая передача привилегии от authID1
к authID3
(на самом деле, порядок таких действий не является существенным). Теперь предположим, что от имени authID1
выполняется операция
REVOKE pr1 ON object FROM authID2 CASCADED
В соответствии с правилами SQL:1999 после выполнения этой операции authID3
будет продолжать владеть привилегией pr1
по отношению к объекту object
, поскольку получил данную привилегию двумя разными способами. Грубо говоря, операция REVOKE
, выполняемая от имени authID1
, выполняется только по тем путям графа идентификаторов авторизации и объектов базы данных, которые начинаются с узлов, соответствующих authID
, указанных в разделе FROM
этой операции.
Далее, напомним, что если при передаче от authID1
к authID2
привилегии на выполнение некоторых действий над некоторой таблицей T
(например, UPDATE
) явно не указывается список имен столбцов этой таблицы, то привилегия распространяется на все столбцы этой таблицы (включая столбцы, которые, возможно, еще будут созданы). Если действительно использовался такой способ передачи привилегий, то в дальнейшем можно аннулировать привилегию authID2
на модификацию отдельных (уже определенных) столбцов таблицы T
, оставив привилегию на модификацию всех остальных столбцов (включая те, которые еще не созданы).
И последнее замечание. Если некоторая привилегия была передана псевдоauthID
PUBLIC
, то, конечно, этой привилегией обладают все authID
. Но нет возможности аннулировать такую привилегию у отдельно указываемого authID
. Привилегия была передана всем, и аннулировать ее можно только сразу у всех.
Аннулирование ролей
Вариант оператора REVOKE
, используемый для аннулирования ролей, выглядит следующим образом:
REVOKE [ ADMIN OPTION FOR ] role_name_commalist
FROM { PUBLIC | authID_commalist }
[ GRANTED BY { CURRENT_USER | CURRENT_ROLE } ]
{ RESTRICT | CASCADE }
Действие операции аннулирования ролей очень похоже на действие операции аннулирования привилегий. Отличие состоит в том, что аннулируются не привилегии, а роли, а также в том, что для аннулирования привилегии на передачу роли используется раздел ADMIN OPTION FOR
176).
174 Кстати, это один из тех случаев, когда иметь право не означает автоматически иметь возможность реализации своего права. SQL допускает, например, наличие привилегии INSERT
для представления, к которому операция INSERT
не применима.
175 Кстати, стандарт полностью отдает на волю реализации способ того, каким образом сделать неопределенным значение текущего пользовательского идентификатора SQL-сессии.
176 В действительности, как видно из приведенных описаний, варианты операторов GRANT и REVOKE
для привилегий и ролей настолько близки, что непонятно их синтаксическое разделение, которое, очевидно, усложняет реализацию. Как кажется, это разделение не обосновано в стандарте SQL:1999.
Назад Содержание Вперёд