CheckovでInfrastructure as Code(IaC)のセキュリティを自動化:CI/CDで設定ミスを未然に防ぐ

Security tutorial - IT technology blog
Security tutorial - IT technology blog

現実の課題:クラウドの設定ミスが見逃される代償

前四半期、ある中規模フィンテック企業で、一見すると何の変哲もない日常的なTerraformのプルリクエストが提出されました。対象は内部ステージング用のS3バケットと補助的なKubernetes Podです。コードレビューは滞りなく進み、2名のレビュアーが15分以内にマージを承認し、変更内容はそのままAWSへデプロイされました。しかし48時間も経たないうちに、Shodanの自動スキャンによって、パブリック読み取り権限を持つ暗号化されていないS3バケットと、root UID 0かつ特権ポートが公開された状態で動作しているKubernetesコンテナが検出されたのです。

これは決して例外的な事例ではありません。Palo Alto Networksの調査データによると、クラウドセキュリティインシデントの65%以上は、ハイパーバイザのゼロデイ脆弱性ではなく、純粋な設定ミスに起因しています。本番環境の侵害に高度なマルウェアが使われることは稀です。多くの場合、エンジニアがEBSボリュームの encrypted = true フラグを付け忘れたり、デプロイマニフェスト内に allowPrivilegeEscalation: true を残してしまったりすることが原因です。

多くのチームは、Infrastructure as Code(IaC)を通常のアプリケーションコードと同様に扱い、標準的なピアレビューでミスを防げると信じています。しかし、インフラ構成ファイルの実態は異なります。マニフェストはHCL、YAML、JSONで数千行にも膨れ上がることが珍しくありません。タイトな納期のなかで膨大なdiffをレビューしていると、熟練のプラットフォームアーキテクトであっても、固定されていないegress CIDRブロックやアクセスログの無効化、緩すぎるKMSポリシーなどを見落としてしまいます。

根本原因分析:なぜインフラのデフォルト設定は安全ではないのか

セキュアでないインフラが本番環境へ紛れ込んでしまう背景には、クラウドのリソース定義とIaCエンジンの連携における構造的な欠陥があります。

1. 緩いデフォルト設定と簡潔さを好むバイアス

クラウドプロバイダーは、安全重視のデフォルト設定よりも、導入時の手軽さを優先する傾向があります。Terraformでは、オプションの構成ブロックを省略した場合、大抵は最も制約の緩い設定がデフォルトになります。例えば、encryption ブロックを指定せずに aws_ebs_volume を宣言しても警告は出ず、Terraformは単に暗号化されていないストレージをプロビジョニングします。コードを簡潔に書こうとしたエンジニアが「デフォルトで有効になっているだろう」と思い込んで行を省略した結果、意図せず脆弱性を作り出してしまうのです。

2. ランタイム監査のタイムラグ

従来のクラウドセキュリティポスチャ管理(CSPM)ツールは、デプロイ後に稼働中のクラウドインフラを検査します。CSPMツールがポート22のオープンなingressルールを検出したとき、そのアラートはただでさえ混雑しているSlackチャンネルやPagerDutyのキューに送られます。

  • 欠陥のあるアセットはすでに稼働しており、インターネットの脅威に晒されています。
  • リソース作成から数分以内に、自動化されたボットネットのスキャン対象になっている可能性があります。
  • 稼働中のリソースを修復するには緊急のホットフィックスや手動でのコンソール操作が必要となり、構成ドリフト(乖離)のリスクが生じます。

3. コードレビューにおける認知的過負荷

ピアレビューでは、「これでus-east-1にリードレプリカが正しく起動するか?」といった機能ロジックやアーキテクチャの確認に集中しがちです。入れ子になった子リソースの隅々まで、数十に及ぶ詳細なCISベンチマークの基準を満たしているかを人間のレビュアーが目視で確認するのは困難です。セキュリティの検証に必要なのは人間の記憶力ではなく、再現性のある自動化です。

シークレット情報やサーバーの初期セットアップでも同様の問題が見られます。私がrootクレデンシャルを生成する際は、場当たり的な手入力文字列を避け、toolcraft.app/ja/tools/security/password-generator のようなクライアントサイドのジェネレーターを利用します。これはネットワークを介さずブラウザのメモリ上だけで完結するため安全です。インフラコードにもまったく同じマインドセットが求められます。「自動化されたチェックで検証されるまで、すべてのリソースは安全ではない」と前提を置くべきなのです。

ソリューションの比較:手動レビュー vs ランタイムCSPM vs 静的IaCスキャン

クラウドの設定ミスが本番環境へ流出するのを防ぐため、一般的に3つの主要なアプローチが採られます。それぞれに明確なトレードオフがあります。

アプローチ 検出ポイント メリット デメリット
手動ピアレビュー プルリクエスト時 チームのビジネスコンテキストを理解可能。新しいツールの導入が不要。 低速で一貫性がなく、細かなCISベンチマーク基準を見落としやすい。
ランタイムCSPMスキャナー 稼働中のクラウド(AWS、GCP、Azure) コンソール操作によるドリフトや予期せぬインフラ変更を検知。 対症療法的。問題が本番環境に到達してから発覚し、アラート疲れを招く。
静的IaC分析(シフトレフト) ローカルPre-Commit & CI/CD クラウドへのプロビジョニング前に脆弱性をブロック。影響範囲ゼロ。 初期のパイプライン調整とポリシーベースラインの管理が必要。

人間のレビューだけに頼っていては、脆弱性の見落としは防げません。一方でランタイムCSPMのアラートを待つ運用では、本番環境での火消し作業に追われ続けることになります。静的IaCスキャンはこのギャップを埋め、リソースがまだ実害のないテキストファイルの段階で設定ミスを捕捉します。

解決策:Checkovによるシフトレフト自動スキャン

IaCファイルのセキュリティを確保する最も洗練された方法は、Bridgecrewが開発し、現在はPalo Alto Networksがメンテナンスしているオープンソースの静的解析エンジンCheckovの導入です。Checkovは、Terraform、Kubernetesマニフェスト、Helmチャート、CloudFormation、Dockerfileなどを解析できます。

CIS Benchmarks、NIST 800-53、HIPAA、PCI-DSSにマッピングされた1,000以上の組み込みルールに照らしてインフラを監査します。決定的な利点は、terraform apply や kubectl apply がAPIを呼び出す前に、セキュアでない設定を確実に阻止できる点にあります。

ステップ1:Checkovのローカルインストールと実行

CheckovはPythonまたはDocker経由で実行可能です。ローカルのPython環境の場合は以下の通りです。

# Checkovのインストール
pip3 install checkov

# CLIバイナリの動作確認
checkov --version

Pythonの依存関係を入れずにコンテナとして実行したい場合は、以下を使用します。

docker run --tty --volume $(pwd):/tf --workdir /tf bridgecrew/checkov --directory .

ステップ2:Terraformのセキュリティ欠陥を検出する

例として、セキュリティ上の欠陥を含む最小構成の main.tf を見てみましょう。

resource "aws_s3_bucket" "app_data" {
  bucket = "my-app-user-backups-bucket"
}

resource "aws_ebs_volume" "web_disk" {
  availability_zone = "us-east-1a"
  size              = 40
  # 不足: encrypted = true
}

対象ディレクトリに対してスキャンを実行します。

checkov -d . --framework terraform

Checkovは数秒で暗号化されていないボリュームとS3バケットの不足設定を指摘します。

Check: CKV_AWS_18: "Ensure the S3 bucket has access logging enabled"
	FAILED for resource: aws_s3_bucket.app_data
	File: /main.tf:1-3

Check: CKV_AWS_3: "Ensure all data stored in the EBS is securely encrypted"
	FAILED for resource: aws_ebs_volume.web_disk
	File: /main.tf:5-8
	Guide: https://docs.prismacloud.io/en/enterprise-edition/policy-reference/aws-policies/aws-general-policies/ensure-ebs-volume-is-encrypted

ステップ3:セキュアでないKubernetesマニフェストの監査

CheckovはKubernetesのYAMLファイルも同様に高精度で検査します。以下は過剰な権限を持つ deployment.yaml の例です。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: payment-api
spec:
  replicas: 2
  template:
    spec:
      containers:
      - name: payment-api
        image: payment-api:v1.2.0
        securityContext:
          privileged: true
          runAsUser: 0

Kubernetesリソースを対象にスキャンを実行します。

checkov -f deployment.yaml --framework kubernetes

スキャンにより、root実行(UID 0)と危険な特権コンテナフラグの両方が検出されます。

Check: CKV_K8S_16: "Do not run containers as root user"
	FAILED for resource: Deployment.default.payment-api
	File: /deployment.yaml:9-15

Check: CKV_K8S_17: "Do not use privileged containers"
	FAILED for resource: Deployment.default.payment-api
	File: /deployment.yaml:9-15

ステップ4:CheckovをGitHub Actionsに統合する

ローカルスキャンは個々の開発者には有用ですが、チーム全体を保護するにはCI/CDによるガードレール自動化が不可欠です。以下のGitHub Actionsワークフロー(.github/workflows/iac-security.yml)は、mainブランチに対するすべてのPRをスキャンします。

name: IaC Security Scan

on:
  pull_request:
    branches: [ main ]
  push:
    branches: [ main ]

jobs:
  checkov:
    name: Checkovスキャナーの実行
    runs-on: ubuntu-latest
    steps:
      - name: ソースコードのチェックアウト
        uses: actions/checkout@v4

      - name: Python環境のセットアップ
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Checkovのインストール
        run: pip install checkov

      - name: Checkovスキャンの実行
        run: |
          checkov -d . \
            --compact \
            --quiet \
            --framework terraform,kubernetes \
            --soft-fail

導入戦略:上記のワークフローにおける --soft-fail 引数に注目してください。既存の大規模なコードベースに対して初日から厳格なブロッキングスキャンを強制すると、大量のビルドが失敗してしまいます。まずは --soft-fail を指定して現在のベースラインリスクを可視化し、技術的負債を把握した上で、リポジトリルートに .checkov.yml を配置して承認済みの例外ケースを抑止します。既存の違反が解消された段階でこのフラグを削除するのがスムーズな移行手順です。

ドキュメント化された例外の処理

ワークロードによっては、設計上意図的に緩い設定が必要となる場合があります。ルールカテゴリ全体を無効化したりファイル自体をスキャン対象から除外したりするのではなく、インラインコメントを使用してコード内に明示的なスキップ設定をドキュメント化します。

resource "aws_s3_bucket" "public_assets" {
  bucket = "static-company-logos"
  
  #checkov:skip=CKV_AWS_20:"静的CDNアセット用のため意図的に公開"
}

Checkovをデリバリーパイプラインに導入することで、クラウドセキュリティはデプロイ後の厄介な監査作業から、チームのプルリクエストに直接組み込まれた自動サニティチェックへとシフトします。

Share: