Home Comunidade Eventos YouTube Networks Desafios // produtos Academy News CTI | CVE Contato

02 - Deploy Automatizado com Terraform e GitHub Actions

video explicativo
Video explicativoEspaco reservado para o video desta anotação — adicione 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.