No Db2 v11.5.7 no Linux eu tenho uma tabela simples:
create table admin.patient_data (
patientid int not null primary key,
patient_name varchar(10),
illness varchar(15),
doctor_name varchar(10)
);
insert into admin.patient_data values (1, 'Alice', 'illness A', 'DOCTOR1');
insert into admin.patient_data values (2, 'Bob', 'illness B', 'DOCTOR2');
select * from admin.patient_data;
Resultado:
PATIENTID PATIENT_NAME ILLNESS DOCTOR_NAME
----------- ------------ --------------- ----------
1 Alice illness A DOCTOR1
2 Bob illness B DOCTOR2
A coluna DOENÇA são dados confidenciais. Gostaria de permitir que esta coluna seja exibida apenas se a coluna DOCTOR_NAME corresponder ao usuário logado do Db2.
create mask admin.patient_data on admin.patient_data
for column illness return
case when doctor_name = USER then illness else 'Masked data' end
enable;
alter table admin.patient_data activate column access control;
Agora o usuário DOCTOR1 se conecta ao banco de dados e verifica os dados com:
select * from admin.patient_data
é devolvido:
PATIENTID PATIENT_NAME ILLNESS DOCTOR_NAME
----------- ------------ --------------- -----------
1 Alice illness A DOCTOR1
2 Bob Masked data DOCTOR2
Espera-se que a linha PATIENTID=2 coluna ILLNESS seja mascarada.
Mas o médico é educado, então ele conhece todas as doenças e agora tem como alvo a "doença B"
db2 "select * from admin.patient_data where illness = 'illness B'"
e fica:
PATIENTID PATIENT_NAME ILLNESS DOCTOR_NAME
----------- ------------ --------------- -----------
2 Bob Masked data DOCTOR2
O campo ILLNESS ainda está marcado como esperado, mas agora por causa de onde o DOCTOR1 condicional sabe que o paciente Bob tem "doença B".
Eu esperava que os usuários finais pudessem filtrar por valores que são retornados com where condition. Ou seja: "doença A" e "dados marcados".
Existe alguma solução simples para evitar isso? Espero não ter nenhum registro retornado para a última instrução select.
Isso está funcionando como projetado™ :
Se você quiser impedir o acesso a linhas específicas, precisará ativar o controle de acesso de linha e definir as permissões de linha necessárias.
O mascaramento é feito bem tarde no processo, antes de retornar os dados ao usuário final, muito depois da condição WHERE ser executada.
Se o requisito é fazer o mascaramento estritamente no nível do banco de dados (e não no nível do aplicativo), como todos os médicos precisam ter acesso a todos os nomes dos pacientes, não vejo outra opção a não ser redesenhar o modelo de ER. Esse tipo de mascaramento da ideia principal de "marketing" a ser aplicado em cima das tabelas existentes.
A primeira opção é usar visualizações em vez de mascaramento de dados e os aplicativos acessam visualizações em vez de tabelas.
A segunda opção é separar dados confidenciais e não confidenciais em tabelas separadas. Como ter "patientid", "patient_name", "doctor_name" na tabela "patient" e separar o relacionamento paciente-doença em uma tabela separada com os campos "patientid" e "illness". Ou ter "patientid", "patient_name", "doctor_name" e novo campo "illnessid" na tabela "patient" e diseaseid and disease na nova tabela de doenças. Em seguida, ao lado do mascaramento de coluna, também use o controle de acesso de linha nessas duas tabelas separadas.