Infrastructure as Code Security

Infrastructure as Code はバージョン管理と自動化のメリットをもたらしますが、設定ミスが 自動的に伝播してしまうとリスクを生みます。IaC においてもセキュリティは shift-left すべきです。

IaC における一般的な脆弱性

  • ハードコードされたシークレット:バージョン管理されたコード内の認証情報
  • 過度に緩い許可ルール:セキュリティグループ 0.0.0.0/0
  • 暗号化されていないリソース:暗号化のない S3 バケットや RDS
  • パブリックアクセス:不必要に公開されたリソース
  • ロギングの欠如:無効化された CloudTrail やフローログ
  • 脆弱な認証:MFA が強制されていない

スキャンツール

Terraform - tfsec、Checkov、Terrascan

      # 脆弱性の例 - パブリックな S3 バケット
      resource "aws_s3_bucket" "bad_bucket" {
      bucket = "my-public-bucket"
      acl    = "public-read"  # [エラー] 脆弱
      }
      # 修正
      resource "aws_s3_bucket" "good_bucket" {
      bucket = "my-private-bucket"
      acl    = "private"  # [OK] 安全
      server_side_encryption_configuration {
      rule {
      apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
      }
      }
      }
      versioning {
      enabled = true
      }
      }
      resource "aws_s3_bucket_public_access_block" "good_bucket" {
      bucket = aws_s3_bucket.good_bucket.id
      block_public_acls       = true
      block_public_policy     = true
      ignore_public_acls      = true
      restrict_public_buckets = true
      }
      

tfsec - Terraform のスキャン

      # インストール
      brew install tfsec
      # Terraform ファイルをスキャン
      tfsec .
      # 出力形式を指定
      tfsec --format json --out results.json .
      # CI/CD 連携
      tfsec --soft-fail . || exit 1
      

Checkov - マルチクラウド IaC スキャナー

      # インストール
      pip install checkov
      # Terraform をスキャン
      checkov -d ./terraform
      # CloudFormation をスキャン
      checkov -f template.yaml
      # Kubernetes マニフェストをスキャン
      checkov -d ./k8s
      # 特定のチェックをスキップ
      checkov -d . --skip-check CKV_AWS_20
      # カスタムポリシー
      checkov -d . --external-checks-dir ./custom-policies
      

Policy as Code

Open Policy Agent (OPA)

OPA を使うと、コンプライアンスを強制するためのポリシーを Rego 言語で記述できます:

      # deny_public_s3.rego
      package terraform.aws.s3
      deny[msg] {
      resource := input.resource_changes[_]
      resource.type == "aws_s3_bucket"
      resource.change.after.acl == "public-read"
      msg := sprintf("S3 bucket %s cannot be public", [resource.address])
      }
      deny[msg] {
      resource := input.resource_changes[_]
      resource.type == "aws_s3_bucket"
      not resource.change.after.server_side_encryption_configuration
      msg := sprintf("S3 bucket %s must have encryption enabled", [resource.address])
      }
      

Sentinel (HashiCorp)

Terraform Cloud/Enterprise と統合されたポリシーフレームワーク:

      # enforce-mandatory-tags.sentinel
      import "tfplan/v2" as tfplan
      mandatory_tags = ["Environment", "Owner", "Project"]
      all_resources = filter tfplan.resource_changes as _, rc {
      rc.mode is "managed"
      }
      deny_resources_without_tags = rule {
      all all_resources as _, resource {
      all mandatory_tags as tag {
      resource.change.after.tags contains tag
      }
      }
      }
      

IaC におけるシークレット管理

Terraform - AWS Secrets Manager の利用

      # Secrets Manager に secret を作成
      resource "aws_secretsmanager_secret" "db_password" {
      name = "production/db/password"
      recovery_window_in_days = 30
      }
      resource "aws_secretsmanager_secret_version" "db_password" {
      secret_id     = aws_secretsmanager_secret.db_password.id
      secret_string = random_password.db_password.result
      }
      # secret を参照する(値は公開しない)
      data "aws_secretsmanager_secret_version" "db_password" {
      secret_id = aws_secretsmanager_secret.db_password.id
      }
      # RDS で使用(ハードコードした値ではなく参照)
      resource "aws_db_instance" "main" {
      # ... その他の設定
      password = data.aws_secretsmanager_secret_version.db_password.secret_string
      }
      

git-secrets - シークレットのコミットを防ぐ

      # git-secrets をインストール
      brew install git-secrets
      # リポジトリにフックを設定
      git secrets --install
      git secrets --register-aws
      # コミット履歴をスキャン
      git secrets --scan-history
      # シークレットを含むコミットを防ぐ
      # pre-commit フックにより自動実行
      

State ファイルのセキュリティ

  • リモート state:S3 + DynamoDB ロック、ローカル state は決してコミットしない
  • 暗号化:S3 でのサーバーサイド暗号化
  • アクセス制御:state バケットに対する制限的な IAM ポリシー
  • バージョニング:復旧のためにバージョニングを有効化
  • State ロック:同時変更を防ぐための DynamoDB

安全な Terraform リモートバックエンド

      terraform {
      backend "s3" {
      bucket         = "terraform-state-prod"
      key            = "global/s3/terraform.tfstate"
      region         = "us-east-1"
      encrypt        = true
      dynamodb_table = "terraform-state-lock"
      # MFA 削除保護
      versioning {
      enabled = true
      mfa_delete = true
      }
      }
      }
      

CI/CD 連携

GitHub Actions - 安全な Terraform ワークフロー

      name: 'Terraform Security Scan'
      on:
      pull_request:
      branches: [ main ]
      jobs:
      terraform-security:
      runs-on: ubuntu-latest
      steps:
      - uses: actions/checkout@v3
      - name: Run tfsec
      uses: aquasecurity/[email protected]
      with:
      soft_fail: false
      - name: Run Checkov
      uses: bridgecrewio/checkov-action@master
      with:
      directory: .
      framework: terraform
      output_format: sarif
      output_file_path: checkov.sarif
      - name: Upload results to GitHub Security
      uses: github/codeql-action/upload-sarif@v2
      with:
      sarif_file: checkov.sarif
      

Drift Detection(ドリフト検出)

セキュリティ上のギャップを生む、IaC の外部で行われた手動変更を検出します:

  • Terraform Cloud:自動ヘルスチェック
  • driftctl:オープンソースのドリフト検出
  • CloudFormation Drift Detection:AWS のネイティブサービス
  • スケジュールされたスキャン:定期的な CI/CD ジョブ

コンプライアンスフレームワーク

  • CIS Benchmarks:コンプライアンス向けの Terraform モジュール
  • NIST 800-53:コントロール向けのポリシーパック
  • PCI-DSS:ペイメントカード処理向けのポリシー
  • HIPAA:ヘルスケアのコンプライアンスポリシー
  • SOC 2:セキュリティ組織のポリシー

安全な Terraform モジュール

  • 検証済みの Terraform Registry モジュールを使用する
  • モジュールのバージョンを固定する(latest を使わない)
  • 内部モジュールのコードレビューを行う
  • カスタムモジュール向けにプライベート registry を用いる
  • セキュリティ上の考慮事項を文書化する

ベストプラクティス

  • ピアレビュー:本番環境への変更には PR を必須とする
  • apply の前に plan:提案された変更をレビューする
  • 環境の分離:Dev/Staging/Prod を分離する
  • タグ付け戦略:ガバナンスとコスト配分のためのタグ
  • 最小権限:CI/CD 専用の IAM ロール
  • 自動テスト:検証のための Terratest

最終的な推奨事項

IaC セキュリティは自動化し、最初から CI/CD に統合すべきです。完全なカバレッジのために 複数のスキャンツール(tfsec、Checkov)を使用してください。OPA または Sentinel で policy as code を実装しましょう。シークレットは決してコミットせず、シークレットマネージャーを使用してください。 ドリフトを継続的に監視しましょう。IaC の設定ミスは、クラウド侵害の最も一般的な原因の一つです。