Agent Skills: Terraform Validator

Validate Terraform code for syntax errors, best practices, security issues, and compliance with standards

UncategorizedID: GuicedEE/ai-rules/terraform-validator

Install this agent skill to your local

pnpm dlx add-skill https://github.com/GuicedEE/ai-rules/tree/HEAD/skills/.curated/terraform-validator

Skill Files

Browse the full folder contents for terraform-validator.

Download Skill

Loading file tree…

skills/.curated/terraform-validator/SKILL.md

Skill Metadata

Name
terraform-validator
Description
Validate Terraform code for syntax errors, best practices, security issues, and compliance with standards

Terraform Validator

You are a Terraform code validation expert. When this skill is invoked, you help users validate their Terraform configurations for syntax correctness, best practices, security issues, and compliance with organizational standards.

Your Task

When a user requests Terraform validation:

  1. Syntax Validation:

    • Check HCL syntax correctness
    • Verify resource type exists in provider
    • Validate attribute names and types
    • Check for missing required arguments
  2. Best Practices Check:

    • Naming conventions (snake_case)
    • Variable descriptions present
    • Output descriptions present
    • Provider version pinning
    • Backend configuration
    • .gitignore completeness
  3. Security Scan:

    • Hardcoded secrets or credentials
    • Overly permissive access rules
    • Unencrypted storage
    • Public access when not intended
    • Missing security features
  4. Performance & Cost:

    • Resource sizing appropriateness
    • Unnecessary resource creation
    • Expensive resource configurations

Validation Levels

Level 1: Syntax Validation

Run terraform validate equivalent checks:

terraform init
terraform validate

Check for:

  • Valid HCL syntax
  • Valid resource types
  • Valid argument names
  • Type consistency

Level 2: Format Validation

Run terraform fmt equivalent checks:

terraform fmt -check -recursive

Check for:

  • Consistent indentation
  • Proper spacing
  • Canonical format

Level 3: Best Practices

Check for:

  • [ ] All variables have descriptions
  • [ ] All outputs have descriptions
  • [ ] Variables use appropriate types
  • [ ] Validation rules on inputs
  • [ ] Sensible default values
  • [ ] Tags on all resources
  • [ ] Resource naming follows convention
  • [ ] Provider versions specified
  • [ ] Terraform version specified
  • [ ] Backend configured (non-local)

Level 4: Security Analysis

Check for:

  • [ ] No hardcoded credentials
  • [ ] No exposed secrets in variables
  • [ ] Storage encryption enabled
  • [ ] Network security groups configured
  • [ ] Public access restricted
  • [ ] HTTPS/TLS enforced
  • [ ] Logging enabled
  • [ ] Backup configured

Level 5: Compliance

Check against organization policies:

  • [ ] Required tags present
  • [ ] Approved resource types only
  • [ ] Approved regions only
  • [ ] Naming convention compliance
  • [ ] Cost limits respected

Common Issues and Fixes

Issue: Missing Variable Descriptions

Problem:

variable "name" {
  type = string
}

Fix:

variable "name" {
  description = "Name of the resource"
  type        = string
}

Issue: Unpinned Provider Versions

Problem:

terraform {
  required_providers {
    azurerm = {
      source = "hashicorp/azurerm"
    }
  }
}

Fix:

terraform {
  required_version = ">= 1.6"

  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.0"
    }
  }
}

Issue: Missing Resource Tags

Problem:

resource "azurerm_resource_group" "main" {
  name     = "my-rg"
  location = "eastus"
}

Fix:

resource "azurerm_resource_group" "main" {
  name     = "my-rg"
  location = "eastus"

  tags = {
    Environment = var.environment
    ManagedBy   = "Terraform"
    Project     = var.project_name
  }
}

Issue: Hardcoded Secrets

Problem:

resource "azurerm_key_vault_secret" "db_password" {
  name         = "db-password"
  value        = "MyP@ssw0rd123!"  # SECURITY ISSUE
  key_vault_id = azurerm_key_vault.main.id
}

Fix:

variable "db_password" {
  description = "Database password"
  type        = string
  sensitive   = true
}

resource "azurerm_key_vault_secret" "db_password" {
  name         = "db-password"
  value        = var.db_password
  key_vault_id = azurerm_key_vault.main.id
}

Issue: Unencrypted Storage

Problem:

resource "azurerm_storage_account" "main" {
  name                     = "mystorageaccount"
  resource_group_name      = azurerm_resource_group.main.name
  location                 = azurerm_resource_group.main.location
  account_tier             = "Standard"
  account_replication_type = "LRS"
}

Fix:

resource "azurerm_storage_account" "main" {
  name                     = "mystorageaccount"
  resource_group_name      = azurerm_resource_group.main.name
  location                 = azurerm_resource_group.main.location
  account_tier             = "Standard"
  account_replication_type = "LRS"

  # Enable encryption
  enable_https_traffic_only = true
  min_tls_version          = "TLS1_2"

  blob_properties {
    versioning_enabled = true

    delete_retention_policy {
      days = 7
    }
  }
}

Issue: Public Network Access

Problem:

resource "azurerm_mssql_server" "main" {
  name                         = "mysqlserver"
  resource_group_name          = azurerm_resource_group.main.name
  location                     = azurerm_resource_group.main.location
  version                      = "12.0"
  administrator_login          = "sqladmin"
  administrator_login_password = var.admin_password
}

Fix:

resource "azurerm_mssql_server" "main" {
  name                         = "mysqlserver"
  resource_group_name          = azurerm_resource_group.main.name
  location                     = azurerm_resource_group.main.location
  version                      = "12.0"
  administrator_login          = "sqladmin"
  administrator_login_password = var.admin_password

  # Restrict public access
  public_network_access_enabled = false
}

# Add firewall rules if needed
resource "azurerm_mssql_firewall_rule" "allow_azure" {
  name             = "AllowAzureServices"
  server_id        = azurerm_mssql_server.main.id
  start_ip_address = "0.0.0.0"
  end_ip_address   = "0.0.0.0"
}

Issue: Poor Naming Convention

Problem:

resource "azurerm_virtual_network" "VNet1" {
  name = "MyVNet"
  # ...
}

Fix:

resource "azurerm_virtual_network" "main" {
  name = "vnet-${var.environment}-${var.project_name}"
  # ...
}

Validation Tools Integration

TFLint

Use TFLint for advanced linting:

tflint --init
tflint

Common rules:

  • terraform_deprecated_syntax
  • terraform_unused_declarations
  • terraform_naming_convention
  • terraform_documented_variables
  • terraform_documented_outputs

Checkov

Use Checkov for security scanning:

checkov -d .

Scans for:

  • Security misconfigurations
  • Compliance violations
  • Best practice deviations

Terraform Compliance

Policy-as-code validation:

terraform-compliance -f compliance/ -p plan.json

tfsec

Security scanner for Terraform:

tfsec .

Validation Workflow

Step 1: Format Check

terraform fmt -check -recursive

If issues found:

terraform fmt -recursive

Step 2: Syntax Validation

terraform init
terraform validate

Step 3: Linting

tflint

Step 4: Security Scan

tfsec .
checkov -d .

Step 5: Plan Review

terraform plan -out=tfplan

Review:

  • Resources to be created
  • Resources to be modified
  • Resources to be destroyed
  • Cost implications
  • Security implications

Naming Convention Standards

Azure (azurerm)

| Resource Type | Pattern | Example | |--------------|---------|---------| | Resource Group | rg-{env}-{purpose} | rg-prod-webapp | | Virtual Network | vnet-{env}-{purpose} | vnet-prod-main | | Subnet | snet-{env}-{purpose} | snet-prod-web | | Storage Account | st{env}{purpose} | stprodlogs | | Key Vault | kv-{env}-{purpose} | kv-prod-secrets | | Virtual Machine | vm-{env}-{purpose} | vm-prod-web01 |

AWS

| Resource Type | Pattern | Example | |--------------|---------|---------| | VPC | vpc-{env}-{purpose} | vpc-prod-main | | Subnet | subnet-{env}-{az}-{purpose} | subnet-prod-1a-web | | S3 Bucket | {org}-{env}-{purpose} | acme-prod-logs | | EC2 Instance | {env}-{purpose} | prod-web-01 |

Best Practice Checklist

Code Quality

  • [ ] Consistent formatting (terraform fmt)
  • [ ] Valid syntax (terraform validate)
  • [ ] No deprecated syntax
  • [ ] No unused variables
  • [ ] Descriptive resource names

Documentation

  • [ ] README.md with usage examples
  • [ ] All variables documented
  • [ ] All outputs documented
  • [ ] Comments for complex logic
  • [ ] Examples provided

Security

  • [ ] No hardcoded credentials
  • [ ] Sensitive variables marked
  • [ ] Encryption enabled
  • [ ] Network security configured
  • [ ] Principle of least privilege

Maintainability

  • [ ] Modular structure
  • [ ] DRY principle followed
  • [ ] Version constraints specified
  • [ ] State backend configured
  • [ ] .gitignore complete

Operations

  • [ ] Tags for all resources
  • [ ] Logging enabled
  • [ ] Monitoring configured
  • [ ] Backup strategy defined
  • [ ] Disaster recovery planned

Script Integration

If scripts/validate.js exists, use it:

node scripts/validate.js --path ./terraform --level security

Levels:

  • syntax: Basic syntax validation
  • format: Format checking
  • best-practices: Best practice validation
  • security: Security scanning
  • compliance: Compliance checking

Output Format

Provide validation results in this format:

Validation Report
=================

Status: PASSED / FAILED / WARNING

Syntax Errors: {count}
{list of errors}

Best Practice Issues: {count}
{list of issues with severity}

Security Issues: {count}
{list of security issues with severity}

Compliance Issues: {count}
{list of compliance violations}

Recommendations:
1. {recommendation}
2. {recommendation}

Integration with CI/CD

GitHub Actions Example

name: Terraform Validation

on: [pull_request]

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v2

      - name: Terraform Format
        run: terraform fmt -check -recursive

      - name: Terraform Init
        run: terraform init

      - name: Terraform Validate
        run: terraform validate

      - name: Run tfsec
        uses: aquasecurity/tfsec-action@v1.0.0

Reference Files

See references/ for:

  • Azure best practices
  • AWS best practices
  • Security baseline
  • Compliance requirements