Oracle Data Reduction – Partial Reduction for Numbers

This note is the sequel of Oracle Data Reduction – Full Redaction article. At the first article, I gave a brief introduction about Oracle Data Reduction feature and I implemented full redaction on card_no column . Now we will continue to redact columns which contains numbers.

At the sample l; Appuser contains Card no data and simply application tables. Appuser should reach all data without any restriction. Ad-hoc user were created with the name of USER_* . We will define all security policies against to ad-hos users. Now create all these users , tables and data.

Connect system/oracle

Create user appuser identified by appuser ;

alter user appuser quota unlimited on users;

grant resource to appuser;
grant connect to appuser;

connect appuser/appuser

CREATE TABLE APPUSER.CARD_TABLE
(
  CARD_NO      VARCHAR2(20 BYTE),
  HOLDER       VARCHAR2(16 BYTE),
  EXPIRY_DATE  DATE,
  LIMIT        NUMBER
)
TABLESPACE USERS;

Grant select on APPUSER.CARD_TABLE to public;

SET DEFINE OFF;
Insert into APPUSER.CARD_TABLE
   (CARD_NO, HOLDER, EXPIRY_DATE, LIMIT)
 Values
   ('1234-5678-3456-7845', 'John Carpenter', TO_DATE('7/31/2024 2:37:57 PM', 'MM/DD/YYYY HH:MI:SS AM'), 10000);
Insert into APPUSER.CARD_TABLE
   (CARD_NO, HOLDER, EXPIRY_DATE, LIMIT)
 Values
   ('6789-6467-5567-8967', 'Alvin Newton', TO_DATE('2/2/2024 2:37:57 PM', 'MM/DD/YYYY HH:MI:SS AM'), 30500);
Insert into APPUSER.CARD_TABLE
   (CARD_NO, HOLDER, EXPIRY_DATE, LIMIT)
 Values
   ('1243-9087-4389-8967', 'Joseph Huges', TO_DATE('1/27/2025 2:37:57 PM', 'MM/DD/YYYY HH:MI:SS AM'), 40500);
Insert into APPUSER.CARD_TABLE
   (CARD_NO, HOLDER, EXPIRY_DATE, LIMIT)
 Values
   ('1238-9685-4589-6543', 'Monica Woodo', TO_DATE('5/2/2024 2:37:57 PM', 'MM/DD/YYYY HH:MI:SS AM'), 5000);
Insert into APPUSER.CARD_TABLE
   (CARD_NO, HOLDER, EXPIRY_DATE, LIMIT)
 Values
   ('1245-5620-1256-3412', 'Susen Senior', TO_DATE('7/26/2025 2:37:57 PM', 'MM/DD/YYYY HH:MI:SS AM'), 7500);

commit;

connect system/oracle


Create user user_01 identified by oracle ;
grant connect to user_01;

Create user user_02 identified by oracle ;
grant connect to user_02;


 

Now check database repository to see already defined redaction policies. we already created one policy on Card_Table. REDACTION_POLICIES view is used for selecting redaction policies.

connect system/oracle

BEGIN  DBMS_REDACT.add_policy( 
 object_schema => 'APPUSER', 
 object_name => 'CARD_TABLE', 
 column_name => 'CARD_NO', 
 policy_name => 'REDACT_CARDNO_DATA', 
 function_type => DBMS_REDACT.full, 
 expression => 'SUBSTR( SYS_CONTEXT(''USERENV'',''SESSION_USER''), 1,5 ) = ''USER_''  '); 
 commit;
END; 
/

Set linesize 200

Column Object_owner        format a10
Column Object_name         format a15
Column policy_name         format a30
Column enable              format a10
 
SELECT object_owner, object_name, policy_name,enable
  FROM REDACTION_POLICIES
 WHERE object_name NOT LIKE 'BIN%';

OBJECT_OWN OBJECT_NAME     POLICY_NAME                    ENABLE
---------- --------------- ------------------------------ ----------
APPUSER    CARD_TABLE      REDACT_CARDNO_DATA             YES


Now create a redaction on LIMIT column. At this redaction ; The value 0 is placed between the first and fifth columns.
To do this function_parameters parameter is used

The syntax of this parameter is given below

function_parameters => ‘Mask character,Starting digit position, Ending digit position’ .

The important point is you have to use alter_policy procedure with action => DBMS_REDACT.add_column
parameter to add a new redaction to CARD_TABLE.

function_parameters parameter should be defined like that
function_parameters => ‘0,1,5’

connect system/oracle

BEGIN  DBMS_REDACT.alter_policy( 
 object_schema => 'APPUSER', 
 object_name => 'CARD_TABLE', 
 column_name => 'LIMIT', 
 policy_name => 'REDACT_CARDNO_DATA',
 action => DBMS_REDACT.add_column,
 function_type => DBMS_REDACT.PARTIAL,
 function_parameters => '0,1,5'); 
 commit;
END; 
/

Now Check REDACTION_COLUMNS view to see the definitions of the redaction.

Set linesize 200

Column Object_owner        format a10
Column Object_name         format a15
Column Column_name         format a10
Column Function_Parameters format a50

SELECT object_owner,
       object_name,
       column_name,
       function_type,
       function_parameters
  FROM REDACTION_COLUMNS
 WHERE object_name NOT LIKE 'BIN%';


OBJECT_OWN OBJECT_NAME     COLUMN_NAM FUNCTION_TYPE             FUNCTION_PARAMETERS
---------- --------------- ---------- ------------------------- --------------------------------------------------     
APPUSER    CARD_TABLE      LIMIT      PARTIAL REDACTION         0,1,5                                                
APPUSER    CARD_TABLE      CARD_NO    FULL REDACTION                                                                  


After the reduction is defined, Select the table with ad-hoc users. LIMIT column values are redacted with 0

connect user_01/oracle

alter session set nls_date_format = 'DD-MM-YYYY';

Column Card_No format a22
Column Holder  format a15
Column Expiry_Date format a11
Column Limit format 9999999


select * from appuser.card_table;

CARD_NO                HOLDER          EXPIRY_DATE    LIMIT
---------------------- --------------- ----------- --------
                       John Carpenter  31-07-2024         0
                       Alvin Newton    02-02-2024         0
                       Joseph Huges    27-01-2025         0
                       Monica Woodo    02-05-2024         0
                       Susen Senior    26-07-2025         0


Let’s change the redaction on LIMIT column. In this redaction 7 value is placed between first and second column.
To do this function_parameters parameter defined like that

function_parameters => ‘7,1,2’

And because a policy already was defined for this column; action parameter should be like that
action => DBMS_REDACT.modify_column

connect system/oracle

BEGIN  DBMS_REDACT.alter_policy( 
 object_schema => 'APPUSER', 
 object_name => 'CARD_TABLE', 
 column_name => 'LIMIT', 
 policy_name => 'REDACT_CARDNO_DATA',
 action => DBMS_REDACT.modify_column,
 function_type => DBMS_REDACT.PARTIAL,
 function_parameters => '7,1,2'); 
 commit;
END; 
/

Column Object_owner        format a10
Column Object_name         format a15
Column Column_name         format a10
Column Function_Parameters format a50

SELECT object_owner,
       object_name,
       column_name,
       function_type,
       function_parameters
  FROM REDACTION_COLUMNS
WHERE object_name NOT LIKE 'BIN%';



OBJECT_OWN OBJECT_NAME     COLUMN_NAM FUNCTION_TYPE             FUNCTION_PARAMETERS
---------- --------------- ---------- ------------------------- --------------------------------------------------     
APPUSER    CARD_TABLE      LIMIT      PARTIAL REDACTION         7,1,2
APPUSER    CARD_TABLE      CARD_NO    FULL REDACTION

After the reduction is defined, Select the table with ad-hoc users.

connect user_01/oracle

alter session set nls_date_format = 'DD-MM-YYYY';

Column Card_No format a22
Column Holder  format a15
Column Expiry_Date format a11
Column Limit format 9999999


select * from appuser.card_table;



CARD_NO                HOLDER          EXPIRY_DATE    LIMIT
---------------------- --------------- ----------- --------
                       John Carpenter  31-07-2024     77000
                       Alvin Newton    02-02-2024     77500
                       Joseph Huges    27-01-2025     77500
                       Monica Woodo    02-05-2024      7700
                       Susen Senior    26-07-2025      7700

To drop redaction on LIMIT column use Alter_policy procedure with ;

action => DBMS_REDACT.drop_column parameter

BEGIN
       DBMS_REDACT.Alter_policy(
        object_schema => 'APPUSER',
        object_name => 'CARD_TABLE',
        column_name => 'LIMIT',
        policy_name => 'REDACT_CARDNO_DATA',
        action => DBMS_REDACT.drop_column);
        commit;
        END;
 /


Check the redaction view REDACTION_COLUMNS to control of the operation. At the next note I will give you much more information about redacting Character data types.

Set linesize 200

Column Object_owner        format a10
Column Object_name         format a15
Column Column_name         format a10
Column Function_Parameters format a50

SELECT object_owner,
       object_name,
       column_name,
       function_type,
       function_parameters
  FROM REDACTION_COLUMNS
WHERE object_name NOT LIKE 'BIN%';

OBJECT_OWN OBJECT_NAME     COLUMN_NAM FUNCTION_TYPE             FUNCTION_PARAMETERS
---------- --------------- ---------- ------------------------- --------------------------------------------------
APPUSER    CARD_TABLE      CARD_NO    FULL REDACTION


If you want to get much more for support to hide sensitive data in your Oracle databases you can contact with me.

Yusuf Anıl Akduygu

anil.akduygu@arbosecurity.com

yusufanilakduygu@gmail.com