tfsec — TerraformコードのIaCセキュリティスキャン入門

1. 概要

  • tfsecとは何か(TerraformコードのIaCセキュリティスキャナー)
  • インストールと基本的な使い方
  • GitHub ActionsでのCI/CD統合
  • よく検出されるセキュリティ問題と対処法

tfsecはTerraformコードの静的セキュリティ解析ツールです。plan/apply前にコードをスキャンして、EBSの暗号化漏れ・セキュリティグループの全開放・S3バケットのパブリックアクセス等のセキュリティ問題を検出します。


2. インストールと基本的な使い方

# macOSの場合
brew install tfsec

# Dockerを使う場合
docker run --rm -v "$(pwd):/src" aquasec/tfsec /src

# バージョン確認
tfsec --version
# カレントディレクトリをスキャン
tfsec .

# 特定ディレクトリをスキャン
tfsec ./environments/production

# JSON形式で出力(CIでの解析に便利)
tfsec . --format json > tfsec_results.json

# 重要度の高い問題のみ表示(CRITICAL/HIGH)
tfsec . --minimum-severity HIGH

3. スキャン対象コード例と検出パターン

terraform {
  required_version = ">= 1.9"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

variable "environment" {
  description = "環境名"
  type        = string
  default     = "dev"
}

data "aws_ami" "amazon_linux_2023" {
  most_recent = true
  owners      = ["amazon"]
  filter {
    name   = "name"
    values = ["al2023-ami-*-x86_64"]
  }
}

# ✅ tfsecがPASSするコード
resource "aws_instance" "web" {
  ami           = data.aws_ami.amazon_linux_2023.id
  instance_type = "t3.micro"

  root_block_device {
    volume_size = 20
    volume_type = "gp3"
    encrypted   = true   # ← 暗号化: PASS
  }

  tags = {
    Name        = "${var.environment}-web"
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

# ❌ tfsecが検出する問題
resource "aws_security_group" "bad_example" {
  name   = "bad-sg"
  vpc_id = "vpc-xxx"

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]  # ← SSH全開放: aws-ec2-no-public-ingress-sgd
  }
}

# ✅ tfsecがPASSするセキュリティグループ
resource "aws_security_group" "good_example" {
  name   = "good-sg"
  vpc_id = "vpc-xxx"

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["10.0.0.0/8"]  # ← 社内IPのみ許可
  }

  tags = {
    Name        = "${var.environment}-sg"
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

4. よく検出されるチェックと対処法

チェックID検出内容対処法
aws-ec2-no-public-ingress-sgdSGでSSH(22)/RDP(3389)を0.0.0.0/0で開放cidr_blocksを社内IPに制限
aws-ec2-enable-at-rest-encryptionEBSのencryptedがfalseencrypted = trueを追加
aws-s3-enable-bucket-encryptionS3バケットの暗号化なしserver_side_encryption_configurationを設定
aws-s3-no-public-bucketsS3バケットがパブリックblock_public_aclsをtrueに
aws-rds-encrypt-instance-storage-dataRDSのstorage_encryptedがfalsestorage_encrypted = trueを追加

5. GitHub ActionsへのCI統合

# .github/workflows/tfsec.yml
name: tfsec Security Scan

on:
  pull_request:
    branches: [main]

permissions:
  contents: read
  pull-requests: write
  security-events: write

jobs:
  tfsec:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Run tfsec
        uses: aquasecurity/tfsec-action@v1
        with:
          working_directory: .
          minimum_severity: HIGH
          github_token: ${{ github.token }}
          # PRコメントとして結果を投稿
          soft_fail: true   # エラーでもパイプラインを止めない(段階的導入時)

6. 特定ルールの無効化

# 意図的に全オープンにする場合(例: ALBのHTTPS用80リダイレクト)
resource "aws_security_group_rule" "http_redirect" {
  type        = "ingress"
  from_port   = 80
  to_port     = 80
  protocol    = "tcp"
  cidr_blocks = ["0.0.0.0/0"]  # tfsec:ignore:aws-ec2-no-public-ingress-sgd

  security_group_id = aws_security_group.alb.id
}

# tfsec:ignore:<チェックID>コメントで特定のルールを無効化できます。


7. 関連記事


8. まとめ

  • tfsecはTerraformコードのIaCセキュリティスキャナー。plan前にセキュリティ問題を検出する
  • よく検出される問題: EBS暗号化なし・セキュリティグループの全開放・S3のパブリックアクセス
  • GitHub ActionsのPRチェックに組み込むことで、問題のあるコードがmainに入るのを防げる
  • tfsec:ignore:<ID>コメントで意図的な例外を明示できる

対象バージョン: tfsec v1+ / Terraform >= 1.9 公式ドキュメント: https://aquasecurity.github.io/tfsec/