seminář: Administrace Oracle (NDBI013) LS2017/18 RNDr. Michal Kopecký, Ph.D. Department of Software Engineering, Faculty of Mathematics and Physics, Charles University in Prague
Rozšíření bezpečnostní politiky Oracle o omezení na úrovni jednotlivých řádků a sloupců Pro uživatele, kterého se bezpečnostní politika týká, je v zásadě transparentní realizace příslušného omezení se provádí přidáním další vygenerované podmínky do WHERE klauzule
Původní dotaz od uživatele SELECT rc FROM zamestnanci; Uplatnění bezpečnostní politiky, která zakazuje každému zaměstnanci prohlížet si osobní údaje jiných zaměstnanců SELECT rc FROM zamestnanci WHERE id=sys_context( 'USERENV', 'SESSION_USER'); M. Kopecký NDBI013 3
Bezpečnost omezení jsou vynucována databází přímo nad jejími objekty (tabulky, pohledy, atd.) aplikace nemá možnost tato omezení měnit Jednoduchost je vynucována vůči všem aplikacím stejně a automaticky Flexibilita dotčené typy dotazů, sloupce, funkce generující podmínku do WHERE,... Optimalizace vyhodnocení podmínek M. Kopecký NDBI013 4
Generující funkce, která vrací WHERE podmínku Jejími argumenty jsou jméno schématu a jméno databázového objektu Vrací typ varchar2 Návratová hodnota musí být validní WHERE podmínkou Nesmí číst data z tabulky, se kterou je svázána M. Kopecký NDBI013 5
Politika svazující funkci s konkrétními objekty Příslušné procedury pracující s politikami jsou implementovány v balíčku DBMS_RLS Oprávnění definovat nové politiky má pouze uživatel SYS a uživatelé s právem EXECUTE tohoto balíčku Nejdůležitějšími procedurami pro manipulaci s politikami jsou ADD_POLICY a DROP_POLICY M. Kopecký NDBI013 6
CREATE OR REPLACE FUNCTION hide_admins ( v_schema IN varchar2, v_objname IN varchar2 ) RETURN varchar2 AS con varchar2(100); BEGIN con := 'usergroup!=0 RETURN (con); END hide_admins; M. Kopecký NDBI013 7
BEGIN DBMS_RLS.ADD_POLICY( object_schema => 'test', object_name => 'users', policy_name => 'admin_protection', policy_function => 'hide_admins', statement_types => 'SELECT,INDEX ); END; M. Kopecký NDBI013 8
Alternativa pro výchozí filtrování po řádcích pomocí klauzule WHERE (viz minulý slide) Používá se pouze pro SELECT Uživatel dostane všechny řádky, ale hodnoty chráněných sloupců v dříve neviditelných řádcích budou nahrazeny za NULL Je potřeba definovat sloupce, kterých se skrývání týká M. Kopecký NDBI013 9
BEGIN DBMS_RLS.ADD_POLICY( object_schema => 'test', object_name => 'users', policy_name => 'admin_protection', policy_function => 'hide_admins', sec_relevant_cols_opt => DBMS_RLS.ALL_ROWS, sec_relevant_cols => 'hashpwd,name,surname'); END M. Kopecký NDBI013 10
BEGIN DBMS_RLS.ADD_POLICY( object_schema => 'test', object_name => 'users', policy_name => 'admin_protection', policy_function => 'hide_admins', --sec_relevant_cols_opt => -- DBMS_RLS.ALL_ROWS, sec_relevant_cols => 'hashpwd,name,surname'); END Bez DBMS_RLS.ALL_ROWS jiné chování Pokud v SELECT není žádný relevantní sloupec, potom se zobrazí všechny řádky Pokud v SELECT je nějaký relevantní sloupec, zobrazí se jen řádky s ohledem na přidané WHERE M. Kopecký NDBI013 11
Možnost seskupování politik a jejich společné aplikace vhodné především v případě, kdy aplikace používá mnoho bezpečnostních politik na málo databázových objektů Další procedury v DBMS_RLS {CREATE DELETE}_POLICY_GROUP {ADD DROP}_GROUPED_POLICY {ADD DROP}_POLICY_CONTEXT M. Kopecký NDBI013 12
Pokud není definován POLICY_CONTEXT, použijí se všechny skupiny politik Výchozí skupina politik je SYS_DEFAULT je vždy platná a nelze jí smazat Aplikace si může vybrat další skupiny politik, které bude používat M. Kopecký NDBI013 13
Kontext aplikace je vhodným místem pro ukládání informací o uživateli a dalších relevantních údajů Přístup k němu je rychlejší než provádění dotazů zejména pokud závisí na více atributech M. Kopecký NDBI013 14
Parametr POLICY_TYPE v proceduře ADD_POLICY Hodnoty DYNAMIC STATIC SHARED_STATIC CONTEXT_SENSITIVE SHARED_CONTEXT_SENSITIVE M. Kopecký NDBI013 15
Politiky nelze aplikovat na objekty ve schématu SYS SYS a uživatelé s právem EXEMPT_ACCESS_POLICY nepodléhají politikám M. Kopecký NDBI013 16
Vytvoření politiky, která limituje přístup zákazníkům do tabulky OE.ORDERS pouze na své vlastní objednávky 1) Uživatel SYS vytvoří administrátora politiky a svěří mu potřebná oprávnění GRANT CREATE SESSION, CREATE ANY CONTEXT, CREATE PROCEDURE, CREATE TRIGGER, ADMINISTER DATABASE TRIGGER TO sysadmin_vpd IDENTIFIED by password ; GRANT EXECUTE ON DBMS_SESSION to sysadmin_vpd; GRANT EXECUTE ON DBMS_RLS to sysadmin_vpd; X xx M. Kopecký NDBI013 17
2) Dále vytvoří účty dvěma ukázkovým zákazníkům GRANT CREATE SESSION TO brooke IDENTIFIED by pwd1 ; GRANT CREATE SESSION TO woods IDENTIFIED by pwd2 ; 3) Odemkne uživatelský účet pro samotnou aplikaci a nastaví mu nové heslo ukázkový uživatel a schéma scott ALTER USER SCOTT ACCOUNT UNLOCK IDENTIFIED by pwd3 ; 4) Uživatel SCOTT se přihlásí a vytvoří a naplní tabulky zákazníků a objednávek M. Kopecký NDBI013 18
CREATE TABLE customers ( cust_no NUMBER(4), cust_email VARCHAR(20), cust_name VARCHAR(20)); INSERT INTO customers VALUES (1234, 'BROOKE', 'Ted Brooke'); INSERT INTO customers VALUES (5678, 'WOODS', 'Bill Woods'); CREATE TABLE orders_tab ( cust_no NUMBER(4), ord_no NUMBER(4)); M. Kopecký NDBI013 19
INSERT INTO orders_tab VALUES (1234, 9876); INSERT INTO orders_tab VALUES (5678, 5432); INSERT INTO orders_tab VALUES (5678, 8765); 5) Uživatel SCOTT udělí právo čtení tabulky uživatelů správci VPD a oběma uživatelů právo čtení objednávek GRANT SELECT ON CUSTOMERS TO sysadmin_vpd; GRANT SELECT ON ORDERS TO brooke; GRANT SELECT ON ORDERS TO woods; 6) SYSADMIN_VPD vytvoří kontext X xx M. Kopecký NDBI013 20
CREATE OR REPLACE CONTEXT orders_ctx USING orders_pkg; 7) A definuje jeho balíček CREATE OR REPLACE PACKAGE orders_pkg IS PROCEDURE set_custnum; END; CREATE OR REPLACE PACKAGE BODY orders_pkg IS PROCEDURE set_custnum AS custnum NUMBER; BEGIN SELECT cust_no INTO custnum FROM scott.customers WHERE cust_email=sys_context('user_env', 'SESSION_USER'); DBMS_SESSION.SET_CONTEXT('orders_ctx', 'cust_no', custnum); M. Kopecký NDBI013 21
... EXCEPTION WHEN NO_DATA_FOUND THEN NULL; END SET_CUSTNUM; END; 8) Vytvoří trigger, který při každém přihlášení uživatele zaznamená jeho ID do kontextu CREATE TRIGGER set_custno_trig AFTER LOGON ON DATABASE BEGIN sysadmin_vpd.orders_pkg.set_custnum; END; M. Kopecký NDBI013 22
9) Správce VPD nadefinuje generující funkci CREATE OR REPLACE FUNCTION get_user_orders( in_schema IN varchar2, in_object IN varchar2) RETURN varchar2 AS orders_pred varchar2(400); BEGIN orders_pred := 'cust_no=sys_context(''orders_ctx'',''cust_no'')'; RETURN orders_pred; END; 10) A nakonec vytvoří samotnou politiku M. Kopecký NDBI013 23
BEGIN DBMS_RLS.ADD_POLICY( object_schema => 'scott', object_name => 'orders', policy_name => 'orders_policy', function_schema => 'sysadmin_vpd', policy_function => 'get_user_orders', statement_types => 'select ); END; M. Kopecký NDBI013 24
Ukázka filtrování sloupců podle právě přihlášeného uživatele 1) SYS vytvoří administrátora skupiny politik a uživatele GRANT CREATE SESSION TO apps_user IDENTIFIED by pwd1 ; GRANT CREATE SESSION, CREATE PROCEDURE, CREATE ANY CONTEXT TO sysadmin_pg IDENTIFIED by pwd2; 2) Pověří ho administrováním politik GRANT EXECUTE ON DBMS_RLS TO sysadmin_pg; M. Kopecký NDBI013 25
3) Uživatel SCOTT vytvoří a naplní tabulku produktů a nechá z ní číst aplikačního uživatele CREATE TABLE product_codes ( group_a varchar(32), year_a varchar(32), group_b varchar(32), year_b varchar(32)); INSERT INTO product_codes VALUES ('BF', 2008, 'BI', 2004); INSERT INTO product_codes VALUES ('HT', 2008, 'BN', 2008); INSERT INTO product_codes VALUES ('BP', 2006, 'HT', 2003); GRANT SELECT ON product_codes TO apps_user; M. Kopecký NDBI013 26
3) SYSADMIN_PG vytvoří dvě skupiny politik BEGIN DBMS_RLS.CREATE_POLICY_GROUP( object_schema => 'scott', object_name => 'product_codes', policy_group => 'provider_{a b}_group'); END; M. Kopecký NDBI013 27
4) A k oběma politikám vytvoří generující funkci CREATE OR REPLACE FUNCTION vpd_function_provider_{a b}( in_schema IN varchar2, in_object IN varchar2) return varchar2 AS predicate varchar2(8) default NULL; BEGIN IF LOWER(SYS_CONTEXT( 'USERENV', 'CLIENT_IDENTIFIER'))='provider_{a b} THEN predicate := '1=2'; ELSE predicate := NULL; END IF; RETURN predicate; END; M. Kopecký NDBI013 28
5) Přidá obě politiky do svých skupin BEGIN DBMS_RLS.ADD_GROUPED_POLICY( object_schema => 'scott', object_name => 'product_codes', policy_group => 'provider_{a b}_group', policy_name => 'filter_provider_{a b}', function_schema => 'sysadmin_pg', policy_function => 'vpd_function_provider_{a b}', policy_type => DBMS_RLS.CONTEXT_SENSITIVE, sec_relevant_cols => 'group_(b a),year_{b a}', sec_relevant_cols_opt => DBMS_RLS.ALL_ROWS); END; M. Kopecký NDBI013 29
6) Vytvoří řídící kontext aplikace a jeho balíček CREATE OR REPLACE CONTEXT provider_ctx USING provider_package; CREATE OR REPLACE PACKAGE provider_package AS PROCEDURE set_provider_context( policy_group varchar2 default NULL); END; CREATE OR REPLACE PACKAGE BODY provider_package AS PROCEDURE set_provider_context( policy_group varchar2 default NULL) IS M. Kopecký NDBI013 30
BEGIN CASE LOWER(SYS_CONTEXT( 'USERENV', 'CLIENT_IDENTIFIER')) WHEN 'provider_a' THEN DBMS_SESSION.SET_CONTEXT( 'provider_ctx', 'policy_group', 'PROVIDER_A_GROUP'); WHEN 'provider_b' THEN DBMS_SESSION.SET_CONTEXT( 'provider_ctx', 'policy_group' 'PROVIDER_B_GROUP'); END CASE; END SET_PROVIDER_CONTEXT; END; M. Kopecký NDBI013 31
7) Nakonec spojí kontext s tabulkou a přidělí aplikačnímu uživateli právo spouštět jeho balíček BEGIN DBMS_RLS.ADD_POLICY_CONTEXT( object_schema => 'scott', object_name => 'product_codes', namespace => 'provider_ctx', attribute => 'policy_group'); END; GRANT EXECUTE ON provider_package TO apps_user; M. Kopecký NDBI013 32