Начало Сигурност Oracle Label Security - част II
Oracle Label Security - част II
Четвъртък, 03 Август 2006 11:07
Създаване на нива

Вече споменахме, че политиката на достъп се състои от три компонента - нива, области и групи, като последните два са опционални. Нивата на достъп определят чувствителността на информацията. Всяко ниво има три основни характеристики, а именно:

  • номер, който е уникален и еднозначно идентифицира отделните нива. Добра практика е нивото на конфиденциалност да нараства пропорционално със стойността на номера;
  • кратко име, което е съкращение използвано при дефиницията на етикетите. Добре е да го ограничим в рамките на два-три знака;
  • пълно име, което дава по-детайлно описание за нивото;

Нека дефинираме три нива на чувствителност на информацията със съответните им атрибути:

 номеркратко име пълно име 
 1000 PUPublic Information 
 2000 COConfidential Information
 3000 SESecret Information

Съгласно тази класификация най-ниско защитено ще бъде нивото обозначаващо публична информация (1000), а най-високо защитено - ниво 3000 (чувствителна информация).

За създаване на самите нива използваме процедурата CREATE_LEVEL. Можем да напишем следния скрипт:

/*
* ORACLE LABEL SECURITY
*
* CREATE_LEVELS.SQL
*
*/

connect lbacsys/lbacsys;

BEGIN

SA_COMPONENTS.CREATE_LEVEL(
  policy_name=>'ACCESS_EMPLOYEES',
  level_num=>'1000',
  short_name=>'PU',
  long_name=>'Public Information'
);

SA_COMPONENTS.CREATE_LEVEL(
  policy_name=>'ACCESS_EMPLOYEES',
  level_num=>'2000',
  short_name=>'CO',
  long_name=>'Confidential Information'
);

SA_COMPONENTS.CREATE_LEVEL(
  policy_name=>'ACCESS_EMPLOYEES',
  level_num=>'3000',
  short_name=>'SE',
  long_name=>'Sensitive Information'
);

END;

/

Изпълнението му създава трите нива:

SQL> @/home/oracle/create_levels.sql
Connected.

PL/SQL procedure successfully completed.

SQL>

Лесно можем да реализираме примерния сценарий използвайки нивата на достъп. За целите на демонстрацията обаче ще използваме само едно ниво, но към него ще добавим области и групи, чрез които ще изградим нужната йерархия, за да можем да добием по-пълна представа от възможностите на OLS. И така, да продължим с областите.


Създаване на областите


Чрез областите можем да опишем функционални зони, за които влизат в сила различни ограничения в зависимост от етикетите. Това, че дадени данни попадат в определена област не означава, че те нямат съответното ниво на достъп.

Да вземем един пример. Нека имаме таблица, в която всеки ред представлява транзакция платена от даден клиент. Да кажем, че в компанията имаме два независими отдела – наеми и продажби. В таблицата има колона, която указва типа на транзакцията – наем/продажба. Можем да дефинираме две области за съответния тип транзакция и да дадем права на двата отдела само за конкретната област. Във всяка отделна област отново можем да имаме различни нива на сигурност, които вече да ограничават достъпа на служителите от отдела до различните записи в групата която виждат – наеми или продажби.

Областите се дефинират също с три атрибута - номер, кратко и пълно име, които са напълно аналогични по предназначение с атрибутите на нивата. Дори и нашите примерни потребители да споделят една и съща област с информация, поне за целите на упражнението можем да дефинираме няколко различни области. Нека ги опишем така.

 номеркратко име пълно име 
 1000 AD Administration
 2000 FI Finance
 3000 AC Accounting
 4000 HR Human Relations

За създаването на тези области конструираме следния скрипт, в който извикваме CREATE_COMPARTMENT процедурата. Скриптът изглежда така:

/*
* ORACLE LABEL SECURITY
*
* CREATE_COMPARTMENTS.SQL
*
*/

connect lbacsys/lbacsys;

BEGIN

SA_COMPONENTS.CREATE_COMPARTMENT(
   policy_name=>'ACCESS_EMPLOYEES',
   comp_num=>1000,
   short_name=>'AD',
   long_name=>'Administration'
);

SA_COMPONENTS.CREATE_COMPARTMENT(
   policy_name=>'ACCESS_EMPLOYEES',
   comp_num=>2000,
   short_name=>'FI',
   long_name=>'Finance'
);

SA_COMPONENTS.CREATE_COMPARTMENT(
  policy_name=>'ACCESS_EMPLOYEES',
  comp_num=>3000,
  short_name=>'AC',
  long_name=>'Accounting'
);

SA_COMPONENTS.CREATE_COMPARTMENT(
  policy_name=>'ACCESS_EMPLOYEES',
  comp_num=>9000,
  short_name=>'HR',
  long_name=>'Human Resources'
);

END;

/

Изпълняваме го по следния начин:

SQL> @/home/oracle/create_compartments.sql
Connected.

PL/SQL procedure successfully completed.

SQL>


Създаване на групите

Последното, за което трябва да се погрижим са групите. Тях ще използваме за да лимитираме достъпа до данните в таблицата само до собствениците на самите данни. В допълнение, ще опишем йерархия, чрез която ще реализираме демонстрационният сценарий с президента и вицепрезидентите на компанията. Йерархията, която ще използваме изглежда така:

Hierarchy Schema

Групите също имат номер, кратко и пълно име, но и един атрибут в повече – родител. Чрез него описваме йерархията на отделните групи. Родителят съдържа като стойност краткото име на групата, към която е причислен текущия запис. Ако стойността на полето родител е null, това означава че текущата група няма родител. Освен четирите групи описани на схемата, създаваме и една допълнителна група – TOP, която служи за начален елемент на йерархията (в схемата е означена с кръг, към който са вързани базовите групи). Стойностите на атрибутите, чрез които ще конструираме групите са следните:

 номеркратко име пълно име родител 
 1000 TOP Hierarchy Top
null 
 2000 USA USA Operations
 TOP
 3000 CAN Canadian Operations
 USA
 4000 UK UK Operations
 TOP
 5000 GER German Operations
 TOP

За създаването на описаните групи използваме следния скрипт:

/*
* ORACLE LABEL SECURITY
*
* CREATE_GROUPS.SQL
*
*/

connect lbacsys/lbacsys;

BEGIN

SA_COMPONENTS.CREATE_GROUP(
   policy_name=>'ACCESS_EMPLOYEES',
  group_num=>1000,
  short_name=>'TOP',
  long_name=>'Hierarchy Top',
  parent_name=>NULL
);

SA_COMPONENTS.CREATE_GROUP(
  policy_name=>'ACCESS_EMPLOYEES',
  group_num=>2000,
  short_name=>'USA',
  long_name=>'USA Operations',
  parent_name=>'TOP'
);

SA_COMPONENTS.CREATE_GROUP(
  policy_name=>'ACCESS_EMPLOYEES',
  group_num=>3000,
  short_name=>'CAN',
  long_name=>'Canadian Operations',
  parent_name=>'TOP'
);

SA_COMPONENTS.CREATE_GROUP(
  policy_name=>'ACCESS_EMPLOYEES',
  group_num=>4000,
  short_name=>'UK',
  long_name=>'UK Operations',
  parent_name=>'TOP'
);

SA_COMPONENTS.CREATE_GROUP(
  policy_name=>'ACCESS_EMPLOYEES',
  group_num=>5000,
  short_name=>'GER',
  long_name=>'German Operations',
  parent_name=>'TOP'
);

END;

/

Изпълняваме го:

SQL> @/home/oracle/create_groups.sql
Connected.

PL/SQL procedure successfully completed.

SQL>

С което изграждането на групите и описването на йерархията приключва.


Създаване на етикетите

След като политиката е цялостно описана най-накрая трябва да дефинираме етикетите за достъп и да ги приложим към данните и различните потребители.

Етикетите се създават чрез SA_LABEL_ADMIN.CREATE_LABEL и се описват чрез следните атрибути:

  • таг - уникална целочислена стойност, използвана главно за определяне на реда на сортиране на етикетите;
  • стойност - комбинация от ниво, област и група, определяща достъпа до информацията;
  • етикет за данни - стойността е от булев тип и показва дали етикета може да се прилага към ред от таблица (т.е. да ограничава данни);

Съгласно описаните нива, области и групи и имайки предвид йерархията от примерния сценарий, дефинираме етикетите по следния начин:

 тагстойност етикет за данни 
 10000 PUtrue 
 20000 COtrue
 30000 SE true
 30100 SE:AD:TOP true
 30200 SE:AD:USA true
 30300 SE:AD:UK true
 30400 SE:AD:CAN true
 30500 SE:AD:GER true

Съгласно препоръката на Oracle сме подбрали такива стойности на таговете, че различните нива са отделени в ясни логически групи. Създаването на самите етикети ще направим чрез следния скрипт:

/*
* ORACLE LABEL SECURITY
*
* CREATE_LABELS.SQL
*
*/

connect lbacsys/lbacsys;

BEGIN

SA_LABEL_ADMIN.CREATE_LABEL(
  policy_name=>'ACCESS_EMPLOYEES',
  label_tag=>10000,
  label_value=>'PU',
  data_label=>TRUE
);

SA_LABEL_ADMIN.CREATE_LABEL(
  policy_name=>'ACCESS_EMPLOYEES',
  label_tag=>20000,
  label_value=>'CO',
  data_label=>TRUE
);

SA_LABEL_ADMIN.CREATE_LABEL(
  policy_name=>'ACCESS_EMPLOYEES',
  label_tag=>30000,
  label_value=>'SE',
  data_label=>TRUE
);

SA_LABEL_ADMIN.CREATE_LABEL(
  policy_name=>'ACCESS_EMPLOYEES',
  label_tag=>30100,
  label_value=>'SE:AD:TOP',
  data_label=>TRUE
);

SA_LABEL_ADMIN.CREATE_LABEL(
  policy_name=>'ACCESS_EMPLOYEES',
  label_tag=>30200,
  label_value=>'SE:AD:USA',
  data_label=>TRUE
);

SA_LABEL_ADMIN.CREATE_LABEL(
  policy_name=>'ACCESS_EMPLOYEES',
  label_tag=>30300,
  label_value=>'SE:AD:UK',
  data_label=>TRUE
);

SA_LABEL_ADMIN.CREATE_LABEL(
  policy_name=>'ACCESS_EMPLOYEES',
  label_tag=>30400,
  label_value=>'SE:AD:CAN',
  data_label=>TRUE
);

SA_LABEL_ADMIN.CREATE_LABEL(
  policy_name=>'ACCESS_EMPLOYEES',
  label_tag=>30500,
  label_value=>'SE:AD:GER',
  data_label=>TRUE
);

END;

/

След изпълнението на скрипта, всички нужни етикети са създадени:

SQL> @/home/oracle/create_labels.sql
Connected.

PL/SQL procedure successfully completed.

SQL>


Прилагане на политиката към потребителите

Преди да приложим политиката към данните трябва да дадем на потребителите нужните права за да могат да имат достъп до защитените данни. Съгласно нашия демонстрационен сценарий, правата които те ще получат изглеждат така:

 потребителпозици достъп 
 Steven King
 президент SE:AD:TOP
 Neena Kochhar
 вицепрезидент SE:AD:USA
 Lex De Haan
 вицепрезидент SE:AD:UK
 Shanta Vollman
 управител склад
 PU


За да получат горните потребители описаните права трябва да приложим политиката към тях със съответните параметри. За целта ще използваме процедурата SA_USER_ADMIN.SET_USER_LABELS. Чрез нея можем да укажем нивата на достъп за четене и писане, а също така и етикетът по подразбиране на сесията. В случаят ще използваме само един от параметрите – max_read_label, чрез който задаваме максималното ниво на достъп за четене на потребителя. Тъй като не задаваме изрично етикет по подразбиране за сесията, то процедурата ще използва зададената в max_read_label стойност, което ни устройва.

С оглед на казаното до тук, можем да конструираме следния скрипт, чрез който да приложим създадената политика към определените от нас потребители:

/*
* ORACLE LABEL SECURITY
*
* APPLY_POLICY_USERS.SQL
*
*/

connect lbacsys/lbacsys;

BEGIN

SA_USER_ADMIN.SET_USER_LABELS(
  policy_name=>'ACCESS_EMPLOYEES',
  user_name=>'sking',
  max_read_label=>'SE:AD:TOP'
);

SA_USER_ADMIN.SET_USER_LABELS(
  policy_name=>'ACCESS_EMPLOYEES',
  user_name=>'nkochhar',
  max_read_label=>'SE:AD:USA'
);

SA_USER_ADMIN.SET_USER_LABELS(
  policy_name=>'ACCESS_EMPLOYEES',
  user_name=>'ldehaan',
  max_read_label=>'SE:AD:UK'
);

END;

/

Изпълняваме скрипта и предоставяме достъп на потребителите, както решихме. Изключение прави акаунта на Shanta Vollman, към който нарочно не внасяме никакви промени:

SQL> @/home/oracle/apply_policy_users.sql
Connected.

PL/SQL procedure successfully completed.

SQL>


Прилагане на политиката върху таблицата

За да приложим политиката ACCESS_POLICY върху таблицата EMPLOYEES използваме процедурата SA_POLICY_ADMIN.APPLY_TABLE_POLICY. Тя приема като параметри името на политиката, схемата и таблицата, върху която искаме да я приложим. Можем да зададем и допълнителни опции по контрол на достъпа. Ако такива не са зададени се прилагат опциите по подразбиране, дефинирани в самата политика.

Когато прилагаме политика към дадена таблица трябва да знаем, че след прилагането й тя автоматично се активира. Съществува две отделни процедури за деактивиране и активиране на политика съответно – SA_POLICY_ADMIN.DISABLE_TABLE_POLICY и SA_POLICY_ADMIN.ENABLE_TABLE_POLICY. Дори когато една политика е деактивирана, тя все още остава приложена към таблицата. Ако искаме да я премахнем изцяло съществува трета процедура – SA_POLICY_ADMIN.REMOVE_TABLE_POLICY. Особеното в случая е, че дори при цялостното премахване, колоната с етикетите ще остане в таблицата и ще трябва ръчно да я изтрием.

Освен за отделна таблица, политиката може да се приложи и генерално за цяла схема. Тогава тя е валидна за всички таблици в схемата и автоматично се прилага върху всяка новосъздадена таблица. Съществуват аналогични процедури (например SA_POLICY_ADMIN.APPLY_SCHEMA_POLICY), но за целите на нашия примерен сценарий и една таблица е достатъчна.

Скриптът, който ще използваме за прилагане на политиката към таблицата EMPLOYEES в схемата HR е съвсем прост:

/*
* ORACLE LABEL SECURITY
*
* APPLY_POLICY_TABLE.SQL
*
*/

connect lbacsys/lbacsys;

BEGIN

SA_POLICY_ADMIN.APPLY_TABLE_POLICY(
  policy_name=>'ACCESS_EMPLOYEES',
  schema_name=>'HR',
  table_name=>'EMPLOYEES'
);

END;

/

След като приложим политиката върху таблицата, дори и собственикът на данните няма повече да може да ги вижда. Нека опитаме да достъпим таблицата EMPLOYEES чрез потребителя HR:


SQL> connect hr/hr;
Connected.
SQL> select first_name from employees;

no rows selected

SQL>

В OLS съществува допълнителна процедура, чрез която можем да задаваме права на отделните потребители за дадена политика. Тази процедура се нарича SA_USER_ADMIN.SET_USER_PRIVS и ще я използваме, за да дадем достъп до данните на потребителя HR. Ще използваме следния скрипт:


/*
* ORACLE LABEL SECURITY
*
* SET_HR_PRIVS.SQL
*
*/

connect lbacsys/lbacsys;

BEGIN
SA_USER_ADMIN.SET_USER_PRIVS(
  policy_name=>'ACCESS_EMPLOYEES',
  user_name=>'HR',
  privileges=>'FULL,PROFILE_ACCESS'
);
END;
/

Както се вижда процедурата приема три параметъра – име на политика, име на потребител и привилегии, които му делегираме. Те могат да са READ (да чете всички данни защитени от политиката), FULL (да чете и да ги променя) и други, които са описани подробно в документацията. PROFILE_ACCESS позволява потребителят да подменя етикета по подразбиране и правата на сесията си с тези на други потребители. Това е мощна привилегия, която потенциално може да се използва за придобиване на пълни права над политиката, така че трябва да се използва разумно.

Изпълняваме скрипта:

SQL> @/home/oracle/set_hr_privs.sql
Connected.

PL/SQL procedure successfully completed.

SQL>

Променените права влизат в сила единствено след рестарт на сесията, така че ако искаме да направим нова проверка с потребителя HR, трябва да приключим текущата му сесия и да създадем нова.

SQL> connect hr/hr;
Connected.
SQL> select first_name from employees;

FIRST_NAME
-------------------
Ellen
Sundar
Mozhe
David
Hermann
Shelli
...
Eleni

107 rows selected.

SQL>

Сега вече hr има пълни права над данните и вижда всичките 107 записа в таблицата EMPLOYEES. Време е да настроим етикетите на данните, за да ограничим достъпа на тестовите потребители.


Задаване на етикети към данните

Последното, което остава да направим е да поставим етикетите в колоната на политиката. За да определим кой служител в коя държава е използваме таблицата DEPARTMENTS, в която е описано в кой точно отдел работи и която е свързана с LOCATIONS, където има колона COUNTRY_ID. Следния скрипт ъпдейтва последователно всички служители в с COUNTRY_ID = USA като им поставя етикет SE:AD:USA, а тези с COUNTRY_ID = UK получават етикет SE:AD:UK:

/*
* ORACLE LABEL SECURITY
*
* APPLY_POLICY_ROWS.SQL
*
*/

connect hr/hr;

-- All employees in department located in US will be update with security label SE:AD:USA

update employees set security_labels=char_to_label('ACCESS_EMPLOYEES', 'SE:AD:USA')
where exists (
  select * from departments, locations
    where (employees.department_id = departments.department_id)
        and (departments.location_id = locations.location_id)
        and (locations.country_id = 'US')
);

-- All employees in department located in Canada will be update with security label SE:AD:CAN

update employees set security_labels=char_to_label('ACCESS_EMPLOYEES', 'SE:AD:CAN')
where exists (
  select * from departments, locations
    where (employees.department_id = departments.department_id)
       and (departments.location_id = locations.location_id)
       and (locations.country_id = 'CA')
    );

-- All employees in department located in UK will be update with security label SE:AD:UK

update employees set security_labels=char_to_label('ACCESS_EMPLOYEES', 'SE:AD:UK')
where exists (
   select * from departments, locations
     where (employees.department_id = departments.department_id)
       and (departments.location_id = locations.location_id)
       and (locations.country_id = 'UK')
);

Изпълняваме скрипта:

SQL> @/home/oracle/apply_policy_rows.sql
Connected.

68 rows updated.

2 rows updated.

35 rows updated.

SQL>

Очевидно 68 от служителите са в USA, 2 в Канада и 35 в UK. С това, внедряването на нашия пример с OLS приключва. Време е да направим няколко проби с отделните потребители.


Няколко примерни заявки

И така, да изпълним един SELECT, който връща FIRST_NAME и LAST_NAME за всички служители от таблицата EMPLOYEES. Изпълнението чрез акаунта на Lex De Haan изглежда така:

SQL> connect ldehaan/ldehaan;
Connected.
SQL> select first_name, last_name from hr.employees;

FIRST_NAME LAST_NAME
-------------------- -------------------------
Susan Mavris
John Russell
Karen Partners
Alberto Errazuriz
Gerald Cambrault
...
Charles Johnson

35 rows selected

SQL>

Заявката връща само 35 реда от таблицата – тези съдържащи служителите намиращи се в UK. Изпълняваме същата заявка през акаунта на Neena Kochhar:

SQL> connect nkochhar/nkochhar;
Connected.
SQL> select first_name, last_name from hr.employees;

FIRST_NAME LAST_NAME
-------------------- -------------------------
Donald OConnell
Douglas Grant
Jennifer Whalen
Michael Hartstein
Pat Fay
Shelley Higgins
William Gietz
Steven King
...
Kevin Feeney

70 rows selected

SQL>

Този път резултатът е 70 записа. Това са служителите в USA (68 на брой) и тези в Canada (2 на брой). Това показва, че както наложените ограничения, така и настроената йерархия работят коректно. Един последен тест чрез акаунта на президента на компанията изглежда така:

SQL> connect sking/sking;
Connected.
SQL> select first_name, last_name from hr.employees;

FIRST_NAME LAST_NAME
-------------------- -------------------------
Donald OConnell
Douglas Grant
Jennifer Whalen
Michael Hartstein
Pat Fay
Susan Mavris
Shelley Higgins
William Gietz
Steven King
Neena Kochhar
...
Kevin Feeney

105 rows selected

SQL>

Ако опитаме да изпълним заявката чрез потребителя svollman, който има достъп само до публична информация (такава в таблицата Employees няма), то тя няма да върне никакъв резултат:

SQL> connect svollman/svollman;
Connected.
SQL> select first_name, last_name from hr.employees;

no rows selected

SQL>


Няколко думи на финала

Още много може да се каже за Oracle Label Security. Самата OLS технология от своя страна стъпва на Oracle Virtual Private Database, която е още по-гъвкава (и разбира се много по-сложна) система за управление на достъпа, така че може би е добре да се запознаем и с нея, ако искаме в дълбочина да проучим възможностите за защита на информацията в базата.

Също така освен чрез пакетите и процедурите, които използвахме в тази демонстрация има още един начин да се управлява Oracle Label Security и той е през GUI инструмента наречен Oracle Policy Manager, който се инсталира заедно с Oracle Client дистрибуцията. Въпреки, че показахме нещата по малко по-трудния начин, след като сме ги разбрали ще е още по-лесно да използваме такъв инструмент на по-високо ниво за да ги управляваме и настройваме допълнително, ако се наложи.

Policy Manager

Oracle Label Security също така се интегрира с Oracle Database Vault, като по този начин може да намеси и инфраструктурата в различните политики (например може да се присвояват етикети на IP адреси достъпващи базата). Интеграцията на OLS пък Oracle Identity Management, позволява правата на всички потребители да се държат в Oracle Internet директорията и да бъдат обвързани с обща споделена схема. Но за тези неща – по-нататък.

Коментари

Име
URL
Код   
Запис
 

КНИГАТА

Oracle Database Security Book
(c) 2004-2008 Николай Манчев. Освен ако изрично не е споменато нещо друго, всички материали публикувани тук се разпространяват под Creative Commons Attribution License. Материали, коментари и изображения, които не са създадени и подписани от мен са собственост на съответните им автори.