DeepEdit!

Программирование баз данных на Oracle, техническая документация, литература, статьи и публикации

  • Увеличить размер шрифта
  • Размер шрифта по умолчанию
  • Уменьшить размер шрифта

Контроль доступа к таблице

Области применения RLS не ограничиваются обеспечением безопасности и упрощением процесса разработки приложений. Технология RLS также чрезвычайно полезна в случаях, когда необходимо в зависимости от ряда условий менять состояние таблицы с «доступна только для чтения» на «доступна для чтение и записи». Без применения RLS администратор базы данных может изменить разрешение на доступ для целого табличного пространства, но не для его отдельных таблиц. При этом табличное пространство невозможно сделать доступным только для чтения при наличии хотя бы одной активной транзакции. Поскольку, возможно, не найдется такого периода времени, в течение которого в базе данных не выполняется ни одной транзакции, то перевод табличного пространства в состояние «только для чтения» окажется невозможным. В таких ситуациях единственно возможным решением будет использование технологии RLS.
Если быть до конца честным, то следует сказать, что RLS не выполняет реального перевода таблицы в состояние «только для чтения», а позволяет нам эмулировать такой перевод, запретив любые попытки изменения содержимого таблицы. Проще всего это сделать, применив к любому оператору UPDATE, DELETE и INSERT заведомо ложный предикат (всегда вычисляемый как FALSE), например 1=2.
Приведем пример обеспечения доступа только для чтения к таблице EMP при помощи использования этой наипростейшей предикатной функции:

На основе этой функции можно создать политику RLS для таблицы EMP в отношении изменяющих данные операторов DML: INSERT, UPDATE и DELETE.
Обратите внимание, что параметр statement_types не включает в себя оператор SELECT, так как использование этого оператора не ограничивается.
Теперь текущий пользователь, не являющийся владельцем функции политики, сможет только выбирать данные из таблицы EMP:

Когда приходит время снова разрешить запись в таблицу, мы просто отменяем политику.

Теперь и не-владельцы функции политики могут успешно выполнять DML-операции над таблицей.
Фактически таблица никогда не переходит в состояние доступа только для чтения. Политика гарантирует, что при выполнении пользователем DML-оператора для таблицы строки изменены не будут. Т. к. никакого сообщения об ошибке не выдается, а политика игнорирует DML-операторы, то следует внимательно анализировать код приложений, использующих такую функциональность. Программисты могут неумышленно и ошибочно интерпретировать отсутствие ошибки как успешное выполнение операции DML.
Технология RLS позволяет не только переводить таблицы в состояние доступа только для чтения или для чтения и записи по требованию, но и делать это динамически в зависимости от любых пользовательских условий. Например, вы можете написать функцию политики, которая делает таблицы доступными только для чтения с 5 часов вечера и до 9 часов утра для всех пользователей за исключением владельца пакетного задания (BATCHUSER), а для BATCHUSER таблица будет доступна только для чтения с 9 часов утра до 5 часов вечера. Тело такой функции могло бы выглядеть следующим образом:

Используя временные метки, вы можете обеспечить детальный доступ к таблице. Можно использовать анализ и других различных атрибутов (например, IP-адрес, тип аутентификации, клиентские данные, терминал, пользователь операционной системы и многое другое). Нужно лишь получить соответствующую переменную из системного контекста (SYS_CONTEXT; мы поговорим об этой функции далее в этой главе) сеанса и проверить ее значение. Предположим, например, что пользователю King (который является президентом компании) разрешено видеть все записи при выполнении двух таких условий:
Подключение осуществляется с компьютера KINGLAP с фиксированным IP-адресом (192.168.1.1) и из домена Windows NT с именем AC-
MEBANK.
В Windows регистрируется пользователь King. Теперь функция политики будет выглядеть так:


Здесь использована встроенная функция SYS_CONTEXT для получения атрибутов контекста. Использованию системных контекстов будет посвящен раздел «Контексты приложения». Пока вам нужно знать лишь то, что вызов функции возвращает имя клиентского терминала, с которого осуществлен вход в систему. Другие строки с вызовом функции также возвращают соответствующие значения.
Функцию SYS_CONTEXT можно использовать для получения разнообразной информации о пользовательском подключении. На основе такой информации вы можете настроить функцию политики таким образом, чтобы фильтр отвечал вашим специфическим требованиям. Полный перечень атрибутов, которые можно получить вызовом функции SYS_CONTEXT, можно найти в справочном руководстве по Oracle SQL.
RLS в Oracle 10g
В этом разделе описаны новые возможности RLS, появившиеся в версии Oracle 10g.
Применение RLS к отдельным столбцам
Давайте вернемся к примеру с приложением HR, использованному в предыдущих разделах. Была создана политика, реализующая следующие требования: просмотр всех записей разрешен только пользователю King; все остальные пользователи могут видеть только информацию о сотрудниках своего отдела. В некоторых ситуациях такая политика может оказаться слишком строгой.
Предположим, что мы хотим сделать так, чтобы пользователи не могли «пронюхать», у кого из сотрудников какая зарплата. Рассмотрим два запроса:

Первый запрос выводит данные о зарплате - те самые данные, которые мы хотим защитить. В этом случае следует отображать сведения только о служащих, входящих в отдел пользователя. Второй запрос выводит только номера служащих. Следует ли выполнять фильтрацию, отображая номера только для служащих того отдела, к которому относится пользователь?
Ответ зависит от того, какая политика безопасности принята в каждой конкретной организации. Вполне возможно, было бы удобнее, если бы второй запрос выводил всех сотрудников, вне зависимости от отдела, в котором они работают.
В Oracle9i невозможно настроить RLS так, чтобы выполнить наше новое требование. В версии Oracle 10^ у процедуры ADD_POLICY появляется
необходимый для этого новый параметр sec_relevant_cols. Я хочу изменить предыдущий сценарий так, чтобы фильтр применялся только в том случае, когда выбираются данные из столбцов SAL и COMM. Новая политика будет такой (новый параметр выделен жирным шрифтом):

После ввода в действие новой политики запросы пользователя Martin будут выполнены по-другому.

При попытке выборки данных из столбца SAL политика RLS предотвращает отображение всех строк, отфильтровывая строки, в которых значение DEPTNO отлично от 30 (от номера отдела пользователя (Martin), выполняющего запрос).
Политика будет применяться для выбранных столбцов не только при их появлении в списке SELECT, но и при любой (явной или неявной) ссылке на такие столбцы. Рассмотрим, например, запрос:

Столбец SAL упоминается в предложении WHERE. В дело вступает политика RLS, что приводит к тому, что отображаются только записи для отдела 30. Давайте рассмотрим еще один пример, в котором я попытаюсь вывести значение SAL.

Явной ссылки на столбец SAL нет, но неявно на него ссылается предложение SELECT *, поэтому политика RLS отфильтровывает все строки, не относящиеся к отделу 30. Запрос был вызван для отдела 10, поэтому ни одной строки не возвращено.
Теперь давайте несколько изменим условия. В прошлый раз мы добивались того, чтобы не отображались значения столбца SAL для тех строк, видеть которые пользователь не авторизован. Однако получилось так, что мы подавили вывод всей строки, а не только значения отдельного столбца. Сформулируем новое требование: следует маскировать только столбец, а не всю строку (то есть все остальные столбцы должны отображаться). Можно ли этого добиться?
Эту задачу легко решить при помощи еще одного параметра процедуры
ADD_POLICY, sec_relevant_cols_opt. Единственное, что нужно сделать, - это пересоздать политику, установив этот параметр в константу
Если Martin теперь выполнит тот же запрос, результат будет другим (в последующем выводе вместо значений NULL отображается «?»):
DBMS RLS.ALL ROWS.

7782
CLARK
MANAGER
7839
09-
JUN-
81
?
?
10
7839
KING
PRESIDENT

17-
NOV-
81
?
?
10
7934
MILLER
CLERK
7782
23-
JAN-
82
?
?
10
7369
SMITH
CLERK
7902
17-
DEC-
80
?
?
20
7876
ADAMS
CLERK
7788
12-
JAN-
83
?
?
20
7902
FORD
ANALYST
7566
03-
DEC-
81
?
?
20
7788
SCOTT
ANALYST
7566
09-
DEC-
82
?
?
20
7566
JONES
MANAGER
7839
02-
APR-
81
?
?
20
7499
ALLEN
SALESMAN
7698
20-
FEB-
81
1,600
300
30
7698
BLAKE
MANAGER
7839
01-
MAY-
81
2,850
?
30
7654
MARTIN
SALESMAN
7698
28-
SEP-
81
1,250
1,400
30
7900
JAMES
CLERK
7698
03-
DEC-
81
950
?
30
4 4 8 7
TURNER
SALESMAN
7698
08-
SEP-
81
1,500
0
30
7521
WARD
SALESMAN
7698
22-
FEB-
81
1,250
500
30
14 rows selected

Как видите, выведены все 14 строк, причем со значениями всех столбцов, только значения SAL и COMM заменены на NULL в тех строках, которые пользователь не должен видеть (то есть относящиеся не к отделу 30).
Новые параметры процедуры ADD_POLICY позволяют создать такую политику RLS, чтобы выводить все строки, скрывая лишь секретные значения. До выхода версии Oracle 10^ для решения этой задачи пришлось бы использовать представления, и все было бы значительно сложнее.
Последнюю возможность следует применять с особой осторожностью, так как в некоторых случаях возможны неожиданные результаты. Предположим, например, что Martin выдает следующий запрос:
Получены следующие данные: служащих - 14, средняя зарплата равна 1566. Но на самом деле средняя зарплата вычислена только для тех 6 служащих, данные о которых доступны пользователю Martin, а не для всех 14! Возможна путаница: какие значения следует считать корректными? Ведь если тот же запрос выдаст владелец схемы HR, то результат будет другим.
В версии Oracle 10^ Release 2 можно применять средства RLS даже к оператору CREATE INDEX. Для этого задайте INDEX в качестве значения параметра statement_types в процедуре ADD_POLICY.
При анализе результатов необходимо помнить о том, что они зависят от пользователя, выполнившего запрос. В противном случае в приложении могут возникнуть ошибки, которые сложно отследить.
 









jAntivirus