DEV Community

Cover image for Automatizando a Segurança na AWS: Um Guia Prático com Terraform
Marcos Vilela
Marcos Vilela

Posted on

Automatizando a Segurança na AWS: Um Guia Prático com Terraform

Introdução

No mundo da computação em nuvem, garantir a segurança da nossa infraestrutura é uma prioridade absoluta. A AWS oferece um ecossistema rico de serviços de segurança, mas configurá-los e integrá-los manualmente pode ser um processo complexo e propenso a erros. É aqui que a Infraestrutura como Código (IaC) com o Terraform se torna uma ferramenta poderosa.

Neste artigo, vou compartilhar como estruturei um módulo Terraform para implantar e configurar uma base de segurança robusta em uma conta AWS. O objetivo é criar uma configuração "standalone" que habilita e integra serviços essenciais como AWS Security Hub, Amazon GuardDuty, Amazon Inspector e Amazon Macie. Além disso, centralizaremos todos os achados de segurança (findings) usando o Amazon EventBridge e um tópico Amazon SNS, facilitando a integração com ferramentas de gerenciamento de incidentes.

Vamos mergulhar no código e entender como cada parte funciona.

Estrutura do Projeto

Para manter o projeto organizado e escalável, dividi o código em vários arquivos, cada um com uma responsabilidade clara:

infra/terraform/
├── locals.tf
├── main.tf
├── outputs.tf
├── variables.tf
├── version.tf
└── envs/
    └── staging/
        └── variables.tfvars
Enter fullscreen mode Exit fullscreen mode
  • version.tf: Define a versão do Terraform e dos providers, além de configurar o backend para armazenamento do estado.
  • variables.tf: Declara todas as variáveis de entrada do nosso módulo, permitindo customização.
  • locals.tf: Contém a lógica interna e as variáveis locais para evitar repetição de código.
  • main.tf: O coração do nosso módulo, onde todos os recursos da AWS são definidos.
  • outputs.tf: Expõe informações importantes sobre os recursos criados.
  • envs/staging/variables.tfvars: Um arquivo de exemplo para configurar as variáveis para um ambiente específico (neste caso, "staging").

Configurando o Backend e os Providers

Todo projeto Terraform começa com a definição de suas dependências e de como o estado será gerenciado. No arquivo version.tf, configuramos o backend para usar um bucket S3, o que é uma prática recomendada para colaboração e para manter o estado de forma segura e remota.

Substitua o valor de bucket por um bucket S3 que você tenha criado para armazenar o estado do Terraform.

# infra/terraform/version.tf

terraform {
  backend "s3" {
    bucket  = "meu-projeto-terraform-state-bucket" # ATENÇÃO: Substitua pelo seu bucket
    key     = "env/sec-hub"
    region  = "us-east-1"
    encrypt = false # Recomendo fortemente usar 'true' em produção
  }

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 6.4.0, < 7.0.0"
    }
  }

  required_version = ">= 1.6.0"
}
Enter fullscreen mode Exit fullscreen mode

Variáveis: A Porta de Entrada para a Customização

O arquivo variables.tf torna nosso módulo flexível. Nele, definimos opções para habilitar ou desabilitar serviços, configurar padrões de segurança e passar informações como nomes de recursos e endpoints.

Aqui estão algumas das variáveis mais importantes:

# infra/terraform/variables.tf

variable "enable_inspector" {
  description = "Habilita e configura o Amazon Inspector."
  type        = bool
  default     = false
}

variable "enable_macie" {
  description = "Habilita o Amazon Macie."
  type        = bool
  default     = false
}

variable "enable_guardduty" {
  description = "Habilita o Amazon GuardDuty."
  type        = bool
  default     = false
}

variable "securityhub_enabled_standards" {
  description = "Define quais padrões de segurança do Security Hub serão habilitados."
  type = object({
    fsbp = bool
    cis_v140 = bool
    pci_dss_v321 = bool
    # ... e outros padrões
  })
}

variable "sns_topic_name" {
  description = "Nome do tópico SNS para roteamento de incidentes."
  type        = string
  default     = "security-hub-incidents"
}

variable "incident_subscription_endpoint" {
  description = "Endpoint para se inscrever no tópico SNS (URL HTTPS, ARN de Lambda/SQS)."
  type        = string
  default     = ""
}
Enter fullscreen mode Exit fullscreen mode

Para configurar um ambiente, usamos um arquivo .tfvars. Veja um exemplo para "staging":

# infra/terraform/envs/staging/variables.tfvars

securityhub_enabled_standards = {
  fsbp     = true
  cis_v140 = false
  pci_dss_v321 = false
  # ...
}

enable_inspector = true
enable_macie     = true
enable_guardduty = true

sns_topic_name                   = "sec-hub-incidents-staging"
incident_subscription_endpoint = "https://api.minha-ferramenta.com/v2/alertas/sns/WEBHOOK_ID"

tags = {
  Environment = "staging"
  Project     = "sec-hub"
}
Enter fullscreen mode Exit fullscreen mode

Orquestrando os Recursos de Segurança

O arquivo main.tf é onde a mágica acontece. Vamos ver como os principais serviços são configurados.

1. AWS Security Hub

O Security Hub é o pilar da nossa configuração. Ele agrega, organiza e prioriza os achados de segurança de vários serviços da AWS. Primeiro, habilitamos a conta do Security Hub e, em seguida, inscrevemos os padrões de segurança que foram ativados através das nossas variáveis.

# infra/terraform/main.tf

resource "aws_securityhub_account" "this" {
  enable_default_standards  = false
  control_finding_generator = "SECURITY_CONTROL"
  auto_enable_controls      = true
}

resource "aws_securityhub_standards_subscription" "selected" {
  for_each      = local.securityhub_standards_to_enable
  standards_arn = each.value

  depends_on = [aws_securityhub_account.this]
}
Enter fullscreen mode Exit fullscreen mode

A variável local.securityhub_standards_to_enable é preenchida no arquivo locals.tf, que filtra apenas os padrões marcados como true no nosso arquivo de variáveis.

2. GuardDuty, Inspector e Macie

Com o Security Hub no lugar, habilitamos os outros serviços de segurança. A configuração é notavelmente simples, pois estamos usando o modo "standalone". O mais importante é que, após ativá-los, nós os integramos ao Security Hub.

# Habilitando o GuardDuty
resource "aws_guardduty_detector" "this" {
  count                        = var.enable_guardduty ? 1 : 0
  finding_publishing_frequency = "FIFTEEN_MINUTES"
  tags                         = var.tags
}

# Integrando o GuardDuty com o Security Hub
resource "aws_securityhub_product_subscription" "guardduty" {
  product_arn = "arn:aws:securityhub:${data.aws_region.current.name}::product/aws/guardduty"
  depends_on  = [aws_securityhub_account.this]
}

# Habilitando o Inspector v2
resource "aws_inspector2_enabler" "this" {
  count = var.enable_inspector ? 1 : 0
  account_ids    = [data.aws_caller_identity.current.account_id]
  resource_types = ["ECR", "EC2", "LAMBDA", "LAMBDA_CODE"]
}

# Integrando o Inspector com o Security Hub
resource "aws_securityhub_product_subscription" "inspector" {
  count       = var.enable_inspector ? 1 : 0
  product_arn = "arn:aws:securityhub:${data.aws_region.current.name}::product/aws/inspector"
  depends_on  = [aws_securityhub_account.this]
}
Enter fullscreen mode Exit fullscreen mode

A mesma lógica se aplica ao Amazon Macie.

3. Roteamento Centralizado com EventBridge e SNS

Ter os serviços habilitados é ótimo, mas precisamos de uma forma de agir sobre os achados. Para isso, criamos um pipeline de eventos:

  1. EventBridge Rule: Uma regra no EventBridge captura os findings de todos os nossos serviços de segurança (securityhub, guardduty, inspector2, etc.).
  2. SNS Topic: A regra do EventBridge encaminha esses eventos para um tópico SNS.
  3. SNS Subscription: Uma ferramenta externa (como uma plataforma de gerenciamento de incidentes, um Slack, ou uma função Lambda) se inscreve neste tópico para receber os alertas em tempo real.
# infra/terraform/main.tf

# Tópico SNS para receber todos os eventos
resource "aws_sns_topic" "incidents" {
  name = var.sns_topic_name
  tags = var.tags
}

# Regra do EventBridge para capturar os findings
resource "aws_cloudwatch_event_rule" "securityhub_findings" {
  name        = var.event_rule_name
  description = "Captura findings de segurança e encaminha para o SNS"
  event_pattern = jsonencode({
    source = [
      "aws.securityhub",
      "aws.guardduty",
      "aws.inspector2",
      "aws.cloudtrail",
      "aws.macie",
      "aws.config"
    ]
  })
  tags = var.tags
}

# Conecta a regra do EventBridge ao tópico SNS
resource "aws_cloudwatch_event_target" "to_sns" {
  rule      = aws_cloudwatch_event_rule.securityhub_findings.name
  arn       = aws_sns_topic.incidents.arn
  target_id = "securityhub-to-sns"
}

# Cria a inscrição no tópico para um endpoint externo
resource "aws_sns_topic_subscription" "incident_tool" {
  count     = local.subscription_provided ? 1 : 0
  topic_arn = aws_sns_topic.incidents.arn
  protocol  = local.protocol
  endpoint  = var.incident_subscription_endpoint
}
Enter fullscreen mode Exit fullscreen mode

A variável local.protocol inteligentemente detecta se o endpoint fornecido é uma URL HTTPS, um ARN de Lambda ou de SQS, ajustando o protocolo da inscrição automaticamente.

Conclusão

Com este módulo Terraform, conseguimos criar uma base de segurança automatizada, integrada e facilmente customizável para uma conta AWS. Centralizar os findings com o Security Hub e roteá-los via EventBridge e SNS nos dá uma visibilidade unificada e a capacidade de responder rapidamente a possíveis ameaças.

A Infraestrutura como Código não apenas acelera a implantação, mas também garante que nossas configurações de segurança sejam consistentes, versionadas e auditáveis. Espero que este guia prático sirva como um bom ponto de partida para você automatizar a segurança em seus próprios projetos na AWS.

Top comments (0)