LiteLLMのv1.87.3リリースノートを眺めていたら、Docker imageのcosign署名検証についての記述が思ったより丁寧で、ちょっと立ち止まった。
うちのチームでもLiteLLMをProxyとして立てて、複数のLLM APIを束ねている。OpenAI、Anthropic、あとGeminiのエンドポイントを一箇所に集めて、upstream先をコード側に露出させないようにしてる構成だ。コスト管理のためにrpm/tpmのlimitもProxyで制御してる。わりと中心的なinfraになってきたので、そろそろイメージの信頼性をちゃんと担保したかった。
リリースノートにはtagとcommit hashの2パターンで検証する方法が書いてある。
tagベースの検証はお手軽だけど、「tagが上書きされる可能性がある」という注記がある。commit hashは cryptographically immutable、つまり書き換えが不可能なので、こっちを使うのが筋だ。リリースノートでも「recommended」と明記されている。GitHubのsupply chain attackの文脈では、tagのmutableさは割と既知のリスクで、npm installでversion rangeを広く取りすぎるのと似た話だと思う。自分もいままで何となくtagでpullしてたのを反省した。
starは50.3k、forkが8.9k。かなり使われてるOSSなので、ちゃんとした署名フローが入ってるのは正直ありがたい。このスケールのプロジェクトでcosignを全リリースに適用してるのは、わりと本気でセキュリティに向き合ってるなという印象だ。
うちはGitHub ActionsでCI回してて、LiteLLMのimageをpullしてからintegration testを流す構成になってる。今回の件を受けてworkflowに検証ステップを1個追加した。
cosign自体はGitHub Actionsのrunnerに入ってないので、sigstoreのsetup-cosignアクションで先に入れる必要がある。そこだけちょっとハマった。ドキュメントにはcosignのインストール手順が載ってないので、自分で調べた。あとcosignのverifyが成功すると「The cosign claims were validated」「The signatures were verified against the specified public key」という2行が出力されるんだけど、初回はそれを見るまで「本当に通ってるのか?」と不安だった。ちゃんと通ってたので一安心。
ここ数ヶ月、LiteLLM Proxyのfallbackとretryロジックをいじって、Anthropicが高い時間帯にGeminiへ逃がす、みたいな設定を試してる。コスト最適化という観点でLiteLLMを使い続けてきたけど、インフラの信頼性を担保しないまま「安くなった」は片手落ちだなと今回気づいた。ちょっとした設定ミスやイメージの差し替えで意図しないトラフィックが流れるリスクもある。
supply chain側の穴を塞いだ上でコスト周りのチューニングをしていかないと、土台がぐらついてる状態で最適化だけ積み上げてることになる。v1.87.3を契機に、自分のLiteLLM運用を一段ちゃんとした形に整えられた気がする。次はimageのversionをdependabotで自動追跡しつつ、署名検証も自動で走る仕組みにしようと思ってる。
うちのチームでもLiteLLMをProxyとして立てて、複数のLLM APIを束ねている。OpenAI、Anthropic、あとGeminiのエンドポイントを一箇所に集めて、upstream先をコード側に露出させないようにしてる構成だ。コスト管理のためにrpm/tpmのlimitもProxyで制御してる。わりと中心的なinfraになってきたので、そろそろイメージの信頼性をちゃんと担保したかった。
commit hashでpinするのが正解だった
リリースノートにはtagとcommit hashの2パターンで検証する方法が書いてある。
cosign verify \
--key https://raw.githubusercontent.com/BerriAI/litellm/0112e53046018d726492c814b3644b7d378029d0/cosign.pub \
ghcr.io/berriai/litellm:v1.87.3tagベースの検証はお手軽だけど、「tagが上書きされる可能性がある」という注記がある。commit hashは cryptographically immutable、つまり書き換えが不可能なので、こっちを使うのが筋だ。リリースノートでも「recommended」と明記されている。GitHubのsupply chain attackの文脈では、tagのmutableさは割と既知のリスクで、npm installでversion rangeを広く取りすぎるのと似た話だと思う。自分もいままで何となくtagでpullしてたのを反省した。
starは50.3k、forkが8.9k。かなり使われてるOSSなので、ちゃんとした署名フローが入ってるのは正直ありがたい。このスケールのプロジェクトでcosignを全リリースに適用してるのは、わりと本気でセキュリティに向き合ってるなという印象だ。
自分のDocker運用のどこを直したか
うちはGitHub ActionsでCI回してて、LiteLLMのimageをpullしてからintegration testを流す構成になってる。今回の件を受けてworkflowに検証ステップを1個追加した。
- name: Verify LiteLLM image signature
run: |
cosign verify \
--key https://raw.githubusercontent.com/BerriAI/litellm/0112e53046018d726492c814b3644b7d376029d0/cosign.pub \
ghcr.io/berriai/litellm:v1.87.3cosign自体はGitHub Actionsのrunnerに入ってないので、sigstoreのsetup-cosignアクションで先に入れる必要がある。そこだけちょっとハマった。ドキュメントにはcosignのインストール手順が載ってないので、自分で調べた。あとcosignのverifyが成功すると「The cosign claims were validated」「The signatures were verified against the specified public key」という2行が出力されるんだけど、初回はそれを見るまで「本当に通ってるのか?」と不安だった。ちゃんと通ってたので一安心。
LLM API cost最適化との接点
ここ数ヶ月、LiteLLM Proxyのfallbackとretryロジックをいじって、Anthropicが高い時間帯にGeminiへ逃がす、みたいな設定を試してる。コスト最適化という観点でLiteLLMを使い続けてきたけど、インフラの信頼性を担保しないまま「安くなった」は片手落ちだなと今回気づいた。ちょっとした設定ミスやイメージの差し替えで意図しないトラフィックが流れるリスクもある。
supply chain側の穴を塞いだ上でコスト周りのチューニングをしていかないと、土台がぐらついてる状態で最適化だけ積み上げてることになる。v1.87.3を契機に、自分のLiteLLM運用を一段ちゃんとした形に整えられた気がする。次はimageのversionをdependabotで自動追跡しつつ、署名検証も自動で走る仕組みにしようと思ってる。