Fine-Grained Access в Oracle DB 11g R1 и нагоре.
Този документ има за цел да опише подробно как се добавят в ACL Oracle потребители или роли за да могат да използват PL/SQL пакетите: UTL_TCP, UTL_HTTP, UTL_SMTP, UTL_MAIL, UTL_INADDR, DBMS_LDAP.
Проблема се състои в това, че информацията е кратка и много разхвърляна. В Металинк известна информация може да се намери в следният документ:
ORA-24247 When Executing UTL_HTTP UTL_INADDR Packages [ID 453786.1]
Но дори и в него няма отговор на следното. Кагато посочваш host – кой е този адрес? Когато създаваш xml файл за всеки юзер отделен файл ли се създава?
Най общо казано ще се придържам към начина, по който Оракъл описват документите, но съм добавил и друга информация, която съм намерил в мрежата. Освен всичко друго тази информация е много необходима за всеки администратор, на който му се налага да извърши “upgarede” към 11g,
Симптоми
Когато изпълнявате DBMS_LDAP, UTL_INADDR (или) UTL_HTTP (или) всеки UTL пакет след ъпгрейд до 11gR2 приключва с грешка.
Например:
SQL> DECLARE
l_url varchar2(32767);
l_conn utl_http.req;
BEGIN
l_url := 'http://www.oracle-bg.com';
l_conn := utl_http.begin_request(
url => l_url,
method => 'POST',
http_version=> 'HTTP/1.0');
dbms_output.put_line('Anonymous Block Executed Successfully');
END;
/
declare
*
ERROR at line 1:
ORA-29273: HTTP request failed
ORA-6512: at "SYS.UTL_HTTP", line 1029
ORA-24247: network access denied by access control list (ACL)
ORA-6512: at line 6
SQL> select utl_inaddr.get_host_address('www.oracle-bg.com') from dual;
select utl_inaddr.get_host_address('www.oracle-bg.com') from dual
*
ERROR at line 1:
ORA-24247: network access denied by access control list (ACL)
ORA-06512: at "SYS.UTL_INADDR", line 19
ORA-06512: at "SYS.UTL_INADDR", line 40
ORA-06512: at line 1
Причина
Една нова секюрити мярка е въведена от Oracle 11g Release 1 (11.1) и нагоре, за PL/SQL пакети имащи отношение към външни мрежови услуги, като: UTL_TCP, UTL_HTTP, UTL_SMTP, UTL_MAIL, UTL_INADDR, DBMS_LDAP и HttpUriType типа. Този който се обръща към тези пакети се нуждае от допълнителни привилегии за да се свърже към външен хост или да да резолвне името или IP адреса на този хост. Пакетите проверяват дали извикващият има необходимите привилегии само когато обръщенията са направени по време на стартиране и връща изключение ако лепсват нужните привилегии. Тази нова сукюрити мярка е имплементирана от XML DB access control list (ACL) механизъм и поради това,
изисква XML DB да бъде инсталиран и конфигуриран network Access Control Lists (ACLs) в базата, преди тези пакети да могат да работят по същият начин, както в предишните версии.
Access control lists(ACL) може да бъде създаден, коригиран и премахнат в XML DB репозитори-то директно използвайки FTP или WebDav. В допълнение, Oracle предоставят DBMS_NETWORK_ACL_ADMIN и DBMS_NETWORK_ACL_UTILITY пакети, които позволяват управлението на ACL чрез PL/SQL.
Решение
Създаване на Access control lists(ACL)
Access control lists могат да се манипулират използвайки DBMS_NETWORK_ACL_ADMIN пакета. Процедурата CREATE_ACL (от същият пакет) има следните параметри за да създадем нов ACL:
- acl – е името на access control list XML файл, генериран в "/sys/acls" директорията в XML DB Repository-то.
- description – Задайте свое кратко описание за ACL-а.
- principal – потребителя или ролята на които ще бъдат дадени или отнети правата в ACL-а . Текста е „case sensitive”.
- is_grant - TRUE за разрешение, FALSE за отказ напривилегията.
- privilege - Използвайте 'connect' за UTL_TCP, UTL_SMTP, UTL_MAIL and UTL_HTTP достъп. Използвайте 'resolve' за UTL_INADDR име/IP „resolution”. Текста е „case sensitive”.
- start_date – Стойноста по подразбиране е NULL. Когато е специфицирана, ACL ще бъде активна на/или след тази дата.
- end_date – опция за крайна дата на даден ACL.
Синтаксиса е следният:
BEGIN
DBMS_NETWORK_ACL_ADMIN.CREATE_ACL (
acl => 'file_name.xml',
description => 'file description',
principal => 'user_or_role',
is_grant => TRUE|FALSE,
privilege => 'connect|resolve',
start_date => null|timestamp_with_time_zone,
end_date => null|timestamp_with_time_zone);
END;
/
Следният код създава два тестови потребителя за демонстрационна цел.
CONN sys/password@db11g AS SYSDBA
CREATE USER test1 IDENTIFIED BY test1;
GRANT CONNECT TO test1;
CREATE USER test2 IDENTIFIED BY test2;
GRANT CONNECT TO test2;
BEGIN
DBMS_NETWORK_ACL_ADMIN.create_acl (
acl => 'test_acl_file.xml',
description => 'A test of the ACL functionality',
principal => 'TEST1',
is_grant => TRUE,
privilege => 'connect',
start_date => NULL,
end_date => NULL);
COMMIT;
END;
/
Веднъж създаден, ACL може да се види в "http://host:port/sys/acls/" директорията.
Допълнителни потребители или роли се добавят в ACL чрез процедурата ADD_PRIVILEGGE. Валидните параметри са подобни на тези от CREATE_ACL процедуратар с тази разлика ,
че няма DESCRIPTION параметър и е добавен друг POSITION параметър, който оказва ред на предимство в xml файла. Малко трудно може да се обясни,
но след известни тренировки и наблюдения ще разберете за както става въпрос. Сега нека добавим и вторият тестов потребител.
BEGIN
DBMS_NETWORK_ACL_ADMIN.add_privilege (
acl => 'test_acl_file.xml',
principal => 'TEST2',
is_grant => FALSE,
privilege => 'connect',
position => NULL,
start_date => NULL,
end_date => NULL);
COMMIT;
END;
/
Всеки потребител или роля е дефиниран като отделен "access control element (ACE)" към ACL. Когато имаме много дефинирани потребители,
те се оценяват от горе на долу с последната приложена дефиниция използвата за дефиниране на привилегия.
Това означава, че роля, която отказва достъп до ресурс може да бъде грантната на потребител, но ако потребителя е дефиниран като "principal" по-надолу във файла,
тази дефиниция ще препокрие дефиницията за роля на този юзер. Използвайте POSITION параметъра за да сте сигурни, че привилегиите се оценяват поред.
Привилегии се премахват чрез DELETE_PRIVILEGE процедурата. Ако IS_GRANT или PRIVILEGE параметъра са NULL, всичке „grants”-ове или привилегии за ACL-та и principal are removed.
- acl – е името на access control list XML файл, генериран в "/sys/acls" директорията в XML DB Repository-то.
- principal – потребителя или ролята на които ще бъдат дадени или отнети правата в ACL-а . Текста е „case sensitive”.
- is_grant - TRUE за разрешение, FALSE за отказ на привилегията.
- privilege - Привилегия, която трябва да бъде премахната. Използвайте 'connect' за UTL_TCP, UTL_SMTP, UTL_MAIL and UTL_HTTP достъп. Използвайте 'resolve' за UTL_INADDR име/IP „resolution”. Текста е „case sensitive”.
BEGIN
DBMS_NETWORK_ACL_ADMIN.DELETE_PRIVILEGE(
ACL => 'test_acl_file.xml',
PRINCIPAL => 'TEST2',
IS_GRANT => FALSE,
PRIVILEGE => 'connect');
commit;
END;
/
Ако искате да изтриете даден ACL, изпълнете следното:
BEGIN
DBMS_NETWORK_ACL_ADMIN.drop_acl (
acl => 'test_acl_file.xml');
COMMIT;
END;
/
Ако искате да изтриете даден ACL, изпълнете следното:
Всеки Access control lists се определят към мрежа чрез ASSIGN_ACL процедурата, чиито параметри са :
- acl – е името на access control list XML файл, генериран в "/sys/acls" директорията в XML DB Repository-то.
- host – Хост име, домейн, IP адрес или подмрежа към която да бъде зададен ACL. Имената на хостовете са „case sensitive” и “*” e позволено при дефиниране на IP адреси или домейн.
- lower_port – по подразбиране е NULL. Оказва по-малкият порт за 'connect' привилегията.
- upper_port - по подразбиране е NULL. Ако lower_port е оказан и upper_port е NULL, тогава upper_port = lower_port.
BEGIN
DBMS_NETWORK_ACL_ADMIN.assign_acl (
acl => 'test_acl_file.xml',
host => '192.168.1.100',
lower_port => 80,
upper_port => NULL);
DBMS_NETWORK_ACL_ADMIN.assign_acl (
acl => 'test_acl_file.xml',
host => '173.18.*',
lower_port => NULL,
upper_port => NULL);
COMMIT;
END;
/
Важно при използването и:
Само един ACL може да бъде зададен за всеки хост, домейн, IP подмрежа, и ако е оказан диапазон от TCP портове. Когато задавате нов ACL към дадена мрежа, Oracle
отписва предишният списък за контролиран достъп, който е бил зададен за същият хост, домейн или адрес. Можете да изтривате даден списък за контролиран достъп,
чрез DROP_ACL процедурата. За да отпишете деден запис от списък за контролиран достъп(ACL), използвайте процедурата UNASSIGN_ACL.
UNASSIGN_ACL процедурата ви позволява ръчно да изтриете запис от списък за контролиран достъп(ACL). Тя използва същите параметри, както при ASSIGN_ACL процедурата.
BEGIN
DBMS_NETWORK_ACL_ADMIN.unassign_acl (
acl => 'test_acl_file.xml',
host => '192.168.1.100',
lower_port => 80,
upper_port => NULL);
COMMIT;
END;
/