04 - Testes Automatizados e CI-CD para Detecções
video: https://youtu.be/... no frontmatter da nota.Testes Automatizados e CI-CD para Detecções
Nota de fechamento da pasta de Detection-as-Code do capítulo 18, sobre Detection Engineering e Automação.
Define a pirâmide de testes de detecção e a pipeline de CI/CD que valida e publica regras por estágio, com exemplo completo de workflow.
Dialoga com os repositórios de regras da nota anterior, com a conversão de Sigma e o deploy automatizado da pasta de Pipeline de Detecção.
1. Contexto e Posicionamento na Biblioteca
As notas anteriores organizaram o ciclo de vida das detecções e o repositório que as versiona, e esta nota descreve o componente que dá confiabilidade ao processo: os testes automatizados e a pipeline de integração e entrega contínua. Sem testes, a revisão por pares julga aparência, e sem pipeline, o deploy volta a ser manual e o console reconquista seu papel de caminho real de mudança. Juntas, as duas práticas transformam o fluxo de regras em uma esteira com portões objetivos, onde a qualidade é verificada por máquina e o humano decide o que a máquina não decide.
A nota segue a lógica da pirâmide de testes da engenharia de software, adaptada à natureza das detecções, e apresenta um exemplo completo de pipeline em GitHub Actions que pode ser adaptado pelo leitor. A pasta de Pipeline de Detecção assume o conteúdo desta nota como base: a conversão de Sigma roda dentro de pipelines como a descrita aqui, e o deploy automatizado é o estágio final dessa mesma esteira.
2. A Pirâmide de Testes de Detecção
Os testes de detecção organizam-se em quatro camadas de custo e valor crescentes, e a composição equilibrada de todas as camadas é o que protege o catálogo. A tabela abaixo define cada camada com o objetivo, o insumo típico e a velocidade de execução, critério que determina onde cada teste roda, se em pull request, em merge ou em cadência programada.
| Camada | Objetivo | Insumo típico | Velocidade |
|---|---|---|---|
| Teste unitário de arquivo | Valida schema, metadados obrigatórios e lint | Arquivo YAML ou TOML da regra | Segundos, roda em todo PR |
| Teste de lógica | Confirma que a consulta expressa a lógica do desenho | Consulta compilada e eventos sintéticos | Segundos a minutos, em todo PR |
| Teste de integração | Confirma que a regra compila e dispara no motor real | Instância do SIEM ou EDR de teste | Minutos, em merge na principal |
| Teste de regressão | Confirma que mudanças não degradam comportamento anterior | Corpus histórico rotulado | Minutos a horas, em merge e diário |
O teste unitário de arquivo é a base da pirâmide e o mais barato de manter, verificando sintaxe do formato, campos obrigatórios, unicidade de identificadores e padrões de nomenclatura. O teste de lógica executa a consulta contra eventos sintéticos preparados para casar e para não casar com a detecção, um verdadeiro positivo obrigatório e falsos positivos planejados no desenho. O teste de integração sobe o motor real, Elastic, Splunk ou Wazuh em ambiente efêmero de CI, compila e executa a regra contra os dados injetados, pegando incompatibilidades de dialeto que a compilação isolada não pega. O teste de regressão roda o catálogo inteiro contra o corpus histórico sempre que algo muda, e é ele que responde a pergunta da revisão: esta mudança quebrou alguma outra regra?
A disciplina essencial da pirâmide é o rótulo dos dados: cada evento sintético e cada amostra histórica carrega a expectativa, alerta esperado ou não alerta, e a pipeline compara o comportamento do motor com a expectativa declarada. Sem essa comparação declarativa, o teste degrada a log de execução sem veredito, e log que ninguém avalia não é teste, é telemetria.
3. Dados Sintéticos e Representatividade do Ambiente de Teste
O dado sintético é a matéria-prima dos testes, e sua qualidade determina o valor de toda a pirâmide. Existem três modos de obtê-lo: geradores que emitem eventos construídos campo a campo, frameworks de emulação de adversário como o Atomic Red Team, que executam técnicas ATT&CK reais em ambiente controlado e capturam a telemetria resultante, e amostras históricas reais extraídas do próprio ambiente, com dados sensíveis mascarados quando necessário.
A representatividade é o critério central de um ambiente de teste útil, e tem duas dimensões que o time precisa equilibrar. A dimensão de fidelidade exige que os eventos sintéticos tenham os mesmos nomes de campo, tipos e valores que a produção produz, porque uma regra validada contra um campo do tipo errado quebra silenciosamente em produção. A dimensão de volume e ruído exige que o corpus inclua os padrões benignos do ambiente real, como varreduras de inventário, jobs de backup e ferramentas de administração, porque é contra esse ruído que a regra precisa manter precisão.
- Manter corpus versionado no repositório: os eventos de teste vivem junto às regras, em formato JSON ou NDJSON, com entrada por evento e expectativa explícita, e a mudança de uma regra que altera a expectativa de um evento precisa justificar a alteração do corpus no mesmo pull request.
- Capturar telemetria de emulação no laboratório: executar o caso de teste do Atomic Red Team, por exemplo o caso T1059.001 de PowerShell com cradle, em uma VM instrumentada com Sysmon produz o evento real que a regra encontrará, e esse evento capturado alimenta o teste de integração de forma permanente.
- Mascarar dados sensíveis nas amostras históricas: nomes de usuários, endereços e hostnames reais são substituídos de forma reversível antes de o corpus entrar no repositório, preservando estrutura e mantendo conformidade com a política de dados da organização.
- Revalidar o corpus com mudanças de schema: atualizações do agente de coleta ou do produto mudam nomes de campos, e a cadência trimestral de comparação entre corpus e schema de produção evita testes verdes contra uma realidade desatualizada.
O ambiente de teste ideal não é uma cópia de produção, é uma amostra de produção: um conjunto de indexadores ou uma instância reduzida recebendo o corpus rotulado, com versões de plataforma e configurações de coleta equivalentes às de produção. A cópia integral de produção traz custo e risco de dados que raramente se justificam, e a amostra traz a fidelidade necessária aos testes da pipeline.
4. Pipeline de CI/CD para Detecções, Estágio por Estágio
A pipeline de detecções encadeia os estágios de validação e publicação, e cada estágio é um portão: o falhar de qualquer checagem interrompe o fluxo e impede o merge ou o deploy. A sequência típica em pull request é lint, validação de schema, compilação e conversão, teste de lógica e relatório de impacto, e a sequência após o merge é teste de integração, deploy por estágio e verificação pós-deploy. O exemplo abaixo mostra um workflow completo de GitHub Actions para um catálogo em Sigma com destino em Elastic e Splunk.
name: detection-pipeline
on:
pull_request:
paths:
- "rules/**"
push:
branches: [main]
paths:
- "rules/**"
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: yamllint nos arquivos de regra
run: yamllint -d relaxed rules/
- name: validacao de schema e checagens Sigma
run: |
pip install sigma-cli pysigma
sigma check rules/sigma/
test-logic:
needs: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: testes de logica com eventos sinteticos
run: python tests/run_detection_tests.py --corpus tests/synthetic/
- name: regressao contra corpus historico
run: python tests/run_regression.py --corpus tests/regression/ --threshold 95
build:
needs: test-logic
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: converter Sigma para KQL e SPL
run: |
sigma convert -t kusto -p microsoft_sentinel rules/sigma/ -o out/kql/
sigma convert -t splunk -p splunk rules/sigma/ -o out/spl/
- uses: actions/upload-artifact@v4
with:
name: compiled-rules
path: out/
deploy-dev:
needs: [build, test-integration]
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment: dev
steps:
- uses: actions/download-artifact@v4
with: { name: compiled-rules }
- name: publicar regras no ambiente de desenvolvimento
run: python tools/push_rules.py --env dev --src out/
deploy-prod:
needs: deploy-dev
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/download-artifact@v4
with: { name: compiled-rules }
- name: publicar regras em producao
run: python tools/push_rules.py --env prod --src out/
- name: verificacao pos-deploy
run: python tools/verify_rules.py --env prod --expected-manifest manifest.json
test-integration:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: subir motor de teste e rodar casos
run: docker compose -f tests/docker/elasticsearch.yml up --exit-code-from runner
O workflow acima ilustra três decisões de desenho que valem destaque. O uso de ambientes do GitHub, com o bloco environment, permite exigir aprovação humana antes do deploy de produção, implementando o estágio de homologação descrito na nota de DDLC. A separação entre jobs de build e deploy garante que o artefato publicado em produção é exatamente o artefato testado, e não uma recompilação. A verificação pós-deploy compara o manifesto esperado com o estado da plataforma e falha o job se algo divergir, fechando o ciclo de garantia dentro da própria pipeline.
5. Métricas de Qualidade da Pipeline
A pipeline é um produto, e medir sua saúde evita que a esteira vire gargalo invisível. As métricas relevantes dividem-se em duas famílias: as de eficiência do fluxo, que medem velocidade, e as de eficácia da barreira, que medem o quanto a pipeline captura de defeitos antes de produção.
| Métrica | Como medir | Alvo indicativo |
|---|---|---|
| Lead time de detecção | Tempo da abertura do PR ao deploy em produção | Menos de 2 dias úteis para regras de nível alto |
| Taxa de falso verde | Defeitos encontrados em produção que os testes deveriam ter pegado | Tendendo a zero, com análise por caso |
| Duração da pipeline de PR | Tempo total do ciclo de jobs no pull request | Menos de 10 minutos para não travar o fluxo |
| Taxa de re-trabalho pós-deploy | Proporção de deploys seguidos de tuning corretivo imediato | Abaixo de 20 por cento das regras novas |
| Cobertura da pipeline | Regras que passam por todas as camadas de teste | Cem por cento, exceções registradas |
| Flakiness de teste | Testes que alternam resultado sem mudança de código | Abaixo de 1 por cento das execuções |
O falso verde é a métrica mais importante da família de eficácia, porque cada defeito que passa pela barreira mina a confiança no processo e convida ao deploy manual de emergência. Cada caso de falso verde gera um teste novo que impede a reincidência: o incidente vira corpus, e a barreira aprende com a falha, que é exatamente o comportamento que se espera de um processo de engenharia maduro.
6. Erros Comuns e Pontos de Atenção
- Pipeline que só roda lint: a esteira que valida formato sem testar comportamento dá falsa sensação de qualidade, porque schema correto não implica detecção correta. Pelo menos uma camada de teste de lógica é o mínimo aceitável.
- Corpus congelado há anos: dados de teste que não acompanham a evolução da telemetria passam a validar contra uma realidade inexistente, e a cadência de revisão do corpus é tão importante quanto a cadência das regras.
- Teste de integração frágil por dependência externa: subir motor de teste que depende de serviço externo instável torna a pipeline intermitente, e a equipe aprende a ignorar falhas, queimando a confiança na barreira. Instâncias efêmeras em contêiner resolvem a maior parte dos casos.
- Deploy sem verificação pós-publicação: publicar e assumir sucesso esconde falhas de API, rate limit e regras rejeitadas silenciosamente pela plataforma, e a comparação de manifesto pós-deploy custa minutos e evita semanas de lacuna invisível.
- Threshold de regressão arbitrário: exigir 100 por cento de paridade histórica trava evoluções legítimas de schema, enquanto thresholds frouxos deixam passar degradação. O número é negociado por classe de regra e revisado com dados.
- Testar apenas regras novas: mudanças em regras antigas e em configurações de plataforma afetam o catálogo inteiro, e a execução de regressão completa em merges de manutenção cobre exatamente essa lacuna.
7. Integração com o Restante da Biblioteca
Na pasta de Pipeline de Detecção, a nota de conversão de Sigma executa o estágio de build descrito aqui, com aprofundamento nos backends e nas limitações da tradução entre dialetos, e a nota de deploy automatizado expande o estágio final com Terraform, estados e estratégias de rollback. A nota de simulação de alertas fornece a camada que complementa esta pirâmide: os testes aqui descritos comprovam a lógica e a publicação, e a simulação comprova o circuito completo, do evento injetado no agente até o alerta criado na plataforma.
No restante da biblioteca, o controle SIM.5 sobre medição de cobertura de detecção consome os resultados desta pipeline como evidência de comportamento testado, o controle SIM.4 sobre teste de detecção de IOCs e IOAs fornece os casos de emulação que abastecem o corpus sintético, e a nota de KPIs para CTI do capítulo 11 incorpora as métricas de lead time e falso verde como indicadores do programa. O controle DAT.5 sobre qualidade e retenção de dados define as condições que o corpus precisa manter para continuar representativo, fechando o vínculo entre engenharia de detecção e engenharia de dados.