К каждой строке охранника приставишь!
Одним рассказ казался длинен, другие утверждали, что он
слишком краток, большинство же, как всегда, скромно молчало...
М. Горький. Публика
Одни утверждали, что он [дом] трехэтажный, другие – что
четырех.
А. и Б. Стругацкие. Град обреченный
Введение
Механизм virtual private database (VPD) в Oracle позволяет регламентировать доступ к частям таблицы, но использует для этого весьма примитивную систему понятий. В версии 8.1.7 в Oracle появилось другое средство, Label Security, система понятий которого более продумана и лучше приспособлена под задачи защиты частей таблицы. Технически оно опирается на VPD, но реализует подход, известный в ИТ под названием «мандатного управления доступом», регулирующим в данном случае доступ к отдельным строкам таблиц разным категориям пользователей. Реализация соответствует ISO/IEC 15408 Common Criteria.
Каждая строка нужной таблицы помечается специальной меткой, допускающей впоследствии изменение. Пользователям выдается разрешение работать со строками, помеченными только определенными метками. При разборе запроса к таблице СУБД выполнит проверки обычных полномочий доступа (выдаваемых командой GRANT), а при выполнении запроса отфильтрует из таблицы только строки со значениями меток, разрешенными для пользователя. Логически это выглядит как автоматическое добавление предиката AND P(метка_строки, контекст_сеанса) в конструкцию WHERE запроса. В конечном счете не предназначенные для него строки пользователь не сможет ни увидеть, ни изменить.
Label Security – дополнительная возможность Oracle. Для того, чтобы ею пользоваться, нужно (а) завести при установке ПО СУБД Oracle нужные компоненты и (б) завести необходимые структуры в БД. Первое делается установщиком OUI, а второе – конфигуратором БД DCA или простым прогоном сценария catols.sql из каталога $ORACLE_HOME/rdbms/admin. Наблюдаемый результат – новый пользователь LBACSYS и целая серия принадлежащих ему объектов, включая пакеты, имена которых начинаются с 'SA_'.
Простой пример
Данные для регламентируемого доступа
Пусть у сотрудников из таблицы EMP имеются телефоны:
CONNECT scott/tiger
CREATE TABLE phone AS SELECT empno FROM emp;
ALTER TABLE phone ADD (pno VARCHAR(20));
ALTER TABLE phone ADD PRIMARY KEY (empno, pno);
UPDATE phone
SET pno = TRUNC(dbms_random.value(100, 999))
||'-'
||TRUNC(dbms_random.value(1000, 9999));
Какие-то из них будут общедоступны, а какие-то нет, но об этом будет сообщено позже.
Заведем пользователей Oracle, представляющих сотрудника и административное лицо. Дадим им минимум необходимых для данного примера полномочий:
CONNECT / AS SYSDBA
CREATE USER employee IDENTIFIED BY employee;
CREATE USER head IDENTIFIED BY head;
CREATE ROLE minimal;
GRANT CREATE SESSION TO minimal;
GRANT SELECT ON scott.phone TO minimal;
GRANT SELECT ON scott.emp TO minimal;
GRANT minimal TO employee, head;
GRANT UPDATE ON scott.phone TO lbacsys;
GRANT UPDATE ON scott.emp TO lbacsys;
Политика безопасности
Создадим политику безопасности, регулирующую доступ пользователей EMPLOYEE и HEAD к номерам телефонов. Она будет базироваться на значении метки в столбце EMPSEC_LABEL, который мы специально добавим в таблицу телефонов позже:
CONNECT lbacsys/lbacsys
BEGIN
SA_SYSDBA.CREATE_POLICY
(POLICY_NAME => 'EMPSEC_POLICY'
, COLUMN_NAME => 'EMPSEC_LABEL');
END;
/
Отключить, снова включить и удалить политику безопасности можно процедурами DISABLE_POLICY, ENABLE_POLICY и DROP_POLICY.
Определим в рамках политики безопасности два уровня секретности:
BEGIN
SA_COMPONENTS.CREATE_LEVEL
(POLICY_NAME => 'EMPSEC_POLICY'
, LEVEL_NUM => 1000
, SHORT_NAME => 'OPEN'
, LONG_NAME => 'Open level');
SA_COMPONENTS.CREATE_LEVEL
(POLICY_NAME => 'EMPSEC_POLICY'
, LEVEL_NUM => 2000
, SHORT_NAME => 'LIMITED'
, LONG_NAME => 'Limited level');
END;
/
Каждый уровень задается тройкой
<номер, краткое название, развернутое название>.
Номер носит технический характер, а развернутое название – характер комментария (но до 30 символов).
Предполагается, что создаваемые уровни линейно упорядочены в соответствии с номером. Содержательно за уровнем удобно видеть степень секретности, причем чем выше степень секретности («открытые данные» - «ограниченный доступ» - «секретно» ...), тем больший нужно связать с ней номер.
Заводим метки доступа
Заданные в рамках политики EMPSEC_POLICY уровни секретности используем для формирования меток доступа. Именно метки и будут регламентировать доступ к строкам таблицы. В нашем простейшем случае каждая метка соответствуют попросту уровню секретности:
BEGIN
SA_LABEL_ADMIN.CREATE_LABEL
(POLICY_NAME => 'EMPSEC_POLICY'
, LABEL_TAG => 10000
, LABEL_VALUE => 'OPEN'
, DATA_LABEL => TRUE);
SA_LABEL_ADMIN.CREATE_LABEL
(POLICY_NAME => 'EMPSEC_POLICY'
, LABEL_TAG => 20000
, LABEL_VALUE => 'LIMITED'
, DATA_LABEL => TRUE);
END;
/
Номер метки LABEL_TAG имеет технический смысл, выбирается произвольно и безотносительно к номерам уровней. Его даже можно порождать автоматически специальной функцией TO_DATA_LABEL. Значение TRUE для DATA_LABEL указывает, что меткой можно будет помечать строки таблиц.
Приписываем метки доступа пользователям
Пользователю EMPLOYEE дадим право доступа только к «открытым» строкам, а пользователю HEAD – к «открытым» и «ограниченного пользования»:
BEGIN
SA_USER_ADMIN.SET_USER_LABELS
(POLICY_NAME => 'EMPSEC_POLICY'
, USER_NAME => 'EMPLOYEE'
, MAX_READ_LABEL => 'OPEN');
SA_USER_ADMIN.SET_USER_LABELS
(POLICY_NAME => 'EMPSEC_POLICY'
, USER_NAME => 'HEAD'
, MAX_READ_LABEL => 'LIMITED');
END;
/
Приписываем метки доступа строкам
Для этого сначала «применим политику доступа» к таблице PHONE в целом:
BEGIN
SA_POLICY_ADMIN.APPLY_TABLE_POLICY
(POLICY_NAME => 'EMPSEC_POLICY'
, SCHEMA_NAME => 'SCOTT'
, TABLE_NAME => 'PHONE'
, TABLE_OPTIONS => 'LABEL_DEFAULT,
READ_CONTROL, WRITE_CONTROL');
END;
/
В результате она автоматически окажется пополнена столбцом EMP_DATA_LABEL, указанным в самом начале для нашей политики EMPSEC_POLICY. Его можно легко наблюдать командой SQL*Plus DESCRIBE. Если же в параметре TABLE_OPTIONS в число свойств через запятую включить HIDE, новый служебный столбец обычным пользователям виден не будет. В этом же параметре свойство WRITE_CONTROL можно для нашего случая спокойно опустить.
Теперь появилась возможность разметить конкретными метками конкретные строки:
UPDATE scott.phone
SET emp_data_label = CHAR_TO_LABEL('EMPSEC_POLICY',
'OPEN');
UPDATE scott.phone
SET emp_data_label = CHAR_TO_LABEL('EMPSEC_POLICY',
'LIMITED')
WHERE empno IN (SELECT empno
FROM scott.emp
WHERE job IN ('MANAGER', 'PRESIDENT'));
Вместо обращения к функции
CHAR_TO_LABEL('EMPSEC_POLICY', 'OPEN')
можно было сразу указать число 10000, номер метки, так как именно число будет храниться в поле метки фактически; аналогично же и во второй команде UPDATE. Однако для содержательной ясности удобнее воспользоваться функцией.
Проверяем, как работает
SQL> CONNECT employee/employee
Connected.
SQL> SELECT ename, pno
2 FROM scott.emp LEFT OUTER JOIN scott.phone
3 USING (empno);
ENAME PNO
---------- --------------------
SMITH 409-2351
ALLEN 625-1171
WARD 506-9715
MARTIN 108-8113
SCOTT 187-3972
TURNER 609-2430
ADAMS 421-3324
JAMES 550-4204
FORD 713-9878
MILLER 924-5401
KING
CLARK
BLAKE
JONES
14 rows selected.
SQL> SAVE phones REPLACE
Wrote file phones.sql
SQL> CONNECT head/head
Connected.
SQL> /
ENAME PNO
---------- --------------------
SMITH 409-2351
ALLEN 625-1171
WARD 506-9715
JONES 600-1573
MARTIN 108-8113
BLAKE 738-6815
CLARK 650-1728
SCOTT 187-3972
KING 393-8155
TURNER 609-2430
ADAMS 421-3324
JAMES 550-4204
FORD 713-9878
MILLER 924-5401
14 rows selected.
Упражнение. Выдать вслед за предыдущим:
CONNECT scott/tiger
/
CONNECT lbacsys/lbacsys
/
Объяснить результаты.
Пусть теперь в рамках той же политики EMPSEC_POLICY часть сотрудников также секретны, например сотрудники отдела разработок RESEARCH:
BEGIN
SA_POLICY_ADMIN.APPLY_TABLE_POLICY
(POLICY_NAME => 'EMPSEC_POLICY'
, SCHEMA_NAME => 'SCOTT'
, TABLE_NAME => 'EMP'
, TABLE_OPTIONS => 'LABEL_DEFAULT, READ_CONTROL');
END;
/
UPDATE scott.emp
SET EMPSEC_LABEL = CHAR_TO_LABEL('EMPSEC_POLICY',
'OPEN');
UPDATE scott.emp
SET EMPSEC_LABEL = CHAR_TO_LABEL('EMPSEC_POLICY',
'LIMITED')
WHERE deptno
IN (SELECT deptno FROM scott.dept
WHERE dname = 'RESEARCH');
Новая проверка:
SQL> CONNECT employee/employee
SQL> @phones
ENAME PNO
---------- --------------------
ALLEN 625-1171
WARD 506-9715
MARTIN 108-8113
TURNER 609-2430
JAMES 550-4204
MILLER 924-5401
BLAKE
KING
CLARK
9 rows selected.
SQL> CONNECT head/head
SQL> /
ENAME PNO
---------- --------------------
SMITH 409-2351
ALLEN 625-1171
WARD 506-9715
JONES 600-1573
MARTIN 108-8113
BLAKE 738-6815
CLARK 650-1728
SCOTT 187-3972
KING 393-8155
TURNER 609-2430
ADAMS 421-3324
JAMES 550-4204
FORD 713-9878
MILLER 924-5401
14 rows selected.
Более сложная логика
Описанная выше простейшая в рамках Label Security логика разграничения доступа к отдельным строкам допускает развитие в нескольких направлениях.
Более сложная структура метки доступа
Важным развитием является возможность формировать метку доступа более сложным путем, нежели чем на основе только уровня секретности. В состав метки можно еще включать следующие компоненты:
- Разделы данных (compartment). Позволяют сгруппировать данные по категориям с общим режимом доступа, например «административные данные», «финансовые данные», «операционные данные».
- Группы безопасности пользователей (security groups). Позволяют сгруппировать пользователей данных по принципу общих правил доступа, например «главное управление», «южное отделение», «северное отделение», «предприятие X», «предприятие Y». В отличие от разделов данных группы пользователей могут формировать древовидную подчиненность.
И разделы данных, и группы пользователей описываются тройками
<номер, краткое название, развернутое название> ,
однако в отличие от уровня секретности номера здесь не несут никакого прикладного смысла и выбираются произвольно.
Таким образом в общем случае метка доступа может иметь вид:
уровень: раздел1, раздел2, ...: группа1, группа2 ...
В версии 10.1 информацию об уровнях, разделах данных и группах пользователей стало возможным помещать в сервер имен OID/LDAP, что существенно для ценности самого подхода.
В отличие от простых меток, соответствующих уровням доступа, составные метки имеют более сложные правила упорядочения, но и обеспечивают большую функциональность.
Метки сеанса
Использовавшаяся выше процедура:
SA_USER_ADMIN.SET_USER_LABELS
приписывает метку доступа пользователю. На деле это не совсем так: она приписывает метку сеансам, порождаемым от имени этого пользователя. По ходу сеанса связи с СУБД эту метку сеанса можно изменить процедурой SA_SESSION.SET_LABEL, правда в пределах, которые есть возможность указать процедурой SA_USER_ADMIN.SET_USER_LABELS, что в примере выше не использовалось.
Другие усложнения
К числу других усложнений и дополнений описанной логики можно отнести инверсные группы, возможность отменять фильтрацию строк метками, возможность создания «доверительных» программных единиц, обращающихся к защищенным строкам; возможность указывать для таблицы, снабжаемой столбцом с меткой безопасности, дополнительный предикат отбора строк по своему желанию, а также ряд других возможностей.
Замечания по технологии
Для работы с размеченными строками разумно завести специального административного пользователя в дополнение к LBACSYS и передать ему необходимые полномочия для работы с объектами LBACSYS.
Справочную информацию о заведенных метках, группах и т. д. можно получить из справочных таблиц пользователя LBACSYS: DBA(USER)_SA_POLICIES, DBA_SA_LEVELS , DBA_SA_LABELS и др.
Для удобства работы в состав ПО Oracle включена программа Policy Manager с графическим интерфейсом.
Автор: Владимир Пржиялковский
Источник: www.citforum.ru
|