Pular para o conteúdo

DBMS_RLS: Implementação de políticas de segurança em nível de linha

DBMS_RLS: Implementação de políticas de segurança em nível de linha

O DBMS_RLS é um pacote fornecido pelo Oracle que permite implementar políticas de segurança em nível de linha, ou seja, restringir o acesso aos dados de uma tabela ou de uma view de acordo com critérios definidos pelo administrador do banco de dados. Essas políticas são aplicadas de forma transparente para os usuários, sem a necessidade de modificar as consultas ou as aplicações que acessam os dados.

As políticas de segurança em nível de linha são baseadas em funções que retornam predicados que são adicionados às cláusulas WHERE das consultas que acessam os objetos protegidos. Esses predicados podem variar de acordo com o usuário, o contexto da sessão, o tipo de operação (SELECT, INSERT, UPDATE ou DELETE) ou outros fatores. Por exemplo, uma política de segurança pode permitir que um usuário veja apenas os registros de uma tabela que pertencem ao seu departamento, ou que um gerente possa atualizar apenas os dados dos seus subordinados.

Para criar uma política de segurança em nível de linha, é necessário seguir os seguintes passos:

  1. Criar uma função que retorne o predicado a ser aplicado à consulta. Essa função deve receber como parâmetros o nome do esquema, o nome do objeto, e o tipo de operação. A função deve ser criada no mesmo esquema do objeto protegido, ou em um esquema com privilégios suficientes para acessar o objeto.
  2. Criar uma política de segurança usando a função DBMS_RLS.ADD_POLICY, que recebe como parâmetros o nome do esquema, o nome do objeto, o nome da política, a função que retorna o predicado, e outros parâmetros opcionais, como o tipo de operação, o contexto da sessão, ou a expressão de filtragem.
  3. Testar a política de segurança usando consultas ou aplicações que acessam o objeto protegido, e verificar se os resultados estão de acordo com os critérios definidos pela política.

A seguir, apresentamos um exemplo prático de como implementar uma política de segurança em nível de linha em uma tabela de funcionários, usando o Oracle 19c.

Primeiro, criamos uma tabela de funcionários com os seguintes campos: id, nome, cargo, salário e departamento.

CREATE TABLE funcionarios (
  id NUMBER PRIMARY KEY,
  nome VARCHAR2(50) NOT NULL,
  cargo VARCHAR2(50) NOT NULL,
  salario NUMBER NOT NULL,
  departamento VARCHAR2(50) NOT NULL
);

Em seguida, inserimos alguns registros na tabela, representando funcionários de diferentes departamentos e cargos.

INSERT INTO funcionarios VALUES (1, 'Alice', 'Analista', 5000, 'TI');
INSERT INTO funcionarios VALUES (2, 'Bruno', 'Gerente', 8000, 'TI');
INSERT INTO funcionarios VALUES (3, 'Carlos', 'Desenvolvedor', 4000, 'TI');
INSERT INTO funcionarios VALUES (4, 'Daniela', 'Analista', 4500, 'RH');
INSERT INTO funcionarios VALUES (5, 'Eduardo', 'Gerente', 7000, 'RH');
INSERT INTO funcionarios VALUES (6, 'Fabiana', 'Recrutadora', 3500, 'RH');
INSERT INTO funcionarios VALUES (7, 'Gabriel', 'Analista', 5500, 'Financeiro');
INSERT INTO funcionarios VALUES (8, 'Helena', 'Gerente', 9000, 'Financeiro');
INSERT INTO funcionarios VALUES (9, 'Igor', 'Contador', 6000, 'Financeiro');

Agora, criamos uma função que retorna o predicado a ser aplicado à consulta, de acordo com o departamento do usuário. Para simplificar, vamos assumir que o departamento do usuário é armazenado em uma variável de ambiente chamada DEPT_USER.

CREATE OR REPLACE FUNCTION f_predicado (
  p_schema VARCHAR2,
  p_object VARCHAR2,
  p_operation VARCHAR2
) RETURN VARCHAR2
IS
  v_predicado VARCHAR2(100);
BEGIN
  -- Retorna o predicado que filtra os registros pelo departamento do usuário
  v_predicado := 'departamento = ''' || SYS_CONTEXT('USERENV', 'DEPT_USER') || '''';
  RETURN v_predicado;
END;
/

A função f_predicado é o elemento central da política de segurança em nível de linha, pois é ela que define o critério de filtragem dos dados. A função recebe três parâmetros: p_schema, p_object e p_operation, que representam, respectivamente, o nome do esquema, o nome do objeto e o tipo de operação que está sendo realizada sobre o objeto. Esses parâmetros são passados automaticamente pela função DBMS_RLS.ADD_POLICY quando a política é ativada.

A função deve retornar uma string que contém o predicado a ser adicionado à cláusula WHERE da consulta. O predicado deve ser uma expressão válida em SQL, que pode usar qualquer coluna do objeto protegido, qualquer função ou pacote do Oracle, ou qualquer contexto de sessão definido pelo usuário ou pelo sistema. O predicado deve ser escrito entre aspas simples, e qualquer valor que também esteja entre aspas simples deve ser duplicado, para evitar erros de sintaxe.

No nosso exemplo, a função f_predicado retorna um predicado simples, que compara a coluna departamento com o valor da variável de ambiente DEPT_USER, que armazena o departamento do usuário. Assim, o predicado é algo como departamento = 'TI' ou departamento = 'RH', dependendo do usuário que está acessando os dados.

Em seguida, criamos uma política de segurança usando a função DBMS_RLS.ADD_POLICY, especificando o nome do esquema, o nome do objeto, o nome da política, a função que retorna o predicado, e o tipo de operação (no nosso caso, vamos aplicar a política para todas as operações).

BEGIN
  DBMS_RLS.ADD_POLICY (
    object_schema => 'HR',
    object_name => 'funcionarios',
    policy_name => 'pol_funcionarios',
    function_schema => 'HR',
    policy_function => 'f_predicado',
    statement_types => 'SELECT, INSERT, UPDATE, DELETE'
  );
END;
/

A função DBMS_RLS.ADD_POLICY é a responsável por criar e ativar a política de segurança em nível de linha. Ela recebe vários parâmetros, dos quais os principais são:

  • object_schema: o nome do esquema onde o objeto protegido está localizado. No nosso exemplo, é ‘HR’.
  • object_name: o nome do objeto protegido, que pode ser uma tabela ou uma view. No nosso exemplo, é ‘funcionarios’.
  • policy_name: o nome da política de segurança, que deve ser único dentro do esquema e do objeto. No nosso exemplo, é ‘pol_funcionarios’.
  • function_schema: o nome do esquema onde a função que retorna o predicado está localizada. No nosso exemplo, é ‘HR’.
  • policy_function: o nome da função que retorna o predicado. No nosso exemplo, é ‘f_predicado’.
  • statement_types: os tipos de operação que a política deve ser aplicada, separados por vírgula. Os valores possíveis são: SELECT, INSERT, UPDATE, DELETE, ou ALL. No nosso exemplo, usamos todos os tipos de operação.

Além desses parâmetros, a função DBMS_RLS.ADD_POLICY possui outros parâmetros opcionais, que permitem configurar aspectos adicionais da política, como o contexto da sessão, a expressão de filtragem, o tipo de junção, a coluna de chave primária, ou o modo de atualização. Para mais detalhes sobre esses parâmetros, consulte a documentação do Oracle.

Por fim, testamos a política de segurança usando consultas que acessam a tabela de funcionários, e verificamos se os resultados estão de acordo com os critérios definidos pela política. Para isso, vamos usar dois usuários diferentes, um do departamento de TI e outro do departamento de RH.

-- Conecta como o usuário do departamento de TI
CONNECT ti_user/ti_user

-- Define o departamento do usuário como TI
EXECUTE DBMS_SESSION.SET_IDENTIFIER('TI')

-- Consulta a tabela de funcionarios
SELECT * FROM hr.funcionarios;

-- Resultado: apenas os registros do departamento de TI são retornados
ID NOME    CARGO          SALARIO DEPARTAMENTO
-- ------- -------------- ------- ------------
 1 Alice   Analista        5000    TI
 2 Bruno   Gerente         8000    TI
 3 Carlos  Desenvolvedor   4000    TI

-- Conecta como o usuário do departamento de RH
CONNECT rh_user/rh_user

-- Define o departamento do usuário como RH
EXECUTE DBMS_SESSION.SET_IDENTIFIER('RH')

-- Consulta a tabela de funcionarios
SELECT * FROM hr.funcionarios;

-- Resultado: apenas os registros do departamento de RH são retornados
ID NOME    CARGO       SALARIO DEPARTAMENTO
-- ------- ----------- ------- ------------
 4 Daniela Analista     4500    RH
 5 Eduardo Gerente      7000    RH
 6 Fabiana Recrutadora  3500    RH

Como podemos ver, a política de segurança em nível de linha foi aplicada com sucesso, restringindo o acesso aos dados de acordo com o departamento do usuário.

Neste artigo, vimos como usar o pacote DBMS_RLS para implementar políticas de segurança em nível de linha, que permitem controlar o acesso aos dados de uma tabela ou de uma view de forma transparente e flexível. Vimos também como criar uma função que retorna o predicado a ser aplicado à consulta, e como criar uma política de segurança usando a função DBMS_RLS.ADD_POLICY. Por fim, vimos um exemplo prático de como aplicar uma política de segurança em nível de linha em uma tabela de funcionários, usando o Oracle 19c.

Abs

Referências:

Giovano Silva

Giovano Silva

Giovano Silva é um profissional com mais de 10 anos de experiência em tecnologias Oracle, com ênfase em PL/SQL. Ele adora escrever sobre soluções para problemas comuns enfrentados por profissionais Oracle em seu dia a dia. Seu objetivo é compartilhar conhecimento, simplificar conceitos complexos e ajudar a comunidade Oracle a crescer coletivamente.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

plugins premium WordPress