agentsclimarketplace

Infra terraform security scan

Skill ivanshamaev/de-agent-skills/group_skills/infra_dataops_group_skills/infra_terraform_security_scan

Terraform security scanning — tfsec static analysis (AWS/GCP/Azure misconfigurations), Checkov IaC policy checks (750+ rules, CIS benchmarks), tflint security rules, KICS scanner, S3 encryption/public access/versioning checks, IAM least-privilege patterns, security group rule review (0.0.0.0/0), KMS key rotation, VPC flow logs, CloudTrail enabled, pre-commit hooks, SARIF output for GitHub Security tab, policy-as-code with OPA/SentinelFrom its SKILL.md

Install
npx -y skills add ivanshamaev/de-agent-skills --skill infra_terraform_security_scan

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 15 stars15 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

10.0 KB, ~2.8k tokens by cl100k_base, as published. Nobody here has run it

Terraform Security Scan

When to Use

  • Security review of a Terraform PR before merge
  • Compliance assessment against CIS Benchmarks (AWS/GCP/Azure)
  • Auditing existing infrastructure for misconfigurations
  • Setting up security gates in CI/CD pipelines
  • Establishing policy-as-code for IaC governance

tfsec — Static Analysis

Installation and Basic Usage

# Install
brew install tfsec              # macOS
curl -s https://raw.githubusercontent.com/aquasecurity/tfsec/master/scripts/install_linux.sh | bash

# Scan current directory
tfsec .

# Scan with specific output format
tfsec . --format json | jq '.results[] | {rule: .rule_id, severity: .severity, description: .description}'

# SARIF output for GitHub Security tab
tfsec . --format sarif --out tfsec-results.sarif

# Include tfvars values in analysis
tfsec . --tfvars-file terraform.tfvars

# Ignore low-severity findings
tfsec . --minimum-severity HIGH

Inline Suppressions

resource "aws_s3_bucket" "public_assets" {
  bucket = "my-company-public-assets"

  #tfsec:ignore:aws-s3-no-public-buckets
  #tfsec:ignore:aws-s3-block-public-acls
  tags = local.common_tags
}

Config File

# .tfsec/config.yaml
minimum_severity: MEDIUM
exclude:
  - aws-s3-no-public-buckets   # intentionally public CDN bucket

Checkov — 750+ Policy Checks

Installation and Usage

# Install
pip install checkov

# Scan Terraform directory
checkov -d . --framework terraform

# Scan with specific checks only (CIS AWS benchmark)
checkov -d . --check CKV_AWS_1,CKV_AWS_2  # specific checks
checkov -d . --bc-api-key $BRIDGECREW_API_KEY  # with Bridgecrew cloud

# Output formats
checkov -d . -o json > checkov-results.json
checkov -d . -o sarif > checkov-results.sarif

# Soft-fail: report findings but don't fail the pipeline
checkov -d . --soft-fail

# Skip specific checks
checkov -d . --skip-check CKV_AWS_79,CKV_AWS_91

Key Terraform Checks (AWS)

Check IDDescription
CKV_AWS_18S3 bucket access logging enabled
CKV_AWS_19S3 bucket encryption enabled
CKV_AWS_20S3 bucket not publicly accessible
CKV_AWS_21S3 versioning enabled
CKV_AWS_52S3 MFA delete enabled
CKV_AWS_2ALB/ELB HTTPS listeners only
CKV_AWS_79EC2 IMDSv2 enforced
CKV_AWS_135EC2 no public IP at launch
CKV_AWS_17RDS not publicly accessible
CKV_AWS_16RDS encryption at rest
CKV_AWS_23RDS backup retention >= 7 days
CKV_AWS_25Security group no unrestricted SSH
CKV_AWS_24Security group no unrestricted RDP
CKV_AWS_36CloudTrail logging enabled
CKV_AWS_86CloudFront logging enabled

Common Security Patterns to Enforce

S3 Hardening

# ✅ Correct: fully hardened S3 bucket
resource "aws_s3_bucket" "data_lake" {
  bucket = "${local.name_prefix}-data-lake"
  tags   = local.common_tags
}

resource "aws_s3_bucket_versioning" "data_lake" {
  bucket = aws_s3_bucket.data_lake.id
  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_s3_bucket_server_side_encryption_configuration" "data_lake" {
  bucket = aws_s3_bucket.data_lake.id
  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm     = "aws:kms"
      kms_master_key_id = aws_kms_key.data_lake.arn
    }
    bucket_key_enabled = true
  }
}

resource "aws_s3_bucket_public_access_block" "data_lake" {
  bucket                  = aws_s3_bucket.data_lake.id
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

resource "aws_s3_bucket_logging" "data_lake" {
  bucket = aws_s3_bucket.data_lake.id
  target_bucket = aws_s3_bucket.access_logs.id
  target_prefix = "data-lake/"
}

KMS Key with Rotation

resource "aws_kms_key" "data_lake" {
  description             = "KMS key for data lake S3 encryption"
  enable_key_rotation     = true       # CKV_AWS_7: rotation required
  deletion_window_in_days = 30
  tags                    = local.common_tags
}

resource "aws_kms_alias" "data_lake" {
  name          = "alias/${local.name_prefix}-data-lake"
  target_key_id = aws_kms_key.data_lake.key_id
}

Security Groups — No 0.0.0.0/0

# ❌ Fails CKV_AWS_25 — unrestricted SSH
resource "aws_security_group_rule" "bad_ssh" {
  type        = "ingress"
  from_port   = 22
  to_port     = 22
  protocol    = "tcp"
  cidr_blocks = ["0.0.0.0/0"]   # never do this
}

# ✅ Correct — restrict to VPC CIDR or specific source SG
resource "aws_security_group_rule" "bastion_ssh" {
  type                     = "ingress"
  from_port                = 22
  to_port                  = 22
  protocol                 = "tcp"
  source_security_group_id = aws_security_group.bastion.id
  security_group_id        = aws_security_group.workers.id
}

IAM Least Privilege

# ❌ Overly broad
data "aws_iam_policy_document" "bad" {
  statement {
    actions   = ["s3:*"]
    resources = ["*"]
  }
}

# ✅ Scoped to specific bucket and actions
data "aws_iam_policy_document" "airflow_s3" {
  statement {
    sid     = "ReadDags"
    actions = ["s3:GetObject", "s3:ListBucket"]
    resources = [
      aws_s3_bucket.dags.arn,
      "${aws_s3_bucket.dags.arn}/*",
    ]
  }
  statement {
    sid       = "WriteLogs"
    actions   = ["s3:PutObject"]
    resources = ["${aws_s3_bucket.logs.arn}/airflow/*"]
  }
}

RDS Security

resource "aws_db_instance" "main" {
  engine                  = "postgres"
  engine_version          = "15.4"
  instance_class          = "db.t3.medium"

  # Security requirements
  publicly_accessible     = false          # CKV_AWS_17
  storage_encrypted       = true           # CKV_AWS_16
  kms_key_id              = aws_kms_key.rds.arn
  backup_retention_period = 7              # CKV_AWS_23 — >= 7 days
  deletion_protection     = true
  skip_final_snapshot     = false

  # No default port in production
  port = 5433

  db_subnet_group_name   = aws_db_subnet_group.main.name
  vpc_security_group_ids = [aws_security_group.rds.id]
}

GitHub Actions CI Integration

name: Terraform Security Scan

on:
  pull_request:
    paths:
      - "**.tf"

jobs:
  tfsec:
    runs-on: ubuntu-latest
    permissions:
      security-events: write  # for SARIF upload

    steps:
      - uses: actions/checkout@v4

      - name: tfsec scan
        uses: aquasecurity/[email protected]
        with:
          soft_fail: false
          format: sarif
          sarif_file: tfsec.sarif

      - name: Upload tfsec SARIF
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: tfsec.sarif

  checkov:
    runs-on: ubuntu-latest
    permissions:
      security-events: write

    steps:
      - uses: actions/checkout@v4

      - name: Checkov scan
        uses: bridgecrewio/checkov-action@master
        with:
          directory: .
          framework: terraform
          output_format: sarif
          output_file_path: checkov.sarif
          skip_check: CKV_AWS_79  # IMDSv2 — covered by launch template

      - name: Upload Checkov SARIF
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: checkov.sarif

Pre-commit Hooks

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/antonbabenko/pre-commit-terraform
    rev: v1.92.0
    hooks:
      - id: terraform_fmt
      - id: terraform_validate
      - id: terraform_tflint
      - id: terraform_tfsec
        args:
          - --args=--minimum-severity=HIGH
      - id: terraform_checkov
        args:
          - --args=--skip-check CKV_AWS_79

  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.18.0
    hooks:
      - id: gitleaks   # catch secrets before commit

OPA/Conftest Policy-as-Code

# policies/s3_encryption.rego
package terraform.s3

deny[msg] {
  resource := input.resource.aws_s3_bucket[name]
  not input.resource.aws_s3_bucket_server_side_encryption_configuration[name]
  msg := sprintf("S3 bucket '%s' does not have server-side encryption configured", [name])
}

deny[msg] {
  resource := input.resource.aws_security_group_rule[name]
  resource.cidr_blocks[_] == "0.0.0.0/0"
  resource.from_port <= 22
  resource.to_port >= 22
  msg := sprintf("Security group rule '%s' allows SSH from 0.0.0.0/0", [name])
}
# Run conftest against Terraform plan JSON
terraform plan -out=tfplan.binary
terraform show -json tfplan.binary > tfplan.json
conftest test tfplan.json -p policies/

Anti-Patterns

  1. Skipping security scans in CI for "small changes" — misconfigurations are often in small changes; always scan on every PR.
  2. Mass-suppressing tfsec findings#tfsec:ignore:* hides real issues; document each suppression with a reason.
  3. Not scanning modules separately — root module scan misses issues inside nested modules; use --recursive flag.
  4. Failing CI without human review for warnings — MEDIUM findings block good PRs; set minimum severity to HIGH in blocking gate, report MEDIUM as warnings.
  5. Checking in tfvars with secrets.gitignore terraform.tfvars files containing secrets; inject via env var or Vault.

References

  • tfsec: github.com/aquasecurity/tfsec
  • Checkov: checkov.io
  • pre-commit-terraform: github.com/antonbabenko/pre-commit-terraform
  • KICS: checkmarx.com/blog/kics-open-source-iac-scanning/
  • OPA Conftest: conftest.dev
  • CIS AWS Terraform Benchmark: cisecurity.org
  • Related skills: [[infra-terraform-review]], [[infra-terraform-cost-estimator]], [[infra-kubernetes-security-audit]]

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.