home / skills / physics91 / claude-vibe / terraform-reviewer

terraform-reviewer skill

/skills/terraform-reviewer

This skill reviews Terraform code for module structure, state backend configuration, security policies, and variable validation to improve compliance.

npx playbooks add skill physics91/claude-vibe --skill terraform-reviewer

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
8.0 KB
---
name: terraform-reviewer
description: |
  WHEN: Terraform code review, module structure, state management, security policies
  WHAT: Module organization + State backend + Security policies + Variable validation + Best practices
  WHEN NOT: Kubernetes → k8s-reviewer, Docker → docker-reviewer
---

# Terraform Reviewer Skill

## Purpose
Reviews Terraform code for module structure, state management, security, and best practices.

## When to Use
- Terraform code review
- Module structure review
- State backend configuration
- Security policy review
- Variable and output review

## Project Detection
- `*.tf` files in project
- `main.tf`, `variables.tf`, `outputs.tf`
- `modules/` directory
- `terraform.tfvars`

## Workflow

### Step 1: Analyze Project
```
**Terraform**: 1.6+
**Provider**: AWS/GCP/Azure
**Backend**: S3/GCS/Azure Blob
**Modules**: Custom + Registry
```

### Step 2: Select Review Areas
**AskUserQuestion:**
```
"Which areas to review?"
Options:
- Full Terraform review (recommended)
- Module structure
- State management
- Security and compliance
- Variable validation
multiSelect: true
```

## Detection Rules

### Module Structure
| Check | Recommendation | Severity |
|-------|----------------|----------|
| All resources in main.tf | Split by resource type | MEDIUM |
| No modules | Extract reusable modules | MEDIUM |
| Hardcoded values | Use variables | HIGH |
| No outputs | Add relevant outputs | MEDIUM |

```
# GOOD: Project structure
terraform/
├── environments/
│   ├── dev/
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   └── terraform.tfvars
│   └── prod/
│       ├── main.tf
│       ├── variables.tf
│       └── terraform.tfvars
├── modules/
│   ├── vpc/
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   └── outputs.tf
│   └── eks/
│       ├── main.tf
│       ├── variables.tf
│       └── outputs.tf
└── README.md
```

```hcl
# BAD: Hardcoded values
resource "aws_instance" "web" {
  ami           = "ami-12345678"
  instance_type = "t3.micro"

  tags = {
    Name = "web-server"
  }
}

# GOOD: Parameterized with variables
variable "instance_type" {
  description = "EC2 instance type"
  type        = string
  default     = "t3.micro"

  validation {
    condition     = can(regex("^t3\\.", var.instance_type))
    error_message = "Instance type must be t3 family."
  }
}

variable "environment" {
  description = "Environment name"
  type        = string

  validation {
    condition     = contains(["dev", "staging", "prod"], var.environment)
    error_message = "Environment must be dev, staging, or prod."
  }
}

resource "aws_instance" "web" {
  ami           = data.aws_ami.amazon_linux.id
  instance_type = var.instance_type

  tags = merge(local.common_tags, {
    Name = "${var.project}-${var.environment}-web"
  })
}
```

### State Management
| Check | Recommendation | Severity |
|-------|----------------|----------|
| Local state | Use remote backend | CRITICAL |
| No state locking | Enable DynamoDB/GCS lock | HIGH |
| No state encryption | Enable encryption | HIGH |
| Shared state file | Split by environment | MEDIUM |

```hcl
# BAD: Local state (default)
# No backend configuration

# GOOD: Remote backend with locking
terraform {
  backend "s3" {
    bucket         = "mycompany-terraform-state"
    key            = "prod/vpc/terraform.tfstate"
    region         = "us-east-1"
    encrypt        = true
    dynamodb_table = "terraform-state-lock"
  }
}

# For GCP
terraform {
  backend "gcs" {
    bucket  = "mycompany-terraform-state"
    prefix  = "prod/vpc"
  }
}
```

### Security
| Check | Recommendation | Severity |
|-------|----------------|----------|
| Secrets in tfvars | Use secret manager | CRITICAL |
| Public S3 bucket | Set ACL private | CRITICAL |
| Open security group | Restrict CIDR | CRITICAL |
| No encryption | Enable encryption | HIGH |

```hcl
# BAD: Security issues
resource "aws_security_group" "web" {
  ingress {
    from_port   = 0
    to_port     = 65535
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]  # Wide open!
  }
}

resource "aws_s3_bucket" "data" {
  bucket = "my-data-bucket"
  acl    = "public-read"  # Public!
}

# GOOD: Secure configuration
resource "aws_security_group" "web" {
  name        = "${var.project}-web-sg"
  description = "Security group for web servers"
  vpc_id      = var.vpc_id

  ingress {
    description = "HTTPS from load balancer"
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    security_groups = [aws_security_group.alb.id]
  }

  egress {
    description = "Allow all outbound"
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = local.common_tags
}

resource "aws_s3_bucket" "data" {
  bucket = "${var.project}-${var.environment}-data"
}

resource "aws_s3_bucket_public_access_block" "data" {
  bucket = aws_s3_bucket.data.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

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_master_key_id = aws_kms_key.s3.arn
    }
  }
}
```

### Variable Validation
| Check | Recommendation | Severity |
|-------|----------------|----------|
| No type constraint | Add type | MEDIUM |
| No validation | Add validation block | MEDIUM |
| No description | Add description | LOW |
| Sensitive not marked | Add sensitive = true | HIGH |

```hcl
# GOOD: Well-defined variables
variable "vpc_cidr" {
  description = "CIDR block for VPC"
  type        = string
  default     = "10.0.0.0/16"

  validation {
    condition     = can(cidrnetmask(var.vpc_cidr))
    error_message = "Must be a valid CIDR block."
  }
}

variable "db_password" {
  description = "Database password"
  type        = string
  sensitive   = true  # Won't show in logs

  validation {
    condition     = length(var.db_password) >= 16
    error_message = "Password must be at least 16 characters."
  }
}

variable "allowed_environments" {
  description = "List of allowed environment names"
  type        = list(string)
  default     = ["dev", "staging", "prod"]
}
```

### Resource Naming
| Check | Recommendation | Severity |
|-------|----------------|----------|
| Inconsistent naming | Use naming convention | MEDIUM |
| No tags | Add standard tags | MEDIUM |

```hcl
# GOOD: Consistent naming and tagging
locals {
  name_prefix = "${var.project}-${var.environment}"

  common_tags = {
    Project     = var.project
    Environment = var.environment
    ManagedBy   = "terraform"
    Owner       = var.owner
  }
}

resource "aws_vpc" "main" {
  cidr_block = var.vpc_cidr

  tags = merge(local.common_tags, {
    Name = "${local.name_prefix}-vpc"
  })
}
```

## Response Template
```
## Terraform Review Results

**Project**: [name]
**Terraform**: 1.6 | **Provider**: AWS

### Module Structure
| Status | File | Issue |
|--------|------|-------|
| MEDIUM | main.tf | 500+ lines, should split |

### State Management
| Status | File | Issue |
|--------|------|-------|
| CRITICAL | - | Using local state |

### Security
| Status | File | Issue |
|--------|------|-------|
| CRITICAL | security.tf:23 | Security group allows 0.0.0.0/0 |

### Variables
| Status | File | Issue |
|--------|------|-------|
| HIGH | variables.tf | db_password not marked sensitive |

### Recommended Actions
1. [ ] Configure remote state backend with locking
2. [ ] Restrict security group ingress rules
3. [ ] Mark sensitive variables
4. [ ] Split main.tf into logical files
```

## Best Practices
1. **Structure**: Separate by environment, use modules
2. **State**: Remote backend with locking and encryption
3. **Security**: No secrets in code, least privilege
4. **Variables**: Type constraints, validation, descriptions
5. **Naming**: Consistent convention, standard tags

## Integration
- `k8s-reviewer`: EKS/GKE cluster configs
- `infra-security-reviewer`: Compliance checks
- `ci-cd-reviewer`: Terraform in pipelines

Overview

This skill reviews Terraform projects for module organization, state backend configuration, security posture, variable validation, and general best practices. It identifies structural issues, unsafe defaults, and missing conventions that cause drift, outages, or compliance gaps. The goal is actionable recommendations that developers and infra teams can apply quickly.

How this skill works

The reviewer scans Terraform files (/*.tf, modules/, terraform.tfvars) and detects common anti-patterns like large monolithic main.tf, local state usage, hardcoded values, and open security groups. It rates issues by severity (CRITICAL/HIGH/MEDIUM/LOW) and produces targeted remediation steps: backend config, locking, encryption, variable validation, and module extraction. It can focus on selected areas (full review, modules, state, security, variables) to speed iterative checks.

When to use it

  • During pull requests that modify Terraform code or infrastructure modules
  • When introducing or reorganizing modules and environments
  • Before switching or deploying state backends (S3/GCS/Azure Blob)
  • When auditing security posture: secrets, S3 ACLs, security groups, encryption
  • During CI pipelines to catch policy and validation gaps early

Best practices

  • Separate environments and extract reusable modules under modules/ to reduce duplication
  • Use a remote backend with state locking and server-side encryption (e.g., S3 + DynamoDB, GCS)
  • Never store secrets in tfvars; reference secret managers and mark sensitive variables
  • Add type constraints, validation blocks, and descriptions for all variables
  • Apply consistent naming and tags via locals to enforce conventions across resources

Example use cases

  • Review a repo where main.tf has 500+ lines and recommend splitting by resource type
  • Detect local state and provide a ready S3/GCS backend configuration with locking
  • Find hardcoded AMIs and suggest parameterization with validation for instance types
  • Identify security groups allowing 0.0.0.0/0 and propose least-privilege ingress rules
  • Flag variables missing sensitive = true or lacking validation and provide fixes

FAQ

Can this skill run on mixed-provider projects?

Yes. It detects provider blocks and applies provider-agnostic checks, with specific guidance for AWS, GCP, and Azure backends when relevant.

Does it modify code or only report issues?

It produces actionable recommendations and example code snippets but does not modify your repository automatically.