要約

  • 暗号学的に有効なGitHubの証明は、アーティファクトのダイジェストを記録済みのビルド来歴に結び付けるが、安全性を認定するものではない。
  • 最終的な統制は利用側のポリシーにある。リポジトリ、変更不能なワークフロー識別子、コミットまたはリリース条件、環境、ランナーの信頼境界が一つでも外れれば、デプロイを拒否すべきである。
  • 非公開リポジトリ向けのGitHub Sigstoreインスタンスには公開透明性ログがなく、公開リポジトリとは観測可能性が異なる。ただし、その違いだけで仕組みが弱いとはいえない。

検証成功とデプロイ許可は別の判断

デプロイの入口に、暗号署名が正しく、ダイジェストも一致するコンテナイメージが届いたとする。来歴の記述にも改ざんはない。それでも、入口はイメージを拒否しなければならない場合がある。記録されたリポジトリが想定外かもしれない。外部の再利用可能ワークフローが、固定された識別子ではなく移動可能なタグで参照されているかもしれない。コミットが承認済みリリースの範囲外、環境が別物、あるいはランナーが許容された信頼境界の外という可能性もある。

この拒否は証明の失敗ではない。証明が入場判定に使われた結果である。

GitHubはアーティファクト証明を、ビルドの来歴を確立する暗号署名付きの主張として説明している。そこにはアーティファクトに対応するワークフロー、リポジトリ、組織、環境、コミットSHA、起動イベントを含められる。来歴の確立に使われるOpenID ConnectのIDから得た情報も対象になり得る。

ワークフローではビルドの後に証明を生成し、IDトークンと証明書き込みの権限を付与する。バイナリでは生成物そのものを対象にできる。コンテナでは完全修飾名とダイジェストを使うことで、後から動かせるタグではなく、特定の内容に記録を結び付ける。利用側は、手元の内容が申告された経路から生まれた内容と同じかを確かめられる。

ただし、その問いは限定されている。来歴は、ソースコードに欠陥や悪意がないこと、依存関係が健全であること、ビルド命令が適切であることを判断しない。実行環境が侵害されていなかったことも証明しない。検証可能なのは「何が、どの記録された経路で作られたか」であり、「実行して安全か」という包括的な結論ではない。

GitHub自身も、証明を生成するだけでは安全上の利益はなく、検証して初めて意味を持つと明記している。また、証明はアーティファクトの安全性を保証しない。利用者が評価基準を定め、記録内容を調べ、リスク判断を行う必要がある。署名の真正性だけを確認して終了すれば、署名された経路を信頼してよいかという中心課題が残る。

ポリシーが来歴を統制へ変える

想定リポジトリと組織は出発点だが、それだけでは広すぎる。同じ組織に、中央で審査されたリリース用ワークフローと、異なる管理水準の自動処理が共存することはあり得る。どちらも正当な署名権限を持つからといって、同じデプロイ資格を与えるべきではない。

ワークフローには変更不能な識別が必要になる。GitHubは外部の再利用可能ワークフローについて、完全なコミットSHAを最も安全な参照としている。SHAは不変だが、ブランチは進み、タグは移動できる。証明が参照名を正確に記録していても、その参照が現在指す内容は、審査時の内容と異なるかもしれない。名前だけを許可条件にすれば、ビルド定義の一部が審査から抜け落ちる。

コミット、リリース条件、起動イベント、環境は、許容範囲をさらに狭める。正しいリポジトリの任意のコミットではなく、承認済みリリースに対応するコミットだけを認めることができる。通常のテスト環境ではなく、管理された公開環境からの生成物に限定することもできる。これらは署名が自動的に決める条件ではなく、利用組織の選択である。

ランナーの信頼性は別軸である。GitHubは、セルフホステッドランナーが常に一時的でクリーンなマシンで動く保証はなく、信頼できないワークフローコードによって持続的に侵害され得ると警告している。有効な証明から、特定ランナーが無傷だったとは結論できない。どのランナー群や隔離条件を許容するかは、ポリシーが別途定義しなければならない。

記録を強制力のある入口にする

GitHubはKubernetes向けに、Sigstore Policy Controller、GitHubの信頼ルート、クラスタイメージポリシーを組み合わせる方法を文書化している。対象の名前空間で強制を有効にすると、イメージの受け入れ前に証明を検証し、信頼ポリシーに反するものを拒否できる。

ここでは設定そのものが統制範囲を決める。コントローラを導入しただけでは何も強制されない。ポリシーを用意し、対象名前空間で有効にする必要がある。イメージの照合パターンと除外指定も結果を変える。「証明を利用している」という事実だけでは、どのデプロイが何を拒否するのかは分からない。

公開リポジトリの証明はSigstoreの公共インスタンスを利用し、公開閲覧可能な変更不能の透明性ログにも記録される。非公開リポジトリは、同じコード基盤を使うGitHubのSigstoreインスタンスを利用するが、公開透明性ログを持たず、GitHub Actionsとのみ連携する。これは第三者が記録を観測できる範囲の違いであり、非公開側の弱さを直接証明するものではない。

GitHubの一次資料からは、利用者全体の導入率、拒否率、誤受け入れ率は分からない。すべての利用者がポリシーを強制しているとも、特定ランナーが侵害されていないともいえない。証拠のない部分を安全という言葉で埋めてはならない。

結論は明確である。証明検証を入場管理として扱い、想定リポジトリ、変更不能なワークフロー識別子、承認済みコミットまたはリリース条件、所定の環境、許容可能なランナー信頼境界をデプロイ前に要求する。一つでも異なれば拒否し、どの条件が外れたかを示す拒否記録を保存するべきである。

出典