6.2 Triple-and-Values Security
The triple-and-values security option extends the label security support provided by the triple-level security option to include security for lexical values as well.
This security option provides a thin layer of RDF-specific capabilities on top of
the Oracle AI Database native support for label security. It
provides not only the capabilities supported by the triple-level option but also supports the
additional capability of applying label security to the internal (values
)
table used for mapping RDF lexical values to unique numeric identifiers.
To use triple-and-values security, specify
SEM_RDFSA.TRIPLE_AND_VALUES
as the rdfsa_options
parameter
value when you execute the SEM_RDFSA.APPLY_OLS_POLICY
procedure. For example:
EXECUTE sem_rdfsa.apply_ols_policy('defense', SEM_RDFSA.TRIPLE_AND_VALUES,
network_owner=>‘RDFOWNR’, network_name=>'OLS_NET');
Since the methods for associating label security to the RDF triples are the same as described in the section on Triple-Level Security, we outline below only the methods relevant for associating label security to the lexical values for the (subject, predicate, object, and optionally, named graph) components of an RDF triple.
Note that the labels attached to the individual components of a triple can be independent from one another and from the label attached to the triple. Thus, a single triple can have up to five distinct associated labels – up to four labels for the individual components of the triple and one for the triple itself.
With triple-and-values security, duplicate lexical values with different labels can
be inserted in the values table. For example, assume that you already have a lexical value,
say <urn:Y>
, stored with a very sensitive label
(TOPSECRET
). Now, a low-privileged (UNCLASSIFIED
) user is
inserting the following triple:
<urn:X> <urn:P> <urn:Y> .
Since the already-stored, but TOPSECRET
, <urn:Y>
lexical value is not visible to the low-privileged user, <urn:Y>
gets
stored again, this time with the UNCLASSIFIED
label. A subsequent query posed
by a high-privileged user, with TOPSECRET
label, will see both instances of
the <urn:Y>
lexical value, thereby returning duplicate result rows caused
by presence of the two instances of the <urn:Y>
lexical value. The
following are some of the ways for mitigating the issues related to duplicate lexical
values:
- Preventing or minimizing the occurrence of duplicate lexical values: When inserting triples, associate the lowest label with lexical values that are expected to be used by users with different privilege levels.
- Eliminating duplicate result rows from query results: Use of DISTINCT in the SELECT clause of queries can eliminate the duplicate results. Note that this will eliminate all duplicate result rows including those that may not have been caused by presence of duplicate lexical values.
Parent topic: Fine-Grained Access Control for RDF Data
6.2.1 Extended Example: Applying OLS Triple-and-Values Security on RDF Data
This section presents an extended example illustrating how to apply triple-and-values Oracle Label Security (OLS) to RDF data. The examples are very simplified, and do not reflect recommended practices regarding user names and passwords.
- Create the policy and related administrative users.
The code example in this step performs the following actions in the same or slightly different order:
- Enable OLS in the database.
- Connect as
SYSDBA
to create security admin users:fgac_admin
anddefense_admin
. - Grant the
LBAC_DBA
role tofgac_admin
to allow the creation of a new OLSDEFENSE
policy which creates theDEFENSE_DBA
role. - Grant the
DEFENSE_DBA
role todefense_admin
enabling users to set up the labels for theDEFENSE
policy. - Assign the appropriate labels to the intended users of the database
objects to which the
DEFENSE
policy may be applied.
SQL> conn sys/<password_for_sys> as sysdba Connected. SQL> -- enable OLS in the database SQL> exec LBACSYS.configure_ols; PL/SQL procedure successfully completed. SQL> exec LBACSYS.OLS_ENFORCEMENT.enable_ols; PL/SQL procedure successfully completed. SQL> SQL> -- create user for security admin, grant LBAC_DBA role SQL> create user fgac_admin identified by <password_for_fgac_admin>; User created. SQL> grant connect, unlimited tablespace to fgac_admin; Grant succeeded. SQL> grant LBAC_DBA to fgac_admin; Grant succeeded. SQL> grant execute on sa_sysdba to fgac_admin; Grant succeeded. SQL> SQL> conn fgac_admin/<password_for_fgac_admin> Connected. SQL> -- create policy DEFENSE, which creates the DEFENSE_DBA role SQL> EXECUTE SA_SYSDBA.CREATE_POLICY('DEFENSE','def_label'); PL/SQL procedure successfully completed. SQL> select column_name from lbacsys.all_sa_policies where policy_name='DEFENSE'; COLUMN_NAME --------------- DEF_LABEL 1 row selected. SQL> SQL> conn sys/<password_for_sys> Connected. SQL> -- create user for policy admin of the DEFENSE policy SQL> -- create policy admin user for the DEFENSE policy (created above) SQL> create user defense_admin identified by <password_for_defense_admin>; User created. SQL> grant connect, unlimited tablespace to defense_admin; Grant succeeded. SQL> grant DEFENSE_DBA to defense_admin; Grant succeeded. SQL> grant execute on sa_components to defense_admin; Grant succeeded. SQL> grant execute on sa_user_admin to defense_admin; Grant succeeded. SQL> grant execute on sa_label_admin to defense_admin; Grant succeeded. SQL> grant execute on sa_policy_admin to defense_admin; Grant succeeded. SQL> SQL> conn defense_admin/<password_for_defense_admin> Connected. SQL> SQL> BEGIN 2 ------- create levels ------- 3 SA_COMPONENTS.CREATE_LEVEL('defense',3000,'TS','TOP SECRET'); 4 SA_COMPONENTS.CREATE_LEVEL('defense',2000,'SE','SECRET'); 5 SA_COMPONENTS.CREATE_LEVEL('defense',1000,'UN','UNCLASSIFIED'); 6 7 ------ create labels (using the components defined above) ------- 8 SA_LABEL_ADMIN.CREATE_LABEL('defense',1000,'UN'); 9 SA_LABEL_ADMIN.CREATE_LABEL('defense',1500,'SE'); 10 SA_LABEL_ADMIN.CREATE_LABEL('defense',3100,'TS'); 11 12 ------ assign default labels to users ------- 13 SA_USER_ADMIN.SET_USER_LABELS('defense', 'RDFOWNR', 'SE'); 14 SA_USER_ADMIN.SET_USER_LABELS('defense', 'A', 'UN'); 15 SA_USER_ADMIN.SET_USER_LABELS('defense', 'B', 'SE'); 16 SA_USER_ADMIN.SET_USER_LABELS('defense', 'C', 'TS'); 17 SA_USER_ADMIN.SET_USER_LABELS('defense', 'Q', 'SE'); 18 END; 19 / PL/SQL procedure successfully completed.
- Create an RDF network, RDF graph, and share it with users in various modes.
The code example in this step performs the following actions in the same or slightly different order:
- Connect as
SYSDBA
to create therdfownr
user and several other users such asa
,b
,c
, andq
. - Connect as
rdfownr
to create theNET1
RDF network. - Granting shared access on the RDF network to
a
,b
,c
, andq
(query-only) users. - Grant
SA_ONLY
access on the RDF network to thedefense_admin
user enabling them to perform OLS security related operations on the network only. This does not grant access to the data stored in the RDF network. - Connect as
defense_admin
and apply theDEFENSE
OLS policy (TRIPLE_AND_VALUES
) on the RDF network. - Connect as
rdfownr
to create an RDF graph namedPERSON
and grant DML and query access on the graph to usersa
,b
,c
, and query-only access to userq
.
SQL> conn sys/<password_for_sys> Connected. SQL> -- create user that can be owner of RDF networks SQL> create user rdfownr identified by <password_for_rdfownr>; User created. SQL> grant CREATE JOB, connect, resource, unlimited tablespace to rdfownr; Grant succeeded. SQL> SQL> --- create general users SQL> create user a identified by <password_for_a>; User created. SQL> grant connect, unlimited tablespace to a; Grant succeeded. SQL> create user b identified by <password_for_b>; User created. SQL> grant connect, unlimited tablespace to b; Grant succeeded. SQL> create user c identified by <password_for_c>; User created. SQL> grant connect, unlimited tablespace to c; Grant succeeded. SQL> create user q identified by <password_for_q>; User created. SQL> grant connect, unlimited tablespace to q; Grant succeeded. SQL> SQL> conn rdfownr/<password_for_rdfownr> Connected. SQL> SQL> -- create an RDF network and enable it for sharing with other users SQL> exec sem_apis.create_rdf_network('<tablespace_name>',null,network_owner=>'rdfownr',network_name=>'NET1'); PL/SQL procedure successfully completed. SQL> exec sem_apis.enable_network_sharing(network_owner=>'rdfownr',network_name=>'NET1'); PL/SQL procedure successfully completed. SQL> SQL> -- grant network access to a few users: full-access (they can create their own graphs) or query-only access SQL> EXECUTE sem_apis.enable_network_sharing('RDFOWNR', 'NET1'); PL/SQL procedure successfully completed. SQL> BEGIN 2 sem_apis.grant_network_access_privs('RDFOWNR', 'NET1', 'A'); 3 sem_apis.grant_network_access_privs('RDFOWNR', 'NET1', 'B'); 4 sem_apis.grant_network_access_privs('RDFOWNR', 'NET1', 'C'); 5 sem_apis.grant_network_access_privs('RDFOWNR', 'NET1', 'Q', options=>' QUERY_ONLY=T '); 6 END; 7 / PL/SQL procedure successfully completed. SQL> SQL> -- share in SA_ONLY=T mode with policy admin user (note: this sharing mode provides no visibility to RDF data) SQL> exec sem_apis.grant_network_access_privs('rdfownr', 'NET1', 'DEFENSE_ADMIN', options=>' SA_ONLY=T '); PL/SQL procedure successfully completed. SQL> SQL> -- tables in RDF network are not visible to security and policy admin users (EXCEPT when managing security policies on them) SQL> conn fgac_admin/<password_for_fgac_admin> Connected. SQL> select table_name from SYS.all_tables where table_name LIKE 'NET1#RDF%' order by 1; no rows selected SQL> conn defense_admin/<password_for_defense_admin> Connected. SQL> select table_name from SYS.all_tables where table_name LIKE 'NET1#RDF%' order by 1; no rows selected SQL> SQL> -- APPLY_OLS_POLICY on the RDF network SQL> conn defense_admin/<password_for_defense_admin> Connected. SQL> exec sem_rdfsa.apply_ols_policy('DEFENSE', sem_rdfsa.TRIPLE_AND_VALUES,network_owner=>'rdfownr',network_name=>'NET1'); PL/SQL procedure successfully completed. SQL> SQL> -- after APPLY_OLS_POLICY: a new column gets added to RDF_VALUE$ table and to RDF_LINK$ table SQL> conn rdfownr/<password_for_rdfownr> Connected. SQL> select table_name, column_name, data_type from sys.user_tab_columns where table_name IN ('NET1#RDF_VALUE$', 'NET1#RDF_LINK$') and column_name='DEF_LABEL' order by 1; TABLE_NAME COLUMN_NAME DATA_TYPE ------------------------------ --------------- ---------- NET1#RDF_LINK$ DEF_LABEL NUMBER NET1#RDF_VALUE$ DEF_LABEL NUMBER 2 rows selected. SQL> SQL> -- disable the OLS policy and set the label for all the pre-existing values to the lowest label SQL> conn defense_admin/<password_for_defense_admin> Connected. SQL> exec sem_rdfsa.disable_ols_policy(network_owner=>'rdfownr',network_name=>'NET1'); PL/SQL procedure successfully completed. SQL> SQL> -- re-enable the OLS policy and verify that the values are visible to all (EXCEPT security and policy admin users) SQL> conn defense_admin/<password_for_defense_admin> Connected. SQL> exec sem_rdfsa.enable_ols_policy(network_owner=>'rdfownr',network_name=>'NET1'); PL/SQL procedure successfully completed. SQL> SQL> conn rdfownr/<password_for_rdfownr> Connected. SQL> -- create an RDF graph (owned by rdfownr) SQL> exec sem_apis.create_rdf_graph('PERSON',null,null,network_owner=>'rdfownr',network_name=>'NET1'); PL/SQL procedure successfully completed. SQL> -- the corr. RDFT view, used as target for DML operations for this graph, has the extra label column SQL> desc NET1#RDFT_PERSON Name Null? Type ----------------------------------------------------------------------------------------------------------------- -------- ---------------------------------------------------------------------------- TRIPLE MDSYS.SDO_RDF_TRIPLE_S DEF_LABEL NUMBER SQL> -- the corr. RDFM view, used as source for query processing for this graph, has the extra column SQL> desc NET1#RDFM_PERSON Name Null? Type ----------------------------------------------------------------------------------------------------------------- -------- ---------------------------------------------------------------------------- P_VALUE_ID NOT NULL NUMBER START_NODE_ID NUMBER CANON_END_NODE_ID NUMBER END_NODE_ID NUMBER MODEL_ID NUMBER COST NUMBER DEF_LABEL NUMBER CTXT2 VARCHAR2(4000) DISTANCE NUMBER EXPLAIN VARCHAR2(4000) PATH VARCHAR2(4000) G_ID NUMBER LINK_ID VARCHAR2(89) SQL> SQL> -- share access to the above graph with users who already have shared access to network (Note: user Q is given query-only access) SQL> BEGIN 2 sem_apis.grant_model_access_privs('PERSON','a',sys.odcivarchar2list('INSERT','UPDATE','DELETE','SELECT','QUERY'),network_owner=>'rdfownr',network_name=>'NET1'); 3 sem_apis.grant_model_access_privs('PERSON','b',sys.odcivarchar2list('INSERT','UPDATE','DELETE','SELECT','QUERY'),network_owner=>'rdfownr',network_name=>'NET1'); 4 sem_apis.grant_model_access_privs('PERSON','c',sys.odcivarchar2list('INSERT','UPDATE','DELETE','SELECT','QUERY'),network_owner=>'rdfownr',network_name=>'NET1'); 5 sem_apis.grant_model_access_privs('PERSON','q',sys.odcivarchar2list('QUERY'),network_owner=>'rdfownr',network_name=>'NET1'); 6 END; 7 / PL/SQL procedure successfully completed.
- Connect as
- Set up utility functions and views used for illustration purposes.
The following code creates the utility views,
TRIPLES_VIEW
andVALUES_VIEW
. These return a simplified view of the triples and values, along with the relevant OLS labels, that are visible to the user. If a value is not found for a givenid
, it returns theid
itself but prefixed with an asterisk.SQL> -- set up for reporting visibility of triples and values SQL> column visible_to_users format a30 SQL> column subj format a22 SQL> column pred format a22 SQL> column obj format a22 SQL> column labels format a30 SQL> -- SQL> create or replace function shortval (val_id number) return varchar2 as 2 shval varchar2(100); 3 begin 4 select NVL(vname_suffix, vname_prefix) into shval from rdfownr.net1#rdf_value$ where value_id = val_id and rownum < 2; 5 return substr(shval,1,20); 6 exception 7 when no_data_found then 8 return '*' || val_id; 9 end; 10 / Function created. SQL> grant execute on shortval to public; Grant succeeded. SQL> create or replace view triples_view as 2 select rdfownr.shortval(t.triple.rdf_s_id) subj, rdfownr.shortval(t.triple.rdf_p_id) pred, rdfownr.shortval(t.triple.rdf_c_id) obj, def_label 3 from rdfownr.NET1#RDFT_PERSON t; View created. SQL> grant read on triples_view to public; Grant succeeded. SQL> create or replace view values_view as 2 select value_id, value_name 3 from rdfownr.net1#rdf_value$ 4 where (value_name NOT LIKE '%rdf%' and value_name NOT LIKE '%owl%' and canon_id is NULL); View created. SQL> grant read on values_view to public; Grant succeeded.
- Set Fine Grained Access Control (FGAC) when using SQL insert into RDF
graphs.
Note that the label assigned to a user determines what labels can be associated with the data inserted by the user. It could be the label assigned to the user or any label that is dominated by the user's label. The assigned label also determines what data from such a table is visible to the user.
SQL> -- SQL> -- INSERT using SQL Insert statement SQL> -- SQL> SQL> conn rdfownr/<password_for_rdfownr> Connected. SQL> SQL> -- 1) use default label, which is 'SE::' or 1500 for rdfownr, for the triple as well as the values SQL> INSERT INTO rdfownr.NET1#RDFT_PERSON(triple) values (sdo_rdf_triple_s('person', 2 '<urn:john>','<urn:spouseOf>','<urn:mary>', 3 'rdfownr','NET1')); 1 row created. SQL> COMMIT; Commit complete. SQL> SQL> -- check labels for the visible triples and values SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.triples_view group by subj, pred, obj order by 1,2,3; SUBJ PRED OBJ LABELS ---------------------- ---------------------- ---------------------- ------------------------------ john spouseOf mary 1500 1 row selected. SQL> select value_name, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.values_view group by value_name order by 1; VALUE_NAME LABELS ----------------------------------------------------------------- ------------------------------ urn:john 1500 urn:mary 1500 urn:spouseOf 1500 3 rows selected. SQL> SQL> conn c/<password_for_c> Connected. SQL> -- 2) use default explicit label 'UN::' (1000) for the triple SQL> INSERT INTO rdfownr.NET1#RDFT_PERSON(triple, def_label) values (sdo_rdf_triple_s('person', 2 '<urn:john>','<urn:secretId>','"jasmin#*!@"', 3 sys.odcinumberlist(char_to_label('DEFENSE', 'UN::'), char_to_label('DEFENSE', 'UN::'), char_to_label('DEFENSE', 'TS::')), 4 'rdfownr','NET1'), char_to_label('DEFENSE', 'UN::')); 1 row created. SQL> COMMIT; Commit complete. SQL> SQL> -- check labels for the visible triples and values SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.triples_view group by subj, pred, obj order by 1,2,3; SUBJ PRED OBJ LABELS ---------------------- ---------------------- ---------------------- ------------------------------ john secretId jasmin#*!@ 1000 john spouseOf mary 1500 2 rows selected. SQL> select value_name, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.values_view group by value_name order by 1; VALUE_NAME LABELS ----------------------------------------------------------------- ------------------------------ jasmin#*!@ 3100 urn:john 1500 urn:mary 1500 urn:secretId 1000 urn:spouseOf 1500 5 rows selected. SQL> SQL> conn a/<password_for_a>1 Connected. SQL> -- 3) use default label, which is 'UN::' or 1000 for user A, for both the triple as well as the values SQL> -- this triple already exists, but with a higher label (1500) and hence not visible to the current user: so, a duplicate triple gets inserted SQL> INSERT INTO rdfownr.NET1#RDFT_PERSON(triple) values (sdo_rdf_triple_s('person', 2 '<urn:john>','<urn:spouseOf>','<urn:mary>', 3 'rdfownr','NET1')); 1 row created. SQL> SQL> -- 4) use default label ('UN::' or 1000) for the triple and all its values SQL> INSERT INTO rdfownr.NET1#RDFT_PERSON(triple) values (sdo_rdf_triple_s('person', 2 '<urn:childOf>','owl:inverseOf','<urn:parentOf>', 3 'rdfownr','NET1')); 1 row created. SQL> COMMIT; Commit complete. SQL> SQL> -- check labels for the visible triples and values SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.triples_view group by subj, pred, obj order by 1,2,3; SUBJ PRED OBJ LABELS ---------------------- ---------------------- ---------------------- ------------------------------ childOf inverseOf parentOf 1000 john secretId *7305832552150903811 1000 john spouseOf mary 1000 3 rows selected. SQL> select value_name, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.values_view group by value_name order by 1; VALUE_NAME LABELS ----------------------------------------------------------------- ------------------------------ urn:childOf 1000 urn:john 1000 urn:mary 1000 urn:parentOf 1000 urn:secretId 1000 urn:spouseOf 1000 6 rows selected. SQL> SQL> conn b/<password_for_b> Connected. SQL> -- 5) use default label ('SE::' or 1500) for triple, but lowest label ('UN' or 1000) for values SQL> INSERT INTO rdfownr.NET1#RDFT_PERSON(triple) values (sdo_rdf_triple_s('person', 2 '<urn:spouseOf>','rdf:type','owl:SymmetricProperty', 3 sys.odcinumberlist(char_to_label('DEFENSE', 'UN::'), char_to_label('DEFENSE', 'UN::'), char_to_label('DEFENSE', 'UN::')), 4 'rdfownr','NET1')); 1 row created. SQL> SQL> -- check labels for the visible triples and values SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.triples_view group by subj, pred, obj order by 1,2,3; SUBJ PRED OBJ LABELS ---------------------- ---------------------- ---------------------- ------------------------------ childOf inverseOf parentOf 1000 john secretId *7305832552150903811 1000 john spouseOf mary 1000, 1500 spouseOf type SymmetricProperty 1500 4 rows selected.. SQL> select value_name, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.values_view group by value_name order by 1; VALUE_NAME LABELS ----------------------------------------------------------------- ------------------------------ urn:childOf 1000 urn:john 1000, 1500 urn:mary 1000, 1500 urn:parentOf 1000 urn:secretId 1000 urn:spouseOf 1000, 1500 6 rows selected. SQL> SQL> conn c/<password_for_c> Connected. SQL> -- 6) use default label ('TS::' or 3100) for the triple SQL> INSERT INTO rdfownr.NET1#RDFT_PERSON(triple) values (sdo_rdf_triple_s('person', 2 '<urn:john>','<urn:childOf>','<urn:bob>', 3 'rdfownr','NET1')); 1 row created. SQL> COMMIT; Commit complete. SQL> SQL> -- check labels for the visible triples and values SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.triples_view group by subj, pred, obj order by 1,2,3; SUBJ PRED OBJ LABELS ---------------------- ---------------------- ---------------------- ------------------------------ childOf inverseOf parentOf 1000 john childOf bob 3100 john secretId jasmin#*!@ 1000 john spouseOf mary 1000, 1500 spouseOf type SymmetricProperty 1500 5 rows selected. SQL> select value_name, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.values_view group by value_name order by 1; VALUE_NAME LABELS ----------------------------------------------------------------- ------------------------------ jasmin#*!@ 3100 urn:bob 3100 urn:childOf 1000 urn:john 1000, 1500 urn:mary 1000, 1500 urn:parentOf 1000 urn:secretId 1000 urn:spouseOf 1000, 1500 8 rows selected.
- Perform label-based inference by iterating repeatedly over the given sequence
of labels.
The following code shows label-based inference with the label sequence
<1000, 1500, 3100>
. A derived triple is marked with the earliest (minimum
) label without which it cannot be derived. For example, the derived triplebob parentOf john
will have the3100 ('TS::')
label because it cannot be derived with any label below3100
asjohn childOf bob
is only visible when user has label of at least3100
.SQL> conn sys/<password_for_sys> as sysdba Connected. SQL> -- allow "exchange partition" operations used during inference SQL> grant EXEMPT ACCESS POLICY on schema rdfownr to rdfownr; Grant succeeded. SQL> conn c/<password_for_c> Connected. SQL> BEGIN 2 sem_apis.create_inferred_graph('inf', 3 sem_models('PERSON'), 4 sem_rulebases('OWL2RL'), 5 SEM_APIS.REACH_CLOSURE, 6 null, 7 null, 8 ols_ladder_inf_lbl_seq=>'1000 1500 3100', 9 network_owner=>'RDFOWNR', 10 network_name=>'NET1' 11 ); 12 END; 13 / PL/SQL procedure successfully completed. SQL> conn sys/<password_for_sys> as sysdba Connected. SQL> -- "exchange partition" operations not needed any more SQL> revoke EXEMPT ACCESS POLICY on schema rdfownr from rdfownr; Revoke succeeded. SQL> conn rdfownr/<password_for_rdfownr> Connected. SQL> create or replace view inf_triples_view as 2 select rdfownr.shortval(t.start_node_id) subj, rdfownr.shortval(t.p_value_id) pred, rdfownr.shortval(canon_end_node_id) obj, def_label 3 from rdfownr.NET1#RDFI_INF t; View created. SQL> grant read on inf_triples_view to public; Grant succeeded. SQL> conn c/<password_for_c> Connected. SQL> -- check labels for the visible triples and values SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.inf_triples_view group by subj, pred, obj order by 1,2,3; SUBJ PRED OBJ LABELS ---------------------- ---------------------- ---------------------- ------------------------------ bob parentOf john 3100 mary spouseOf john 1500 parentOf inverseOf childOf 1000 spouseOf inverseOf spouseOf 1500 4 rows selected. SQL> select value_name, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.values_view group by value_name order by 1; VALUE_NAME LABELS ----------------------------------------------------------------- ------------------------------ 1 3100 jasmin#*!@ 3100 true 3100 urn:bob 3100 urn:childOf 1000 urn:john 1000, 1500 urn:mary 1000, 1500 urn:parentOf 1000 urn:secretId 1000 urn:spouseOf 1000, 1500 10 rows selected SQL> SQL> -- visibility note: users with lower label may sometimes be able to see a triple but not the higher-labeled values used in that triple SQL> conn a/<password_for_a> Connected. SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.triples_view group by subj, pred, obj order by 1,2,3; SUBJ PRED OBJ LABELS ---------------------- ---------------------- ---------------------- ------------------------------ childOf inverseOf parentOf 1000 john secretId *7305832552150903811 1000 john spouseOf mary 1000 3 rows selected. SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.inf_triples_view group by subj, pred, obj order by 1,2,3; SUBJ PRED OBJ LABELS ---------------------- ---------------------- ---------------------- ------------------------------ parentOf inverseOf childOf 1000 1 row selected. SQL> conn b/<password_for_b> Connected. SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.triples_view group by subj, pred, obj order by 1,2,3; SUBJ PRED OBJ LABELS ---------------------- ---------------------- ---------------------- ------------------------------ childOf inverseOf parentOf 1000 john secretId *7305832552150903811 1000 john spouseOf mary 1000, 1500 spouseOf type SymmetricProperty 1500 4 rows selected. SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.inf_triples_view group by subj, pred, obj order by 1,2,3; SUBJ PRED OBJ LABELS ---------------------- ---------------------- ---------------------- ------------------------------ mary spouseOf john 1500 parentOf inverseOf childOf 1000 spouseOf inverseOf spouseOf 1500 3 rows selected. SQL> conn c/<password_for_c> Connected. SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.triples_view group by subj, pred, obj order by 1,2,3; SUBJ PRED OBJ LABELS ---------------------- ---------------------- ---------------------- ------------------------------ childOf inverseOf parentOf 1000 john childOf bob 3100 john secretId jasmin#*!@ 1000 john spouseOf mary 1000, 1500 spouseOf type SymmetricProperty 1500 5 rows selected. SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.inf_triples_view group by subj, pred, obj order by 1,2,3; SUBJ PRED OBJ LABELS ---------------------- ---------------------- ---------------------- ------------------------------ bob parentOf john 3100 mary spouseOf john 1500 parentOf inverseOf childOf 1000 spouseOf inverseOf spouseOf 1500 4 rows selected. SQL> conn q/<password_for_q> Connected. SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.triples_view group by subj, pred, obj order by 1,2,3; SUBJ PRED OBJ LABELS ---------------------- ---------------------- ---------------------- ------------------------------ childOf inverseOf parentOf 1000 john secretId *7305832552150903811 1000 john spouseOf mary 1000, 1500 spouseOf type SymmetricProperty 1500 4 rows selected. SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.inf_triples_view group by subj, pred, obj order by 1,2,3; SUBJ PRED OBJ LABELS ---------------------- ---------------------- ---------------------- ------------------------------ mary spouseOf john 1500 parentOf inverseOf childOf 1000 spouseOf inverseOf spouseOf 1500 3 rows selected. SQL> conn rdfownr/<password_for_rdfownr> Connected. SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.triples_view group by subj, pred, obj order by 1,2,3; SUBJ PRED OBJ LABELS ---------------------- ---------------------- ---------------------- ------------------------------ childOf inverseOf parentOf 1000 john secretId *7305832552150903811 1000 john spouseOf mary 1000, 1500 spouseOf type SymmetricProperty 1500 4 rows selected. SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.inf_triples_view group by subj, pred, obj order by 1,2,3; SUBJ PRED OBJ LABELS ---------------------- ---------------------- ---------------------- ------------------------------ mary spouseOf john 1500 parentOf inverseOf childOf 1000 spouseOf inverseOf spouseOf 1500 3 rows selected.
- Define and use label functions.
The following code shows bulkload-time use of a label function that associates a higher label (
'SE::'
) with a triple when the predicate is<urn:salary>
and a lower label ('UN::'
) otherwise.SQL> -- use of label functions and its use during bulk-load SQL> conn sys/<password_for_sys> Connected. SQL> grant execute on to_lbac_data_label to rdfownr; Grant succeeded. SQL> SQL> conn rdfownr/<password_for_rdfownr> Connected. SQL> SQL> CREATE TABLE stage_table ( 2 RDF$STC_sub varchar2(4000) not null, 3 RDF$STC_pred varchar2(4000) not null, 4 RDF$STC_obj varchar2(4000) not null 5 ); Table created. SQL> SQL> insert into stage_table values ('<urn:john>','<urn:lastName>','"Smith"'); 1 row created. SQL> insert into stage_table values ('<urn:john>','<urn:salary>','"100K"'); 1 row created. SQL> commit; Commit complete. SQL> SQL> -- define a label function for generating label for a given triple SQL> -- label function for generating labels for triples (in RDF_LINK$) SQL> CREATE OR REPLACE FUNCTION gen_triple_label_on_pid (p_value_id number) Return LBACSYS.LBAC_LABEL 2 as 3 i_label varchar2(80); 4 vty varchar2(10); 5 vnm varchar2(100); 6 BEGIN 7 select value_type, value_name into vty, vnm from rdfownr.net1#rdf_value$ where value_id=p_value_id; 8 if (vty = 'UR' and vnm = 'urn:salary') then 9 i_label := 'SE::'; 10 else 11 i_label := 'UN::'; 12 end if; 13 RETURN TO_LBAC_DATA_LABEL('DEFENSE',i_label); 14 END; 15 / Function created. SQL> SQL> grant execute on gen_triple_label_on_pid to LBAC_TRIGGER; Grant succeeded. SQL> SQL> -- ALTER_OLS_TABLE_POLICY to include use of label function for triples SQL> conn defense_admin/<password_for_defense_admin> Connected. SQL> exec sem_rdfsa.alter_ols_table_policy('triple', 'label_function', 'rdfownr.gen_triple_label_on_pid(:new.p_value_id)', network_owner=>'rdfownr',network_name=>'net1'); PL/SQL procedure successfully completed. SQL> select * from lbacsys.all_sa_table_policies where schema_name='RDFOWNR' order by policy_name, table_name; POLICY_NAM SCHEMA_NAME TABLE_NAME STATUS ---------- -------------------------------------------------------------------------------------------------------------------------------- ------------------------------ -------- TABLE_OPTIONS -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- FUNCTION -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- PREDICATE -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- DEFENSE RDFOWNR NET1#RDF_LINK$ ENABLED READ_CONTROL, INSERT_CONTROL, UPDATE_CONTROL, DELETE_CONTROL, LABEL_DEFAULT, LABEL_UPDATE, CHECK_CONTROL rdfownr.gen_triple_label_on_pid(:new.p_value_id) DEFENSE RDFOWNR NET1#RDF_VALUE$ ENABLED READ_CONTROL, INSERT_CONTROL, UPDATE_CONTROL, DELETE_CONTROL, LABEL_DEFAULT, LABEL_UPDATE, CHECK_CONTROL 2 rows selected. SQL> SQL> -- bulk-load uses designated label function to mark the salary triple as 'SE::' (1500) while marking the "lastName" triples as 'UN::' (1000) SQL> conn rdfownr/<password_for_rdfownr> Connected. SQL> exec sem_apis.bulk_load_from_staging_table('person','rdfownr','stage_table',network_owner=>'rdfownr',network_name=>'net1'); PL/SQL procedure successfully completed. SQL> SQL> select subj, pred, obj, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.triples_view group by subj, pred, obj order by 1,2,3; SUBJ PRED OBJ LABELS ---------------------- ---------------------- ---------------------- ------------------------------ childOf inverseOf parentOf 1000 john lastName Smith 1000 john salary 100K 1500 john secretId *7305832552150903811 1000 john spouseOf mary 1000, 1500 spouseOf type SymmetricProperty 1500 6 rows selected. SQL> select value_name, listagg(def_label,', ') within group (order by def_label) labels from rdfownr.values_view group by value_name order by 1; VALUE_NAME LABELS ----------------------------------------------------------------- ------------------------------ 100K 1500 Smith 1500 urn:childOf 1000 urn:john 1000, 1500 urn:lastName 1500 urn:mary 1000, 1500 urn:parentOf 1000 urn:salary 1500 urn:secretId 1000 urn:spouseOf 1000, 1500 10 rows selected
Parent topic: Triple-and-Values Security