03 - Validação de Detecção em CI-CD Pipelines
video: https://youtu.be/... no frontmatter da nota.Validação de Detecção em CI-CD Pipelines
Nota da pasta 04 - Purple Teaming em Cloud e Containers, no Capítulo 19 (Purple Teaming Contínuo).
Trata da validação de detecções dentro do pipeline de CI/CD: injeção de eventos de teste em staging, verificação automática de alerta e gate de qualidade que impede a entrada de regra sem teste aprovado.
Dialoga com o AUT.3 e o AUT.4 do Capítulo 15, com o BAS contínuo da pasta 03 e com as notas de emulação da pasta 02 deste capítulo.
1. Contexto e Posicionamento na Biblioteca
As detecções de uma organização moderna vivem em um ciclo de mudança tão acelerado quanto o código: regras são escritas, ajustadas, desativadas e reescritas toda semana, e a maior parte dessas mudanças hoje chega por repositório e pipeline, na prática de detecção como código. Nesse regime, validar a detecção manualmente após cada mudança é economicamente inviável, e a resposta é colocar a validação dentro do pipeline: o mesmo pull request que propõe a regra carrega o teste que a exercita, o job de CI injeta o evento de teste em staging e o pipeline falha se o alerta esperado não aparecer. Esta nota desenha essa mecânica ponta a ponta.
A nota fecha o capítulo ao conectar a emulação à mudança: o BAS contínuo da pasta 03 valida o parque existente em cadência semanal, e o gate de CI valida cada mudança no momento em que ela nasce, impedindo que regressão entre pela porta da frente. Dialoga com o AUT.3 do Capítulo 15, que trata da automação de detecção, e com o AUT.4, que cobre a orquestrações de hunting automatizado. O pressuposto operacional é o mesmo de todo o capítulo: ambiente de staging fiel, eventos sintéticos marcados e nenhuma validação sobre dados reais de produção.
2. Por Que Validar Detecções no Pipeline
O custo da detecção quebrada cresce com o tempo até a descoberta, e o pipeline comprime esse tempo ao máximo possível: a quebra é descoberta na própria mudança, em minutos, com o autor presente e o diff à mão. Sem o gate, a mesma quebra é descoberta na próxima rodada do BAS contínuo, dias depois, ou pior, no incidente real. A economia do gate é direta e mensurável: cada regra nova entra com prova de detecção, e cada ajuste carrega o teste que impede a regressão silenciosa.
O segundo argumento é cultural e transforma o relacionamento entre engenharia de detecção e o resto da organização. Quando a regra de detecção exige teste para entrar, ela se comporta como código de verdade, com revisão, teste e histórico, e a qualidade média do parque sobe de forma estrutural. O gate também formaliza a definição de pronto: uma regra não está pronta quando escrita, e sim quando o teste passa no pipeline, e essa definição objectiva elimina as discussões de exclusividade sobre o que é uma regra finalizada.
O terceiro argumento é a rastreabilidade. O registro de execução do pipeline liga a versão da regra, o hash do commit, o evento injetado e o alerta gerado em uma cadeia de evidência auditável. Quando o incidente real exige saber se a detecção estava ativa e funcional, essa cadeia responde com commit e job, e não com memória de equipe.
3. Arquitetura da Validação: Staging, Injeção e Verificação
A arquitetura do gate tem três peças. O ambiente de staging é um espaço fiel, com a mesma pilha de coleta e o mesmo motor de regras da produção, alimentado por dados sintéticos e pelos fluxos de teste. O mecanismo de injeção produz o evento que a regra deveria capturar, e assume três formas conforme a regra: injeção direta no pipeline de ingestão, quando se quer testar apenas a regra; execução de um atomic no host de staging, quando se quer testar a cadeia completa de coleta; e geração de eventos sintéticos por script, quando a regra é de correlação temporal. A verificação consulta o motor de alertas na janela do teste e compara o resultado com o esperado.
A tabela resume as três formas de injeção e quando usar cada uma.
| Forma de injeção | O que valida | Quando usar |
|---|---|---|
| Evento direto na ingestão | A lógica da regra e a sintaxe da consulta | Mudanças de regra puras, iteração rápida |
| Atomic no host de staging | Coleta, pipeline e regra, ponta a ponta | Regras novas de endpoint antes de produção |
| Sintéticos de correlação | A janela temporal e a lógica de correlação | Regras que cruzam eventos em sequência |
A escolha da forma define o custo do job. A injeção direta é a mais barata e rápida, e serve a maioria dos ajustes; a injeção ponta a ponta com atomic é a mais completa e a mais lenta, e serve a regras novas; os sintéticos de correlação são intermediários e servem às regras de cadeia. Um pipeline maduro usa as três, com o tipo declarado no próprio pull request pela convenção de pastas ou por etiqueta no arquivo da regra.
A verificação precisa de margem de tempo realista. A janela entre injeção e consulta considera a ingestão do SIEM, a janela de execução das regras e a latência da API de alertas, e o job espera com backoff em vez de consultar uma vez e desistir. Um teste que falha por latência de ingestão gera falso negativo do gate, e o backoff curto e a janela generosa são os antídotos baratos.
4. Gate de Qualidade para Novas Regras
O gate de qualidade é a política que dá consequência ao teste: nenhuma regra entra na ramificação principal sem job de validação aprovado, e nenhum ajuste de regra entra sem o teste existente passando. A política se implementa nas proteções da ramificação, com o job obrigatório na verificação de pull request, e se complementa com a convenção de repositório: cada regra tem arquivo, metadados com dono e severidade, e um diretório de teste com o evento ou o roteiro de injeção correspondente.
A convenção de repositório vale um esqueleto concreto, porque é ela que torna o gate operável por qualquer pessoa do time.
repo-deteccoes/
regras/
endpoint/
ED-140-macro-powershell.yml
ED-141-tarefa-agendada-suspeita.yml
testes/
endpoint/
ED-140/
evento-sintetico.json
README.md
ED-141/
roteiro-atomic.yml
pipeline/
validar-regra.sh
injetar-evento.py
verificar-alerta.py
POLITICA.md
O par regra e teste é indivisível pelo contrato do repositório. Um pull request que adiciona regra sem teste é rejeitado automaticamente pelo job, que verifica a existência do diretório correspondente, e um pull request que muda a lógica da regra sem atualizar o teste do comportamento novo também falha na revisão. Esse contrato é a materialização do gate, e a política escrita em arquivo dá o embasamento para a conversa quando alguém tenta contorná-lo.
A exceção existe e precisa ser disciplinada. Regras emergenciais, publicadas durante incidente, entram por caminho acelerado com aprovação documentada, e o teste é compensatório, entrando no próximo sprint obrigatoriamente. O registro das exceções é revisado na reunião semanal do programa, e a meta é que o caminho acelerado seja raro, porque cada exceção é uma regra sem prova em produção.
5. Exemplo de Job de CI que Falha sem Alerta
O exemplo completo amarra as peças em um job real de pipeline. O job roda no pull request, injeta o evento sintético da regra proposta, espera a janela, consulta a API de alertas do motor de detecção em staging e falha se o alerta não aparecer. O bloco a seguir mostra o job em formato GitHub Actions, com o padrão aplicável a outros runners.
name: gate-de-deteccao
on:
pull_request:
paths: ["regras/**", "testes/**"]
jobs:
validar-regra:
runs-on: self-hosted
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Verificar par regra e teste
run: |
for regra in $(git diff --name-only origin/main...HEAD -- regras/ | grep '\.yml$'); do
id=$(basename "$regra" .yml)
tipo=$(dirname "$regra" | xargs basename)
test -d "testes/${tipo}/${id}" || \
{ echo "FALHA: regra ${id} sem diretório de teste"; exit 1; }
done
- name: Injetar evento sintético em staging
run: python3 pipeline/injetar-evento.py --teste testes/endpoint/ED-140/evento-sintetico.json
- name: Verificar alerta na janela do teste
run: |
python3 pipeline/verificar-alerta.py \
--regra "ED-140-macro-powershell" \
--ambiente staging \
--timeout 300 \
--backoff 15
- name: Publicar resultado na ficha da regra
run: python3 pipeline/publicar-resultado.py --ambient staging --job "${{ github.run_id }}"
O script de verificação é o coração do gate, e o esqueleto a seguir mostra a lógica com backoff e falha explícita.
import argparse, time, sys, requests
def alerta_existe(api, regra, janela):
r = requests.get(f"{api}/alertas", params={"regra": regra, "janela": janela}, timeout=30)
r.raise_for_status()
return len(r.json().get("alertas", [])) > 0
def main():
p = argparse.ArgumentParser()
p.add_argument("--regra", required=True)
p.add_argument("--ambiente", default="staging")
p.add_argument("--timeout", type=int, default=300)
p.add_argument("--backoff", type=int, default=15)
a = p.parse_args()
fim = time.time() + a.timeout
while time.time() < fim:
if alerta_existe(f"https://detecao-{a.ambiente}.lab.local/api", a.regra, a.timeout):
print(f"APROVADO: regra {a.regra} alertou em staging")
return 0
time.sleep(a.backoff)
print(f"FALHA: regra {a.regra} não alertou em {a.timeout}s de janela")
return 1
if __name__ == "__main__":
sys.exit(main())
O job falho é o produto do gate: o pull request recebe o vermelho com a mensagem de que a regra não alertou, e o autor corrige antes da revisão humana. A mensagem do job deve apontar para o README do teste, que explica o evento sintético e o comportamento esperado, transformando a falha em instrução em vez de barreira. Publicar o resultado na ficha da regra, o último passo, liga o gate ao índice de resultados do programa, e a regra aprovada nasce com o primeiro registro de detecção comprovada.
6. Métricas do Pipeline de Detecção
O próprio gate gera métricas que medem a saúde do processo de detecção. A taxa de aprovação em primeiro pull request revela a maturidade do time, o tempo médio de ciclo da regra, da proposta à aprovação, revela o gargalo do fluxo, e a proporção de regras com teste em relação ao parque total mede o avanço da cobertura de teste. A tabela fixa as métricas canônicas e o uso de cada uma.
| Métrica | Definição | Uso no programa |
|---|---|---|
| Taxa de aprovação em 1ª tentativa | Pull requests aprovados no primeiro job sobre o total | Qualidade da escrita de regra |
| Tempo de ciclo de regra | Horas entre abertura e merge do pull request | Gargalo do fluxo de detecção |
| Cobertura de teste do parque | Regras com teste sobre regras totais | Meta de migração para o gate |
| Falsos negativos do gate | Testes aprovados em CI que não alertam em produção | Qualidade do staging e dos sintéticos |
| Exceções de emergência | Regras entradas por caminho acelerado no período | Disciplina do processo |
A métrica de falsos negativos do gate merece vigilância especial, porque é a que mede se o staging continua fiel à produção. Um gate que aprova tudo e deixa passar regressões é pior que nenhum gate, porque confere falsa segurança, e qualquer divergência entre staging e produção, de versão de motor, de esquema de log ou de política de ingestão, aparece nessa métrica antes de aparecer em incidente.
7. Erros Comuns e Pontos de Atenção
- Implementar o gate apenas para regras novas e deixar os ajustes sem teste, que é justamente onde a maioria das regressões nasce; o teste acompanha a regra por toda a vida.
- Validar a regra só com injeção direta na ingestão, ignorando a cadeia de coleta, e descobrir em produção que o log source não chega; regras novas de endpoint merecem teste ponta a ponta.
- Rodar o job com janela curta demais e gerar falsos negativos de latência, ensinando o time a ignorar o vermelho; janela generosa e backoff são o desenho correto.
- Manter staging divergente de produção, com versões de motor ou esquemas diferentes, e aprovar no staging o que quebra na produção; a fidelidade do staging é medida, não presumida.
- Permitir exceções de emergência sem registro e sem teste compensatório, transformando o caminho acelerado em rota de fuga permanente.
- Tratar o gate como fim e esquecer que o BAS contínuo revalida o parque inteiro; o gate protege a mudança, e a rodada semanal protege o todo.
8. Integração com o Restante da Biblioteca
O gate consome a mesma infraestrutura do capítulo: os atomics e sintéticos da pasta 02 fornecem os eventos de teste, o cyber range e o staging da pasta 03 fornecem o ambiente, e o índice de resultados da pasta 03 recebe os registros de aprovação, alimentando o painel e o SIM.5. O AUT.3 do Capítulo 15 é o controle que esta nota materializa em prática de engenharia, e o AUT.4 recebe os testes aprovados como blocos de automação reutilizáveis para caças automatizadas. As métricas do pipeline alimentam o grupo MET e o relatório executivo, provando velocidade e qualidade do fluxo de detecção.
No conjunto do capítulo, o gate é o que impede o programa de andar para trás: o BAS contínuo descobre regressões depois, o gate impede regressões na origem, e o painel mostra a tendência do todo. A combinação fecha o ciclo do purple teaming contínuo em regime de engenharia: cada detecção nasce testada, vive validada e quebra com alarme, e a série histórica do índice é a prova disso para qualquer auditoria.