-- ----------------------------------------------------------------------------- -- File Name : vpd2.sql -- ----------------------------------------------------------------------------- -- Maintainer : Pete Finnigan (http://www.petefinnigan.com) -- Copyright : Copyright (C) 2009 PeteFinnigan.com Limited. All rights -- reserved. All registered trademarks are the property of their -- respective owners and are hereby acknowledged. -- ----------------------------------------------------------------------------- -- Usage : The script provided here is available free. You can do anything -- you want with it commercial or non commercial as long as the -- copyright and this notice are not removed or edited in any way. -- The scripts cannot be posted / published / hosted or whatever -- anywhere else except at www.petefinnigan.com/vpd2.sql -- ------------------------------------------------------------------------------ prompt [*] connect as SYS pause connect sys/oracle1 as sysdba prompt [*] Drop the test user drop user pxf cascade; prompt [*] Recreate the test user create user pxf identified by pxf default tablespace users temporary tablespace temp; grant create session to pxf; grant create any context to pxf; grant create table to pxf; grant unlimited tablespace to pxf; grant create procedure to pxf; grant execute on dbms_rls to pxf; grant execute on dbms_session to pxf; create table pxf.emp as select * from scott.emp; prompt [*] Now connect as PXF pause connect pxf/pxf prompt [*] Select from the sample table - should be 15 rows pause select * from emp; Prompt [*] Let everyone see the table and connect as SCOTT and select again prompt [*] should still be 15 rows grant select on pxf.emp to public; connect scott/tiger select * from pxf.emp; prompt [*] connect as PXF again and set up a simple VPD prompt [*] that restricts access to dept 10 pause connect pxf/pxf create or replace function predicate (pv_schema in varchar2, pv_object in varchar2) return varchar2 as begin return 'deptno != ''10'''; end; / begin dbms_rls.add_policy( object_schema => 'PXF', object_name => 'EMP', policy_name => 'PXFTEST', policy_function => 'PREDICATE'); end; / prompt [*] Finally connect as SCOTT and see if he is blocked from seeing the data prompt [*] should now be 12 rows! pause connect scott/tiger select * from pxf.emp; prompt [*] pause sho user prompt [*] set up trace and dump the predicate pause alter session set sql_trace=true; alter session set events '10730 trace name context forever'; prompt [*] Dump the data from the emp table select * from pxf.emp; prompt [*] Turn trace off alter session set events '10730 trace name context off'; alter session set sql_trace=false; prompt [*] Lets look at the trace file pause prompt [*] pause prompt [*] View the predicate pause select object_owner,object_name,policy_name, pf_owner,pf_owner,function from all_policies; set serveroutput on size 1000000 declare predic varchar2(1000); begin dbms_output.put_line('The predicate is :'||pxf.predicate('PXF','EMP')); end; / prompt [*] I have seen this type of design: prompt [*] where the predicate functions are executable by all pause connect pxf/pxf grant execute on predicate to public; connect scott/tiger set serveroutput on size 1000000 declare predic varchar2(1000); begin dbms_output.put_line('The predicate is :'||pxf.predicate('PXF','EMP')); end; / prompt [*] Access the data directly pause -- ------------------------------------------------------- -- change the file number and block number to suit your -- database not mine. -- ------------------------------------------------------- select distinct dbms_rowid.rowid_block_number(rowid) blk, dbms_rowid.rowid_relative_fno(rowid) fno from pxf.emp; select file_name from dba_data_files where file_id=4; alter system dump datafile 4 block 444; prompt [*] Lets try again as monitor pause connect monitor/monitor select distinct dbms_rowid.rowid_block_number(rowid) blk, dbms_rowid.rowid_relative_fno(rowid) fno from pxf.emp; select file_name from dba_data_files where file_id=4; alter system dump datafile 4 block 444;