У версії Oracle10 «віртуальні приватні бази даних» даних стали виборчі, Інші СУБД, Бази даних, статті

Якщо на клітці буйвола прочитаєш “Слон” – не вір очам своїм.
Козьма Прутков


Зміст



Введення


Нагадаю, що поняття віртуальна приватна база даних (virtual private database, VPD), з’явилося у версії Oracle 8.1 для позначення можливості обмежити конкретним сеансам доступне безліч рядків у таблиці (в тому числі виведеної, view), щоб кожен сеанс, звертаючись формально до однієї і тієї ж таблиці, мав доступ в ній (“бачив”) тільки покладені рядка. Сам термін VPD рекламний, його технічний еквівалент, що фігурує нарівні в документації – детальний контроль доступу [до рядків] (fine grained access control, FGAC) 1. Користуватися VPD можна напряму, через пакет SYS.DBMS_RLS, а так же неявно і не здогадуючись про це, оскільки це засіб покладено в основу іншого, label security, що реалізує відому модель мандатної доступу стосовно до рядків таблиці з додатку. Приклад роботи безпосередньо з VPD наводився в статті кожному (користувачеві) своє (дане в таблиці). Частина 2 , А приклад роботи з label security наводився в статті “до кожного рядка охоронця приставиш!”.


Фірма Oracle не вважає для себе напрямок VPD випадковим, про що свідчить безперервний розвиток цього засобу від однієї версії СУБД до іншої. Так, в числі нововведень VPD у версії 9 – власна GUI-програма адміністрування Policy Manager та підтримка синонімів, а у версії 10.1 – відбір рядків (і навіть значень у рядках) з урахуванням зазначених стовпців і можливість вибору між статичним і динамічним обчисленням заданого предикатом відбору критерію видимості.


Саме перша із зазначених двох нових можливостей VPD версії 10.1 і буде продемонстрована в цій статті.


Підготовка прикладу


Хоча формально цього не потрібно, при використанні VPD методологічно правильно завести спеціального користувача-адміністратора. Нижче йому надається мінімум повноважень, достатніх для прикладів з цієї статті. Видаємо в SQL * Plus:


CONNECT / AS SYSDBA


CREATE USER vpd_admin IDENTIFIED BY vpd_admin
DEFAULT TABLESPACE sysaux
TEMPORARY TABLESPACE temp
QUOTA UNLIMITED ON sysaux;


GRANT CREATE SESSION TO vpd_admin;


GRANT CREATE PROCEDURE TO vpd_admin;


GRANT CREATE TABLE TO vpd_admin;


GRANT EXECUTE ON dbms_rls TO vpd_admin;


Вибірковість рядків і значень з урахуванням стовпців


“Старе” рішення


Спочатку відтворимо приклад зі згаданої вище по тексту першої статті з тією різницею, що тепер функція політики доступу до таблиці SCOTT.EMP та допоміжна таблиця, яка регулює доступ, створюються в окремій схемі VPD_ADMIN “адміністратора політик” (що в методологічно більш правильно):


CONNECT vpd_admin/vpd_admin


Таблиця з даними, параметризуються доступ:


CREATE TABLE permissions_table
(
username VARCHAR2(14)
, deptno NUMBER (2)
);


INSERT INTO permissions_table VALUES (“SCOTT”, 10);


INSERT INTO permissions_table VALUES (“SCOTT”, 30);


INSERT INTO permissions_table VALUES (“ADAM”, 10);


(Вважаємо, що користувач SCOTT буде працювати з співробітниками 10-го і 30-го відділів, а користувач ADAM – з співробітниками тільки 10-го).


Функція, що служить предикатом доступу, що задає фільтр для рядків при зверненні до таблиці SCOTT.EMP:


CREATE OR REPLACE FUNCTION permissions_function
(
obj_schema IN VARCHAR2
,obj_name IN VARCHAR2
)
RETURN VARCHAR2
IS
BEGIN RETURN
“deptno IN (SELECT deptno FROM permissions_table “
// “WHERE username = USER)”;
END;
/


Політику доступу до таблиці SCOTT.EMP як і раніше назвемо EPOLICY:


BEGIN
DBMS_RLS.ADD_POLICY
(
POLICY_NAME => “epolicy”
,OBJECT_SCHEMA => “scott”
,OBJECT_NAME => “emp”
,FUNCTION_SCHEMA => “vpd_admin”
,POLICY_FUNCTION => “permissions_function”
);
END;
/


GRANT EXECUTE ON permissions_function TO scott;


Перевірка:


SQL> CONNECT scott/tiger
Connected.
SQL> SELECT ename, sal, deptno FROM emp;



Нові параметри політики доступу у версії 10


У версії 10.1 у процедури DBMS_RLS.ADD_POLICY з’явилися нові необов’язкові (умолчательной значення – NULL) параметри:


Параметр SEC_RELEVANT_COLS


Тут через кому вказуються стовпці таблиці, що містять, на нашу хотінням, дані обмеженого доступу. Якщо при зверненні до таблиці ми звернемося до цих стовпцях, значень в них не побачимо. Приклад:


CONNECT vpd_admin /vpd_admin


HOST echo CONNECT vpd_admin/vpd_admin > drop_policy.sql


BEGIN
DBMS_RLS.DROP_POLICY
(
POLICY_NAME => “epolicy”
,OBJECT_SCHEMA => “scott”
,OBJECT_NAME => “emp”
);
END;
/


SAVE drop_policy APPEND


(Файл drop_policy.sql я створив заради зручності, щоб більш економно видалити політику вдруге, нижче по тексту).


BEGIN
DBMS_RLS.ADD_POLICY
(
POLICY_NAME => “epolicy”
,OBJECT_SCHEMA => “scott”
,OBJECT_NAME => “emp”
,FUNCTION_SCHEMA => “vpd_admin”
,POLICY_FUNCTION => “permissions_function”
,SEC_RELEVANT_COLS => “sal, comm”
);
END;
/


Перевірка:


SQL> CONNECT scott/tiger
Connected.
SQL> SELECT ename, sal, deptno FROM emp;



А ось що отримаємо, якщо не звернемося до “секретного” стовпцю з оплатою:


SQL> SELECT ename, deptno FROM emp;



У будь-якому випадку захищених даних ми не побачимо, але спосіб досягнення цього своєрідний: як тільки ми звертаємося до “секретним” стовпцях, політика перешкоджає показу деяких рядків (як і раніше), але якщо ми до “секретним” стовпцях не звертаємося, то будь ласка – нам даються всі рядки, немов би ніякої політики і не було.


Досить незвично: кількість доступних рядків при запиті до таблиці залежить від того, запросили ми “секретний” стовпець, або ж ні. Більш традиційного поведінки можна досягти вживанням ще одного нового параметра.


Параметр SEC_RELEVANT_COLS_OPT


Якщо для нього вказати константу DBMS_RLS.ALL_ROWS, то при операції SELECT будуть видаватися всі рядки, але значення в “секретних” стовпцях деяких рядків (захищених політикою) ми не побачимо:



Перевірка:




Зверніть увагу, що розрізнити в стовпцях пропуски значень, зобов’язані застосуванню політики, від пропусків у вихідних даних в Oracle можна. Це контрастує з можливістю аналогічного розрізнення “вихідних” і “набутих” перепусток, існуючої, наприклад, в SELECT з використанням GROUP BY ROLLUP / CUBE.


Деякі зауваження щодо вживання


Не зовсім очевидними можуть представитися правила видимості рядків. Так зверніть увагу, що політика EPOLICY обмежує користувачеві SCOTT доступ до рядків навіть власної таблиці! Можливо, це не найреалістичніший приклад, і частіше розробник буде поміщати таблицю з даними в окрему схему, але такі властивості VPD. З іншого боку, користувач SYS має доступ до всіх даних будь-якої таблиці поза Залежно від того, пов’язана з нею якась політика чи ні. Точніше, не помічати політики буде будь-який користувач, що володіє привілеєм EXEMPT ACCESS POLICY (перевірте це!).


Звертає на себе увагу змістовна спрощеність прикладу вище. Частково вона навмисна, а почасти вимушена. Наприклад, прямолінійна спроба реалізувати більш цікавий варіант, при якому кожен співробітник буде “бачити” рядки тільки про себе і про своїх підлеглих, приречена на невдачу, в чому легко переконатися. Дійсно, формулювання у функції-предикаті умови відбору, що містить згадування самої таблиці EMP (що буде потрібно, якщо ми захочемо відбирати з EMP рядки з підлеглими) призведе до рекурсивного обігу до політики EPOLICY, тобто до помилки. Як вчинити в цьому випадку?


По-перше, створити окрему таблицю, на зразок того, як це зроблено вище, і перенести в неї потрібні дані з EMP.


По-друге, створити не нову таблицю, а materialized view на основі EMP, і в функції-предикаті звертатися саме до materialized view. Це буде технологічніше, так як зніме проблему синхронізації даних в допоміжній таблиці зі змінами в EMP. Materialized view в цьому випадку зручно створити з властивістю REFRESH ON COMMIT.


На жаль, в будь-якому випадку доведеться дублювати частину даних з основної таблиці EMP.


Ну, і, нарешті, в реальній практиці ефективно використовувати контекст сеансу, хоча це і ускладнить програмування.

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*