O Oracle Virtual Private Database é uma feature inclusa na versão Enterprise Edition, sendo introduzida a partir do Oracle 8i.
O principal objetivo do VPD é permitir a criação de políticas para acesso aos dados, em nível de linha e coluna (disponibilizada a partir da versão 10g). Basicamente o VPD inclui dinamicamente uma clausula where nas consultas que são realizadas nas tabelas/views/sinônimos que possuem o VPD ativo.
As políticas criadas com o VPD podem ser simples ou complexas, dependendo dos requerimentos de segurança necessários. Estas políticas, por serem associadas diretamente aos objetos no banco de dados, são aplicadas automaticamente a qualquer usuário e meio de acesso aos dados. Desde que estes usuários não tenham a permissão EXEMPT ACCESS POLICY.
Quando um usuário, seja direta ou indiretamente acessa um objeto com VPD ativo, o Oracle modifica a consulta SQL executada. Esta modificação cria uma clausula where retornada por uma função usada na implementação da politica de segurança. A modificação ocorre de forma transparente para o usuário e desta forma não necessita de nenhum ajuste a "nível de aplicação". O VPD pode ser aplicado a operações de select, insert, update, index e delete.
Neste artigo irei abordar um exemplo de criação de VPD "simples" a nível de linha.
Primeiramente estarei realizando a criação de uma tabela chamada notas, na qual estaremos aplicando uma política VPD para que apenas os usuários autorizados possam visualizar as informações contidas.
SQL> show user; USER is "LAMIM" SQL> create table notas( id_aluno number(4), id_curso number (2), nome_aluno varchar2 (100), nota number(4,1) ); 2 3 4 5 6 Table created. SQL>Criada a tabela, vamos inserir alguns valores na mesma afim de possibilitar nossa demonstração de um política VPD.
SQL> SQL> insert into notas values (1,15,'Scot',8.0); 1 row created. SQL> insert into notas values (2,15,'Smith',6.5); 1 row created. SQL> insert into notas values (3,25,'Tiger',3.3); 1 row created. SQL> insert into notas values (4,25,'Sarah',4.7); 1 row created. SQL> insert into notas values (5,25,'Jessie',10); 1 row created. SQL> insert into notas values (7,30,'Roth',9.3); 1 row created. SQL> insert into notas values (8,30,'John',10); 1 row created. SQL> insert into notas values (9,10,'Allen',7.7); 1 row created. SQL> insert into notas values (10,10,'Paul',5.1); 1 row created. SQL> commit; Commit complete.Para que seja possível demonstrar o funcionamento do VPD, será criado o usuário consulta, que terá permissão de leitura na tabela notas.
SQL> create user consulta identified by consulta;
User created.
SQL>
SQL> grant create session to consulta;
Grant succeeded.
SQL> grant select on notas to consulta;
Grant succeeded.
SQL>
SQL> select * from lamim.notas;
ID_ALUNO ID_CURSO NOME_ALUNO NOTA
---------- ---------- ---------- ----------
1 15 Scot 8
2 15 Smith 6,5
3 25 Tiger 3,3
4 25 Sarah 4,7
5 25 Jessie 10
7 30 Roth 9,3
8 30 John 10
9 10 Allen 7,7
10 10 Paul 5,1
9 rows selected.
SQL>
Apos a criação do usuário, realizando um select na tabela notas do schema lamim, podemos ver todos os dados da tabela. Porém imagine que exista uma regra de negócio na qual o usuário consulta só pode visualizar os alunos vinculados ao curso de id 15 e 25.Vamos criar um VPD para atender esta regra. É importante destacar que a complexidade da politica, depende exclusivamente da necessidade de segurança a ser implementada.
Para um controle mais "dinâmico" do meu VPD, estarei criando duas tabelas de controle chamadas DENY_ACESS onde serão cadastrados os usuário que serão afetados (limitados - usuário consulta) pela política e a BLOCKED_ACCESS onde serão cadastrados os registros que serão afetados (limitados id_curso 10 e 30).
SQL>
SQL> create table DENY_ACCESS(
nome varchar2(50)); 2
Table created.
SQL>
SQL> insert into DENY_ACCESS values ('CONSULTA');
1 row created.
SQL> create table blocked_access(
ID_CURSO number(20)
); 2 3
Table created.
SQL> insert into blocked_access values (10);
1 row created.
SQL> insert into blocked_access values (30);
1 row created.
SQL> commit;
Commit complete.
SQL> grant select on deny_access to consulta;
Grant succeeded.
SQL> grant select on blocked_access to consulta;
Grant succeeded.
SQL>
Realizada a criação das tabelas, estaremos criando agora a função que será associada a politica para restrição de acesso. Esta função irá basicamente comparar se o usuário da sessão conectada está cadastrado na blocked_access. Caso o usuário esteja cadastrado, ele cairá na condição que restringe o acesso ao ID_CURSO diferente dos ID_CURSO cadastrados na tabela DENY_ACCESS.SQL> CREATE OR REPLACE FUNCTION VPD_DENY_ACCESS_NOTAS
(schema in varchar2, table_p in varchar2) return varchar2 as
2 3 w_exists number :=0;
4 predicate varchar2(100) default null;
5 BEGIN
6 select max(vlr) into w_exists
7 from (select 0 vlr
8 from dual
9 union
10 select 1 vlr
11 from lamim.deny_access
12 where nome = UPPER(SYS_CONTEXT('USERENV', 'SESSION_USER')));
IF w_exists = 1
13 14 THEN
15 predicate := 'ID_CURSO not in (select ID_CURSO from lamim.blocked_access)';
16 ELSE
17 predicate := '1=1';
18 END IF;
19 RETURN predicate;
END;
20 21 /
Function created.
SQL>
Após a criação da função, devemos realizar a criação da politica. A documentação da politica pode ser verificada aqui.SQL> BEGIN DBMS_RLS.ADD_POLICY ( 2 3 object_schema => 'LAMIM', 4 object_name => 'NOTAS', 5 policy_name => 'VPD_DENY_ACCESS_NOTAS', 6 function_schema => 'LAMIM', 7 policy_function => 'VPD_DENY_ACCESS_NOTAS', 8 statement_types => 'SELECT, INSERT, UPDATE,DELETE'); 9 END; 10 / PL/SQL procedure successfully completed. SQL>Assim que a política é criada, nosso VPD já está ativo. Para demonstrar o funcionamento, estarei criando o usuário teste, que não será incluido no bloqueio. Desta forma, em nosso teste, o usuário consulta deverá visualizar todos os dados da tabela consulta, desde que o ID_CURSO seja diferente de 10 e 30 e o usuário teste, conseguirá ver normalmente.
SQL> create user teste identified by teste;
User created.
SQL> grant create session to teste;
Grant succeeded.
SQL> grant select on lamim.notas to teste;
Grant succeeded.
SQL> conn teste/teste
Connected.
SQL> show user;
USER is "TESTE"
SQL> set lines 150
SQL> col NOME_ALUNO for a10
SQL> select * from lamim.notas;
ID_ALUNO ID_CURSO NOME_ALUNO NOTA
---------- ---------- ---------- ----------
1 15 Scot 8
2 15 Smith 6,5
3 25 Tiger 3,3
4 25 Sarah 4,7
5 25 Jessie 10
7 30 Roth 9,3
8 30 John 10
9 10 Allen 7,7
10 10 Paul 5,1
9 rows selected.
--COM O USUÁRIO TESTE, TEMOS ACESSO A TODOS OS REGISTROS
--VAMOS CONECTAR COM O USUARIO RESTRITO NO VPD - USUARIO CONSULTA
SQL> conn consulta/consulta
Connected.
SQL> show user;
USER is "CONSULTA"
SQL> set lines 150
SQL> col NOME_ALUNO for a10
SQL> select * from lamim.notas;
ID_ALUNO ID_CURSO NOME_ALUNO NOTA
---------- ---------- ---------- ----------
2 15 Smith 6,5
1 15 Scot 8
5 25 Jessie 10
4 25 Sarah 4,7
3 25 Tiger 3,3
SQL>
-- COM O USUARIO CONSULTA, SAO LITADOS APENAS OS CURSOS DE ID_CURSO 15 E 25.
--MOSTRANDO QUE NOSSA POLITICA FUNCIONOU CONFORME PLANEJADO.
SQL>
Em um próximo post, estarei abordando a criação de uma política a nível de coluna.Fonte:
http://www.dba-oracle.com/t_dbms_rls.htm
https://uhesse.com/2013/06/18/fine-grained-access-control-with-dbms_rls-using-update_checktrue/
https://docs.oracle.com/cd/B28359_01/appdev.111/b28419/d_rls.htm
https://docs.oracle.com/cd/B28359_01/network.111/b28531/vpd.htm

Comentários
Postar um comentário