LESSON 30分

IaCセキュリティとベストプラクティス

ストーリー

「IaCで自動化できたからといって、セキュリティを疎かにしていいわけじゃない」

木村先輩が警告した。

「むしろIaCだからこそ、セキュリティの問題がコードに残る。 セキュリティグループを 0.0.0.0/0 で全開放するコードが レビューをすり抜けてapplyされたら、大事故だ」

「コードレビューで見つけられませんか?」

「人間の目だけに頼るな。自動化できるものは自動化する。 セキュリティスキャンツールをCIに組み込むんだ」


IaCのセキュリティリスク

よくあるセキュリティ問題

リスク影響
過度に緩い権限SG で 0.0.0.0/0 を全ポート許可不正アクセス
シークレットのハードコードパスワードを .tf に直接記述認証情報漏洩
暗号化の未設定S3/EBS/RDS の暗号化なしデータ漏洩
パブリックアクセスS3バケットのパブリック公開データ漏洩
ログ未設定CloudTrail/VPC Flow Logs なし監査不能

セキュリティスキャンツール

tfsec

Terraformコードのセキュリティスキャンツールです。

bash
# インストール
brew install tfsec

# スキャン実行
tfsec .

# 出力例
Result #1 CRITICAL Security group rule allows ingress from public internet
  Resource: aws_security_group.web
  File:     main.tf:45-52
  Reason:   Security group rule allows ingress from 0.0.0.0/0 on port 22

  55 |   ingress {
  56 |     from_port   = 22
  57 |     to_port     = 22
  58 |     protocol    = "tcp"
  59 |     cidr_blocks = ["0.0.0.0/0"]    ← SSH を全世界に公開
  60 |   }

checkov

包括的なIaCセキュリティスキャナーです。

bash
# インストール
pip install checkov

# スキャン実行
checkov -d .

# 特定のチェックをスキップ
checkov -d . --skip-check CKV_AWS_18

CIへの組み込み

yaml
# .github/workflows/terraform-security.yml
name: Terraform Security

on:
  pull_request:
    paths:
      - 'infrastructure/**'

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

      - name: tfsec scan
        uses: aquasecurity/tfsec-action@v1.0.3
        with:
          working_directory: infrastructure/
          soft_fail: false

      - name: checkov scan
        uses: bridgecrewio/checkov-action@v12
        with:
          directory: infrastructure/
          framework: terraform
          quiet: true
          soft_fail: false

セキュアなTerraformコーディング

1. セキュリティグループ:最小権限

hcl
# NG: 全ポートを全世界に公開
resource "aws_security_group" "bad" {
  ingress {
    from_port   = 0
    to_port     = 65535
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]    # 全世界からアクセス可能
  }
}

# OK: 必要なポートのみ、必要なソースから
resource "aws_security_group" "good" {
  ingress {
    description     = "HTTP from ALB only"
    from_port       = 80
    to_port         = 80
    protocol        = "tcp"
    security_groups = [aws_security_group.alb.id]    # ALBからのみ
  }
}

2. S3バケット:パブリックアクセスブロック

hcl
# 全てのS3バケットにパブリックアクセスブロックを設定
resource "aws_s3_bucket_public_access_block" "this" {
  bucket = aws_s3_bucket.this.id

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

3. 暗号化の徹底

hcl
# S3
resource "aws_s3_bucket_server_side_encryption_configuration" "this" {
  bucket = aws_s3_bucket.this.id
  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}

# EBS
resource "aws_instance" "web" {
  root_block_device {
    encrypted = true
  }
}

# RDS
resource "aws_db_instance" "this" {
  storage_encrypted = true
}

4. シークレットの外部管理

hcl
# NG: パスワードをハードコード
resource "aws_db_instance" "bad" {
  password = "MyP@ssw0rd123"    # コードに直接記述
}

# OK: 変数で注入(CI/CDから渡す)
resource "aws_db_instance" "good" {
  password = var.db_password     # 変数で外部から注入
}

# さらに良い: AWS Secrets Managerを使用
data "aws_secretsmanager_secret_version" "db_password" {
  secret_id = "myapp/db-password"
}

resource "aws_db_instance" "best" {
  password = data.aws_secretsmanager_secret_version.db_password.secret_string
}

5. ログの有効化

hcl
# VPC Flow Logs
resource "aws_flow_log" "vpc" {
  vpc_id          = aws_vpc.this.id
  traffic_type    = "ALL"
  iam_role_arn    = aws_iam_role.flow_log.arn
  log_destination = aws_cloudwatch_log_group.flow_log.arn
}

# S3 アクセスログ
resource "aws_s3_bucket_logging" "this" {
  bucket        = aws_s3_bucket.this.id
  target_bucket = aws_s3_bucket.logs.id
  target_prefix = "s3-access-logs/"
}

Terraformコーディング規約

ファイル構成

ファイル内容
main.tfメインのリソース定義
variables.tf入力変数
outputs.tf出力値
providers.tfプロバイダ設定
backend.tfStateバックエンド設定
locals.tfローカル変数
data.tfデータソース
versions.tfバージョン制約

命名規則

対象規則
リソース名snake_caseaws_instance.web_server
変数名snake_casevar.instance_type
モジュール名snake_casemodule.vpc
タグPascalCase or kebab-caseName = "web-server"

コードレビューチェックリスト

Terraform PRレビューチェックリスト

[ ] terraform fmt が適用されている
[ ] terraform validate が通る
[ ] tfsec / checkov でセキュリティスキャン済み
[ ] plan の出力で意図しない削除(-)がない
[ ] シークレットがハードコードされていない
[ ] 暗号化が有効になっている
[ ] タグが適切に設定されている
[ ] 削除保護が必要なリソースに prevent_destroy がある

まとめ

ポイント内容
セキュリティスキャンtfsec / checkov をCIに組み込む
最小権限SG、IAMは必要最小限の権限のみ
暗号化S3、EBS、RDS の暗号化を必須化
シークレットコードにハードコードせず外部管理

チェックリスト

  • IaCのセキュリティリスクを説明できる
  • tfsec / checkov のCIへの組み込み方法を理解した
  • セキュアなTerraformコーディングパターンを把握した
  • PRレビューでのセキュリティチェックポイントを理解した

次のステップへ

次のセクションでは、学んだ知識を全て使って、フルスタックIaCを構築する演習に挑戦します。


推定読了時間: 30分