Aprenda a conceder acesso seguro e temporário para DBA terceirizado no PostgreSQL. Guia completo com pgaudit, privilégios granulares, expiração automática, masking de dados sensíveis e scripts de automação. Proteja seu banco sem sacrificar a produtividade do consultor.
Contratar um DBA terceirizado para otimizar, auditar ou solucionar problemas do seu PostgreSQL é uma prática cada vez mais comum. Mas entregar as chaves do castelo sem controle é receita para desastre. Já vi empresas simplesmente compartilharem a senha do superusuáriopostgres por Slack. Isso é inaceitável em qualquer ambiente que se preze — seja produção, staging ou até desenvolvimento com dados sensíveis.
Neste guia, vou mostrar como conceder acesso temporário, auditável e com privilégios mínimos necessários para um DBA externo trabalhar com segurança no seu PostgreSQL.
Por que a abordagem ingênua é perigosa
O cenário típico: alguém cria um usuário assim:CREATE USER dba_consultor WITH PASSWORD 'senha123' SUPERUSER;
Isso entrega ao consultor:
- Acesso irrestrito a todos os bancos e schemas
- Capacidade de criar, alterar e excluir qualquer objeto
- Leitura de dados potencialmente sensíveis (PII, financeiros)
- Possibilidade de alterar configurações do servidor
- Zero rastreabilidade se algo der errado
Princípios para acesso seguro de terceiros
Antes de partir para a implementação, estabeleça estes princípios:- Privilégio mínimo: O DBA acessa apenas o que precisa, nada mais
- Temporalidade: O acesso expira automaticamente após um período definido
- Auditabilidade: Toda ação fica registrada e atrelada ao usuário do consultor
- Revogabilidade: É possível remover o acesso instantaneamente, sem efeitos colaterais
- Segregação: Dados sensíveis podem ser mascarados ou omitidos
Passo 1: Crie um role específico para o DBA
Nunca use roles existentes. Crie uma dedicada:CREATE ROLE dba_externo WITH LOGIN PASSWORD 'senha_temporaria_segura' VALID UNTIL '2025-12-31 23:59:59' CONNECTION LIMIT 3;
Explicação de cada cláusula:
LOGIN: Permite que o role se conecte ao bancoPASSWORD: Defina uma senha forte. Use um gerador comoopenssl rand -base64 32VALID UNTIL: O acesso expira automaticamente nesta data. Sem lembretes humanos, sem esquecimentosCONNECTION LIMIT: Limita conexões simultâneas, evitando abusos acidentais ou intencionais
Passo 2: Conceda apenas os privilégios necessários
O que um DBA terceirizado normalmente precisa fazer:- Ler estatísticas e métricas do servidor
- Visualizar consultas em execução (
pg_stat_activity) - Analisar planos de execução (
EXPLAIN) - Acessar logs e eventos do sistema
- Eventualmente, criar índices ou alterar parâmetros de configuração
-- Acesso às views de estatísticas do sistema GRANT pg_read_server_files TO dba_externo; GRANT pg_read_all_stats TO dba_externo; -- Acesso ao banco específico que será analisado GRANT CONNECT ON DATABASE meu_banco TO dba_externo; -- Acesso de leitura nas tabelas (schema por schema) GRANT USAGE ON SCHEMA public TO dba_externo; GRANT SELECT ON ALL TABLES IN SCHEMA public TO dba_externo; -- Se precisar criar índices para otimização GRANT CREATE ON SCHEMA public TO dba_externo; -- Se precisar rodar EXPLAIN (já coberto pelo SELECT, mas seja explícito) -- EXPLAIN não requer privilégios especiais além de SELECT na tabela analisada
Para garantir que novas tabelas também sejam acessíveis, configure permissões padrão:
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO dba_externo;
Passo 3: Configure auditoria com pgaudit
O PostgreSQL não registra comandos por padrão. Instale a extensão pgaudit:
CREATE EXTENSION pgaudit;
Configure o postgresql.conf:
shared_preload_libraries = 'pgaudit' pgaudit.log = 'ddl, role, write' pgaudit.log_level = 'notice' pgaudit.log_catalog = off
Para auditar ações de um usuário específico (disponível a partir do PostgreSQL 16):
-- Apenas para o DBA externo, registre todas as sessões ALTER ROLE dba_externo SET pgaudit.log = 'all'; ALTER ROLE dba_externo SET pgaudit.log_level = 'notice';
Em versões anteriores, você pode auditar por role usando pgaudit.log = 'role' e configurando a classe de auditoria adequada.
Os logs vão para o log do PostgreSQL (stderr, syslog ou csvlog, dependendo da sua configuração). Centralize-os com ferramentas como pgbadger para análise posterior.
Passo 4: Mascare dados sensíveis
Se o DBA não precisa ver dados reais, mas apenas estruturas e estatísticas, use anonymization ou masking:-- Crie uma view que mascara emails CREATE VIEW public.usuarios_mascarados AS SELECT id, overlay(email placing '***' from 3 for length(email) - 4) AS email, nome FROM public.usuarios; -- Conceda acesso apenas à view mascarada GRANT SELECT ON public.usuarios_mascarados TO dba_externo; REVOKE SELECT ON public.usuarios FROM dba_externo;
Para casos mais complexos, considere extensões como pg_anonymize ou postgresql_anonymizer.
Passo 5: Estabeleça um túnel seguro
Nunca exponha o PostgreSQL diretamente na internet. Use:- VPN: WireGuard ou OpenVPN. O DBA se conecta à sua rede privada primeiro
- SSH Tunnel: Simples e eficaz. O DBA recebe acesso a um usuário SSH limitado que só faz port forwarding
- Bastion Host: Uma instância intermediária com IP allowlist e autenticação reforçada
pg_hba.conf para permitir apenas conexões locais ou via rede privada:
# Permitir conexão local host meu_banco dba_externo 127.0.0.1/32 scram-sha-256 # Permitir via VPN (ajuste o CIDR para sua rede) host meu_banco dba_externo 10.0.0.0/8 scram-sha-256
Combine com ssl = on no postgresql.conf para criptografar a conexão.
Passo 6: Automatize o ciclo de vida do acesso
Como Senior Engineer, você não quer fazer isso manualmente toda vez. Automatize com um script ou migration:// grant-dba-access.js — rode como parte da sua pipeline de segurança const { Client } = require('pg'); const crypto = require('crypto'); async function grantDbaAccess({ dbName, dbaUser, validUntil, // '2025-12-31 23:59:59' allowedSchemas = ['public'], connectLimit = 3, }) { const client = new Client({ database: dbName }); await client.connect(); const password = crypto.randomBytes(32).toString('base64'); await client.query(` CREATE ROLE ${dbaUser} WITH LOGIN PASSWORD '${password}' VALID UNTIL '${validUntil}' CONNECTION LIMIT ${connectLimit}; `); await client.query(`GRANT pg_read_all_stats TO ${dbaUser};`); await client.query(`GRANT CONNECT ON DATABASE ${dbName} TO ${dbaUser};`); for (const schema of allowedSchemas) { await client.query(`GRANT USAGE ON SCHEMA ${schema} TO ${dbaUser};`); await client.query(`GRANT SELECT ON ALL TABLES IN SCHEMA ${schema} TO ${dbaUser};`); await client.query(` ALTER DEFAULT PRIVILEGES IN SCHEMA ${schema} GRANT SELECT ON TABLES TO ${dbaUser}; `); } // Configurar auditoria await client.query(`ALTER ROLE ${dbaUser} SET pgaudit.log = 'all';`); await client.end(); // Retorne a senha de forma segura (ex: encriptada, ou via cofre) return { user: dbaUser, password, validUntil }; } module.exports = { grantDbaAccess };
E o script de revogação, igualmente importante:
// revoke-dba-access.js async function revokeDbaAccess({ dbName, dbaUser }) { const client = new Client({ database: dbName }); await client.connect(); // Revoga todos os privilégios await client.query(`REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA public FROM ${dbaUser};`); await client.query(`REVOKE ALL PRIVILEGES ON SCHEMA public FROM ${dbaUser};`); await client.query(`REVOKE ALL PRIVILEGES ON DATABASE ${dbName} FROM ${dbaUser};`); await client.query(`REVOKE pg_read_all_stats FROM ${dbaUser};`); // Força desconexão de sessões ativas await client.query(` SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE usename = '${dbaUser}'; `); // Remove o role await client.query(`DROP ROLE IF EXISTS ${dbaUser};`); await client.end(); console.log(`Acesso de ${dbaUser} revogado com sucesso.`); }
Checklist final antes de liberar o acesso
Antes de enviar as credenciais para o DBA terceirizado, confirme:- ✅ O role tem
VALID UNTILdefinido para uma data razoável - ✅ A senha foi gerada aleatoriamente e não é compartilhada em texto plano
- ✅ Os grants são mínimos: sem
SUPERUSER, semCREATEDB, sem acesso a schemas irrelevantes - ✅
pgauditestá ativo e configurado para o role - ✅ Dados sensíveis estão mascarados ou inacessíveis
- ✅ A conexão é via túnel seguro (VPN/SSH) e
pg_hba.confestá restritivo - ✅ Você tem um script de revogação pronto para execução imediata
- ✅ O
CONNECTION LIMITestá definido para evitar abusos
O que fazer se algo der errado
Se suspeitar de uso indevido, aja imediatamente:-- 1. Congele o acesso (não remove o role, mas impede novas conexões) ALTER ROLE dba_externo WITH NOLOGIN; -- 2. Mate todas as sessões ativas SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE usename = 'dba_externo'; -- 3. Revogue tudo e drope o role quando seguro -- (use o script de revogação acima)
Conclusão
Conceder acesso a um DBA terceirizado não precisa ser um pulo no escuro. Com roles dedicados, privilégios granulares, expiração automática, auditoria viapgaudit e automação do ciclo de vida, você mantém o controle total enquanto permite que o consultor faça o trabalho dele.
Como DBA e Engineer, seu papel é garantir que a segurança nunca seja sacrificada em nome da conveniência. Essas práticas não são exagero — são o padrão mínimo para qualquer ambiente que lida com dados de produção.
Implemente isso antes de contratar o próximo consultor. Seu futuro eu — e seu compliance officer — vão agradecer.
Continue aprendendo
3 Técnicas para Reduzir Consumo de Tokens no Claude Code e Codex
