Banco de dados
Isolamento multi-tenant com RLS em PostgreSQL — o que quebra em testes e por quê
Papel em tabela separada, função security definer e uma suíte que tenta vazar dado entre tenants de propósito.
Row Level Security move o isolamento para onde ele resiste a erro de aplicação. Um filtro esquecido em uma consulta não vaza dado se a política do banco não deixar. Isso só vale se as políticas forem escritas com cuidado, e há dois erros que aparecem quase sempre.
Erro 1: papel guardado na tabela de perfil
Se o papel do usuário está em uma coluna da tabela que o próprio usuário pode atualizar, o sistema tem escalonamento de privilégio por design. Papel vive em tabela própria, com chave única por usuário e papel, sem política de escrita para o usuário comum.
Erro 2: política que consulta a própria tabela
Uma política que precisa ler outra tabela protegida por RLS entra em recursão ou avalia com o contexto errado. A saída é uma função security definer, estável, com search_path fixo, que faz a checagem fora do alcance da política.
create or replace function public.tem_papel(_user_id uuid, _papel app_role)
returns boolean
language sql
stable
security definer
set search_path = public
as $$
select exists (
select 1 from public.user_roles
where user_id = _user_id and role = _papel
)
$$;A suíte que precisa existir
Teste de RLS que só verifica o caminho feliz não prova nada. O teste útil autentica como o tenant A e tenta ler, escrever, atualizar e apagar linha do tenant B, em cada tabela, por cada papel. Ele falha o build quando qualquer uma dessas operações retorna linha ou sucesso.
- Leitura cruzada direta em cada tabela.
- Leitura cruzada por junção — o vazamento costuma aparecer aqui, não na consulta simples.
- Escrita com id de outro tenant no corpo da requisição.
- Consulta agregada: count e sum vazam existência mesmo sem devolver linha.
- Acesso por função e por view, que podem carregar security definer sem que ninguém tenha pensado nisso.
Também vale conferir os GRANTs. RLS sem GRANT bloqueia legítimo; GRANT sem RLS libera tudo. Os dois precisam estar na mesma migração, na mesma revisão.
Próximo passo
Vale ocupar uma hora da sua agenda?
Se o problema é visão computacional, dado ou decisão automatizada que precisa sustentar auditoria, a conversa começa direto comigo. Sem camada intermediária.