08 - Pipeline de Coleta e Enriquecimento de CTI
video: https://youtu.be/... no frontmatter da nota.Pipeline de Coleta e Enriquecimento de CTI
Nota do capítulo 02 (Fontes de Dados e Coleta), onde a biblioteca organiza como a inteligência técnica entra na organização.
Este arquivo define a arquitetura que converte fontes dispersas em indicadores confiáveis, com estágios de ingestão, fila, processamento, enriquecimento, armazenamento e distribuição.
Dialoga diretamente com as notas de normalização e deduplicação, resolução de entidades, automação de coleta via APIs e governança de dados.
1. Contexto e Posicionamento na Biblioteca
As fontes descritas nas notas anteriores deste capítulo (feeds públicos, OSINT, feeds comerciais, coleções TAXII, ISACs e submissões internas) chegam em formatos, volumes e cadências completamente diferentes. Consumir cada fonte de forma ad hoc, com um script isolado por fonte, funciona em prova de conceito e colapsa em produção: duplicatas se acumulam, falhas silenciosas interrompem a coleta sem aviso e nenhuma métrica responde quando o time pergunta por que determinado IOC não chegou ao SIEM. O pipeline é a resposta de engenharia a esse problema, tratando coleta e enriquecimento como um sistema com contrato de dados, observabilidade e ciclo de vida.
O papel do pipeline no estudo integrado de CTI e Threat Hunting é garantir que a matéria-prima da inteligência chegue correta, no tempo certo e rastreável até o destino final: as regras de detecção, as watchlists de hunting e os produtos analíticos. Todo o esforço de análise produzido a jusante depende da robustez desta esteira, no mesmo espírito do controle DAT.4 da seção 15, que cobre ingestão e centralização de logs. A diferença é que aqui o pipeline carrega inteligência estruturada, como objetos STIX 2.1 e observáveis com atributos, e não telemetria bruta.
2. Estágios do Pipeline: da Fonte à Distribuição
Um pipeline maduro separa responsabilidades em estágios independentes, de modo que cada um possa escalar, falhar e ser monitorado sem afetar os demais. Acoplar coleta, parse, enriquecimento e gravação em um único processo monolítico é a receita clássica para interrupções longas: uma mudança de formato em uma fonte derruba tudo. A tabela abaixo resume os estágios, a responsabilidade central de cada um e os modos de falha mais frequentes, que orientam os controles das seções seguintes.
| Estágio | Responsabilidade central | Modos de falha típicos |
|---|---|---|
| Coletores | Baixar ou receber dados de cada fonte, respeitando rate limits | Fonte muda de formato, credencial expira, bloco de IP do coletor |
| Ingestão | Validar schema, desarmar IOCs ofuscados, normalizar timestamp para UTC | Dado malformado quebrando o parse, fusos inconsistentes |
| Fila | Amortecer picos entre coletores e workers com entrega durável | Fila crescendo sem limite, mensagens reentregas infinitas |
| Workers | Parsear, transformar em STIX 2.1, aplicar regras de filtragem | Bug em um worker parando o tópico inteiro, processamento duplicado |
| Enriquecimento | Adicionar contexto, como RDAP, geo, reputação e passive DNS | Estourar quotas de API pagas, enriquecimento bloqueando o fluxo |
| Armazenamento | Persistir no TIP com metadados de origem e versão | Escrita não idempotente gerando duplicatas, índice corrompido |
| Distribuição | Empurrar para SIEM, EDR, SOAR e watchlists de hunting | Divergência de formato por destino, falta de confirmação de entrega |
A fronteira entre coletores e o restante do pipeline merece atenção especial. O coletor deve ser burro e resiliente: ele apenas baixa, valida minimamente e publica a mensagem bruta na fila, sem decidir nada sobre o conteúdo. Toda a lógica de negócio fica nos workers, o que permite reprocessar todo o histórico quando uma regra melhora, simplesmente relendo a fila ou o arquivo morto de ingestão.
Cabe ao pipeline também aplicar a política de filtragem cedo, sem adiar decisões para a distribuição. Indicadores de escopo interno (faixas RFC 1918, domínios da organização), valores já marcados como falso positivo recorrente e material fora do escopo dos requisitos de inteligência (PIRs) devem ser descartados ou arquivados com etiqueta antes do enriquecimento, evitando pagar contexto caro por dado que nunca será usado. Esse filtro inicial é barato, reversível e reduz drasticamente o volume que chega aos estágios mais custosos.
3. Fila, Reconhecimento e Backpressure
A fila é o coração do pipeline e resolve dois problemas ao mesmo tempo: desacoplamento temporal entre produção e consumo e amortecimento de picos, como um feed que publica dez mil indicadores de uma vez após uma campanha relevante. Ferramentas de mercado como RabbitMQ e Kafka cumprem esse papel com diferenças importantes: RabbitMQ entrega flexibilidade de roteamento por fila e confirmação individual, enquanto Kafka oferece log imutável e reprocessamento por offset, útil para reconstruir o estado do TIP do zero. A escolha importa menos do que a disciplina operacional em torno dela.
Backpressure é o mecanismo que impede o produtor de afogar consumidores lentos. Sem ele, a fila cresce até estourar memória ou disco e o pipeline inteiro cai, justamente no dia mais movimentado. As práticas essenciais são: limitar o tamanho da fila com política explícita de descarte ou spill para disco; usar prefetch limitado nos consumidores, entregando pacotes pequenos de mensagens por vez; e reconhecer a mensagem (ack) somente após o processamento completo, nunca na recepção. O OpenCTI documenta exatamente esse problema em seus conectores, que publicam eventos via RabbitMQ e dependem de controle de backpressure para não sobrecarregar a plataforma.
Mensagens que falham repetidamente precisam de destino separado. A configuração padrão recomendada é uma fila de letra morta (dead letter queue) com reentrega limitada, por exemplo, três tentativas com backoff exponencial antes do desvio. A DLQ não é cemitério: é triagem operacional. Cada mensagem na DLQ deve gerar métrica e, quando o volume sobe de patamar, alerta com o motivo parseado, pois picos de DLQ quase sempre indicam mudança silenciosa de formato em alguma fonte.
O dimensionamento da fila deve partir da vazão esperada por fonte e do pior pico histórico, não da média. Uma prática operacional útil é definir a capacidade de amortecimento em horas de processamento a vazão nominal dos workers, de modo que uma janela de manutenção não force descarte de dados. Fontes de baixa cadência e alto valor, como boletins de ISAC, podem ter fila própria com retenção longa, enquanto feeds volumosos de baixa confiança justificam fila com limite agressivo, porque perder algumas janelas delas tem impacto analítico pequeno.
4. Idempotência e Contrato de Mensagem
Sistemas de fila oferecem garantia de entrega pelo menos uma vez (at-least-once), o que significa que mensagens duplicadas vão ocorrer em reentregas, reconexões e falhas parciais entre worker e banco. Todo estágio downstream deve, portanto, ser idempotente: processar a mesma mensagem duas vezes produz o mesmo resultado que processar uma. A chave de idempotência mais simples e eficaz para CTI é o par tipo e valor canônico do indicador, complementado pelo hash de origem, como detalhado na nota de normalização e deduplicação.
O contrato de mensagem versionado protege o pipeline contra mudanças quebrando tudo de uma vez. Cada mensagem carrega um envelope com identificação, chave de deduplicação, origem, classificação TLP e o conteúdo. Um exemplo de envelope em YAML:
mensagem:
id: "urn:uuid:0f5c2a1e-9f6b-4d58-8b31-7c2e1a9d4f03"
chave_dedup: "ipv4:185.220.101.34"
schema: "cti.envelope.v1"
origem:
fonte: feed_osint_saidas_tor
url: "https://exemplo.org/feeds/tor-exit.csv"
tlp: "TLP:GREEN"
hash_arquivo: "sha256:4f2a9c8d3e1b7a6f0c5d9e8b2a1f3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b"
conteudo:
tipo: "ipv4-addr"
valor: "185.220.101.34"
primeiro_visto: "2025-11-03T12:40:00Z"
confianca: 70
etiquetas: ["anonimizador", "tor-exit"]
Com esse contrato, um worker pode ser reescrito, um worker novo pode consumir o mesmo tópico e uma migração de TIP pode ser executada relendo o histórico, sem consultar as fontes originais de novo. Mudanças de schema entram como versão nova (cti.envelope.v2), com período de convivência, e nunca como mutação silenciosa da versão vigente. Essa disciplina vale mais que qualquer ferramenta de schema registry isolada, porque estabelece o hábito de tratar o dado de inteligência como produto.
5. Enriquecimento: Ordem, Cache e Custo
Enriquecimento é o estágio que transforma um valor nu em contexto acionável: um IP vira IP com ASN, país, operador, histórico RDAP e reputação; um domínio ganha idade de registro, nameserver e relações de passive DNS. O princípio de projeto é enriquecer por estágio e por necessidade, em cadeia ordenada do dado mais barato para o mais caro. A ordem típica é: normalização e validação local, geolocalização e ASN a partir de bases locais atualizáveis, RDAP e passive DNS com cache agressivo e, por último, consultas a serviços pagos com quota, como reputação de arquivo e IP.
O cache é o controle de custo mais importante do enriquecimento. Consultas repetidas ao mesmo valor devem ser servidas do cache local (Redis ou similar) com TTL compatível com a dinâmica do dado: anos para hash de arquivo, semanas para domínio, dias para IP. Sem cache, um feed de cinquenta mil IOCs com enriquecimento por consulta estoura qualquer quota em minutos; a API pública do VirusTotal, por exemplo, permite apenas quatro requisições por minuto e quinhentas por dia. Além do cache, vale agendar o enriquecimento pesado como job em lote fora do caminho crítico, deixando o fluxo contínuo apenas para o mínimo necessário à triagem.
Dois cuidados de qualidade se aplicam a todo enriquecimento. Primeiro, o dado adicionado deve preservar a rastreabilidade de origem: cada atributo enriquecido carrega fonte e timestamp, para que uma informação errada possa ser rastreada e corrigida em massa. Segundo, a classificação TLP do material original nunca deve ser violada pelo enriquecimento: anexar a um indicador TLP:AMBER um contexto que só pode circular internamente exige cuidado com o destino da distribuição, tema retomado na nota de governança.
6. Arquitetura de Referência com MISP e Workers
A composição mais comum em times de CTI que constroem a própria esteira usa MISP como TIP central, com workers Python consumindo fontes e publicando eventos estruturados. O MISP oferece três pontos de integração úteis: a API restSearch para busca paginada de eventos e atributos, o feed de sincronização entre instâncias e a publicação ZeroMQ de eventos em tempo real, que pode alimentar a fila do pipeline. A arquitetura de referência, sem setas e em camadas, fica assim:
[1] Coletores feeds CSV, coleções TAXII 2.1, hub de ISAC, submissões de sandbox
[2] Ingestao validacao de envelope, desarme de ofuscacao, timestamp em UTC
[3] Fila RabbitMQ, topico por classe de fonte, DLQ com reentrega limitada
[4] Workers parse, mapeamento para objetos MISP/STIX 2.1, dedup exata
[5] Enriquecimento cache Redis, RDAP, passive DNS, reputacao em lote fora do fluxo
[6] Armazenamento MISP (TIP), indice de busca (Elasticsearch), export frio comprimido
[7] Distribuicao SIEM (watchlist), EDR (bloqueio), SOAR (playbooks), relatorios
O trecho abaixo ilustra o consumidor de fila em Python com reconhecimento após o processamento e desvio para DLQ em caso de falha estrutural, usando a biblioteca pika:
import json
import pika
def processar(ch, metodo, props, corpo):
try:
envelope = json.loads(corpo)
if envelope["schema"] != "cti.envelope.v1":
ch.basic_nack(delivery_tag=metodo.delivery_tag, requeue=False)
return
objeto_stix = mapear_para_stix(envelope["conteudo"])
gravar_no_tip(objeto_stix, origem=envelope["origem"])
ch.basic_ack(delivery_tag=metodo.delivery_tag)
except (KeyError, ValueError) as erro:
registrar_dlq(corpo, motivo=str(erro))
ch.basic_nack(delivery_tag=metodo.delivery_tag, requeue=False)
canal = pika.BlockingConnection(pika.ConnectionParameters("rabbitmq.interno")).channel()
canal.basic_qos(prefetch_count=25)
canal.basic_consume(queue="cti.ingestao", on_message_callback=processar)
canal.start_consuming()
Nessa arquitetura, o MISP permanece a fonte de verdade dos indicadores, o Elasticsearch dá busca analítica rápida e o export frio permite reprocessamento barato. A distribuição para o SIEM usa watchlists sincronizadas por intervalo, e a para o EDR só passa o subconjunto de alta confiança com TLP compatível com bloqueio automatizado. Essa separação entre o que é publicado para detecção e o que é publicado para bloqueio evita o erro clássico de mandar feed bruto de baixa confiança direto para prevenção.
7. Métricas e Observabilidade do Pipeline
Pipeline sem métrica é caixa preta, e a primeira evidência de problema costuma ser um analista perguntando por que um IOC noticiado não está no SIEM. As métricas mínimas cobrem as quatro dimensões operacionais: vazão por estágio, atraso de ponta a ponta, taxa de erro e utilização de recursos externos. A tabela abaixo propõe o conjunto inicial, com origem e uso prático de cada uma.
| Métrica | Origem típica | Uso prático |
|---|---|---|
| Mensagens por minuto por estágio | Contador do worker ou broker | Detectar gargalo comparando vazão entre estágios |
| Lag de fila (mensagens e idade da mais antiga) | Broker (RabbitMQ, Kafka) | Alertar quando idade ultrapassar o SLO de ingestão |
| Taxa de DLQ sobre total | Contador no consumidor | Pico indica mudança de formato ou dado corrompido |
| Latência de enriquecimento por provedor | Timer no cliente HTTP | Negociar quota e decidir cache por provedor |
| Cobertura de fontes ativas | Job de saúde por fonte | Fonte sem publicação em janela esperada gera alerta |
| Duplicatas evitadas | Contador na deduplicação | Mede a economia real da deduplicação e valida regras |
Em ambientes com Prometheus, um conjunto inicial de consultas cobre o essencial e cabe em três linhas, que devem virar painel com SLO explícito por estágio:
sum(rate(cti_pipeline_mensagens_total[5m])) by (estagio)
histogram_quantile(0.95, sum(rate(cti_pipeline_idade_mensagem_bucket[15m])) by (le, estagio))
sum(rate(cti_pipeline_dlq_total[1h])) / sum(rate(cti_pipeline_mensagens_total[1h]))
O SLO de ingestão recomendado para feeds táticos é de até uma hora entre publicação na fonte e disponibilidade consultável no TIP, com alerta quando o percentil 95 romper o limite por duas janelas consecutivas. Métricas sem alvo numérico viram decoração; cada linha do painel deve ter dono e meta, em linha com o que a seção de métricas da biblioteca aprofunda no capítulo 11.
8. Erros Comuns e Pontos de Atenção
O erro estrutural mais comum é acoplar tudo em um script único por fonte, sem fila nem estágios, o que transforma qualquer manutenção em reprocessamento completo e qualquer pico em perda de dados. O segundo erro frequente é reconhecer a mensagem na recepção em vez de reconhecer após processamento, produzindo perda silenciosa quando o worker cai no meio do lote. O terceiro é ignorar idempotência e aceitar duplicatas silenciosas, inflando contagens de IOC e gerando falsos sinais de correlação entre fontes que, na verdade, repetem a mesma mensagem.
No enriquecimento, os erros clássicos são estourar quotas pagas por falta de cache, enriquecer dados que nunca serão usados e bloquear o fluxo principal esperando uma API lenta. A regra de bolso é: nada de chamada externa síncrona no caminho crítico de ingestão, apenas cache local e consultas absolutamente necessárias à triagem imediata. Também é comum esquecer que o enriquecimento pode revelar dado pessoal (por exemplo, e-mail de registrante em RDAP), o que aproxima o pipeline das obrigações de privacidade tratadas na nota de governança e retenção.
Por fim, a falta de observabilidade é o erro que impede os outros de serem detectados. Times sem métrica de lag e DLQ descobrem falhas semanas depois, quando o prejuízo analítico já se acumulou. Cada fonte nova integrada ao pipeline deve entrar com três itens obrigatórios: contrato de mensagem validado, métrica de saúde com janela esperada de publicação e dono nominal no time. Fonte sem esses três itens não está em produção, está em fase de teste, e o painel deve refletir essa distinção.
9. Integração com o Restante da Biblioteca
Este pipeline é a espinha dorsal que conecta o capítulo 02 ao restante da biblioteca. A saída do estágio de workers alimenta a nota de normalização e deduplicação (09), que define as chaves canônicas aqui assumidas; a saída enriquecida alimenta a resolução de entidades e correlação (10), que constrói grafos sobre esses objetos; e a qualidade percebida a jusante é medida pela nota de qualidade, completude e atualidade (11), que fecha o loop de feedback sobre as fontes. A automação de coleta via APIs (12) detalha os clientes HTTP que os coletores deste pipeline executam, incluindo rate limits e autenticação.
Com o capítulo de detecção e hunting, a distribuição assume dois papéis distintos: watchlists consultáveis para hunting retroativo e export de alta confiança para detecção automatizada, preservando o princípio da Pirâmide de Dor de investir mais em TTPs do que em artefatos voláteis. Com a seção 15, os estágios aqui descritos materializam os controles DAT.4 e CTI.5 (processamento e normalização), e as métricas da seção 7 dialogam com os KPIs de ingestão do grupo MET. Uma evolução natural deste desenho é publicar os objetos STIX como eventos de stream (em vez de snapshots) para os consumidores, permitindo que o OpenCTI e o MISP compartilhem a mesma base canônica sem duplicar lógica de enriquecimento em cada plataforma.