Beneficios e implementación de Oracle Virtual Private Database (VPD)

Por Y V Ravi Kumar Oracle ACE director, Hela Khazri, Julio César Ayapán Oracle Associate,

Publicado en Diciembre 2019

Revisado por Francisco Riccio

Definición de Oracle Virtual Private Database:

Oracle Virtual Private Database (VPD) es una utilidad para reforzar la seguridad incorporada en la edición Enterprise de Oracle Database e introducida en la versión 8i. Como sabemos, en algunos casos el control de acceso discrecional (DAC) es insuficiente para cumplir con los requisitos de seguridad de la aplicación, ya que generalmente se utiliza para otorgar o restringir el acceso a nivel de objeto. DAC puede ser el origen de muchas amenazas, como asignar privilegios a objetos ajenos a las funciones de trabajo de un usuario, además, el usuario dueño de la aplicación puede ser objetivo de ataques o vulnerabilidades.

Con Virtual Private Database es posible controlar el acceso a los datos de manera granular a nivel de filas y columnas. Los accesos a los datos son aplicados directamente en las tablas, vistas o sinónimos a través del uso de políticas que se aplican de manera dinámica durante la ejecución de un SELECT, INSERT, UPDATE, DELETE y sentencias sobre índices.

Cuando un usuario accede a una tabla, vista o sinónimo que esta protegido por una política de Oracle VPD, la política añade de manera transparente y dinámica una clausula WHERE a la sentencia SQL. Esta cláusula dinámica es llamada Predicado y es generada por una función implementada por la política de seguridad. 

Por ejemplo, un usuario ejecuta la siguiente consulta:

Select * from order_details;

La política de Oracle VPD agrega de manera dinámica la cláusula where a la sentencia ejecutada, de esta manera la clausula que se ejecuta será:

Select * from order_details where id_order=222;

Y así, el usuario podrá ver únicamente el detalle de la orden con ID=222.

Beneficios de Oracle Virtual Private Database:

Oracle PDV provee los siguientes beneficios:

  • Las políticas de seguridad se basan en objetos de la base de datos en lugar de aplicaciones
  • Facilita el mantenimiento de código
  • Facilita la auditoria de las acciones de usuario
  • Permite controlar cuando y bajo qué circunstancias la base de datos aplica el predicado

Implementación:

Cuando se añaden políticas a objetos, el comportamiento default de Oracle VPD es agregar y aplicar una nueva clausula WHERE a la sentencia SQL original al momento de ser ejecutada para restringir el acceso a nivel de objeto, independiente de la aplicación que lo ejecute y del usuario que este tratando de acceder a los datos en lugar de evaluar el rol y privilegios, esto ocurrirá siempre y cuando no se haya agregado una exención a esta regla.

A continuación, se muestra el proceso normal para la implementación de una política VPD:

Implementación de una política VPD

Figura 1 – Implementación de una política VPD

  • Contexto de la aplicación: contexto de la aplicación que cuenta al menos con un atributo. Aunque su uso no es obligatorio dentro de una política VPD, es una efectiva técnica de diseño que a menudo se utiliza. Su función principal en una implementación de VPD es recuperar información sobre la sesión y determinar de acuerdo con esta, que grupo de políticas serán aplicadas para permitir o denegar acceso a ciertos datos. La inicialización del contexto de la aplicación se realiza mediante un paquete PL/SQL usado en su definición.

    Los contextos de aplicación basados en sesiones de base de datos pueden ser inicializados de manera local, externa, o global. En modo global, los datos de sesión son recuperados por el Area Global de Usuario (User Global Area – UGA). En modo externo, los datos se pueden obtener desde una aplicación externa (OCI, JDBC), una cola de procesos, o a través de un objecto Database Link conectado a la base de datos.  

  • Función de política: es utilizada para retornar un predicado que será aplicado en la cláusula WHERE de la sentencia SQL.  
  • Política VPD: existen cinco tipos de políticas basadas en la frecuencia con que se evalúa una función de política:

    DBMS_RLS.DYNAMIC es el default.

    DMBS_RLS.STATIC

    DBMS_RLS.SHARED_STATIC

    DBMS_RLS.CONTEXT_SENSITIVE

    DBMS_RLS.SHARED_CONTEXT_SENSITIVE

Como podemos ver, el comportamiento default de VPD es: cualquier política definida sobre una tabla o vista es aplicada para todas las sentencias SQL siempre que una aplicación la ejecute.

Así que, en caso de que muchas aplicaciones compartan la misma tabla o vista, es recomendado crear y utilizar grupos de políticas para determinar el predicado que debería ser retornado y que políticas deberían ser aplicadas. Si ya existen políticas definidas, se deben identificar qué políticas deberían estar vigentes cuando cada aplicación acceda a la tabla o vista. Cada objeto tiene un grupo de políticas predeterminado ya definido (SYS_DEFAULT), y las políticas definidas en este grupo serán siempre aplicadas para ese objeto particular. Un contexto de aplicación puede ayudar en este caso a determinar qué otro grupo de políticas se aplicarán también en ese momento.

Imaginemos que hay dos aplicaciones (A y B) que acceden a la tabla TEST. Sus políticas especificas son determinadas por dos grupos de políticas (GRP_A y GRP_B) y todas las demás políticas que debe aplicarse en cualquier caso están definidas en el grupo predeterminado (GRP_DEFAULT). Cuando la aplicación A accede los datos, las políticas que pertenecen a GRP_A y GRP_DEFAULT son aplicadas; y cuando la aplicación B accede los datos, las políticas que pertenecen a GRP_B y GRP_DEFAULT son aplicadas.

Implementación los grupos de políticas VPD

Figura 2 – Implementación los grupos de políticas VPD

1. Ejemplos: Paso a Paso

1.1 Contexto de aplicación basado en sesión:

En este ejemplo, aplicaremos un paquete PL/SQL para establecer el contexto de la aplicación. Crearemos un tipo de contexto inicializado localmente, utilizando un procedimiento que inicializara el valor para el contexto. El valor será generado utilizando un trigger de inicio de sesión.

En primer lugar, creamos el usuario VPD y la tablas ‘personnel’, ‘service’, ‘job’, ‘department’ y ‘region’ en el esquema VPD:

SQL> Connect system/manager@TEST
Connected.

SQL> create user VPD IDENTIFIED BY VPD profile DEFAULT;
User created.

SQL>  grant dba to VPD;
Grant succeeded.

SQL> connect VPD/VPD@TEST
Connected.

SQL> ---Schema-----
SQL> Create table personnel (
  2     Pers_id  VARCHAR2(10),
  3     Pers_name VARCHAR2(40)not null,
  4     Hire_date DATE,
  5     Job_id    NUMBER(4) not null,
  6     Serv_id   VARCHAR2(10) not null,
  7     Region_id NUMBER(4),
  8     Salary VARCHAR2(20)
  9  );
Table created.

SQL> Create table service (
  2       Serv_id VARCHAR2(10),
  3       Serv_name VARCHAR2(40),
  4       Dept_id VARCHAR2(10) not null
  5  );
Table created.

SQL> Create table job (
  2        Job_id NUMBER(4),
  3        Job_title VARCHAR2(40)
  4  );
Table created.

SQL> Create table department (
  2        Dept_id VARCHAR2(10) ,
  3        Dept_name VARCHAR2(40)
  4  );
Table created.

SQL> Create table region (
  2        Region_id  NUMBER(4),
  3        Region_name VARCHAR2(40)
  4  );
Table created.

A continuación, con el usuario VPD añadimos los siguientes constraints:

SQL> alter table PERSONNEL add constraint PK_PERSONNEL primary key (Pers_id);
Table altered.

SQL> alter table service add constraint PK_Service primary key (serv_id);
Table altered.

SQL> alter table job add constraint PK_JOB primary key (job_id);
Table altered.

SQL> alter table department add constraint PK_Departement primary key (Dept_id);
Table altered.

SQL> alter table region add constraint PK_Region primary key (region_id);
Table altered.

SQL> alter table PERSONNEL add constraint FK_Service foreign key (serv_id) 
references Service (serv_id);
Table altered.

SQL> alter table PERSONNEL add constraint FK_Job foreign key (job_id) 
references Job (job_id);
Table altered.

SQL> alter table PERSONNEL add constraint FK_Region foreign key (Region_id) 
references Region (Region_id);
Table altered.

Ejecutamos los siguientes insert sobre las talas creadas:

SQL> insert into  SERVICE values ('00110','It_serv','0100');
1 row created.

SQL> insert into  SERVICE values ('00210','Account_Serv','0200');
1 row created.

SQL> insert into  SERVICE values ('00220','Finance_Serv','0200');
1 row created.

SQL> insert into  SERVICE values ('00310','Rs_Manag','0300');
1 row created.

SQL> insert into   department values ('0100','It_Dep');
1 row created.

SQL> insert into   department values ('0200','Account_Fin_Dep');
1 row created.

SQL> insert into   department values ('0300','RUM_Dep');
1 row created.

SQL> insert into   job values ('500','PDG');
1 row created.

SQL> insert into   job values ('400','Director_Serv');
1 row created.

SQL> insert into   job values ('350','Engineer');
1 row created.

SQL> insert into   job values ('330','Pharmacist');
1 row created.

SQL> insert into   job values ('320','Mastery');
1 row created.

SQL> insert into   job values ('210','controller');
1 row created.

SQL> insert into   job values ('110','worker');
1 row created.

SQL> insert into   Personnel values ('002110', 'aaaa',null,'400','00210',null,null);
1 row created.

SQL> insert into   Personnel values ('002120', 'bbbb',null,'320','00210',null,null);
1 row created.

SQL> insert into   Personnel values ('002130', 'cccc',null,'210','00210',null,null);
1 row created.

SQL> insert into   Personnel values ('002210', 'dddd',null,'400','00220',null,null);
1 row created.

SQL> insert into   Personnel values ('002220', 'eeee',null,'320','00220',null,null);
1 row created.

SQL> insert into   Personnel values ('002230', 'ffff',null,'210','00220',null,null);
1 row created.

SQL> insert into   Personnel values ('001110', 'gggg',null,'400','00110',null,null);
1 row created.

SQL> insert into   Personnel values ('001120', 'eeee',null,'350','00110',null,null);
1 row created.

SQL> insert into   Personnel values ('001130', 'llll',null,'320','00110',null,null);
1 row created.

SQL> insert into   Personnel values ('003110', 'gggg',null,'400','00310',null,null);
1 row created.

SQL> insert into   Personnel values ('003120', 'eeee',null,'210','00310',null,null);
1 row created.

SQL> insert into   Personnel values ('003130', 'llll',null,'110','00310',null,null);
1 row created.

En el siguiente paso, dentro del esquema VPD, creamos una vista llamada VIEW_DATA_1 basada en las tablas personnel, service, job y department.

SQL> CREATE VIEW VIEW_DATA_1 AS
  SELECT Pers_id, Pers_name, Hire_date, 
         Job_title, Serv_name, Dept_name, Salary 
  FROM personnel a, job b, service c, department d
  WHERE a.Job_id = b.Job_id
  AND   a.Serv_id = c.Serv_id
  AND   c.Dept_id = d.Dept_id;
View created.

A continuación, como usuario system creamos los usuarios vpdhrm, vpdacnt, vpdit y vpdfin y les otorgamos privilegios de ‘Select’ sobre la vista VIEW_DATA_1 creada en el paso anterior.

Con el usuario system creamos el paquete ‘set_service_context_pkg’ para crear el contexto ‘hr_serv_context’:

SQL>  ----------Contexto----------------

SQL> create or replace context HR_SERV_CONTEXT using set_service_context_pkg;
Context created.

SQL> create or replace PACKAGE set_service_context_pkg IS
  2    PROCEDURE set_service_id;
  3  END;
  4  /
Package created.

SQL> CREATE OR REPLACE PACKAGE BODY set_service_context_pkg IS
  2  PROCEDURE set_service_id IS
  3         v_serv_id VARCHAR2(10);
  4  BEGIN
  5    IF (SYS_CONTEXT('USERENV', 'SESSION_USER')='VPDHRM')
  6      THEN
  7      v_serv_id:='00310';
  8    ELSIF (SYS_CONTEXT('USERENV', 'SESSION_USER')='VPDACNT')
  9      THEN
 10      v_serv_id:='00210';
 11        ELSIF (SYS_CONTEXT('USERENV', 'SESSION_USER')='VPDFIN')
 12      THEN
 13       v_serv_id:='00220';
 14   ELSIF (SYS_CONTEXT('USERENV', 'SESSION_USER')='VPDIT')
 15      THEN
 16      v_serv_id:='00110';
 17    END IF;
 18    DBMS_SESSION.SET_CONTEXT('HR_SERV_CONTEXT','serv_id',v_serv_id);
 19  END set_service_id;
 20  END set_service_context_pkg;
 21  /
Package body created.

El siguiente paso será crear un trigger para establecer el valor de serv_id en el contexto ‘hr_serv_context’ cada vez que el usuario inicie sesión:

SQL> --------------------Trigger--------------------------------

SQL> CREATE OR REPLACE TRIGGER set_service_context_trg
  2  AFTER LOGON ON DATABASE
  3    BEGIN
  4     set_service_context_pkg.set_service_id ;
  5    END;
  6  /
Trigger created.

A continuación, nos conectaremos con los usuarios vpdhrm, vpdacnt, vpdit y vpdfin y ejecutaremos una sentencia SELECT desde la vista VIEW_DATA_1. Los valores serán obtenidos basados en las condiciones dinámicas establecidas por SYS_CONTEXT('HR_SERV_CONTEXT','serv_id'):

SQL> ----------PRUEBA-----------------

SQL> CONNECT vpdhrm/hrm@test
Connected.

SQL> select  (SYS_CONTEXT('HR_SERV_CONTEXT','serv_id')) as Service_id from dual;

SERVICE_ID
-----------------------------------------------------------------------
00310

SQL> select t.Pers_id,t.serv_id,t.Serv_name from VPD.VIEW_DATA_1 t where Serv_id = 
SYS_CONTEXT('HR_SERV_CONTEXT','serv_id') ;

PERS_ID    SERV_ID    SERV_NAME
---------- ---------- ----------------------------------------
003110     00310      Rs_Manag
003120     00310      Rs_Manag
003130     00310      Rs_Manag

SQL> CONNECT vpdacnt/acnt@test
Connected.

SQL> select  (SYS_CONTEXT('HR_SERV_CONTEXT','serv_id')) as Service_id from dual;

SERVICE_ID
--------------------------------------------------------------------------
00210

SQL> select t.Pers_id,t.serv_id,t.Serv_name from VPD.VIEW_DATA_1 t where Serv_id = 
SYS_CONTEXT('HR_SERV_CONTEXT','serv_id');

PERS_ID    SERV_ID    SERV_NAME
---------- ---------- ----------------------------------------
002110     00210      Account_Serv
002120     00210      Account_Serv
002130     00210      Account_Serv

SQL> CONNECT vpdit/it@test
Connected.

SQL> select  (SYS_CONTEXT('HR_SERV_CONTEXT','serv_id')) as Service_id from dual;

SERVICE_ID
--------------------------------------------------------------------------
00110

SQL> select t.Pers_id,t.serv_id,t.Serv_name from VPD.VIEW_DATA_1 t where Serv_id = 
SYS_CONTEXT('HR_SERV_CONTEXT','serv_id');

PERS_ID    SERV_ID    SERV_NAME
---------- ---------- ----------------------------------------
001110     00110      It_serv
001120     00110      It_serv
001130     00110      It_serv

SQL> CONNECT vpdfin/fin@test
Connected.

SQL> select  (SYS_CONTEXT('HR_SERV_CONTEXT','serv_id')) as Service_id from dual;

SERVICE_ID
--------------------------------------------------------------------------
00220

SQL> select t.Pers_id,t.serv_id,t.Serv_name from VPD.VIEW_DATA_1 t where Serv_id = 
SYS_CONTEXT('HR_SERV_CONTEXT','serv_id');

PERS_ID    SERV_ID    SERV_NAME
---------- ---------- ----------------------------------------
002210     00220      Finance_Serv
002220     00220      Finance_Serv
002230     00220      Finance_Serv

Como podemos observar, el valor del contexto del usuario es establecido por el paquete y mostrado cada vez que se acceden a los datos de la vista. Con estos valores podemos crear políticas de acceso utilizando VPD.

1.2 Implementando políticas de acceso a nivel de fila:

1.2.1 Sentencia SELECT:

Como usuario VPD creamos una tabla TABLE_DATA_1 y le otorgaremos privilegios de SELECT sobre está a los usuarios vpdhrm, vpdacnt, vpdit y vpdfin:

SQL> CREATE Table Table_DATA_1 AS
  2  SELECT  p.Pers_id,
  3     p.Pers_name,
  4     j.Job_title,
  5     p.serv_id,
  6     s.Serv_name,
  7     d.Dept_name,
  8     p.region_id,
  9     p.salary
 10    FROM vpd.personnel p
 11    JOIN vpd.service s
 12    ON p.serv_id=s.serv_id
 13    JOIN vpd.job j
 14    ON p.job_id=j.job_id
 15    JOIN vpd.department d
 16    ON s.dept_id=d.dept_id;
Table created.

SQL> grant select on vpd.Table_DATA_1  to vpdhrm, vpdacnt, vpdit, vpdfin;
Grant succeeded.

Como usuario system crearemos la función de política VPD ‘Serv_ID_Func’, este será nuestro predicado dinámico:

SQL> CREATE OR REPLACE
  2    FUNCTION serv_id_func
  3      (
  4        schema_v IN VARCHAR2,
  5        tbl_v VARCHAR2)
  6      RETURN VARCHAR2
  7    IS
  8      ret_val VARCHAR2(200);
  9    BEGIN
 10      ret_val := 'serv_id =sys_context(''hr_serv_context'', ''serv_id'')';
 11      RETURN ret_val;
 12    END;
 13  /

Function created.

Ahora, definiremos una política llamada ‘SELECT_SERVICE_POLICY’,  definida sobre el objeto TABLE_DATA_1 desde el esquema VPD y aplicable solo para las sentencias SELECT:

SQL> BEGIN
  2    DBMS_RLS.ADD_POLICY (object_schema => 'VPD'
  3  , object_name =>'TABLE_DATA_1'
  4  , policy_name => 'SELECT_Service_POLICY'
  5  , function_schema => 'SYSTEM'
  6  , policy_function =>'serv_id_func'
  7  , statement_types => 'select');
  8  END;
  9  /
PL/SQL procedure successfully completed.

Nos conectamos con cada uno de los usuarios vpdhrm, vpdacnt, vpdit y vpdfin y ejecutamos una sentencia SELECT para verificar si la política SELECT_SERVICE_POLICY es correctamente aplicada:

SQL> ----------PRUEBA-----------------------

SQL> CONNECT vpdhrm/hrm@test
Connected.

SQL> select  (SYS_CONTEXT('HR_SERV_CONTEXT','serv_id')) as Service_id from dual;

SERVICE_ID
--------------------------------------------------------------------
00310

SQL> select t.Pers_id,t.serv_id,t.Serv_name,t.Dept_name from vpd.Table_DATA_1 t;

PERS_ID    SERV_ID      SERV_NAME  DEPT_NAME
=================================================
003110     00310        Rs_Manag  RUM_Dep
003120     00310        Rs_Manag  RUM_Dep
003130     00310        Rs_Manag  RUM_Dep

SQL> CONNECT vpdacnt/acnt@test
Connected.

SQL> select  (SYS_CONTEXT('HR_SERV_CONTEXT','serv_id')) as Service_id from dual;

SERVICE_ID
-------------------------------------------------------------------
00210

SQL> select t.Pers_id,t.serv_id,t.Serv_name,t.Dept_name from vpd.Table_DATA_1 t;

PERS_ID    SERV_ID      SERV_NAME  DEPT_NAME
=================================================
002110     00210        Account_Serv  Account_Fin_Dep
002120     00210        Account_Serv  Account_Fin_Dep
002130     00210        Account_Serv  Account_Fin_Dep

SQL> CONNECT vpdit/it@test
Connected.

SQL> select  (SYS_CONTEXT('HR_SERV_CONTEXT','serv_id')) as Service_id from dual;

SERVICE_ID
-------------------------------------------------------------------
00110

SQL> select t.Pers_id,t.serv_id,t.Serv_name,t.Dept_name from vpd.Table_DATA_1 t;

PERS_ID    SERV_ID      SERV_NAME  DEPT_NAME
============================================
001110     00110        It_serv    It_Dep
001120     00110        It_serv    It_Dep
001130     00110        It_serv    It_Dep

SQL> CONNECT vpdfin/fin@test
Connected.

SQL> select  (SYS_CONTEXT('HR_SERV_CONTEXT','serv_id')) as Service_id from dual;

SERVICE_ID
-------------------------------------------------------------------
00220

SQL> select t.Pers_id,t.serv_id,t.Serv_name,t.Dept_name from vpd.Table_DATA_1 t;

PERS_ID    SERV_ID      SERV_NAME    DEPT_NAME
=============================================================
002210     00220        Finance_Serv    Account_Fin_Dep
002220     00220        Finance_Serv    Account_Fin_Dep
002230     00220        Finance_Serv    Account_Fin_Dep

Como usuario system creamos otro usuario no_vpd y le otorgaremos privilegios de SELECT sobre la tabla VPD.TABLE_DATA_1.

Si tratamos de ejecutar una sentencia select sobre la tabla VPD.TABLE_DATA_1 conectados como usuario no_vpd, ninguna fila será retornada.

SQL> Connect system/manager
Connected.

SQL> create user no_vpd IDENTIFIED BY no_vpd profile DEFAULT;
User created.

SQL> Grant create session to no_vpd;
Grant succeeded.

SQL> Grant select on vpd.Table_DATA_1  to no_vpd;
Grant succeeded.

SQL> CONNECT no_vpd /no_vpd@test
Connected.

SQL> select  (SYS_CONTEXT('HR_SERV_CONTEXT','serv_id')) as Service_id from dual;

SERVICE_ID
-------------------------------------------------------------------


SQL> select t.Pers_id, t.Pers_name, t.Job_title, t.serv_id, t.Serv_name, 
t.Dept_name from vpd.Table_DATA_1 t ;

no rows selected

1.2.2 Sentencia INSERT:

En los siguientes pasos crearemos una tabla vacía y una política VPD aplicable a sentencias INSERT.

Como usuario VPD creamos una tabla vacía llamada TABLE_DATA_2 basada en la estructura de la tabla TABLE_DATA_1:

SQL> Connect VPD/VPD
Connected.

SQL> CREATE Table vpd.Table_DATA_2 AS SELECT * from vpd.Table_DATA_1;
Table created.

Como usuario system creamos la función de política VPD ‘Serv_ID_add_Func’ que permitirá inserciones solo para las filas correspondientes al servicio ‘IT’ (00110):

SQL> Connect system/manager
Connected.

SQL> CREATE OR REPLACE
  2        FUNCTION Serv_ID_add_Func
  3          (
  4            schema_v IN VARCHAR2,
  5            tbl_v VARCHAR2)
  6          RETURN VARCHAR2
  7        IS
  8          ret_val VARCHAR2(200);
  9        BEGIN
 10          ret_val := 'serv_id = 00110';
 11          RETURN ret_val;
 12        END;
 13  /

Function created.

A continuación, crearemos una política de inserción llamada ‘INSERT_IT_POLICY’. Para aplicar la política VPD en una instrucción INSERT, debemos habilitar el parámetro update_check.

SQL> BEGIN
  2   DBMS_RLS.ADD_POLICY (object_schema =>'VPD', object_name=>
      'Table_DATA_2',policy_name =>'INSERT_IT_POLICY'
  3  , function_schema => 'SYSTEM', policy_function =>'Serv_ID_add_Func', 
      statement_types => 'insert',update_check=>true);
  4  END;
  5  /
PL/SQL procedure successfully completed.

Para verificar nuestra política VPD:

Primero, trataremos de insertar algunos valores que no cumplen con INSERT_IT_POLICY. Después, ejecutamos sentencias insert que si cumplirán con la política.

SQL> CONNECT VPD/VPD@test
Connected.

SQL> --------violación de la política-------------

SQL> insert into  vpd.Table_DATA_2 values ('001110', 'hela',null, '00220',
'Finance_Serv','0200',10,1500);
insert into  vpd.Table_DATA_2 values ('001110', 'hela',null, '00220',
'Finance_Serv','0200',10,1500)
                 *
ERROR at line 1:
ORA-28115: policy with check option violation

SQL> insert into  vpd.Table_DATA_2 values ('001110', 'hela1',null, '00110',
'It_serv','0100',10,1500);
1 row created.

SQL> insert into  vpd.Table_DATA_2 values ('001110', 'hela2',null, '00110',
'It_serv','0100',10,3000);
1 row created.

1.2.3 Sentencia DELETE:

En los siguientes pasos crearemos una política de función y una política VPD para lidiar con una sentencia DELETE.

Conectado como usuario system creamos una función de política VPD llamada ‘Salary_delete_Func’ que será aplicada a salarios mayores de 2000 y al servicio ‘IT service’:

SQL> Connect system/manager
Connected.

SQL> CREATE OR REPLACE
  2       FUNCTION Salary_delete_Func
  3         (
  4           schema_v IN VARCHAR2,
  5           tbl_v VARCHAR2)
  6         RETURN VARCHAR2
  7       IS
  8         ret_val VARCHAR2(200);
  9       BEGIN
 10         ret_val := 'salary > 2000 and serv_id=''00110'' ';
 11         RETURN ret_val;
 12       END;
 13  /

Function created.

A continuación, creamos una política sobre la tabla TABLE_DATA_2 utilizando la función ‘Salary_delete_Func’ para sentencias DELETE, llamada ‘Salary_delete_policy’:

SQL> BEGIN
  2    DBMS_RLS.ADD_POLICY (object_schema => 'VPD'
  3  , object_name => 'Table_DATA_2'
  4  , policy_name =>'SALARY_Delete_POLICY'
  5  , function_schema => 'SYSTEM'
  6   , policy_function => 'Salary_delete_Func '
  7  , statement_types => 'delete');
  8   END;
  9  /

PL/SQL procedure successfully completed.

Finalmente, verificamos la tabla Table_Data_2 y ejecutamos una sentencia DELETE:

SQL> select count(*) from vpd.Table_DATA_2;
  COUNT(*)
  ----------
         2

SQL>  connect VPD/VPD
Connected.

SQL> delete from vpd.table_DATA_2;
1 row deleted.

SQL> select count(*) from vpd.Table_DATA_2;

  COUNT(*)
  --------------
         1

SQL> select * from vpd.Table_DATA_2;

PERS_ID    PERS_NAME
---------- ----------------------------------------
JOB_TITLE                                SERV_ID
---------------------------------------- ----------
SERV_NAME
----------------------------------------
DEPT_NAME                                 REGION_ID SALARY
---------------------------------------- ---------- ---------------
001110     hela1
                                         00110
It_serv
0100                                             10 1500

1.3 Implementando políticas de acceso a nivel de columna:

Cuando implementamos restricciones a nivel de fila, la política es aplicada sin importar las columnas seleccionadas. Sin embargo, con restricciones a nivel de columna, la política de acceso se aplica solo cuando las columnas protegidas por la política son incluidas en la sentencia DML. Además, es posible enmascarar los datos de la columna en cualquier momento. Por lo tanto, las filas que no se ajustan a los criterios definidos tienen sus valores de columna ocultos por la política y se muestran como nulos.

Como usuario VPD creamos una tabla Table_DATA_3 basada en la tabla Table_DATA_2 en el esquema VPD y otorgamos privilegios de select sobre esta a los usuarios vpdhrm, vpdacnt, vpdit y vpdfin:

SQL> Connect VPD/VPD
Connected.

SQL> CREATE Table vpd.Table_DATA_3 AS SELECT  * from vpd.Table_DATA_1;
Table created.

SQL> Grant select on vpd.Table_DATA_3  to vpdhrm, vpdacnt, vpdit, vpdfin;
Grant succeeded.

SQL> insert into  vpd.Table_DATA_3 values ('001130', 'name1', 'Director_Serv', 
'00110','It_serv', 'It_Dep',10, 3500);
1 row created.

SQL> insert into  vpd.Table_DATA_3 values ('001140', 'name2', 'Engineer', '00110',
'It_serv', 'It_Dep',20,2500);
1 row created.

SQL> insert into  vpd.Table_DATA_3 values ('001150', 'name3', 'worker', '00110',
'It_serv', 'It_Dep',30, 500);
1 row created.

SQL> insert into  vpd.Table_DATA_3 values ('003130', 'name4', 'Director_Serv', 
'00310','Rs_Manag', 'RUM_Dep',40, 3500);
1 row created.

SQL> insert into  vpd.Table_DATA_3 values ('003140', 'name5', 'Mastery', '00310',
'Rs_Manag', 'RUM_Dep',50,1500);
1 row created.

SQL> insert into  vpd.Table_DATA_3 values ('003150', 'name6', 'worker', '00310',
'Rs_Manag', 'RUM_Dep',60, 500);
1 row created.

Primero, conectado como usuario system creamos una función de política llamada ‘saljob_plc_func’:

SQL> Connect system/manager
Connected.

SQL> CREATE OR REPLACE
  2  FUNCTION saljob_plc_func
  3    (
  4      schema_v IN VARCHAR2,
  5      tbl_v VARCHAR2)
  6    RETURN VARCHAR2
  7  IS
  8    ret_val VARCHAR2(200);
  9  BEGIN
 10    ret_val := 'serv_id = sys_context(''hr_serv_context'',''serv_id'')';
 11    RETURN ret_val;
 12  END;
 13  /

Function created.

A continuación, definiremos una política a nivel de columna llamada ‘saljob_plc’:

SQL> BEGIN
  2      DBMS_RLS.add_policy (object_schema => 'VPD'
  3  , object_name => ' Table_DATA_3', policy_name => ' saljob_plc '
  4  , policy_function => ' saljob_plc_func ', statement_types => 'SELECT'
  5  , sec_relevant_cols => 'Job_title, SALARY');
  6    END;
  7  /
PL/SQL procedure successfully completed.

Para verificar el resultado, conectado como usuario vpdhrm y vpdit ejecutamos una sentencia SELECT, sin incluir las columnas protegidas Salary y Job_title:

SQL>  Connect vpdhrm/hrm@test
Connected.

SQL>  Select p.Pers_id, serv_id from vpd.Table_DATA_3 p;

PERS_ID    SERV_ID
---------- ----------
001130     00110
001140     00110
001150     00110
003130     00310
003140     00310
003150     00310

6 rows selected.

SQL> Connect vpdit/it@test
Connected.

SQL>  Select p.Pers_id, serv_id from vpd.Table_DATA_3 p;

PERS_ID    SERV_ID
---------- ----------
001130     00110
001140     00110
001150     00110
003130     00310
003140     00310
003150     00310

6 rows selected.

La política no se aplica, ya que las columnas protegidas salary y job_title no se incluyen en la sentencia SELECT.

Ahora, ejecutamos la sentencia SELECT que incluya las columnas salary o job_title y también las dos al mismo tiempo:

SQL> Connect vpdhrm/hrm@test
Connected.

SQL> Select p.Pers_id, serv_id, p.job_title from vpd.Table_DATA_3 p;

PERS_ID    SERV_ID    JOB_TITLE
---------- ---------- ----------------------------------------
003130     00310      Director_Serv
003140     00310      Mastery
003150     00310      worker

SQL> Select p.Pers_id, serv_id, p.salary from vpd.Table_DATA_3 p;

PERS_ID    SERV_ID    SALARY
---------- ---------- --------------------
003130     00310      3500
003140     00310      1500
003150     00310      500

SQL> Select p.Pers_id, serv_id, p.job_title , p.salary from vpd.Table_DATA_3 p;

PERS_ID    SERV_ID    JOB_TITLE    SALARY
----------------------------------------------------------------
003130     00310      Director_Serv  3500
003140     00310      Mastery    1500
003150     00310      worker    500

SQL> Connect vpdit/it@test
Connected.

SQL> Select p.Pers_id, serv_id, p.job_title from vpd.Table_DATA_3 p;

PERS_ID    SERV_ID    JOB_TITLE
---------- ---------- ----------------------------------------
001130     00110      Director_Serv
001140     00110      Engineer
001150     00110      worker

SQL> Select p.Pers_id, serv_id, p.salary from vpd.Table_DATA_3 p;

PERS_ID    SERV_ID    SALARY
---------- ---------- --------------------
001130     00110      3500
001140     00110      2500
001150     00110      500

SQL> Select p.Pers_id, serv_id, p.job_title , p.salary from vpd.Table_DATA_3 p;

PERS_ID    SERV_ID    JOB_TITLE    SALARY
---------------------------------------------------------------
001130     00110      Director_Serv  3500

001140     00110      Engineer    2500
001150     00110      worker    500

En este paso, veremos como enmascarar columnas. Primero, como usuario system deshabilitaremos la ‘policita saljob_plc’:

SQL> connect system/manager@Test
Connected.

SQL> BEGIN
  2  dbms_rls.enable_policy(policy_name=>'saljob_plc'
  3  ,object_name=>' Table_DATA_3'
  4  , object_schema=>'VPD',enable=>FALSE);
  5   END;
  6  /

PL/SQL procedure successfully completed.

A continuación, definiremos una nueva política llamada ‘saljob_plc_mask’ usando la opción data masking:

BEGIN
DBMS_RLS.add_policy (object_schema => 'VPD'
, object_name => ' Table_DATA_3', policy_name => 'saljob_plc_mask'
, policy_function => ' saljob_plc_func ', statement_types => 'SELECT'
, sec_relevant_cols => 'Job_title, SALARY'
, sec_relevant_cols_opt =>DBMS_RLS.all_rows);
  END;  
/

Conectado como vpdhrm y vpdit, ejecutamos una sentencia SELET que incluya las columnas salary y job_title:

SQL> Connect vpdhrm/hrm@test
Connected.

SQL> Select p.Pers_id,p.serv_id,p.job_title , p.salary from vpd.Table_DATA_3 p;

PERS_ID    SERV_ID    JOB_TITLE    SALARY
----------------------------------------------------------------
001130     00110
001140     00110
001150     00110
003130     00310      Director_Serv  3500
003140     00310      Mastery    1500
003150     00310      worker    500
6 rows selected.

SQL> Connect vpdit/it@test
Connected.

SQL> Select p.Pers_id,p.serv_id,p.job_title , p.salary from vpd.Table_DATA_3 p;

PERS_ID    SERV_ID    JOB_TITLE    SALARY
=============================================
001130     00110      Director_Serv  3500
001140     00110      Engineer    2500
001150     00110      worker    500
003130     00310
003140     00310
003150     00310

6 rows selected.

Como podemos ver, las columnas salary y job_title retornadas por la consulta de vpdhrm contiene valores solo para el nombre de servicio ‘hrm’ y para el resto de las filas el valor desplegado es null. Y además, para vpdit, las columnas salay y job_title tienen valores solo para el servicio ‘it’.

1.4 Implementando políticas grupales VPD:

La característica políticas grupales es usada para aplicar diferentes políticas VPD sobre el mismo objeto. En algunos casos las políticas grupales son usadas para asignar políticas a diferentes grupos y ejecutarlas dependiendo de ciertas condiciones. La activación de una política o de otra dependerá del contexto de una aplicación de acuerdo con ciertos parámetros declarados previamente.

A continuación, crearemos una tabla que contendrá tres diferentes categorías diferentes de departamentos. Otorgaremos privilegios de select a los usuarios vpdhrm, vpdacnt, vpdit y vpdfin. Para cada grupo de departamentos definiremos una política grupal. Estas políticas grupales aislarán la función de cada grupo en función de la membresía de cada uno. Cada usuario podrá ver su propio departamento determinado por un valor de contexto de aplicación.

Primero, nos conectamos como usuario VPD y creamos la tabla DEPT_CATEG. Otorgamos privilegios de SELECT los usuarios vpdhrm, vpdacnt, vpdit y vpdfin:

SQL> Connect VPD/VPD
Connected.

SQL> CREATE TABLE DEPT_CATEG
  2        (
  3          CAT1_ID NUMBER,
  4          CAT1_Name   VARCHAR2(100),
  5          CAT2_ID NUMBER,
  6          CAT2_Name   VARCHAR2(100),
  7          CAT3_ID NUMBER,
  8          CAT3_Name   VARCHAR2(100)
  9        );
Table created.

SQL> grant select on vpd.DEPT_CATEG to vpdhrm, vpdacnt, vpdit, vpdfin ;
Grant succeeded.

A continuación, insertamos datos en la tabla DEPT_CATEG. Los datos serán usados por el contexto:

SQL> Insert into DEPT_CATEG values (101,'Admin_RH', 201,'Admin_Act_Fin', 301,'Admin_IT');
1 row created.

SQL> Insert into DEPT_CATEG values (102,'Control_RH', 202,' Control_Act_Fin', 
302,' Control_IT');
1 row created.

SQL> Insert into DEPT_CATEG values (103,'Publ_Relat_RH', 203, 'Publ_Relat_Act_Fin', 
303,'Publ_Relat_IT');
1 row created.

SQL> Insert into DEPT_CATEG values (104,'Executive_RH', 204,'Executive _Act_Fin', 
304,'Executive_IT');
1 row created.

SQL> Insert into DEPT_CATEG values (105,'Recruit_RH', 205,'Recruit _Act_Fin', 
305,'Recruit_IT');
1 row created.

SQL> Commit;
Commit complete.

Conectado como usuario system creamos el contexto dept_categ_context:

SQL> connect system/manager
Connected.

SQL> CREATE OR REPLACE CONTEXT dept_categ_context USING dept_categ_pkg;
Context created.

En este paso crearemos una política para cada categoría:

  • Creamos la política grupal dept_categ1:
SQL> BEGIN
  2  DBMS_RLS.CREATE_POLICY_GROUP(object_schema =>'VPD'
  3  , object_name => 'DEPT_CATEG'
  4  , policy_group =>'dept_categ1');
  5   END;
  6   /

PL/SQL procedure successfully completed.
  • Creamos la política grupal dept_categ2:
SQL> BEGIN
  2  DBMS_RLS.CREATE_POLICY_GROUP(object_schema =>'VPD'
  3  , object_name =>'DEPT_CATEG'
  4  , policy_group =>'dept_categ2');
  5   END;
  6   /

PL/SQL procedure successfully completed.
  • Creamos la política grupal dept_categ3:
SQL> BEGIN
  2  DBMS_RLS.CREATE_POLICY_GROUP(object_schema => 'VPD'
  3  ,object_name => 'DEPT_CATEG'
  4  ,policy_group =>'dept_categ3');
  5   END;
  6   /

PL/SQL procedure successfully completed.

En el siguiente paso, crearemos tres funciones de política que serán asignadas a cada política agrupada.

  • Creamos la función de política para la categoría uno llamada ‘vpd_func_dept_cate1’:
SQL> CREATE OR REPLACE
  2  FUNCTION vpd_func_dept_categ1
  3  (
  4  V_SCHEMA IN VARCHAR2,
  5  V_TABLE  IN VARCHAR2)
  6  RETURN VARCHAR2
  7  AS
  8  PREDICATE VARCHAR2(8) DEFAULT NULL;
  9  BEGIN
 10  IF (SYS_CONTEXT('USERENV','SESSION_USER')) = 'VPDHRM' THEN
 11  predicate                               := '1=2';
 12  ELSE NULL;
 13  END IF;
 14  RETURN predicate;
 15  END;
 16  /

Function created.
  • Creamos la función de política para la categoría dos, llamada ‘vpd_func_dept_categ2’:
SQL> CREATE OR REPLACE
  2  FUNCTION vpd_func_dept_categ2
  3  (
  4  V_SCHEMA IN VARCHAR2,
  5  V_TABLE  IN VARCHAR2)
  6  RETURN VARCHAR2
  7  AS
  8  PREDICATE VARCHAR2(8) DEFAULT NULL;
  9  BEGIN
 10  IF (SYS_CONTEXT('USERENV','SESSION_USER'))= 'VPDACNT' THEN
 11  predicate                               := '1=2';
 12  ELSE NULL;
 13  END IF;
 14  RETURN predicate;
 15  END;
 16  /

Function created.
  • Creamos la función de política para la categoría tres, llamada ‘vpd_func_dept_categ3’:
QL> CREATE OR REPLACE
  2  FUNCTION vpd_func_dept_categ3
  3  (
  4  V_SCHEMA IN VARCHAR2,
  5  V_TABLE  IN VARCHAR2)
  6  RETURN VARCHAR2
  7  AS
  8  PREDICATE VARCHAR2(8) DEFAULT NULL;
  9  BEGIN
 10  IF (SYS_CONTEXT('USERENV','SESSION_USER')) = 'VPDIT' THEN
 11  predicate                               := '1=2';
 12  ELSE NULL;
 13  END IF;
 14  RETURN predicate;
 15  END;
 16  /

Function created.

En este paso, crearemos la política grupal para cada categoría de departamento.

  • Creamos la política grupal llamada ‘vpd_func_dept_categ1_plc’ para la categoría uno: 
SQL> BEGIN
  2   DBMS_RLS.ADD_GROUPED_POLICY( object_schema => 'VPD'
  3  , object_name =>'DEPT_CATEG'
  4  , policy_group => 'dept_categ1'
  5  , policy_name => 'vpd_func_dept_categ1_plc'
  6  , policy_function =>'vpd_func_dept_categ1'
  7  , statement_types => 'select'
  8  , policy_type => DBMS_RLS.CONTEXT_SENSITIVE
  9  , sec_relevant_cols=> 'CAT2_ID, CAT2_Name, CAT3_ID,CAT3_Name'
 10  , sec_relevant_cols_opt => DBMS_RLS.ALL_ROWS);
 11  END;
 12  /

PL/SQL procedure successfully completed.
  • Creamos la política grupal llamada ‘vpd_func_dept_categ2_plc’ para la categoría dos:
SQL> BEGIN
  2   DBMS_RLS.ADD_GROUPED_POLICY( object_schema =>'VPD'
  3  , object_name => 'DEPT_CATEG'
  4  , policy_group => 'dept_categ2'
  5  , policy_name => 'vpd_func_dept_categ2_plc'
  6  , policy_function =>' vpd_func_dept_categ2'
  7  , statement_types => 'select'
  8  , policy_type => DBMS_RLS.CONTEXT_SENSITIVE
  9  , sec_relevant_cols=> 'CAT1_ID, CAT1_Name,CAT3_ID,CAT3_Name'
 10  , sec_relevant_cols_opt => DBMS_RLS.ALL_ROWS);
 11  END;
 12  /
PL/SQL procedure successfully completed.
  • Creamos la política grupal llamada ‘vpd_func_dept_categ3_plc’ para la categoría tres:
SQL> BEGIN
  2   DBMS_RLS.ADD_GROUPED_POLICY( object_schema =>'VPD'
  3  , object_name => 'DEPT_CATEG'
  4  , policy_group => 'dept_categ3'
  5  , policy_name => 'vpd_func_dept_categ3_plc '
  6  , policy_function =>' vpd_func_dept_categ3 '
  7  , statement_types => 'select'
  8  , policy_type => DBMS_RLS.CONTEXT_SENSITIVE
  9  , sec_relevant_cols=> 'CAT1_ID, CAT1_Name,CAT2_ID,CAT2_Name'
 10  , sec_relevant_cols_opt => DBMS_RLS.ALL_ROWS);
 11  END;
 12  /
PL/SQL procedure successfully completed.

A continuación, creamos el package y el package body ‘dept_categ_pkg’ con el contexto ‘dept_categ_context’:

SQL> CREATE OR REPLACE PACKAGE dept_categ_pkg

  2   IS
  3  PROCEDURE set_dept_categ_context
  4   (
  5   plc_grp VARCHAR2 DEFAULT NULL
  6    );
  7  END;
  8   /
Package created.

SQL> CREATE OR REPLACE PACKAGE BODY dept_categ_pkg
  2   AS
  3   PROCEDURE set_dept_categ_context
  4   (plc_grp VARCHAR2 DEFAULT NULL)
  5    IS
  6    BEGIN
  7    CASE (SYS_CONTEXT('USERENV','SESSION_USER'))
  8    WHEN 'VPDHRM'
  9    THEN
 10    DBMS_SESSION.SET_CONTEXT('dept_categ_context'
 11    ,'plc_grp','dept_categ1');
 12    WHEN 'VPDACNT'
 13    THEN
 14    DBMS_SESSION.SET_CONTEXT('dept_categ_context'
 15    ,'plc_grp','dept_categ2');
 16        WHEN 'VPDIT' THEN
 17    DBMS_SESSION.SET_CONTEXT('dept_categ_context'
 18    ,'plc_grp','dept_categ3');
 19  ELSE
 20  NULL;
 21  END CASE;
 22  EXCEPTION
 23  WHEN NO_DATA_FOUND THEN
 24     NULL;
 25  END set_dept_categ_context;
 26  END;
 27  /
Package body created.

Ahora, asignaremos el contexto ‘dept_categ_context’ al contexto de aplicación DEPT_CATEG:

SQL> BEGIN
  2  DBMS_RLS.ADD_POLICY_CONTEXT(object_schema =>'VPD'
  3  , object_name =>'DEPT_CATEG'
  4  , namespace =>'dept_categ_context'
  5  ,attribute =>'plc_grp');
  6  END;
  7  /
PL/SQL procedure successfully completed.

En el siguiente paso, crearemos un nuevo trigger que se activara con el evento de inicio de sesión para activar el contexto de aplicación:

SQL> CREATE OR REPLACE TRIGGER set_dep_categ_context_trg AFTER LOGON ON DATABASE
  2  BEGIN
  3  dept_categ_pkg.set_dept_categ_context;
  4  END;
  5  /
Trigger created.

Finalmente, conectados como usuario vpdhrm, verificamos el valor plc_grp desde el contexto de la aplicación y ejecutamos una sentencia SELECT sobre DEPT_CATEG para verificar si la política agrupada se aplica:

SQL> Connect VPDHRM/hrm
Connected.

SQL> select CAT1_ID, CAT1_NAME, CAT2_ID, CAT2_NAME, CAT3_ID, CAT3_NAME from vpd.DEPT_CATEG;

CAT1_ID  CAT1_NAME  CAT2_ID C    CAT3_ID C
==============================================
       101    Admin_RH
       102    Control_RH
       103    Publ_Relat_RH
       104    Executive_RH
       105    Recruit_RH

Como podemos ver solamente los departamentos desde la categoría 1 son visibles para vpdrm.

Como podemos ver solamente los departamentos desde la categoría 1 son visibles para vpdrm.

Conectado como usuario vpdacnt, verificamos el valor de plc_grp desde el contexto de aplicación y ejecutamos una sentencia SELECT sobre DEPT_CATEG para verificar si la política agrupada se aplica:

SQL> Connect vpdacnt/acnt
Connected.

SQL> select CAT1_ID, CAT1_NAME, CAT2_ID, CAT2_NAME, CAT3_ID, CAT3_NAME from vpd.DEPT_CATEG;

CAT1_ID C    CAT2_ID    CAT2_NAME     CAT3_ID C
--------------------------------------------------------------------
          201    Admin_Act_Fin
          202    Control_Act_Fin
          203    Publ_Relat_Act_Fin
          204    Executive _Act_Fin
          205    Recruit _Act_Fin

Y finalmente conectado como usuario vpdit, verificamos el valor de plc_grp desde el contexto de aplicación y ejecutamos una sentencia SELECT sobre DEPT_CATEG para verificar si la política agrupada se aplica:

SQL> Connect vpdit/it
Connected.

SQL> select CAT1_ID, CAT1_NAME, CAT2_ID, CAT2_NAME, CAT3_ID, CAT3_NAME from vpd.DEPT_CATEG;

CAT1_ID C    CAT2_ID C    CAT3_ID    CAT3_NAME
--------------------------------------------------------------------
                   301      Admin_IT
                           302      Control_IT
                           303      Publ_Relat_IT
                           304      Executive_IT
                           305      Recruit_IT

En políticas agrupadas, el contexto de la aplicación determina la política activa. En nuestro ejemplo, el procedimiento DBMS_RLS.add_policy_context fefine nuestro contexto de aplicación y sus atributos según el usuario que se conecte.

1.5 Otorgando exenciones a las políticas VPD

El comportamiento default de VPD es, una vez la política se haya declarado sobre un objeto, esta no puede ser omitida independientemente de los privilegios del usuario. Pero, en algunos casos, necesitamos acceder a todos los datos de un objeto que tiene una política aplicada.

A continuación, usando el mismo escenario, mostraremos como eximir al usuario VPDHRM de todas las políticas declaradas dentro del esquema VPD.

Primero, nos conectamos como el usuario vpdhrm y ejecutamos una sentencia SELECT sobre la tabla TABLE_DATA_1:

SQL> Connect Vpdhrm/hrm
Connected.

SQL> select t.pers_id, t.serv_id from vpd.Table_DATA_1 t ;

PERS_ID    SERV_ID
---------- ----------
003110     00310
003120     00310
003130     00310

Luego, nos conectamos como usuario system y eximimos al usuario vpdhrm de cualquier política VPD:

SQL>  Connect system/manager
Connected.

SQL> GRANT  EXEMPT ACCESS POLICY TO vpdhrm;
Grant  succeeded.

Nos conectamos como usuario vpdhrm nuevamente y ejecutamos una sentencia SELECT similar al primer paso:

SQL> Connect Vpdhrm/hrm
Connected.

SQL> select t.pers_id, t.serv_id from vpd.Table_DATA_1 t ;

PERS_ID    SERV_ID
---------- ----------
002110     00210
002120     00210
002130     00210
002210     00220
002220     00220
002230     00220
001110     00110
001120     00110
001130     00110
003110     00310
003120     00310
003130     00310

12 rows selected.

Resumen:

Las políticas Oracle Virtual Private Database proporcionan los siguientes beneficios:

  • Basan las políticas de seguridad en objetos de bases de datos en lugar de aplicaciones
  • Permite controlar la manera en que las políticas son evaluadas mediante una alta granularidad
  • Mediante la creación de políticas basadas en objetos el rendimiento no se ve impactado dentro de la base de datos.

YV Ravi Kumar un Oracle ACE Director y Oracle Certified Master (OCM) con 20 años de experiencia en Banca, Servicios financieros y seguros (BFSI) y ha ocupado varios puestos como Vise Presidente (IT), Senior Database Architect y Production DBA. Tambien es OCP en Oracle 8i, 9i, 10g, 11g y 12c y posee certificaciones en Golden Gate, RAC, Performance Tuning y Oracle Exadata. Ha publicado mas de 100 articulos para OTN-Español, OTN-Portugues, OTN-Ingles, TOAD World,

UKOUG, OTech Magazine y Redgate. Ha sido speaker en @OOW, @NYOUG, @OTN, @AIOUG, Samgam y @IOUG. Diseñó, arquitectó e implementó la Base de Datos del Sistema Bancario Central (CBS) para los Bancos Centrales de dos países: India y Mahe, Seychelles. Es cofundador de OraWorld (www.oraworld.com). Aprenda mas sobre su perfil en LaseSoft.

Hela Khazri es Oracle Certified Professional (OCP 12c R1) con 8 años de experiencia como Administrador de base de datos Senior y Project Manager utilizando metodologías scrum master. Hela posee una capacidad comprobada para mantener la alta disponibilidad usando Oracle RAC y ASM y para monitorear el rendimiento de la base de datos usando AWR, ASH, ADDM y la seguridad de las bases de datos mediante habilidades analíticas y orientadas a los detalles para resolver problemas de la base de datos y ayudar el día a día soporte diurno.

Julio Ayapán es Ingeniero en Ciencias y Sistemas, Administrador de base de datos Oracle con más de 4 años de experiencia en proyectos de infraestructura, Bases de Datos Oracle 10g, 11g y 12c sobre Linux y Solaris. Posee la certificación “Oracle Certified Professional 11g y 12c” y Oracle ACE Associate. Ha sido Conferencista en OTN Tour Latinoamericano 2016 y 2017 en Guatemala. Es parte de la junta directiva del Grupo de Usuarios Oracle de Guatemala (GOUG). Actualmente es Consultor de Bases de datos Oracle en eProseed Central America. Publica artículos frecuentemente en su blog http://oraclehomegt.blogspot.com. Twitter @jayapangt.

Este artículo ha sido revisado por el equipo de productos Oracle y se encuentra en cumplimiento de las normas y prácticas para el uso de los productos Oracle.