02 - Deploy Automatizado com Terraform e GitHub Actions
video: https://youtu.be/... no frontmatter da nota.Deploy Automatizado com Terraform e GitHub Actions
Nota da pasta de Pipeline de Detecção do capítulo 18, sobre Detection Engineering e Automação.
Trata a infraestrutura de detecção como infraestrutura como código, com Terraform para configurações de SIEM e EDR e GitHub Actions para publicação de regras.
Dialoga com a conversão de Sigma da nota anterior, com os testes e a CI da pasta de DaC e com o controle AUT.3 do framework CTH.
1. Contexto e Posicionamento na Biblioteca
A pasta até aqui tratou das regras, e esta nota trata do ambiente que as executa: índices e retenção do SIEM, policies de telemetria do EDR, regras de correlação, listas de referência e integrações de API. O princípio é o mesmo do DaC aplicado à camada de infraestrutura, conhecido como infraestrutura como código, ou IaC: o estado desejado do ambiente é declarado em arquivos versionados, e a ferramenta reconcilia a realidade com a declaração. Terraform é a ferramenta mais comum para essa declaração, e GitHub Actions é a esteira que executa o plano e a aplicação com controle de acesso e auditoria.
A separação conceitual importa: regras de detecção são conteúdo, com ciclo de vida rápido e deploy contínuo, e infraestrutura de detecção é plataforma, com ciclo de vida mais lento e mudanças avaliadas por plano de execução. Um pipeline maduro tem duas esteiras, uma para regras e outra para infraestrutura, ambas partindo do mesmo repositório ou de repositórios irmãos, e ambas terminando em ambientes com verificação pós-aplicação.
2. Terraform Aplicado a SIEM e EDR
Terraform descreve recursos em arquivos HCL, e a disponibilidade de providers determina o que é possível gerenciar. O ecossistema de providers relevantes a detecção inclui o provider oficial da Elastic, que gerencia espaços, configurações de detecção e integrações; providers comunitários e oficiais para Splunk, que gerenciam indexes, entradas de dados e savesearches; o provider genérico REST, que cobre APIs sem provider dedicado, incluindo APIs de políticas de EDR e de regras de SIEM menores; e providers de cloud para os serviços de detecção nativos, como Sentinel e Security Hub.
O exemplo abaixo declara, em formato simplificado, um índice com retenção, uma política de detecção do EDR com modo de telemetria reforçado para o grupo de servidores e uma lista de referência do SIEM, três artefatos de infraestrutura que tipicamente vivem espalhados em consoles e agora têm fonte única.
terraform {
required_providers {
elasticstack = {
source = "elastic/elasticstack"
version = "~> 0.11"
}
restapi = {
source = "Mastercard/restapi"
}
}
}
provider "elasticstack" {
elasticsearch {
endpoints = [var.es_endpoint]
username = var.es_user
password = var.es_password
}
}
resource "elasticstack_elasticsearch_index" "edr_telemetry" {
name = "logs-edr-telemetry-000001"
number_of_shards = 3
number_of_replicas = 1
# retenção de 180 dias gerenciada por ILM declarada à parte
}
resource "restapi_object" "edr_policy_servers" {
path = "/api/policies"
data = jsonencode({
name = "policy-servers-telemetry-max"
telemetry = "full"
response = "detect"
scope = "servers"
})
}
A escolha entre provider dedicado e provider genérico REST segue um critério simples: provider dedicado quando existe, porque traz modelagem de recursos, validação e detecção de mudança; provider REST quando não existe provider e a API é estável, aceitando o custo de declarar os endpoints e payloads à mão. APIs instáveis de produto, que mudam entre versões, são o pior caso para IaC, e nesses casos vale pinar a versão do produto e acompanhar o changelog antes de aplicar atualizações que quebrem a configuração declarada.
3. Estados, Drift e Governança da Infraestrutura
O estado do Terraform é o registro do que a ferramenta entende que gerencia, e o armazenamento remoto do estado é obrigatório em ambiente de equipe: blob storage com locking, como Azure Storage, S3 com DynamoDB ou a infraestrutura de estado do próprio provedor, evita que duas execuções simultâneas corrompam o registro. O estado contém potencialmente segredos de conexão, e o uso de variáveis injetadas pela esteira em vez de credenciais literais nos arquivos reduz a exposição, complementado por cifragem do bucket de estado.
O drift é a divergência entre o estado declarado e a realidade da plataforma, causada por mudanças manuais no console, e é o principal inimigo do modelo. A detecção de drift é executada com cadência programada, tipicamente diária ou semanal, rodando o plano em modo somente leitura e alertando quando recursos mudam fora do controle do repositório. A resposta ao drift é padronizada: investigar quem mudou, decidir se a mudança é desejada, caso positivo incorporá-la ao repositório com commit, caso negativo aplicar o plano e restaurar o estado declarado. O drift crônico em um recurso específico costuma indicar que o recurso pertence a outro time, e a solução correta é mover a propriedade, não brigar com o console.
A governança do repositório de infraestrutura usa o mesmo aparato do repositório de regras: branch principal protegida, pull request obrigatório com o plano de execução colado no PR pelo bot da esteira, revisão por pares focada no impacto do plano e CODEOWNERS por domínio. O plano no PR é o documento de mudança que o revisor aprova, e a cultura de ler o plano antes de aprovar é o que separa IaC de sucesso de IaC decorativo.
4. Workflow de Deploy por Ambiente no GitHub Actions
A esteira de infraestrutura executa plan e apply por ambiente, com aprovação humana nos ambientes de maior risco e varredura de segredos e qualidade de código antes de qualquer aplicação. O workflow abaixo mostra a estrutura típica, com ambientes de desenvolvimento e produção, e o princípio vale para qualquer provedor de CI com recurso de environments e approvals.
name: infra-detection-pipeline
on:
pull_request:
paths: ["infra/**"]
push:
branches: [main]
paths: ["infra/**"]
permissions:
id-token: write
contents: read
jobs:
plan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
- name: init e validate
working-directory: infra/
run: |
terraform init -backend-config=env/dev.hcl
terraform validate
- name: plano somente leitura para revisão
working-directory: infra/
run: terraform plan -var-file=env/dev.tfvars -out=tfplan
- name: publicar plano no PR
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const out = fs.readFileSync('infra/tfplan.txt', 'utf8');
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: 'Plano de execução:\n```\n' + out + '\n```'
});
apply-dev:
needs: plan
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment: dev
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
- working-directory: infra/
- run: terraform apply -auto-approve -var-file=env/dev.tfvars
apply-prod:
needs: apply-dev
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
- working-directory: infra/
- run: terraform apply -auto-approve -var-file=env/prod.tfvars
- name: verificação pós-aplicação
run: python tools/verify_infra.py --env prod --manifest manifest_infra.json
drift-detect:
schedule:
- cron: "0 7 * * 1-5"
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
- working-directory: infra/
- run: terraform plan -var-file=env/prod.tfvars -detailed-exitcode || echo "drift detectado"
Três detalhes do workflow merecem explicação. O job de plan roda em todo pull request e posta o resultado como comentário, tornando o impacto da mudança visível antes da aprovação, e o apply roda apenas na branch principal, garantindo que o que é aplicado é o que foi revisado. O bloco environment de produção carrega aprovação humana configurada no GitHub, implementando o portão de homologação sem código adicional. O job de drift-detect roda em cadência com a flag detailed-exitcode, cujo código 2 indica mudanças pendentes, e abre issue ou alerta quando detecta divergência, transformando o drift em evento gerenciado em vez de surpresa.
5. Rollback e Recuperação
O rollback em IaC tem duas formas, e escolher corretamente entre elas evita agravar incidentes. A forma preferencial é o rollback por reverter o repositório: o commit que causou o problema é revertido com git revert, a esteira recalcula o plano e aplica o estado anterior, e o histórico permanece linear e auditável. Essa forma resolve mudanças declarativas, como uma policy que causou perda de telemetria ou um índice mal dimensionado que degradou o cluster.
A segunda forma é o rollback do estado, usado quando a aplicação corrompeu o registro de estado, por exemplo após aplicação parcial falha, e o Terraform deixa de entender o que gerencia. O Terraform mantém backups do estado em cada aplicação, e restaurar o backup permite refazer o plano a partir de um ponto consistente, seguido da reconciliação manual dos recursos que ficaram em estado intermediário. Essa operação é rara e sensível, e a política do time deve tratar qualquer restauração de estado como incidente com análise posterior.
Para os artefatos de conteúdo, as regras publicadas, o rollback segue o modelo da esteira de regras descrita na pasta de DaC: reverter o commit da regra e publicar a versão anterior pelo mesmo caminho de pipeline, nunca editando a regra no console durante o incidente. A combinação de duas esteiras, conteúdo e infraestrutura, com estados remotos e planos auditáveis, dá ao programa de detecção a capacidade de voltar atrás em minutos com prova documental de quem mudou o quê.
6. Erros Comuns e Pontos de Atenção
- Estado local no disco do engenheiro: o arquivo de estado localizado fragmenta a gestão, impede colaboração e some quando a pessoa sai do time. Estado remoto com locking é o primeiro item a implantar, antes de qualquer recurso importante.
- Aplicar sem ler o plano: a esteira com auto-approve na produção e plano ignorado transforma IaC em automação de erro em massa. O plano é o artefato de revisão, e a aprovação humana existe para lê-lo.
- Gerenciar em Terraform o que muda por design: objetos criados dinamicamente pela plataforma, como índices diários e alertas criados por playbooks de SOAR, não são recursos de Terraform, e tentar gerenciá-los gera drift eterno. Declarar fronteira clara entre o estático gerenciado e o dinâmico.
- Segredos em arquivos HCL: credenciais literais em variáveis versionadas vazam no histórico do Git para sempre. Variáveis sensíveis com valor injetado pela esteira e arquivos tfvars sensíveis fora do repositório, com as chaves em cofre.
- Drift tratado como exceção individual: cada drift resolvido à mão e não documentado repete a próxima semana. O registro do drift com causa e decisão vira inventário de console paralelo e insumo para integrar recursos ao controle.
- Importar recursos sem padronizar tags e organização: a importação de tudo que já existe no console para o controle gera um arquivo gigantesco sem revisão possível. Importar por domínio, com plano revisado, é o caminho que mantém a confiança na declaração.
7. Integração com o Restante da Biblioteca
Esta nota fecha o circuito iniciado pela conversão de Sigma: o catálogo compilado é publicado pela esteira de regras, e a infraestrutura que o recebe é declarada e aplicada pela esteira de Terraform descrita aqui, com o drift sob vigilância programada. A nota seguinte da pasta simula alertas com inputs controlados contra esse ambiente implantado, provando que a infraestrutura declarada produz a telemetria e os alertas esperados.
No restante da biblioteca, o controle AUT.3 sobre automação de detecção do framework CTH é a consagração do modelo aqui descrito, e o controle DAT.4 sobre ingestão e centralização de logs fornece os recursos de plataforma, índices, conectores e retenção, que a esteira de infraestrutura declara. A nota de engenharia de dados e pipelines do capítulo 9 dialoga com o desenho de estado e drift aqui apresentado, e a nota de maturidade em CTI do capítulo 1 situa o IaC de detecção no contexto mais amplo de maturidade do programa, onde a capacidade de declarar e restaurar o ambiente é um marcador de nível avançado de operação.