12

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

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
Aula Anterior: Views e Procedures Casos Práticos