Analisador de Segurança Terraform
Analise código Terraform HCL para misconfigurações de segurança e portas abertas
Terraform Security Analysis
Terraform security analysis is the practice of scanning Infrastructure-as-Code (IaC) configurations
to identify insecure resource definitions, overly permissive access policies, unencrypted storage,
exposed network surfaces, and compliance violations before infrastructure is provisioned. Terraform
configurations declaratively define cloud resources — from S3 buckets and RDS instances to IAM roles
and security groups — but a syntactically valid configuration is not necessarily a secure one. A
publicly accessible S3 bucket, a security group allowing ingress from 0.0.0.0/0 on all
ports, or an RDS instance without encryption at rest are all valid Terraform that provisions dangerous
infrastructure. Security analysis catches these misconfigurations at the code review stage, long before
terraform apply creates real attack surfaces in production.
The shift-left security approach treats infrastructure code with the same rigor as application code. Just as static analysis tools detect SQL injection or buffer overflows in application source, Terraform security analyzers detect overly permissive IAM policies, missing encryption configurations, disabled logging, and network rules that violate the principle of least privilege. By integrating these checks into CI/CD pipelines and developer workflows, teams catch security issues when the cost of remediation is a code change rather than an incident response — reducing mean time to remediation from days to minutes and preventing security debt from accumulating in deployed infrastructure.
Common Terraform Security Misconfigurations
Certain categories of misconfiguration appear repeatedly across Terraform codebases, regardless of cloud provider or team size. Understanding these patterns is the first step toward preventing them:
-
Public S3 buckets and storage: Setting
acl = "public-read"or omittingblock_public_accessconfiguration onaws_s3_bucketresources exposes bucket contents to the internet. Numerous data breaches trace back to this single misconfiguration — leaked customer records, backup databases, and credential files discovered by automated scanners within hours of exposure. -
Overly permissive security groups: Ingress rules with
cidr_blocks = ["0.0.0.0/0"]on sensitive ports (SSH 22, RDP 3389, database ports 3306/5432/27017) allow connection attempts from any IP address globally. Brute-force attacks target these open ports continuously, and a single weak password becomes a complete compromise. -
Unencrypted data stores: RDS instances without
storage_encrypted = true, EBS volumes withoutencrypted = true, and ElastiCache clusters withoutat_rest_encryption_enabledstore sensitive data in plaintext on disk. Physical access to storage media, snapshot theft, or cross-account access bypasses all application-layer security controls. -
Wildcard IAM policies: Using
"Action": "*"or"Resource": "*"in IAM policy documents grants unrestricted permissions. An compromised credential withAdministratorAccesscan delete all resources, exfiltrate all data, and provision cryptocurrency miners — the maximum possible blast radius from a single leaked key. - Disabled logging and monitoring: Resources without CloudTrail enabled, VPC Flow Logs configured, or access logging on load balancers create blind spots where attacks proceed undetected. Post-incident forensics becomes impossible without audit trails.
-
Secrets in Terraform state: Storing passwords, API keys, or certificates
directly in
terraform.tfvarsor as default variable values embeds them in state files. Terraform state contains every attribute of every managed resource in plaintext — a state file is a complete inventory of credentials for the entire infrastructure.
Infrastructure Security Patterns and Best Practices
Secure Terraform configurations follow established patterns that enforce defense in depth, least privilege, and encryption by default:
-
Least privilege IAM: Define granular IAM policies that specify exact actions
on exact resources. Instead of
"s3:*"on"*", use"s3:GetObject"on"arn:aws:s3:::my-bucket/prefix/*". Useaws_iam_policy_documentdata sources with conditions for additional constraints like source IP, MFA requirement, or time-based access. - Encryption everywhere: Enable encryption at rest for all storage resources (S3, RDS, EBS, DynamoDB, ElastiCache) and encryption in transit via TLS for all network communication. Use AWS KMS customer-managed keys (CMK) rather than AWS-managed keys for granular key rotation control and access auditing.
- Network segmentation: Place resources in private subnets with no direct internet access. Route outbound traffic through NAT gateways. Restrict security group rules to specific CIDR ranges for known office IPs or VPN endpoints. Use VPC endpoints for AWS service access without traversing the public internet.
- Immutable infrastructure: Use launch templates with hardened AMIs rather than provisioning instances that require post-deployment configuration. Treat infrastructure as disposable — replace rather than patch, rebuild rather than repair.
-
State file protection: Store Terraform state in encrypted S3 backends with
versioning enabled, DynamoDB locking, and restrictive bucket policies. Never commit state files
to version control. Use
sensitive = trueon variables and outputs containing credentials to prevent them from appearing in CLI output.
Compliance Frameworks and CIS Benchmarks
Industry compliance frameworks provide structured rule sets that security analyzers evaluate Terraform configurations against. These benchmarks codify security best practices into auditable, enforceable policies:
- CIS AWS Foundations Benchmark: Covers 49+ controls across IAM, logging, monitoring, networking, and storage. Key checks include ensuring MFA is enabled for the root account, CloudTrail is enabled in all regions, S3 bucket logging is active, and security groups do not allow unrestricted ingress to high-risk ports. Each control maps directly to Terraform resource attributes that can be validated statically.
-
CIS Azure Foundations Benchmark: Defines controls for Azure-specific resources
including Network Security Groups, Storage Account configurations, Azure SQL auditing, and
Key Vault access policies. Validates that
azurerm_storage_accountresources havemin_tls_version = "TLS1_2"andenable_https_traffic_only = true. -
CIS GCP Foundations Benchmark: Covers Compute Engine firewall rules, Cloud
Storage bucket IAM, BigQuery dataset access, and Cloud SQL instance configurations. Ensures
that
google_compute_firewallrules do not allow SSH from0.0.0.0/0and that Cloud SQL instances require SSL connections. - SOC 2 and HIPAA mapping: Terraform security rules can be mapped to SOC 2 trust service criteria (security, availability, confidentiality) and HIPAA technical safeguards. Encryption at rest satisfies HIPAA §164.312(a)(2)(iv), while access logging maps to SOC 2 CC6.1 monitoring requirements.
A security analyzer evaluates each resource block against applicable benchmark rules,
reporting violations with severity levels (critical, high, medium, low) and direct references to
the specific CIS control or compliance requirement that the finding violates.
Security Group and Network ACL Analysis
Network security configuration is one of the highest-impact areas for Terraform security analysis. A single overly permissive rule can expose entire application stacks to the internet:
-
Port exposure analysis: Evaluates which ports are open to which CIDR ranges.
Flags administrative ports (SSH 22, RDP 3389, WinRM 5985) open to
0.0.0.0/0, database ports (MySQL 3306, PostgreSQL 5432, MongoDB 27017, Redis 6379) accessible from outside the VPC, and any rule usingprotocol = "-1"(all traffic) without CIDR restriction. -
Egress rule validation: Default egress rules allowing all outbound traffic
(
0.0.0.0/0on all ports) enable data exfiltration and command-and-control communication. Hardened configurations restrict egress to known required destinations — specific CIDR ranges for API endpoints, port 443 for HTTPS services, and VPC endpoint prefixes for AWS service access. -
Cross-reference with resource types: A security group attached to a public-facing
ALB has different risk characteristics than one on a private backend service. The analyzer
considers the security group's attachment context — a rule allowing port 80/443 from
0.0.0.0/0is expected on a load balancer but critical on a database instance. - NACL layer analysis: Network ACLs provide stateless subnet-level filtering as a second defense layer. The analyzer verifies that NACLs do not accidentally deny legitimate traffic (blocking ephemeral ports breaks TCP return traffic) and that they complement security group rules rather than creating conflicting allow/deny logic.
Code Examples
Insecure vs Secure Terraform Configuration
# ❌ INSECURE — Common misconfigurations found by security analysis
resource "aws_s3_bucket" "data" {
bucket = "company-sensitive-data"
# Missing: block_public_access, versioning, encryption, logging
}
resource "aws_s3_bucket_acl" "data" {
bucket = aws_s3_bucket.data.id
acl = "public-read" # ❌ CRITICAL: Publicly accessible bucket
}
resource "aws_security_group" "web" {
name = "web-server-sg"
ingress {
from_port = 0
to_port = 65535
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # ❌ CRITICAL: All ports open to internet
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"] # ⚠️ HIGH: Unrestricted egress
}
}
resource "aws_db_instance" "main" {
engine = "postgres"
instance_class = "db.t3.medium"
# ❌ storage_encrypted = false (default)
# ❌ publicly_accessible = true
# ❌ No backup or logging
publicly_accessible = true
skip_final_snapshot = true
}
resource "aws_iam_policy" "admin" {
name = "developer-policy"
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Action = "*" # ❌ CRITICAL: Wildcard actions
Resource = "*" # ❌ CRITICAL: Wildcard resources
}]
})
}
# ─────────────────────────────────────────────────
# ✅ SECURE — Hardened configuration passing all CIS checks
resource "aws_s3_bucket" "data" {
bucket = "company-sensitive-data"
}
resource "aws_s3_bucket_versioning" "data" {
bucket = aws_s3_bucket.data.id
versioning_configuration {
status = "Enabled" # ✅ Version history for recovery
}
}
resource "aws_s3_bucket_server_side_encryption_configuration" "data" {
bucket = aws_s3_bucket.data.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "aws:kms" # ✅ KMS encryption at rest
kms_master_key_id = aws_kms_key.data.arn
}
}
}
resource "aws_s3_bucket_public_access_block" "data" {
bucket = aws_s3_bucket.data.id
block_public_acls = true # ✅ Block public ACLs
block_public_policy = true # ✅ Block public policies
ignore_public_acls = true # ✅ Ignore existing public ACLs
restrict_public_buckets = true # ✅ Restrict public access
}
resource "aws_security_group" "web" {
name = "web-server-sg"
vpc_id = aws_vpc.main.id
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["10.0.0.0/16"] # ✅ VPC-only HTTPS access
}
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
security_groups = [aws_security_group.bastion.id] # ✅ SSH via bastion only
}
egress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # ✅ HTTPS-only egress
}
}
resource "aws_db_instance" "main" {
engine = "postgres"
instance_class = "db.t3.medium"
storage_encrypted = true # ✅ Encryption at rest
kms_key_id = aws_kms_key.rds.arn
publicly_accessible = false # ✅ Private subnet only
deletion_protection = true # ✅ Prevent accidental deletion
backup_retention_period = 7 # ✅ 7-day backup retention
db_subnet_group_name = aws_db_subnet_group.private.name
enabled_cloudwatch_logs_exports = [
"postgresql", "upgrade" # ✅ Audit logging enabled
]
}
resource "aws_iam_policy" "developer" {
name = "developer-policy"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = ["s3:GetObject", "s3:ListBucket"] # ✅ Specific actions
Resource = [
aws_s3_bucket.data.arn, # ✅ Specific bucket
"${aws_s3_bucket.data.arn}/*"
]
},
{
Effect = "Allow"
Action = ["logs:GetLogEvents", "logs:FilterLogEvents"]
Resource = "arn:aws:logs:*:*:log-group:/app/*" # ✅ Scoped resource
}
]
})
}Standards & Specifications
- Terraform AWS Provider Documentation — Official HashiCorp documentation for all AWS resource types, their arguments, and security-relevant attributes
- CIS Amazon Web Services Foundations Benchmark — Industry-standard security benchmark defining 49+ controls for AWS infrastructure configuration and monitoring
- HashiCorp Terraform Security Best Practices — Official HashiCorp guidance on securing Terraform workflows, state management, and provider authentication
- AWS Well-Architected Framework — Security Pillar — AWS reference architecture covering identity management, detection, infrastructure protection, data protection, and incident response