CheckovによるInfrastructure as Codeのセキュリティ確保:CI/CDでのTerraformとKubernetesスキャンガイド

DevOps tutorial - IT technology blog
DevOps tutorial - IT technology blog

たった一行の設定ミスが招く代償

2021年の午前3時、PagerDutyのアラートが鳴り響いた時のことを今でも覚えています。あるジュニアエンジニアが、誤ってS3バケットをパブリック読み取りアクセス可能な状態でデプロイしてしまったのです。それは不注意なミスではなく、ピアレビューをすり抜けてしまったコミュニティのTerraformモジュールのデフォルト設定でした。15分もしないうちに、自動スキャナーがエンドポイントを検知しました。幸運にもデータ漏洩は免れましたが、これは身の引き締まるような教訓となりました。セキュリティは月に一度の「最終チェック」であってはなりません。すべてのコミットに組み込まれるべきものです。

Infrastructure as Code (IaC) で規模を拡大すると、それに伴ってヒューマンエラーも拡大します。TerraformでAWS環境を管理している場合でも、Helmでクラスターをオーケストレーションしている場合でも、属性が一つ欠けているだけでスタック全体が危険にさらされる可能性があります。手動レビューは価値がありますが、数千行のコードには対応しきれず、決して万全ではありません。

なぜIaCはデフォルトで安全ではないのか

設定ミスは通常、3つの特定のプレッシャーポイントから発生します。第一に、クラウドプロバイダーは「オンボーディングの速さ」を優先します。ユーザーに5分で結果を実感してもらいたいため、彼らの「クイックスタート」テンプレートでは権限が広く開放されていたり、暗号化が無効化されていたりすることがよくあります。

第二に、現代の設定ボリュームは膨大です。一般的なマイクロサービスアーキテクチャでは、5,000行を超えるYAMLやHCL (HashiCorp Configuration Language) が含まれることもあります。疲弊したレビュー担当者が、Kubernetesマニフェストの中に埋もれた allow_privileged_escalation: false の欠落を見つけ出すことを期待するのは、現実的ではありません。

最後に、知識のギャップが広がっています。ほとんどのDevOpsエンジニアはオーケストレーションの専門家ですが、必ずしもセキュリティ研究者ではありません。数十ものクラウドサービスに対して、新しいCVEやCISベンチマークのすべてに追従し続けるのは、ほとんどのチームにとって不可能なフルタイムの仕事です。

スキャナーの比較:なぜCheckovなのか?

これを自動化するためにツールを評価した際、私は TFSecTerrascanKICS を検討しました。それぞれに利点はありますが、私は以下の4つの主な理由から Checkov を標準として採用しました:

  • 幅広いエコシステムのサポート: Terraformだけではありません。Kubernetes、CloudFormation、Bicep、ARMテンプレート、さらにはDockerfileまでスキャン可能です。
  • 膨大なポリシーライブラリ: CISやNISTなどの業界標準に対応した1,000以上の組み込みポリシーが提供されています。
  • Pythonベースの拡張性: 独自のロジックをPythonで記述できるため、ツール独自のドメイン固有言語 (DSL) を学ぶよりも多くのチームにとって直感的です。
  • グラフベースの分析: 単純なテキスト検索ツールとは異なり、Checkovはリソース間の関係を理解します。特定のセキュリティグループが実際にインスタンスにアタッチされているかを把握できるため、誤検知を減らせます。

より良いワークフロー:Checkovの統合

ゴールは単にレポートを作成することではありません。コードがマージされる前に、悪いコードを阻止するフィードバックループを作ることです。私は、ローカルテスト、pre-commitフック、そしてCI/CDによる強制という、階層的な戦略を推奨します。

1. ローカルテストとセットアップ

開始するのに1分もかかりません。私はPythonのパッケージマネージャーを使うのが好きですが、ローカル環境をクリーンに保つにはDockerイメージが理想的です。

# pipでインストール
pip install checkov

# またはDockerで実行
docker run -v $(pwd):/tf bridgecrew/checkov -d /tf

現在のTerraformディレクトリに対してスキャンを実行します。もし赤いテキストの壁が表示されても、パニックにならないでください。これは普通のことです。ほとんどの本番プロジェクトには、段階的に対処が必要なレガシーな技術的負債が蓄積されています。

checkov -d ./terraform_project

2. Kubernetesマニフェストのセキュリティ確保

Checkovの強力な機能の一つは、「不完全な」Kubernetes設定を検出できることです。リソース制限を忘れたり、コンテナをrootで実行したままにしたりしがちです。一つのコマンドでYAMLファイルのディレクトリ全体をスキャンできます:

checkov -d ./k8s_manifests --framework kubernetes

Checkovは、以下のような高リスクの問題を即座に指摘します:

  • privileged: true で実行されているコンテナ。
  • 可用性に影響を与えるLivenessおよびReadinessプローブの欠如。
  • CPU/メモリ制限のないPod(共有クラスター内での「ノイジーネイバー」問題の原因となります)。

3. CI/CDでの自動強制

ここで自動化の真価が発揮されます。設定がセキュリティスキャンに合格しない場合、ビルドを停止させるべきです。GitHub Actionsは、これを強制する最も簡単な方法です。以下は本番環境で使用できるスニペットです:

name: IaCセキュリティスキャン
on: [push, pull_request]

jobs:
  checkov-job:
    runs-on: ubuntu-latest
    steps:
      - name: リポジトリをチェックアウト
        uses: actions/checkout@v3

      - name: Checkovを実行
        uses: bridgecrewio/checkov-action@master
        with:
          directory: terraform/
          framework: terraform
          soft_fail: false # セキュリティチェックに失敗した場合、PRをブロックする
          output_format: cli
          download_external_modules: true

このセットアップにより、セキュリティの退行(デグレード)を招くプルリクエストはすべてブロックされます。これにより、開発者はコードが本番環境に到達する前に、脆弱性を修正するか、文書化された正当な理由を提供することを強制されます。

現場からの教訓

数多くのエンタープライズプロジェクトでCheckovを導入してきた結果、「すべてをオンにする」アプローチは、アラート疲れによって失敗することが多いと分かりました。うまく導入するための方法は以下の通りです。

設定ファイルによる標準化

長いCLIフラグに頼らないでください。ルートディレクトリに .checkov.yaml ファイルを作成しましょう。これにより、すべての開発者とCI/CDランナーがまったく同じルールを使用することを保証し、「自分のマシンでは動いた」というセキュリティ問題を排除できます。

# .checkov.yaml
directory:
  - terraform
  - k8s
skip-check:
  - CKV_AWS_144 # 例:S3の暗号化は組織のグローバルポリシーで処理されている
soft-fail: false
output: cli

例外を適切に処理する

セキュリティルールは常に万能ではありません。ルールをグローバルに無効化するのではなく、インラインコメントを使用して特定のリソースに対してのみスキップさせます。将来のレビューのために監査証跡を残すよう、常に「Reason(理由)」コメントを求めるようにしています。

# terraform
resource "aws_security_group" "bastion" {
  # checkov:skip=CKV_AWS_24: "ポート22への0.0.0.0/0の許可を禁止する" 
  # 理由: これは緊急SSHアクセス専用の、セキュリティを強化したパブリック踏み台ホストです
  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

「段階的」な導入

レガシープロジェクトを初めてスキャンする場合、500以上のエラーが表示されるかもしれません。それらを一つのスプリントですべて修正しようとしないでください。 --check フラグを使用して、まずは「Critical(緊急)」と「High(高)」の深刻度の問題だけに集中します。「Critical」がゼロになったら、徐々に目標を「Medium(中)」や「Low(低)」のチェックまで広げていきます。

checkov -d . --check CRITICAL,HIGH

最後に

インフラのセキュリティ確保は短距離走ではなく、マラソンです。Checkovを使用することで、推測を排除し、チームに即座に実行可能なフィードバックを提供できます。単にコードをスキャンしているのではなく、セキュリティをアプリケーションロジックと同じ厳密さで扱う culture を築いているのです。小さく始め、パイプラインで「Critical」な問題をブロックし、クラウドのデフォルト設定によって門戸が開放されていないという安心感とともに眠りにつきましょう。

Share: