- Anderson Graf
Oracle Virtual Private Database – VPD
O Virtual Private Database, mais conhecido como VPD, é um recurso do Oracle Database Enterprise Edition (EE) existente desde a versão 8i que permite criar políticas de segurança sobre objetos, sejam eles tabelas, views ou sinônimos.
O VPD é usado quando os privilégios de objeto padrão e funções de banco de dados associados são insuficientes para atender às exigências de segurança do aplicativo, deste modo, políticas personalizadas podem limitar o acesso a informações restritas.
Como as políticas de segurança estão associadas a um objeto (tabela, view ou sinônimo), sempre que ocorrer o acesso ao objeto elas são automaticamente acionadas independente da fonte (por meio de um aplicativo, uma interface Web ou SQL * Plus) proporcionando sempre o mesmo resultado e impedindo a violação da segurança.
Ao acessar o objeto protegido com o Oracle Virtual Private Database policy, o Oracle dinamicamente modifica o comando SQL do usuário. A modificação cria a condição WHERE (caso não exista na SQL) e retorna a função de segurança implementada de forma totalmente transparente para o usuário.
Podemos aplicar com o VPD políticas de segurança sobre sentenças como SELECT, INSERT, UPDATE, INDEX e DELETE.
Neste artigo será demonstrado a criação de uma VPD simples a nível de linha (Row Level Security), ou seja, limitando usuários apenas a não poderem visualizar determinados registros em um tabela.
Criando e populando uma tabela FUNCIONARIO onde posteriormente será aplicado a política de segurança.
Criando a tabela DENY_ACCESS_FUN onde será cadastrado os usuários que serão afetados(limitados) pela policy.
Criando a tabela BLOCKED_ACCESS_FUN onde será cadastrado o nome dos registros da tabela FUNCIONARIO que não podem ser visualizados pelos usuários cadastrados na tabela DENY_ACCESS_FUN.
Criando a FUNÇÃO que será chamada pela policy e que irá retornar a condição (PREDICATE) para a cláusula WHERE, ou seja, quando um usuário cadastrado na tabela DENY_ACCESS_FUN realizar um select na tabela FUNCIONARIO a policy vai atribuir na condição WHERE a linha abaixo:
nome not in (select nome from blocked_access_fun);
Se o usuário não está cadastrado na DENY_ACCESS_FUN ela retorna: 1=1 o que não afetará qualquer registro.
Observe que na FUNCTION utiliza a SYS_CONTEXT para coletar informações da sessão, no caso o usuário conectado (SESSION_USER).
Ajustando permissões:
Criando a policy:
Na statement_types foi colocado apenas SELECT, desta forma a policy só é executada quando feito um select na tabela FUNCIONARIO.
Criando 2 usuários para testes:
Conectando com os usuários criados todos os registros ainda são acessíveis pois nada foi cadastrado nas tabelas DENY_ACCESS_FUN e BLOCKED_ACCESS_FUN:
Em outra sessão (com permissão de insert nas tabelas de controle), será bloqueado o usuário TESTE1 para não visualizar os registros do funcionário FUNC3:
Observe acima que o FUNC3 já não foi mais retornado para o usuário TESTE1 enquanto para o usuário TESTE2 ainda é apresentado:
Cadastrando mais uma linha(nome) da tabela FUNCIONARIO que não deve ser visualiza pelo usuário TESTE1:
Agora cadastrando também o usuário TESTE2 na tabela DENY_ACCESS_FUN que passa a não conseguir ver os outros registros.
Como falado no inicio do artigo este foi apenas um exemplo simples de implementação com VPD limitando o SELECT a determinados USUÁRIOS X REGISTROS.
A VPD pode ser implementada de muitas outras formas e pode ser muito mais abrangente e complexa. Vários materiais sobre o tema estão disponíveis também no Oracle Help Center (Docs)