Virtual private database Antonín Steinhauser
Základní princip VPD 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
Nástin fungování VPD 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');
Hlavní výhody VPD 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
Komponenty VPD I. 1) Generující funkce, která vrací WHERE podmínku Jejími argumenty jsou jméno schématu a jméno databázového objektu Vrací varchar2 Návratová hodnota musí být validní WHERE podmínkou Nesmí číst data z tabulky, se kterou je svázána
Komponenty VPD II. 2) 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 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
Příklad generující funkce 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;
Příklad přidání politiky BEGIN DBMS_RLS.ADD_POLICY( object_schema => 'test', object_name => 'users', policy_name => 'admin_protection', policy_function => 'hide_admins', statement_types => 'SELECT,INDEX'); END
Maskování sloupců Alternativa pro výchozí filtrování po řádcích pomocí klauzule WHERE Používá se pouze pro SELECT Uživatel dostane všechny řádky, pouze hodnoty chráněných sloupců budou nahrazeny za NULL Je potřeba definovat sloupce, kterých se skrývání týká
Příklad přidání sloupcové politiky 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
Skupiny politik VPD 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
Skupiny politik VPD II 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
Využití aplikačního kontextu 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
Optimalizace politik Parametr policy_type v proceduře ADD_POLICY Hodnoty DYNAMIC STATIC SHARED_STATIC CONTEXT_SENSITIVE SHARED_CONTEXT_SENSITIVE
Systémová omezení VPD Politiky nelze aplikovat na objekty ve schématu SYS SYS a uživatelé s právem EXEMPT_ACCESS_POLICY nepodléhají politikám
1. Příklad 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;
1. Příklad II 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
1. Příklad III 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));
1. Příklad IV 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
1. Příklad V 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 custo INTO custnum FROM scott.customers WHERE cust_email=sys_context('user_env', 'SESSION_USER'); DBMS_SESSION.SET_CONTEXT('orders_ctx', 'cust_no', custnum);
1. Příklad VI 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;
1. Příklad VII 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
1. Příklad VIII 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
2. Příklad 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;
2. Příklad II 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;
2. Příklad III 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 4) A k oběma politikám vytvoří generující funkci
2. Příklad IV 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 NULL END IF RETURN predicate END 5) Přidá obě politiky do svých skupin
2. Příklad V 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
2. Příklad VI 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 IS PROCEDURE set_provider_context (policy_group varchar2 default NULL); CREATE OR REPLACE PACKAGE BODY provider_package AS PROCEDURE set_provider_context (policy_group varchar2 default NULL) IS...
2. Příklad VII 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
2. Příklad VIII 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;