/var/www/yatta47.log

/var/www/yatta47.log

やったのログ置場です。スクラップみたいな短編が多いかと。

ECS FargateにCrowdStrike Falconを導入する2つの方法(falconutil vs タスク定義パッチ)

ECS FargateにCrowdStrike Falconのコンテナセンサーを入れる方法は2つあります。 イメージパッチ(falconutil)とタスク定義パッチ。結論から言うと、ほとんどのケースでイメージパッチが正解っぽいです。

何を比較したか

ECS FargateにはホストOSがないので、EC2のようにFalconセンサーをホストにインストールする方式が使えません。

CrowdStrikeが用意しているコンテナセンサーをタスクに組み込む必要があるんですが、そのやり方が2つあって、名前が似ていてどっちがどう違うのか最初わかりづらかったんですよね。

  • 方式A: イメージパッチ(falconutilでイメージにセンサーを焼き込む)
  • 方式B: タスク定義パッチ(デプロイ時にタスク定義JSONを書き換える)

選択肢の整理

観点 方式A(イメージパッチ) 方式B(タスク定義パッチ)
ツール falconutil パッチングユーティリティ
CI/CDの変更 1ステップ追加 デプロイ毎にパッチ実行
タスク定義の変更 SYS_PTRACE のみ サイドカー + entrypoint + volume
コンテナ構成 1コンテナ 2コンテナ(init + app)
イメージへの影響 センサーが焼き込まれる 変更なし
リポジトリの状態 falconutil-action が active Container-Security が archived
CrowdStrike推奨 推奨 旧方式

方式A: イメージパッチ — CI/CDに1ステップ追加

falconutil でビルド済みのDockerイメージにFalconセンサーを焼き込みます。GitHub Actionsだとこんな感じ。

- uses: CrowdStrike/falconutil-action@v1
  with:
    cloud_service: ECS_FARGATE
    source_image_uri: ${{ steps.build.outputs.image }}
    target_image_uri: ${{ steps.build.outputs.image }}-patched
  env:
    FALCON_CLIENT_ID: ${{ secrets.FALCON_CLIENT_ID }}
    FALCON_CLIENT_SECRET: ${{ secrets.FALCON_CLIENT_SECRET }}

タスク定義の変更は SYS_PTRACE capability を追加するだけ。ECSから見ると普通の1コンテナタスクに見えます。

SYS_PTRACE はFalconセンサーがアプリプロセスのシステムコールを監視するために必要な Linux capability です。Fargateではデフォルトで無効なので明示的に追加します。

GitHub Actions以外のCI/CD(Azure DevOps等)でも docker runfalconutil を動かせるので、特定のCIツールに縛られないのもメリットです。

方式B: タスク定義パッチ — タスク定義を毎回書き換え

デプロイ時にパッチングユーティリティがタスク定義JSONを書き換えます。

  1. falcon-init コンテナを追加(ECSにはKubernetesのinitContainersはないので、dependsOn で先に起動→完了後にアプリが起動する構成)
  2. アプリコンテナのエントリーポイントを差し替え
  3. 共有ボリュームを追加(falcon-initからアプリコンテナにセンサーバイナリを渡す)

タスク定義のdiffが大きくなるので、レビューで「何が変わったのか」が見づらくなります。エントリーポイントの差し替えはアプリの起動シーケンスに影響する可能性もあって、トラブルシューティングが面倒になりがち。

どっちを選んだか・なぜか

方式A(イメージパッチ)を選びました。決め手は3つ。

  1. タスク定義がクリーンに保たれる。SYS_PTRACE を足すだけなので、CrowdStrike導入前後でdiffが小さい
  2. CI/CDに1ステップ足すだけで、デプロイフロー自体の変更が最小限
  3. Container-Security リポジトリがarchived。CrowdStrike側も方式Aに寄せていく方針が見える

方式Bを選ぶ理由があるとすれば、「アプリのDockerイメージに一切手を入れられない」という制約がある場合くらいです。

CrowdStrike Falcon を ECS Fargate に入れたい
  │
  ├─ CI/CDパイプラインを変更できる → 方式A(イメージパッチ)
  │
  ├─ アプリイメージに手を入れられない → 方式B(タスク定義パッチ)
  │
  └─ 迷ったら → 方式A

補足: サイドカーコンテナにもセンサーは必要か

タスク内にNginxやFireLens(Fluent Bit)などのサイドカーがある場合、そちらにもセンサーを入れるべきかは悩ましいところです。

Fargateではホストにセンサーを1つ置く方式が使えないため、監視したいコンテナイメージごとにセンサーを焼き込む必要があります。タスク内の全コンテナに入れるとリソースコストが増えます。Kubernetes向けのfalcon-helmのデフォルト値(requests: 20Mi / limits: 128Mi)が目安になりますが、ECS Fargateではタスクのメモリ割り当てにこの分を上乗せする設計になります。

実務的には、外部通信を受けるコンテナ(Nginx等)には入れて、ログ転送(FireLens)やモニタリング用コンテナは省略し、ECRスキャンで脆弱性管理する、というのが落としどころです。

もう1つ注意点として、Falconセンサーはglibc前提なので、Alpine系(musl libc)のイメージでは動かない可能性があります。Nginxの公式イメージを使っている場合はAlpine版かDebian版かを確認しておくのがおすすめです。

まとめ

ECS FargateへのCrowdStrike Falcon導入は、CI/CDを変更できるならイメージパッチ(falconutil)一択です。タスク定義がクリーンに保たれて、運用負荷が低い。サイドカーへのセンサー導入はリスクとコストを見て判断ですが、タスク内の全コンテナに入れるのは現実的じゃないので、攻撃面の広いコンテナに絞るのが合理的です。

参考