Backup e Segurança
Avançado • 90 minutos • Proteção de dados
Aprenda as melhores práticas para proteger seus dados com backup, segurança e controle de acesso no Supabase.
Objetivos de Aprendizagem
- Implementar estratégias de backup eficazes
- Configurar Row Level Security (RLS)
- Gerenciar usuários e permissões
- Monitorar e auditar o banco de dados
- Aplicar boas práticas de segurança
Estratégias de Backup
O backup é fundamental para proteger seus dados contra perda, corrupção ou ataques. O Supabase oferece várias opções de backup automático e manual.
🛡️ Tipos de Backup
• Backup Automático: Realizado pelo Supabase diariamente
• Backup Manual: Criado sob demanda pelo usuário
• Point-in-Time Recovery: Restauração para momento específico
• Export de Dados: Exportação de tabelas específicas
Backup Automático no Supabase
📋 Configuração Automática
- • Backups diários automáticos (planos pagos)
- • Retenção de 7 dias (Pro) ou 30 dias (Team/Enterprise)
- • Point-in-Time Recovery até 7 dias
- • Backup incremental para otimização
Backup Manual com pg_dump
# Backup completo do banco
pg_dump "postgresql://postgres:[PASSWORD]@[HOST]:5432/postgres" > backup_completo.sql
# Backup apenas da estrutura
pg_dump --schema-only "postgresql://postgres:[PASSWORD]@[HOST]:5432/postgres" > estrutura.sql
# Backup apenas dos dados
pg_dump --data-only "postgresql://postgres:[PASSWORD]@[HOST]:5432/postgres" > dados.sql
# Backup de tabelas específicas
pg_dump --table=produtos --table=clientes "postgresql://postgres:[PASSWORD]@[HOST]:5432/postgres" > backup_parcial.sql
# Backup comprimido
pg_dump "postgresql://postgres:[PASSWORD]@[HOST]:5432/postgres" | gzip > backup.sql.gz
Restauração de Backup
# Restaurar backup completo
psql "postgresql://postgres:[PASSWORD]@[HOST]:5432/postgres" < backup_completo.sql
# Restaurar backup comprimido
gunzip -c backup.sql.gz | psql "postgresql://postgres:[PASSWORD]@[HOST]:5432/postgres"
# Restaurar apenas estrutura
psql "postgresql://postgres:[PASSWORD]@[HOST]:5432/postgres" < estrutura.sql
Importante:
Sempre teste seus backups em um ambiente separado antes de precisar usá-los em produção. Um backup não testado pode não funcionar quando necessário.
Row Level Security (RLS)
O RLS permite controlar quais linhas de uma tabela cada usuário pode ver ou modificar, oferecendo segurança granular ao nível de registro.
🔒 Benefícios do RLS
• Segurança Granular: Controle por linha de dados
• Multi-tenancy: Isolamento de dados por cliente
• Privacidade: Usuários veem apenas seus dados
• Compliance: Atende regulamentações como LGPD
Habilitando RLS
-- Habilitar RLS em uma tabela
ALTER TABLE produtos ENABLE ROW LEVEL SECURITY;
-- Verificar status do RLS
SELECT tablename, rowsecurity
FROM pg_tables
WHERE schemaname = 'public';
Políticas de Segurança
-- Política para usuários verem apenas seus próprios dados
CREATE POLICY "Usuários veem apenas seus dados" ON produtos
FOR ALL USING (auth.uid() = user_id);
-- Política para administradores verem tudo
CREATE POLICY "Admins veem tudo" ON produtos
FOR ALL USING (auth.jwt() ->> 'role' = 'admin');
-- Política para leitura pública
CREATE POLICY "Leitura pública" ON produtos
FOR SELECT USING (publico = true);
-- Política para inserção apenas de dados próprios
CREATE POLICY "Inserir apenas próprios dados" ON produtos
FOR INSERT WITH CHECK (auth.uid() = user_id);
-- Política para atualização apenas de dados próprios
CREATE POLICY "Atualizar apenas próprios dados" ON produtos
FOR UPDATE USING (auth.uid() = user_id)
WITH CHECK (auth.uid() = user_id);
Exemplo Prático: Sistema Multi-tenant
-- Tabela com tenant_id
CREATE TABLE vendas (
id SERIAL PRIMARY KEY,
tenant_id UUID NOT NULL,
cliente_id INTEGER,
valor_total DECIMAL(10,2),
data_venda TIMESTAMP DEFAULT NOW()
);
-- Habilitar RLS
ALTER TABLE vendas ENABLE ROW LEVEL SECURITY;
-- Política para isolamento por tenant
CREATE POLICY "Isolamento por tenant" ON vendas
FOR ALL USING (
tenant_id = (auth.jwt() ->> 'tenant_id')::UUID
);
-- Política para super admin
CREATE POLICY "Super admin acesso total" ON vendas
FOR ALL USING (
auth.jwt() ->> 'role' = 'super_admin'
);
Gerenciando Políticas
-- Listar políticas de uma tabela
SELECT * FROM pg_policies WHERE tablename = 'produtos';
-- Desabilitar uma política
ALTER POLICY "nome_da_politica" ON produtos DISABLE;
-- Remover uma política
DROP POLICY "nome_da_politica" ON produtos;
-- Desabilitar RLS (cuidado!)
ALTER TABLE produtos DISABLE ROW LEVEL SECURITY;
Gerenciamento de Usuários
O Supabase oferece autenticação integrada com diferentes provedores e controle granular de permissões.
Autenticação no Supabase
// Configurar cliente Supabase
const supabase = createClient(url, anonKey);
// Registro de usuário
const { data, error } = await supabase.auth.signUp({
email: 'usuario@email.com',
password: 'senha123',
options: {
data: {
nome: 'João Silva',
role: 'user'
}
}
});
// Login
const { data, error } = await supabase.auth.signInWithPassword({
email: 'usuario@email.com',
password: 'senha123'
});
// Logout
const { error } = await supabase.auth.signOut();
Roles e Permissões
-- Criar roles personalizadas
CREATE ROLE vendedor;
CREATE ROLE gerente;
CREATE ROLE admin;
-- Conceder permissões específicas
GRANT SELECT, INSERT ON vendas TO vendedor;
GRANT SELECT, INSERT, UPDATE ON vendas TO gerente;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO admin;
-- Política baseada em role
CREATE POLICY "Vendedores veem apenas suas vendas" ON vendas
FOR ALL USING (
auth.jwt() ->> 'role' = 'vendedor' AND
vendedor_id = auth.uid()
);
-- Política para gerentes
CREATE POLICY "Gerentes veem vendas da equipe" ON vendas
FOR ALL USING (
auth.jwt() ->> 'role' = 'gerente' AND
vendedor_id IN (
SELECT id FROM usuarios
WHERE gerente_id = auth.uid()
)
);
Middleware de Autenticação
// Middleware para verificar autenticação
function requireAuth(requiredRole = null) {
return async (req, res, next) => {
const token = req.headers.authorization?.replace('Bearer ', '');
if (!token) {
return res.status(401).json({ error: 'Token não fornecido' });
}
try {
const { data: { user }, error } = await supabase.auth.getUser(token);
if (error || !user) {
return res.status(401).json({ error: 'Token inválido' });
}
// Verificar role se necessário
if (requiredRole && user.user_metadata?.role !== requiredRole) {
return res.status(403).json({ error: 'Permissão insuficiente' });
}
req.user = user;
next();
} catch (error) {
return res.status(401).json({ error: 'Erro na autenticação' });
}
};
}
// Uso do middleware
app.get('/admin/users', requireAuth('admin'), (req, res) => {
// Apenas admins podem acessar
});
Monitoramento e Auditoria
Monitorar o banco de dados é essencial para detectar problemas de performance, tentativas de acesso não autorizado e garantir a integridade dos dados.
Logs de Auditoria
-- Tabela de auditoria
CREATE TABLE auditoria (
id SERIAL PRIMARY KEY,
tabela VARCHAR(100) NOT NULL,
operacao VARCHAR(10) NOT NULL,
usuario_id UUID,
dados_antigos JSONB,
dados_novos JSONB,
ip_address INET,
user_agent TEXT,
timestamp TIMESTAMP DEFAULT NOW()
);
-- Function de auditoria genérica
CREATE OR REPLACE FUNCTION auditar_operacao()
RETURNS TRIGGER AS $$
BEGIN
INSERT INTO auditoria (
tabela,
operacao,
usuario_id,
dados_antigos,
dados_novos,
ip_address
) VALUES (
TG_TABLE_NAME,
TG_OP,
auth.uid(),
CASE WHEN TG_OP = 'DELETE' THEN row_to_json(OLD) ELSE NULL END,
CASE WHEN TG_OP != 'DELETE' THEN row_to_json(NEW) ELSE NULL END,
inet_client_addr()
);
RETURN COALESCE(NEW, OLD);
END;
$$ LANGUAGE plpgsql;
-- Aplicar auditoria a tabelas importantes
CREATE TRIGGER trigger_auditoria_produtos
AFTER INSERT OR UPDATE OR DELETE ON produtos
FOR EACH ROW EXECUTE FUNCTION auditar_operacao();
Monitoramento de Performance
-- Consultas mais lentas
SELECT
query,
calls,
total_time,
mean_time,
rows
FROM pg_stat_statements
ORDER BY total_time DESC
LIMIT 10;
-- Tabelas mais acessadas
SELECT
schemaname,
tablename,
seq_scan,
seq_tup_read,
idx_scan,
idx_tup_fetch
FROM pg_stat_user_tables
ORDER BY seq_tup_read DESC;
-- Índices não utilizados
SELECT
schemaname,
tablename,
indexname,
idx_scan
FROM pg_stat_user_indexes
WHERE idx_scan = 0;
Alertas e Notificações
-- Function para detectar tentativas de acesso suspeitas
CREATE OR REPLACE FUNCTION detectar_acesso_suspeito()
RETURNS TRIGGER AS $$
DECLARE
tentativas_recentes INTEGER;
BEGIN
-- Contar tentativas de login falhadas nas últimas 5 minutos
SELECT COUNT(*) INTO tentativas_recentes
FROM auditoria
WHERE operacao = 'LOGIN_FAILED'
AND ip_address = inet_client_addr()
AND timestamp > NOW() - INTERVAL '5 minutes';
-- Se mais de 5 tentativas, bloquear IP
IF tentativas_recentes > 5 THEN
INSERT INTO ips_bloqueados (ip_address, motivo, data_bloqueio)
VALUES (inet_client_addr(), 'Múltiplas tentativas de login', NOW())
ON CONFLICT (ip_address) DO NOTHING;
-- Enviar notificação (implementar webhook)
PERFORM pg_notify('security_alert',
json_build_object(
'type', 'brute_force',
'ip', inet_client_addr(),
'attempts', tentativas_recentes
)::text
);
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
Melhores Práticas de Segurança
🔐 Segurança do Banco
- • Use sempre RLS em tabelas sensíveis
- • Implemente políticas granulares
- • Monitore acessos e operações
- • Mantenha backups atualizados
- • Use conexões SSL/TLS
- • Limite privilégios por role
🛡️ Segurança da Aplicação
- • Valide todas as entradas
- • Use prepared statements
- • Implemente rate limiting
- • Criptografe dados sensíveis
- • Use HTTPS sempre
- • Mantenha dependências atualizadas
👥 Controle de Acesso
- • Princípio do menor privilégio
- • Autenticação multi-fator
- • Rotação regular de senhas
- • Revisão periódica de acessos
- • Logs de auditoria completos
- • Segregação de ambientes
📋 Compliance
- • Atenda à LGPD/GDPR
- • Documente políticas de segurança
- • Implemente direito ao esquecimento
- • Mantenha registros de processamento
- • Realize testes de penetração
- • Treine a equipe em segurança
Lembre-se:
A segurança é um processo contínuo, não um destino. Mantenha-se atualizado com as melhores práticas e revise regularmente suas implementações.
Exercício Final
Teste seus conhecimentos sobre backup e segurança!
Escolha as melhores práticas para cada cenário:
1. Qual é a frequência recomendada para backups em produção?
2. O que é Row Level Security (RLS)?
3. Qual comando é usado para habilitar RLS em uma tabela?
4. Por que é importante testar backups regularmente?
🎉 Parabéns!
Você completou o curso de SQL com Supabase!
O que você aprendeu:
- Fundamentos de bancos de dados
- Criação e manipulação de tabelas
- Consultas SQL avançadas
- Relacionamentos entre tabelas
- Funções de agregação
- Otimização de performance
- Views e procedures
- Backup e recuperação
- Segurança e RLS
- Integração com Supabase
- Casos práticos reais
- Melhores práticas
Continue praticando com os casos práticos e explore mais recursos do Supabase!
Resumo da Aula
- Backups são essenciais para proteger dados contra perda
- RLS oferece controle granular de acesso aos dados
- Monitoramento e auditoria são fundamentais para segurança
- Seguir melhores práticas previne problemas de segurança
- Segurança é um processo contínuo, não um destino