Infrastructure as Code security: scanning de Terraform e CloudFormation
1. Por que Segurança em IaC é Crítica para Devs
A adoção de Infrastructure as Code transformou a forma como provisionamos recursos em nuvem. Com GitOps, qualquer alteração na infraestrutura passa por pull requests, revisões e merge — exatamente como código de aplicação. No entanto, esse mesmo fluxo introduz um risco silencioso: a “misconfiguration as code”. Um bucket S3 configurado como público em um arquivo Terraform pode ser deployado para centenas de ambientes antes que alguém perceba.
Diferente de vulnerabilidades de aplicação (como SQL injection), falhas de infraestrutura costumam ser mais difíceis de detectar em tempo de execução. Uma política IAM com Action: "*" e Resource: "*" não gera erro — ela simplesmente funciona, dando acesso total a quem não deveria ter. As consequências são reais: exposição massiva de dados, cryptojacking em instâncias EC2 mal configuradas e movimentação lateral para outros serviços da conta.
2. Principais Ameaças em Templates Terraform e CloudFormation
Hardcoded Secrets
O erro mais comum entre desenvolvedores é inserir chaves de acesso diretamente nos templates:
resource "aws_iam_user" "deployer" {
name = "deployer"
}
resource "aws_iam_access_key" "deployer_key" {
user = aws_iam_user.deployer.name
}
# Perigoso: secret inline no código
output "secret_key" {
value = aws_iam_access_key.deployer_key.secret
sensitive = true # Apenas esconde no console, mas está no state file
}
Permissões Excessivas
Políticas muito permissivas são um convite para ataques:
resource "aws_iam_role_policy" "lambda_exec_role" {
name = "lambda_exec_policy"
role = aws_iam_role.lambda_exec.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = "*" # Jamais use Action: "*"
Resource = "*" # Jamais use Resource: "*"
}
]
})
}
Configurações Inseguras por Padrão
Muitos recursos têm defaults inseguros. Buckets públicos, security groups abertos para 0.0.0.0/0 e RDS sem SSL habilitado são exemplos clássicos:
resource "aws_security_group" "web_sg" {
name = "web_sg"
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # SSH aberto para o mundo
}
}
3. Ferramentas de Scanning Estático para IaC
checkov
Ferramenta da Bridgecrew que analisa mais de 1000 políticas pré-definidas para Terraform, CloudFormation, Kubernetes e outros. Suporta regras customizadas em Rego (OPA).
# Instalação
pip install checkov
# Scanning básico
checkov -d ./terraform --framework terraform
# Saída compacta (apenas falhas)
checkov -d ./terraform --compact
tfsec / trivy
tfsec é focado exclusivamente em Terraform, com regras específicas para provedores AWS, Azure e GCP. O Trivy (da Aqua Security) unificou o tfsec em sua ferramenta, oferecendo scanning de IaC, containers e dependências.
# Com tfsec (legado)
tfsec ./terraform
# Com trivy (recomendado)
trivy config ./terraform
cfn-lint e cfn-nag
Para CloudFormation, o cfn-lint valida a sintaxe do template, enquanto o cfn-nag busca padrões inseguros:
# cfn-lint
cfn-lint template.yaml
# cfn-nag
cfn_nag_scan --input-path template.yaml
Integração CI/CD
GitHub Actions com checkov:
name: IaC Security Scan
on: [pull_request]
jobs:
checkov:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run Checkov
uses: bridgecrewio/checkov-action@v12
with:
directory: terraform/
framework: terraform
soft_fail: false
output_format: cli
4. Políticas Customizadas e Compliance como Código
Regras Rego no checkov
Crie um diretório custom_policies/ com arquivos .rego:
# custom_policies/block_public_s3.rego
package main
deny[msg] {
resource := input.resource.aws_s3_bucket[_]
resource.config.block_public_access == null
msg := sprintf("Bucket %s não possui block_public_access configurado", [resource.name])
}
Execute com:
checkov -d ./terraform --external-checks-dir ./custom_policies
Mapeamento para Frameworks
O checkov já inclui mapeamentos para CIS Benchmarks, SOC2, PCI-DSS e HIPAA. Use a flag --framework para filtrar:
checkov -d ./terraform --framework terraform --check CKV_AWS_53 # CIS 2.1.1
Exemplo: Bloquear Deploy sem block_public_access
No pipeline, adicione um step que falhe se o bucket não tiver a configuração:
- name: Check S3 Public Access
run: |
checkov -d terraform/ --check CKV_AWS_53 --compact --quiet
if [ $? -ne 0 ]; then
echo "Bucket sem block_public_access. Corrija antes de merge."
exit 1
fi
5. Prevenção de Drift e Segurança Contínua
Detecção em Pull Requests
Configure gatilhos que executem scanning em cada PR:
name: PR Security Gate
on:
pull_request:
paths:
- 'terraform/**'
jobs:
tf-plan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Terraform Plan
run: |
cd terraform
terraform init
terraform plan -out=tfplan
- name: Checkov on Plan
run: |
checkov -f terraform/tfplan --framework terraform
Monitoramento Pós-Deploy
Use ferramentas como AWS Config ou Terraform Cloud Drift Detection para comparar o estado real com o template aprovado:
# AWS Config rule para detectar buckets públicos
resource "aws_config_config_rule" "s3_bucket_public_read_prohibited" {
name = "s3-bucket-public-read-prohibited"
source {
owner = "AWS"
source_identifier = "S3_BUCKET_PUBLIC_READ_PROHIBITED"
}
}
6. Boas Práticas para Devs no Dia a Dia
Use Variáveis, Nunca Literais
# Ruim
resource "aws_db_instance" "db" {
master_password = "MinhaSenhaForte123!"
}
# Bom
variable "db_password" {
type = string
sensitive = true
}
resource "aws_db_instance" "db" {
master_password = var.db_password
}
Menor Privilégio
Sempre restrinja ações e recursos ao mínimo necessário:
resource "aws_iam_policy" "lambda_policy" {
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = ["s3:GetObject", "s3:ListBucket"]
Resource = ["arn:aws:s3:::meu-bucket-app/*", "arn:aws:s3:::meu-bucket-app"]
}
]
})
}
Versionamento e Dependências
Use módulos de fontes confiáveis (Terraform Registry oficial) e fixe versões:
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "5.0.0" # Versão fixa, não latest
}
Documente Exceções
Quando uma regra de segurança precisa ser suprimida, documente no código:
# checkov:skip=CKV_AWS_53: Bucket usado para assets públicos intencionais
resource "aws_s3_bucket" "public_assets" {
bucket = "meu-site-assets"
acl = "public-read"
}
7. Exemplo Prático: Pipeline Seguro com Terraform + checkov
Estrutura do Repositório
terraform/
├── main.tf
├── variables.tf
├── outputs.tf
├── .checkov.yml
└── custom_policies/
└── block_public_s3.rego
Arquivo .checkov.yml
compact: true
quiet: true
skip-check:
- CKV_AWS_18 # Exceção aprovada: bucket de logs
output-format: cli
Pipeline GitHub Actions Completo
name: IaC Security Pipeline
on:
pull_request:
branches: [main]
paths:
- 'terraform/**'
jobs:
security-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: 1.5.0
- name: Terraform Init
run: terraform init
working-directory: ./terraform
- name: Terraform Validate
run: terraform validate
working-directory: ./terraform
- name: Install Checkov
run: pip install checkov
- name: Run Checkov Scan
id: checkov
run: |
checkov -d ./terraform \
--framework terraform \
--external-checks-dir ./terraform/custom_policies \
--config-file ./terraform/.checkov.yml \
--output json > checkov_report.json
# Falha se encontrar erros críticos
CRITICAL=$(jq '.summary.failed | length' checkov_report.json)
if [ "$CRITICAL" -gt 0 ]; then
echo "Falhas críticas encontradas: $CRITICAL"
cat checkov_report.json | jq '.results.failed_checks[] | {resource, check_id, severity}'
exit 1
fi
- name: Upload Report
uses: actions/upload-artifact@v3
with:
name: checkov-report
path: checkov_report.json
Saída Esperada
Quando o scanning encontra falhas críticas, o pipeline bloqueia o merge:
Falhas críticas encontradas: 2
{
"resource": "aws_s3_bucket.public_assets",
"check_id": "CKV_AWS_53",
"severity": "CRITICAL"
}
{
"resource": "aws_security_group.web_sg",
"check_id": "CKV_AWS_260",
"severity": "CRITICAL"
}
Referências
- Checkov Documentation — Documentação oficial da ferramenta de scanning estático para IaC, com exemplos de políticas e integrações.
- tfsec GitHub Repository — Repositório oficial do tfsec (agora parte do Trivy) com regras de segurança para Terraform.
- AWS cfn-nag GitHub — Ferramenta da Stelligent para análise de segurança em templates CloudFormation, com mais de 200 regras.
- Trivy IaC Scanning Guide — Guia oficial do Trivy para scanning de configurações IaC, incluindo Terraform e CloudFormation.
- CIS AWS Foundations Benchmark — Benchmark de segurança da CIS para AWS, com recomendações mapeáveis para políticas de IaC.
- Bridgecrew OPA Policies — Repositório com políticas Rego customizáveis para checkov, abrangendo centenas de recursos AWS.
- Terraform Security Best Practices — Tutoriais oficiais da HashiCorp sobre segurança em Terraform, incluindo gerenciamento de secrets e políticas.