Одна из интересных особенностей меточного («мандатного») доступа в том, что он позволяет обладателю определенного уровня доступа запретить правку строк, не только более секретных, чем ему положено, но также и строк, менее секретных. Это напоминает кастовость по части действия; так сказать, «что положено быку, нельзя делать Юпитеру». В Oracle Label Security эта особенность нашла воплощение, в чем легко убедиться.
Создадим нового пользователя и дадим ему полномочия работы исключительно с «секретными» строками:
CONNECT / AS SYSDBA
CREATE USER secretmanager IDENTIFIED BY secretmanager;
GRANT minimal TO secretmanager;
CONNECT lbacsys/lbacsys
BEGIN
SA_USER_ADMIN.SET_USER_LABELS
(
POLICY_NAME => 'empsec_policy'
, USER_NAME => 'secretmanager'
, MAX_READ_LABEL => 'limited'
, MIN_WRITE_LABEL => 'limited'
);
END;
/
(Заметьте, что ранее параметр MIN_WRITE_LABEL в процедуре SET_USER_LABELS мы не использовали; в результате умолчательного поведения Label Security для пользователя HEAD было MIN_WRITE_LABEL = 'OPEN', что легко проверяется по справочным таблицам).
Проверим теперь возможности SECRETMANAGER по чтению и по изменению полей строк, в том числе поля метки:
SQL> CONNECT secretmanager/secretmanager
Connected.
SQL> @phones
ENAME PNO
---------- --------------------
SMITH 665-7282
ALLEN 882-3154
WARD 610-1718
JONES 100-6539
MARTIN 103-1983
BLAKE 193-3112
CLARK 310-2673
SCOTT 680-4853
KING 542-6672
TURNER 293-1398
ADAMS 278-5105
JAMES 932-6728
FORD 485-9127
MILLER 865-6706
14 rows selected.
SQL> @updateallenpnumber
UPDATE scott.phone
*
ERROR at line 1:
ORA-12406: unauthorized SQL statement for policy EMPSEC_POLICY
... ... ... ...
SQL> @updateallen OPEN
UPDATE scott.phone
*
ERROR at line 1:
ORA-12406: unauthorized SQL statement for policy EMPSEC_POLICY
... ... ... ...
SQL> @updateallen LIMITED
UPDATE scott.phone
*
ERROR at line 1:
ORA-12406: unauthorized SQL statement for policy EMPSEC_POLICY
... ... ... ...
Невозможно поменять ни «основную» строку для Аллена, ни метку доступа к его телефону. Обратите внимание: несмотря на это пользователю SECRETMANAGER видны все строки - как помеченные более слабой меткой OPEN, так и помеченные меткой LIMITED. А теперь переведем телефон Аллена из категории OPEN в категорию LIMITED и понаблюдаем, что он может делать со строкой «своей» категории секретности:
SQL> CONNECT head/head
Connected.
SQL> @updateallen LIMITED
1 row updated.
SQL> CONNECT secretmanager/secretmanager
Connected.
SQL> @updateallenpnumber
1 row updated.
SQL> @updateallen LIMITED
1 row updated.
SQL> @updateallen OPEN
1 row updated.
SQL> @updateallen OPEN
UPDATE scott.phone
*
ERROR at line 1:
ORA-12406: unauthorized SQL statement for policy EMPSEC_POLICY
... ... ... ...
Очевидно, пользователь может читать как "свои" строки, так и менее секретные, а вот изменять менее секретные, чем ему положено, строки он не сможет. В приведенном примере тайный SECRETMANAGER понизил секретность строки и потерял былую возможность строку править. Ну, а более секретные строки он даже не увидит!
Выдача данных: ничего лишнего ?
В завершение знакомства с меточным доступом к строкам в Oracle мне хотелось бы подчеркнуть, что даже без учета структуры меток, привилегий, группирования пользователей и многого прочего, большая часть которого в этих статьях не рассматривалась, мандатный метод доступа не так прямолинеен в поведении, как мог бы показаться поначалу.
Рассмотрим обычную выдачу данных, помеченных метками доступа. Вспомним, что до сих пор в таблице PHONE у нас имелось по одному номеру телефона на каждого сотрудника. Попробуем добавить второй телефон Аллену, а так как сценарий phones.sql использует для выдачи на экран полуоткрытое соединение, употребление его останется корректным и для этих новых данных. Интерес представляет случай, когда телефоны Аллена (когда их станет два) будут иметь метку LIMITED, и когда к ним обратится пользователь EMPLOYEE. Интуиция подсказывает, что «невидимые» телефоны Аллена будут обрабатываться полуоткрытым соединением подобно пропущенному значению (NULL), и в результате выборки мы увидим несколько строк для Аллена с пропущенными значениями номеров телефона. А что на самом деле?
Добавим в таблицу PHONE для Аллена новый телефон и «засекретим» оба:
CONNECT head/head
INSERT INTO scott.phone
SELECT empno, '111-2222', empsec_label
FROM scott.phone
WHERE empno = (SELECT empno FROM scott.emp WHERE ename='ALLEN')
@updateallen LIMITED
Проверяем:
SQL> @phones
ENAME PNO
---------- --------------------
SMITH 665-7282
ALLEN 111-2222
ALLEN 882-3154
WARD 610-1718
JONES 100-6539
MARTIN 103-1983
BLAKE 193-3112
CLARK 310-2673
SCOTT 680-4853
KING 542-6672
TURNER 293-1398
ADAMS 278-5105
JAMES 932-6728
FORD 485-9127
MILLER 865-6706
15 rows selected.
SQL> CONNECT employee/employee
Connected.
SQL> @phones
ENAME PNO
---------- --------------------
ALLEN
WARD 610-1718
MARTIN 103-1983
BLAKE
CLARK
KING
TURNER 293-1398
JAMES 932-6728
MILLER 865-6706
9 rows selected.
Меточный доступ в Oracle справедливо показал пользователю EMPLOYEE имя Аллена (его строка в таблице EMP в открытом доступе), и не показал его телефоны (мы закрыли доступ к телефонам Аллена в таблице PHONE), но вот только открытое соединение таблиц EMP и PHONE показало "отсутствие" (на деле - недоступность) телефона одной строкой, а не двумя! Ничего лишнего: телефон недоступен, а сколько их недоступно - не сообщается. Если же сделать один из телефонов Аллена открытым, информация о наличии второго, недоступного телефона и вовсе пропадет:
SQL> CONNECT head/head
Connected.
SQL> UPDATE scott.phone
2 SET
3 empsec_label
4 = CHAR_TO_LABEL ( 'empsec_policy', 'OPEN' )
5 WHERE
6 pno = '111-2222'
7 /
1 row updated.
SQL> CONNECT employee/employee
Connected.
SQL> @phones
ENAME PNO
---------- --------------------
ALLEN 111-2222
WARD 610-1718
MARTIN 103-1983
BLAKE
CLARK
KING
TURNER 293-1398
JAMES 932-6728
MILLER 865-6706
9 rows selected.
Не думаю, что такое поведение для всех очевидно, а значит приведенные выше примеры могут оказаться небесполезными.