コンテナ内の「見えない」ものによる惨事
午前2時。電話が激しく鳴り響く。セキュリティチームからの緊急通知:「本番環境でLog4jの脆弱性が検出されました」。私は飛び起き、冷や汗が流れた。この時の難題は修正方法ではない。数百もの実行中のコンテナの中から、どのマイクロサービスがその有害なライブラリを「抱え込んでいる」のかを正確に特定することだった。
以前、自分のサーバーがSSHブルートフォース攻撃を受けたことがあったため、最初からセキュリティ設定は非常に念入りに行っていた。しかし、今回は違った。脆弱性はサーバーの設定ではなく、開発者がインストールした依存関係(dependency)の奥深くに潜んでいた。Dockerfileを見れば一見クリーンに見える。しかし、イメージレイヤーの背後には、手動ではほぼ管理不可能なパッケージの「もつれ」が隠されている。
ここでSBOM(Software Bill of Materials:ソフトウェア部品表)の出番だ。これはソフトウェアを構成するすべての要素を詳細に記したリストのようなものだ。SREのようにプロフェッショナルにSBOMを管理するためには、SyftとGrypeのコンビを知っておく必要がある。
SBOM、SyftとGrype:正しく理解して使いこなす
SBOMはインスタントラーメンのパッケージにある原材料表示のようなものだと想像してみてほしい。塩分、調味料、保存料がどれくらい入っているかを正確に教えてくれる。エンジニアリングにおいて、SBOMはライブラリ名、バージョン、ライセンス、そして直接インストールしていないがコード内に現れる「推移的依存関係(transitive dependencies)」をリストアップする。
- Syft: このツールは「スキャナー」の役割を果たす。コンテナイメージやソースコードをスキャンしてSBOMを抽出する。Syftの速度は非常に速く、数百MBのイメージでも通常5〜10秒しかかからない。
- Grype: Syftがスキャナーなら、Grypeは「鑑定士」だ。SBOMのリストを受け取り、グローバルな脆弱性データベース(CVE)と照合する。
この強力なペアは、ソフトウェアサプライチェーン(Software Supply Chain)に強固な盾を築く。自分が何を持っているか、そして持っているものが「汚染」されていないかを知ることができる。
実践的な導入:5分で依存関係を制御する
1. ツールのインストール
両方ともAnchoreによって開発されているため、Linuxへのインストールは公式スクリプトで非常にスムーズに行える:
# Syftをインストール
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
# Grypeをインストール
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin
syft --versionと入力して確認する。バージョンが表示されれば、準備完了だ。
2. 最初のSBOMを出力する
任意のコンテナイメージ(例:nginx:latest)の中身を覗いてみよう:
syft nginx:latest
数十、あるいは数百のパッケージが表示されるはずだ。長期保存や他のツールで使用するために、JSONやCycloneDXなどの標準形式で出力することをお勧めする:
syft webapp:v1.0 -o json > webapp-sbom.json
このJSONファイルこそがコンテナの「出生証明書」だ。新しい脆弱性(Log4jやHeartbleedなど)が発生した際、このファイルをgrepするだけで自分が影響を受けるかどうかがわかる。サーバーにSSHでログインしたり、コンテナを再実行したりする必要はない。
3. Grypeで脆弱性を追跡する
今度はGrypeの出番だ。最新の脆弱性データベースを自動的にダウンロードしてからスキャンを開始する。
grype webapp:v1.0
結果は重要度別に分類される:Low、Medium、High、Critical。Criticalという文字とCVE番号が表示されたら、それはすぐにアップデートが必要なレッドアラートだ。
ちょっとしたコツ:イメージをスキャンする代わりに(帯域を節約するため)、前のステップで作成したSBOMファイルを直接スキャンしよう:
grype sbom:./webapp-sbom.json
4. 「異常」発見時の処理フロー
脆弱性のリストが長くても慌てないでほしい。「Fixed In」カラムに注目しよう。これはアップグレードすべき安全なバージョンだ。私の通常のワークフローは:問題のあるパッケージを特定 -> package.jsonまたはDockerfileを更新 -> イメージを再ビルド -> 最後に再スキャン。
自動化:泥縄にならないために
最大のミスは、思い出した時だけスキャンすることだ。セキュリティをパイプラインの一部にしよう(シフトレフトセキュリティ)。開発者がコードをプッシュするたびに、システムが自動的にSBOMを作成し、即座に脆弱性をスキャンするようにする。
重大な脆弱性を含むイメージをブロックするためのGitHub Actionsの設定例は以下の通り:
- name: Scan image
uses: anchore/scan-action@v3
with:
image: "webapp:latest"
fail-build: true
severity-cutoff: critical
fail-build: trueを設定すると、Criticalな脆弱性が検出された場合、パイプラインは即座に停止する。脆弱なコードが本番環境(Production)に紛れ込むことは決してない。これにより、夜中に電話が鳴ることを心配せずにぐっすり眠ることができる。
おわりに
セキュリティはゴールではなく、継続的な管理のプロセスだ。SyftとGrypeを手にすれば、システム内部を透視できるようになる。SBOMは単なる退屈なコンプライアンス要件ではなく、サプライチェーンへの攻撃に対する迅速な対応ツールなのだ。今日からSBOMを作成する習慣をつけよう。皆さんのシステムが安全に管理され、安眠できることを願っている!

