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
-
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"
}
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 = ""
}
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"
}
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]
}
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]
}
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:
- EventBridge Rule: Uma regra no EventBridge captura os findings de todos os nossos serviços de segurança (
securityhub,guardduty,inspector2, etc.). - SNS Topic: A regra do EventBridge encaminha esses eventos para um tópico SNS.
- 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
}
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)