Oracle Data Redaction: como proteger informações confidenciais
Os bancos de dados costumam armazenar dados dos mais diversos tipos, desde informações operacionais até informações sensíveis, como dados pessoais, números de cartão de crédito, dados financeiros ou informações de propriedade intelectual. Desta forma precisamos unir diversos recursos de segurança para evitar que estes dados caiam em mãos erradas, e caso isso ocorra, garantir que esses dados não possam ser utilizados. Além disso, diversas regulamentações, como a Lei Geral de Proteção de Dados (LGPD) e a Payment Card Industry Data Security Standard (PCI DSS) requerem a anonimização de dados. Visando a adequação destas regulamentações e a criação de uma camada adicional na segurança de dados sensíveis, o banco de dados Oracle possui o Oracle Data Redaction.
O que é o Oracle Data Redaction
De maneira direta, o Oracle Data Redaction permite mascarar os dados selecionados, evitando que aplicações e usuários tenham acesso indevido a informações sensíveis.
Esta funcionalidade é aplicada no banco de dados através de políticas, que podem anonimizar os dados de maneira total, parcial, com expressão regular ou randômica, e são aplicadas a aplicações e usuários, dependendo se a expressão na qual a política se baseia é verdadeira ou falsa. Como o Oracle Data Redaction aplica o mascaramento da informação em tempo de execução, isso garante a integridade dos dados no banco.
Aplicando o Oracle Data Redaction
Criando um schema para teste
A fim de demonstrar o uso do Oracle Data Redaction, estaremos criando um usuário teste, e dando a ele as permissões para criação de sessões no banco de dados, criação de tabelas e execução da package DBMS_REDACT:
create user usr1 identified by senha quota 5M on users; grant create session, create table to usr1; grant execute on dbms_redact to usr1;
Conectados no banco de dados com este usuário, criamos a tabela teste Pessoas, que contém dados como nome, número de cartão de crédito, salário e data de nascimento:
CREATE TABLE Pessoas( Id INT PRIMARY KEY, Nome VARCHAR(20), NumeroCartao VARCHAR(19), Salario DECIMAL(10,2), DataNascimento DATE );
Em seguida a populamos com:
INSERT INTO Pessoas(Id, Nome, NumeroCartao, Salario, DataNascimento) VALUES (1, 'Joao Silva', '1234-5678-9012-3456', 2500.00, TO_DATE('1990-01-01', 'YYYY-MM-DD')); INSERT INTO Pessoas(Id, Nome, NumeroCartao, Salario, DataNascimento) VALUES (2, 'Maria Oliveira', '2345-6789-0123-4567', 3500.00, TO_DATE('1991-05-12', 'YYYY-MM-DD')); INSERT INTO Pessoas(Id, Nome, NumeroCartao, Salario, DataNascimento) VALUES (3, 'Pedro Santos', '3456-7890-1234-5678', 4500.00, TO_DATE('1992-08-23', 'YYYY-MM-DD')); INSERT INTO Pessoas(Id, Nome, NumeroCartao, Salario, DataNascimento) VALUES (4, 'Ana Pereira', '4567-8901-2345-6789', 5500.00, TO_DATE('1993-11-03', 'YYYY-MM-DD')); INSERT INTO Pessoas(Id, Nome, NumeroCartao, Salario, DataNascimento) VALUES (5, 'Carlos Souza', '5678-9012-3456-7890', 6500.00, TO_DATE('1994-02-14', 'YYYY-MM-DD'));
Neste momento se rodarmos uma instrução SELECT nesta tabela, temos acesso a todos os dados, conforme demonstrado abaixo:
SQL> select * from Pessoas; ID NOME NUMEROCARTAO SALARIO DATANASCI ---------- -------------------- ------------------- ---------- --------- 1 Joao Silva 1234-5678-9012-3456 2500 01-JAN-90 2 Maria Oliveira 2345-6789-0123-4567 3500 12-MAY-91 3 Pedro Santos 3456-7890-1234-5678 4500 23-AUG-92 4 Ana Pereira 4567-8901-2345-6789 5500 03-NOV-93 5 Carlos Souza 5678-9012-3456-7890 6500 14-FEB-94
Criação de uma redaction policy e aplicação de uma full redaction
Digamos que desejamos criar uma política impedindo que os usuários do banco tenham acesso aos dados de salário desta tabela. Para isso, criamos uma política usando DBMS_REDACT.add_policy:
begin dbms_redact.add_policy( object_name => 'Pessoas', column_name => 'Salario', policy_name => 'Politica Clientes', function_type => dbms_redact.full, expression => '1=1' ); end; /
Onde:
- object_name: o nome da tabela ou view à qual a política se aplica;
- column_name: a coluna à qual a política se aplica;
- policy_name: o nome da política a ser criada;
- function_type: o tipo da redaction aplicada, neste caso FULL;
- expression: qual condição deve ser satisfeita a fim de que a política se aplique. Neste caso, como 1=1 sempre retornará verdadeiro, estaremos aplicando a política para todos os usuários.
Agora, ao executar o mesmo SELECT na tabela, temos o seguinte resultado:
SQL> select * from Pessoas; ID NOME NUMEROCARTAO SALARIO DATANASCI ---------- -------------------- ------------------- ---------- --------- 1 Joao Silva 1234-5678-9012-3456 0 01-JAN-90 2 Maria Oliveira 2345-6789-0123-4567 0 12-MAY-91 3 Pedro Santos 3456-7890-1234-5678 0 23-AUG-92 4 Ana Pereira 4567-8901-2345-6789 0 03-NOV-93 5 Carlos Souza 5678-9012-3456-7890 0 14-FEB-94
Podemos notar que a política anonimizou os dados da coluna salário, substituindo todos os valores por 0, devido à aplicação da redaction full.
Alteração de uma política e aplicação de uma random redaction
Podemos também alterar essa política, aplicando uma random redaction à coluna DataNascimento, usando DBMS_REDACT.alter_policy:
begin dbms_redact.alter_policy( object_name => 'Pessoas', action => dbms_redact.add_column, column_name => 'DataNascimento', policy_name => 'Politica Clientes', function_type => dbms_redact.random ); end; /
Para que a alteração ocorra, precisamos especificar o objeto e a política que está sendo alterada, bem como informar a ação que está sendo executada. Neste caso, usamos DBMS_REDACT.add_column para adicionar a coluna DataNascimento à política, definida no parâmetro column_name.
Após modificada a política, podemos executar duas vezes o SELECT para verificar o novo comportamento dos dados da coluna alterada:
SQL> select * from Pessoas; ID NOME NUMEROCARTAO SALARIO DATANASCI ---------- -------------------- ------------------- ---------- --------- 1 Joao Silva 1234-5678-9012-3456 0 17-NOV-18 2 Maria Oliveira 2345-6789-0123-4567 0 01-SEP-05 3 Pedro Santos 3456-7890-1234-5678 0 03-JAN-65 4 Ana Pereira 4567-8901-2345-6789 0 01-OCT-12 5 Carlos Souza 5678-9012-3456-7890 0 01-NOV-24 SQL> select * from Pessoas; ID NOME NUMEROCARTAO SALARIO DATANASCI ---------- -------------------- ------------------- ---------- --------- 1 Joao Silva 1234-5678-9012-3456 0 03-JUN-76 2 Maria Oliveira 2345-6789-0123-4567 0 01-OCT-66 3 Pedro Santos 3456-7890-1234-5678 0 12-JUN-49 4 Ana Pereira 4567-8901-2345-6789 0 18-JAN-48 5 Carlos Souza 5678-9012-3456-7890 0 14-APR-03
Podemos notar que, toda vez que executamos uma consulta nesta tabela, a coluna DataNascimento recebe uma data aleatória.
Aplicação de uma partial redaction
Dentro desta tabela teste, ainda temos os dados de número de cartão de crédito. Podemos anonimizá-los de uma forma que sejam mostrados apenas os últimos quatro dígitos, como a maioria dos sites nos mostra quando fazemos compras online. Para isso podemos alterar a política, a fim de aplicar uma partial redaction aos dados:
begin dbms_redact.alter_policy( object_name => 'Pessoas', action => dbms_redact.add_column, column_name => 'NumeroCartao', policy_name => 'Politica Clientes', function_type => dbms_redact.partial, function_parameters => 'vvvvfvvvvfvvvvfvvvv,vvvv-vvvv-vvvv-vvvv,#,1,12' ); end; /
Neste exemplo, estamos passando parâmetros separados por vírgula para a partial redact, através do function_parameters, onde:
- vvvvfvvvvfvvvvfvvvv: é o formato que os dados se encontram na tabela. Usamos “v” para os caracteres que a política aplicará o mascaramento e “f” para os que queremos formatar com caracteres da nossa escolha, como hífens e asteríscos;
- vvvv-vvvv-vvvv-vvvv: é o formato de saída. Mantemos “v” para os caracteres que serão mascarados e substituímos os “f” pelo caracter que desejamos utilizar na saída, neste caso, o hífen;
- #: o caracter de mascaramento, que substituirá os “v”;
- 1: especifica o “v” inicial para o mascaramento;
- 12: especifica o “v” final para o mascaramento.
Agora, fazendo uma consulta na tabela, temos:
SQL> select * from Pessoas; ID NOME NUMEROCARTAO SALARIO DATANASCI ---------- -------------------- ------------------- ---------- --------- 1 Joao Silva ####-####-####-3456 0 02-APR-04 2 Maria Oliveira ####-####-####-4567 0 19-JUL-94 3 Pedro Santos ####-####-####-5678 0 23-APR-23 4 Ana Pereira ####-####-####-6789 0 23-SEP-89 5 Carlos Souza ####-####-####-7890 0 18-FEB-86
Restrição de acesso a colunas por usuário
O Oracle Data Redaction ainda nos possibilita criar expressões e aplicá-las a colunas específicas da política. Suponhamos que desejamos que a coluna de salário seja visível apenas pelo usuário do setor de recursos humanos, o usuário HR em nosso banco de dados.
Para isso, criamos uma expressão nomeada:
begin dbms_redact.create_policy_expression( policy_expression_name => 'politica_HR_salario', expression => 'SYS_CONTEXT(''USERENV'',''SESSION_USER'') != ''HR''', policy_expression_description => 'Habilita a politica para todos os usuários, exceto HR'); end; /
Neste caso o parâmetro policy_expression_name recebe o nome da expressão, e o parâmetro expression recebe a expressão. Lembre que quando a expressão for verdadeira, será aplicado o mascaramento aos dados.
Em seguida, aplicamos a expressão criada à coluna desejada:
begin dbms_redact.apply_policy_expr_to_col( object_name => 'Pessoas', column_name => 'Salario', policy_expression_name => 'politica_HR_salario'); end; /
Para a aplicação, basta que o objeto e a coluna à qual desejamos aplicar a mesma sejam informados.
Neste momento, como estamos conectados com o nosso usuario USR1 criado previamente, podemos executar um SELECT e verificarmos que, para este usuário, não existe nenhuma mudança na forma que os dados estão sendo mostrados:
SQL> select * from pessoas; ID NOME NUMEROCARTAO SALARIO DATANASCI ---------- -------------------- ------------------- ---------- --------- 1 Joao Silva ####-####-####-3456 0 01-DEC-08 2 Maria Oliveira ####-####-####-4567 0 04-SEP-96 3 Pedro Santos ####-####-####-5678 0 12-JUL-37 4 Ana Pereira ####-####-####-6789 0 04-APR-34 5 Carlos Souza ####-####-####-7890 0 06-MAR-13
Por fim damos o privilégio de SELECT na tabela para o usuário HR e realizamos o teste:
SQL> grant select on pessoas to hr; Grant succeeded. SQL> conn hr/hr@pdb1; SQL> select * from usr1.pessoas; ID NOME NUMEROCARTAO SALARIO DATANASCI ---------- -------------------- ------------------- ---------- --------- 1 Joao Silva ####-####-####-3456 2500 09-MAR-75 2 Maria Oliveira ####-####-####-4567 3500 10-MAY-05 3 Pedro Santos ####-####-####-5678 4500 22-NOV-81 4 Ana Pereira ####-####-####-6789 5500 01-NOV-93 5 Carlos Souza ####-####-####-7890 6500 24-AUG-51
Podemos notar que agora o nosso usuário HR consegue ver os dados sem mascaramento, devido à regra aplicada.
Conclusão
Neste artigo procurei demonstrar, em um ambiente teste, a aplicação do Oracle Data Redaction, uma das várias features de segurança do banco de dados Oracle. É importante lembrar que esta feature sozinha não garante a proteção dos dados como um todo, e precisa ser aliada a outras features para que se alcance um alto nível de segurança.
Um grande abraço a todos!
Publicar comentário