コンテナの「野良イメージ」は時限爆弾だ:Cosignによるサプライチェーン・セキュリティの実践
現場でよくある光景だ。開発速度を優先するあまり、Docker Hubで適当に見つけた「Star数が多いイメージ」をそのまま本番環境のK8sクラスタへ流し込む。だが、そのイメージの中身にバックドアが仕込まれていたら?あるいは、ビルドパイプラインの途中で悪意ある中間者攻撃によってイメージが差し替えられていたら?
君たちがどれだけOSをハーデニングし、WAFで攻撃を防いでも、「実行するバイナリそのもの」が汚染されていたらゲームオーバーだ。
今回は、現代のコンテナセキュリティの防波堤となる「イメージ署名と検証」について、泥臭い現場の視点から解説する。
—
なぜ「署名」が必要なのか?(PoC的視点)
攻撃者が狙うのは、CI/CDパイプラインとレジストリの隙間だ。例えば、攻撃者がレジストリ内のイメージを my-app:latest にすり替えたとする。もし検証プロセスが存在しなければ、Kubernetesは「最新のタグだから」と何の疑いもなくその悪意あるコードを実行する。
これを防ぐのが Sigstore/Cosign だ。イメージにデジタル署名を付与し、デプロイ時に「このイメージは信頼できるビルド環境から出力されたものか?」を暗号学的に証明する。
—
1. Cosignを使った署名の付与(CI環境)
まずは、ビルドが完了した直後のCI環境でイメージに署名を行う。ここでは最も手軽な「キーレス署名(OIDCトークン利用)」ではなく、実運用で管理しやすい「秘密鍵/公開鍵」方式での実装例を示す。
# 1. 鍵ペアの生成(秘密鍵は環境変数やSecret管理ツールで厳重に保護すること!)
cosign generate-key-pair
# 2. イメージへの署名(イメージのDigestに対して署名を行う)
# 署名データ自体はOCIレジストリに別のタグとして保存される
cosign sign --key cosign.key my-registry.example.com/my-app:v1.0.0
ここで重要なのは、「イメージのDigest(SHA256ハッシュ)」に対して署名している点だ。タグ(latestなど)は動的に変わるが、Digestは不変。攻撃者がタグを上書きしても、Digestが一致しなければ署名検証は失敗する。
—
2. Admission Controllerによる強制検証(Kubernetes側)
署名しても、誰も検証しなければ意味がない。Kubernetes側で Kyverno や Policy Controller を使い、署名のないイメージのデプロイを物理的に拒否する。
以下は、Kyvernoを用いた「署名検証ポリシー」のYAML設定だ。
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-image-signature
spec:
validationFailureAction: Enforce # 検証失敗時はデプロイをブロックする
rules:
- name: verify-signature
match:
resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "my-registry.example.com/my-app:*"
attestors:
- entries:
- keys:
publicKeys: |-
-----BEGIN PUBLIC KEY-----
... (ここに公開鍵を貼り付け) ...
-----END PUBLIC KEY-----
これをクラスタに適用すれば、開発者がいくら悪意あるイメージをデプロイしようとしても、Kubernetes APIサーバーが Admission webhook を通じて「署名が正しくない」と判断し、Podの起動を即座に遮断する。
—
3. 実務でハマる「盲点」への対策
現場のエンジニアからよく受ける相談が「検証を入れたらデプロイが止まった」というものだ。以下の3点は必ず押さえておいてほしい。
- Digestでの指定を徹底せよ:
デプロイメント定義(YAML)では、極力 image: my-app:latest ではなく image: my-app@sha256:abcdef... を使う癖をつけろ。タグの流動性に依存するリスクを排除できる。
- 鍵の管理が最大の弱点:
せっかく署名しても、cosign.key をGitHubのリポジトリにコミットしてしまっては元も子もない。必ず HashiCorp Vault や AWS KMS、Google Cloud KMS を介して署名を行う運用にすること。
- イメージのSBOM(ソフトウェア部品表)も署名する:
Cosignは署名だけでなく、syft 等で生成したSBOMも一緒に署名・添付できる。何が入っているかわからないイメージは、署名があっても実行すべきではない。
—
最後に:セキュリティは「性悪説」で設計せよ
セキュリティのプロフェッショナルとして君たちに伝えたいのは、「信頼できる人間は存在しないし、完璧なシステムも存在しない」という現実だ。
開発者が悪意を持っているわけではなくても、依存しているライブラリが攻撃されることは往々にしてある。今回紹介した「イメージ署名」は、サプライチェーンという「見えない攻撃経路」を塞ぐための必須の作法だ。
「面倒くさい」はセキュリティの敵だ。だが、一度このパイプラインを構築してしまえば、君たちが寝ている間も、改ざんされたコードが本番環境で暴れることは物理的に不可能になる。
さあ、今すぐ cosign をインストールし、君たちのレジストリに「信頼の証」を刻み込んでくれ。それが、最高峰のエンジニアとしての矜持だ。
コメント