In
one of my previous post on column masking
( http://mfzahirdba.blogspot.com/2011/05/column-masking.html) , I was
explaining   about using VPD to mask the sensitive columns for compliance
and regulatory requirements and so on. 
With
Oracle 12c , Oracle provides package to set up policies to do the same . For
some columns such as ssn , birthdate , there are some preset  masking
patterns available such as DBMS_REDACT.REDACT_US_SSN_ENTIRE
, DBMS_REDACT.REDACT_US_SSN_F5 , DBMS_REDACT.REDACT_NUM_ZIP_CODE,
...) . 
This
is one another complimentary feature that could be used with VPD , OLS , and so
on. 
Here
are the examples. 
SQL> set linesize 1000
SQL> set pagesize 90
SQL> create table employee as
  2  select lpad(object_id * object_id, 9, 5)
 ssn , object_name ename  ,
  3      object_id * 2 as empid
  4      from all_objects
  5      where object_id > 70000
 and rownum <= 10 ;
Table created.
SQL> col ename format a30
SQL> Select * from employee;
SSN       ENAME        
                     
EMPID
--------- ------------------------------ ----------
490014000 /135a6a83_CacheCustomizerError    
140002
490028000 /7b729baa_CacheCustomizerError    
140004
490042000 /5e0f0b23_CacheCustomizerError    
140006
490056001 /f55b0251_CacheCustomizerError    
140008
490070002 /f1dfa39b_CacheCustomizerError    
140010
490084003 /a92f901c_CacheCustomizerError    
140012
490098004 /e56e9991_CacheCustomizerError    
140014
490112006 /72700b70_CacheCustomizerError     140016
490126008 /c00b177b_CacheCustomizerError    
140018
490140010 /791bbe73_CacheCustomizerError    
140020
10 rows selected.
Now
, let us create redaction policy on the SSN column as below. In this example ,
I am using "FULL redaction .  If the "client_info" is set
to "PAYROLL" , I will see the value of 'SSN' with no redaction .
Otherwise , it returns 0 , as it is a Full redaction. 
(
Note : The user needs to be granted EXECUTE privileges on DBMS_REDACT by a
user with SYSDBA privilege ) .
SQL> BEGIN
  2     DBMS_REDACT.ADD_POLICY(
  3       object_schema    
   => 'zahir',
  4       object_name    
     => 'employee',
  5       column_name    
     => 'ssn',
  6       policy_name    
     => 'hide_emp_ssn',
  7       function_type    
   => DBMS_REDACT.FULL,
  8        function_parameters
=> DBMS_REDACT.REDACT_US_SSN_F5,
  9       expression    
      => 'SYS_CONTEXT(''USERENV'',''CLIENT_INFO'') !=
''PAYROLL''');
 10  END;
 11  /
PL/SQL procedure successfully completed.
SQL> exec
dbms_application_info.set_client_info('PAYROLL') ;
PL/SQL procedure successfully completed.
SQL> Select SYS_CONTEXT('USERENV','CLIENT_INFO') from
dual ;
SYS_CONTEXT('USERENV','CLIENT_INFO')
---------------------------------------------------------------
PAYROLL
Let us run query the table again .
As you can see , there is no change 
SQL> Select * from employee;
SSN       ENAME        
                     
EMPID
--------- ------------------------------ ----------
490014000 /135a6a83_CacheCustomizerError    
140002
490028000 /7b729baa_CacheCustomizerError    
140004
490042000 /5e0f0b23_CacheCustomizerError    
140006
490056001 /f55b0251_CacheCustomizerError    
140008
490070002 /f1dfa39b_CacheCustomizerError    
140010
490084003 /a92f901c_CacheCustomizerError    
140012
490098004 /e56e9991_CacheCustomizerError    
140014
490112006 /72700b70_CacheCustomizerError    
140016
490126008 /c00b177b_CacheCustomizerError    
140018
490140010 /791bbe73_CacheCustomizerError    
140020
10 rows selected.
Let us  set the client_info to
other than 'PAYROLL' ( ex: MIS) and run query the table again . As you can see
, the value of SSN is redacted. 
SQL> exec
dbms_application_info.set_client_info('MIS') ;
PL/SQL procedure successfully completed.
SQL> Select
SYS_CONTEXT('USERENV','CLIENT_INFO') from dual ;
SYS_CONTEXT('USERENV','CLIENT_INFO')
---------------------------------------------------------------------
MIS
SQL> Select * from employee;
SSN       ENAME    
                     
    EMPID
--------- ------------------------------
----------
         
/135a6a83_CacheCustomizerError     140002
         
/7b729baa_CacheCustomizerError     140004
         
/5e0f0b23_CacheCustomizerError     140006
         
/f55b0251_CacheCustomizerError     140008
         
/f1dfa39b_CacheCustomizerError     140010
         
/a92f901c_CacheCustomizerError     140012
         
/e56e9991_CacheCustomizerError     140014
         
/72700b70_CacheCustomizerError     140016
         
/c00b177b_CacheCustomizerError     140018
         
/791bbe73_CacheCustomizerError     140020
10 rows selected.
There can be at most only one redaction policy per table / view.
The ADD_POLICY does not accommodate more than one column . To add a column to
the policy / alter the characteristics of the policy we need to use
ALTER_POLICY 
In the example below , we will redact the value of empid to anyone
other than 'PAYROLL' identifier . 
SQL> BEGIN
  2     DBMS_REDACT.ALTER_POLICY(
  3       object_schema
       => 'zahir',
  4       object_name  
       =>  'employee',
  5       column_name  
       => 'empid',
  6       policy_name  
       => 'hide_emp_ssn',
  7       action  
           => DBMS_REDACT.ADD_COLUMN,
  8       function_type
       => DBMS_REDACT.FULL,
  9       expression  
        => 'SYS_CONTEXT(''USERENV'',''CLIENT_INFO'') !=
''PAYROLL''');
 10  END;
 11  /
PL/SQL procedure successfully completed.
SQL>  Select * from employee;
SSN       ENAME    
                     
    EMPID
--------- ------------------------------
----------
         
/135a6a83_CacheCustomizerError          0
         
/7b729baa_CacheCustomizerError          0
         
/5e0f0b23_CacheCustomizerError          0
         
/f55b0251_CacheCustomizerError          0
         
/f1dfa39b_CacheCustomizerError          0
         
/a92f901c_CacheCustomizerError          0
         
/e56e9991_CacheCustomizerError          0
         
/72700b70_CacheCustomizerError          0
         
/c00b177b_CacheCustomizerError          0
         
/791bbe73_CacheCustomizerError          0
10 rows selected.
Personally , I feel , it would have better , if we 'ADD_POLICY'
accommodates more than one column , if they match redaction characteristics /
column datatype , so on.
One another caveat is that you cannot perform CTAS on the redacted
table . 
SQL> Create table t as select * from
employee;
Create table t as select * from employee
             
         *
ERROR at line 1:
ORA-28081: Insufficient privileges - the command
references a redacted object.
Comments welcome.
