8.7

View in English

8.7 ビルドシステムと成果物管理

概要と動機

ビルドは、ソースコードが出荷できるものになる所です。8.1章のすべてのパイプラインはここから始まります。何かをテストし、スキャンし、デプロイし、昇格させる前に、ビルドシステムが、ソースファイルの木を、具体的な成果物、コンパイル済みのバイナリ、パッケージ、コンテナイメージ、あるいは静的アセットの束に変えなければなりません。その最初のステップが遅い、不安定、あるいは再現できないなら、それ以降のすべてのステップがその損害を引き継ぎます。二つのマシンで異なる出力を生むビルドは、走らせるすべてのテストと集めるすべての承認を損ないます。検証したものが、出荷するものだと証明できないからです。

この章は、その最初のステップとその出力についてです。成果物を構築するビルドシステムと、それらを保存し、バージョン管理し、保護し、昇格させる成果物管理。それは、継続的インテグレーションと継続的デリバリー(CI/CD)のパイプライン全体を扱う8.1章より、意図して狭いものです。ここでの主題は、ビルドそのものと、それが出す成果物です。それは、入力をどう追跡し制御するかを扱う2.10章のソフトウェア構成管理と、取り込むサードパーティのコードを扱う2.18章の依存関係とサプライチェーンの管理を補完します。ビルドは、それらの入力が出会う所です。ソース、依存関係、設定のすべてが、一つの不変の出力に収束します。

大きなチームにとって、賭け金は具体的です。数百人のエンジニアが一日に何度も数分のビルドを待つとき、集計された失われた時間は、ほぼ他のどんなエンジニアリングのコストをも小さく見せます。成果物が可変、追跡されない、あるいは環境ごとに再構築されるなら、本番で何が動いているかを自信をもって言う能力を失います。企業と政府の設定では、その追跡可能性は任意ではありません。監査人とセキュリティ責任者は、本番のバイナリが、レビューされたソースから、信頼されたシステムで構築され、記録された管理の連鎖を伴うという証拠を必要とします。規律ある、ビルドと成果物の実践は、その証拠を、すべての監査の前の大慌てではなく、通常の仕事の副産物に変えます。

主要原則

  • ビルドはデリバリーの最初のステップです。その速度と正しさを本番の関心事として扱います。
  • 再現可能で、可能なら閉じた(ハーメティックな)ビルドを目指します。同じ入力は、毎回同じ出力。
  • 成果物を一度構築し、まさにその成果物を環境にわたって昇格させます。
  • 成果物を不変でコンテンツアドレス化されたものにし、意味のあるバージョンを付けます。
  • 成果物を、保持、アクセス制御、出所を備えた管理されたリポジトリに保存します。
  • 積極的にキャッシュしますが、キャッシュを単なる速度の技ではなく、セキュリティの境界として扱います。
  • 出所、署名、部品表を、事後ではなくビルド時に捉えます。

推奨事項

ビルドをデリバリーの最初のステップとして扱う

ビルドシステムは本番のインフラストラクチャで、そのように資金を出して保守すべきです。成果物の速く正しい構築が、CI/CD(8.1章)が乗る基礎です。チームがビルドを後付け、つまり誰も所有しないシェルスクリプトの山として扱うと、不安定なパイプライン、不可解な「自分のマシンでは動く」欠陥、そして第11部で述べるエンジニアリングのフロー全体を侵食する遅いフィードバックという形で代償を払います。ビルドに所有者、コードと並んでバージョン管理に保たれた定義(リポジトリ構造の2.14章)、他のあらゆる重要なシステムと同じレビューの規律を与えてください。

ビルドを再現可能にし、可能なら閉じたものにする

再現可能なビルドは、同じソースからビット単位で同一の出力を生むので、誰でも独立に再構築して、成果物がそのソースと一致することを検証できます。これは、バイナリがコミットとデプロイの間に改ざんされなかったと信頼できるようにする性質です。そこに至るには、非決定性の源を排除することを意味します。埋め込まれたタイムスタンプ、絶対ファイルパス、ビルド順序のランダム性、結果が時間とともにずれるネットワークの取得。

閉じたビルドは、さらに進んで、すべての入力を前もって宣言し、ネットワークやホストの環境状態に到達できない隔離された環境で走ります。宣言したものを除いて、何もビルドに入りません。固定されたツールチェーンのバージョン、固定された依存関係、明示的なソースファイル。閉じていることが、再現性を運任せではなく信頼できるものにします。完全に閉じることには、ツールと規律の本物のコストがあるので、二値ではなく方向として扱ってください。部分的な進歩でも、コンパイラのバージョンを固定する、依存関係をベンダリングあるいはロックする、タイムスタンプを取り除くことで、わずかな労力で信頼の大半が買えます。

ロックファイルで依存関係を決定論的に解決する

すべてのビルドはサードパーティのコードを取り込み、それをどう解決するかが、ビルドが決定論的かを決めます。ロックファイルは、すべての直接および推移的な依存関係の、解決された正確なバージョンと暗号学的ハッシュを記録するので、数か月後のビルドがまったく同じグラフに解決されます。ロックファイルをコミットし、その変更をレビュー可能な出来事として扱い、変異した上流のパッケージが気づかれずに紛れ込めないよう、取得のたびにハッシュを検証します。これは、2.18章のサプライチェーンの規律のビルド時の顔です。ロックファイルがなければ、「昨日はビルドできた」は、今日何がビルドされるかについて何も語りません。浮動するバージョン範囲が静かに新しいリリースを引き込んだり、攻撃者が悪意のあるものを公開したりしうるからです。

ローカルとリモートで、増分ビルドとキャッシュを使う

誰も、変わっていないものを再構築すべきではありません。増分ビルドは、どの入力がどの出力に供給されるかを追跡し、変更で影響を受けた部分だけを再構築します。ビルドキャッシュは、以前の仕事の出力を、その入力のハッシュをキーとして保存するので、変わっていないターゲットは再計算されずに取得されます。ローカルのキャッシュは一人の開発者のループを速め、リモートあるいは分散ビルドキャッシュは、チーム全体とCIのフリートで結果を共有するので、ある入力を最初にビルドした人がコストを払い、他の全員がキャッシュヒットを得ます。大きなモノレポでは、これが10分のビルドと10秒のビルドの違いです。

見返りは開発者のフィードバックの速度で、それは行える最もてこの効く投資の一つです。速く正しいフィードバックは、エンジニアをフローに保ち、コードを書くことと、それが動くかを知ることの間のループを短くします。ただしキャッシュの正しさは慎重に守ってください。実際の入力(環境変数、ツールのバージョン)を省いたキャッシュキーは、デバッグが気が狂いそうなほど難しい古い結果を生みます。キャッシュは、入力のハッシュ化の完全さと同じだけ信頼できます。

規模に合ったビルドツールを選ぶ

ビルドツールには幅があります。軽い端では、Makeや言語ネイティブのツールが単純な依存グラフをモデル化し、単一のサービスや小さなリポジトリには十分です。中間では、JavaのためのGradleやMaven、あるいはGo、Rust、JavaScriptの標準のツールチェーンのようなエコシステムのツールが、依存関係の解決と慣習を加えます。重い端では、Bazelや同様のモノレポ向けビルドツールのようなグラフベースのシステムが、ビルド全体を、ターゲットの細粒度で閉じた有向非巡回グラフとしてモデル化し、大きなコードベースにわたって、正確な増分性、リモートキャッシュ、リモート実行を可能にします。

重いツールは、相互依存する多くのプロジェクト、大きなモノレポ(2.14章)、あるいはチームを絞めるビルド時間がある場合に元を取ります。それは本物の投資を要します。急な学習曲線、移行の労力、ビルド定義を保守する専任のチーム。流行だからといってBazel級のツールを採用しないでください。細粒度のキャッシュと並列性が、ツールの運用コストより多くのエンジニアリングの時間を取り戻すほど、ビルドグラフが大きいときに採用してください。ほとんどの小規模から中規模のシステムでは、リモートキャッシュを備えた良いエコシステムのツールが最適点です。

管理されたリポジトリに成果物を保存する

成果物を構築したら、それには住処が必要です。成果物リポジトリ(レジストリとも呼ばれる)は、パッケージ、コンテナイメージ、バイナリを、バージョニング、アクセス制御、メタデータとともに保存します。それはソースのリポジトリの対です。ソースが入り、成果物が出る、両方が管理される。良いリポジトリは、内部の成果物を公開し取得する単一の信頼できる場所を与え、外部の成果物をプロキシしてキャッシュするので、ビルドのたびに公開インターネットに手を伸ばさずに済み、誰がいつ何を公開したかを記録します。コンテナイメージには独自のレジストリの慣習があり、他のパッケージの種類にもそれぞれの慣習がありますが、規律は同じです。管理されたアクセス制御されたストアから来なかったものは、何も本番で動きません。

成果物にバージョンを付け、不変でコンテンツアドレス化されたものにする

すべての成果物に意味のあるバージョンを与えます。セマンティックバージョニング(major.minor.patch)は、変更の性質を利用者に伝えます。メジャーの上昇は破壊的変更を、マイナーは互換性のある機能の追加を、パッチはバグ修正を示します。人間が読めるバージョンと並んで、各成果物をその内容の暗号学的ハッシュで識別し、コンテンツアドレス化します。コンテンツアドレス、しばしばダイジェストと呼ばれるものは、1バイトでも変われば変わる指紋で、正確な成果物を曖昧さなく参照し、あらゆる改ざんを検知できるようにします。

公開された成果物を不変にします。バージョンが公開されたら、決して変わりません。同じバージョンで異なるバイトを再公開することは、サプライチェーンの危険であり、デバッグの悪夢です。二人が「バージョン1.4.2」を持っていて、異なるソフトウェアを持ちうるからです。「latest」のような可変のタグは人間には便利ですが、重要なものでは、記録した特定の不変のダイジェストに必ず解決されなければなりません。浮動するタグではなくダイジェストでデプロイし、テストしたものが、動かすものだと証明できるようにします。

一度構築し、あらゆる所へ昇格させる

成果物を一度構築し、同じ成果物を、開発、ステージング、本番という環境を通じて動かします。この「一度構築し、あらゆる所へ昇格させる」ルールは、成果物管理で最も重要な唯一の実践です。環境ごとに再構築すれば、テストされた成果物がデプロイされたものだという保証を捨てたことになります。再構築のたびに異なる依存関係を引き込んだり、わずかに異なるマシンで走ったりしうるからです。昇格はメタデータの操作です。すでに構築されテストされたダイジェストを、次の環境のために承認済みと印を付け、再構築ではなく外部化された設定(2.10章)を通じて、その環境向けに設定します。これはバイナリを一定に、設定を可変に保ち、信頼性と監査可能性の両方にまさに望む分離です。

出所を捉え、成果物に署名し、SBOMを生成する

ビルド時に、成果物がどこから来たかを記録し、それが改変されていないことを証明します。出所とは、成果物がどう構築されたかの署名された記述です。どのソースのコミット、どのビルダー、どの入力。成果物に署名することで、利用者は実行する前に真正性と完全性を検証でき、デプロイ時に署名を検証することが輪を閉じます。ソフトウェア部品表(SBOM)、つまり成果物の内側のコンポーネントと依存関係の完全な目録は、新しい脆弱性が開示されたときに、ビルドログを何日も掘り返す代わりに、「影響を受けるか」に数分で答えられるようにします。

SLSA(Supply-chain Levels for Software Artifacts)のような枠組みは、ビルド時の完全性の段階的なモデルを与えます。より高い水準は、閉じた隔離されたビルドと偽造できない出所を要求します。これらすべてを、情報が権威を持ち収集が安いビルドの中で生成してください。高価で信頼できなくなる事後に再構成するのではありません。この仕事は、4.9章のセキュアなソフトウェア開発ライフサイクルと、2.18章のサプライチェーンの関心事に直接仕えます。

キャッシュを保護し、保持とコストを管理する

共有のビルドキャッシュは、共有の信頼の境界です。攻撃者が毒された項目を書き込めれば、それを取得するすべての利用者が侵害されたコードを実行し、速度の利点が攻撃面になります。認証でキャッシュを保護し、書き込みアクセスを狭く(しばしば信頼されたCIだけに、開発者のノートパソコンには決して与えず)絞り、毒された、あるいは古い項目が正当なものを装えないよう、キャッシュキーがすべての実際の入力をハッシュするようにします。特にチーム間で共有されるリモートキャッシュでは、キャッシュの汚染を本物の脅威モデルとして扱います。

成果物はコストも蓄積します。コンテナイメージとビルドの出力は大きく、無制限のレジストリは、ストレージの請求と遅い検索が問題を強いるまで育ちます。保持の方針を定義します。本番に昇格したすべての成果物と、稼働中のシステムが参照するすべてを保ち、古い開発とプルリクエストのビルドを自動的に失効させ、削除したものを記録します。目標は、再現性と監査に必要なものを保ちつつ雑音を落とし、驚きとして来るのではなく、意識して選んだコストで済むストアです。

トレードオフ: 長所と短所

決定長所短所
重いグラフビルドツール(Bazel級)細粒度の増分性、リモートキャッシュと実行、巨大なモノレポにスケール急な学習曲線、移行コスト、専任のビルドチームが必要
軽いビルドツール(Make、ネイティブ)単純、低オーバーヘッド、採用が速い規模での貧しい増分性とキャッシュ、弱い閉鎖性
リモート/分散ビルドキャッシュ共有された結果、フリート全体での劇的な高速化キャッシュ汚染の面、正しさは入力の完全なハッシュ化に依存
完全に閉じたビルド信頼できる再現性、強い出所本物のツールと規律のコスト、ローカルのワークフローが難しい
一度構築し、あらゆる所へ昇格テストされた成果物が出荷された成果物。きれいな監査証跡外部化された設定と規律ある昇格が必要
不変でコンテンツアドレス化された成果物改ざんが明らか、曖昧さのない参照浮動するタグより不便、管理すべきストレージが増える
長い成果物の保持完全な再現性と監査履歴ストレージコスト、クリーンアップの方針なしでは検索が遅い

繰り返される緊張は、速度と信頼の間にあります。キャッシュ、共有のビルドファーム、浮動するタグはすべて、ビルドをより速く便利にしますが、不注意に使えば、それぞれが、何を構築したかを正確に言い、改ざんされなかったと証明する能力を弱めます。信頼できる道を速い道にすることで解決してください。完全な入力のハッシュは、キャッシュを速く、かつ正しくします。ダイジェストによるデプロイは、タグによるデプロイと同じくらい速く、はるかに安全です。ビルドでのSBOMの生成は、数秒かかり、数日を節約します。完全性を最初から速い道に組み込めば、速度のために完全性を犠牲にする必要はめったにありません。

チームで議論すべき問い

  1. 先四半期の本番の成果物を今日再構築して、同じバイトを得られますか。そうでないなら、何が欠けていますか。 これは、ビルドの規律の最も鋭いテストです。再現性は、固定されたツールチェーン、ロックされた依存関係、排除された非決定性がすべて一緒に働くことに依存するからです。数か月前に出荷された特定の成果物を選び、記録されたソースのコミットから実際に再構築を試みてください。その試みから学ぶことは、どんな方針の文書よりも価値があります。依存関係の範囲が浮動したのかもしれず、コンパイラのバージョンが固定されていなかったのかもしれず、タイムスタンプが焼き込まれているのかもしれません。見つけた隙間があなたの再現性の積み残しで、それを閉じることが、監査したものが動かしているものだと信頼できるようにします。その管理の連鎖が法的な要件である、規制対象と政府の設定では、それは非常に重要です。

  2. 各成果物を一度構築して昇格させていますか。それとも環境ごとに再構築していますか。そしてどちらかをどう証明しますか。 多くのチームは単一の成果物を昇格させていると信じていますが、詳しく見ると、ステージングと本番がそれぞれ、微妙に異なる入力で新しいビルドを起動していると気づきます。実際のリリースを一つ、コミットから本番までたどり、まさに同じダイジェストがすべての環境を通じて動いたのか、途中で新しいバイトが作られたのかを確認してください。再構築を見つけたら、テストの保証が思っていたより弱い場所を見つけたのです。テストされた成果物とデプロイされた成果物が、同一だと証明できないからです。設定を外部化し、設定が変わる間バイナリを一定に保つという修正は、信頼性と、はるかにきれいな監査の物語の両方で元を取ります。

  3. 明日、一般的なライブラリに重大な脆弱性が告知されたら、それを含むすべての成果物をどれだけ速く列挙できますか。 この問いは、ビルド時の出所とSBOMの実践が本物か願望かを試します。広く使われるコンポーネントが悪用可能だと判明したとき、数時間で回復する組織は、ビルド時に部品表を生成して各成果物とともに保存している組織で、数週間で回復する組織は、ビルドログをgrepし、エンジニアに聞き取りをしています。実際に依存しているライブラリで、シナリオを具体的に歩き、今日答えにどれだけかかるかを計ってください。その時間と「数分」の間の隔たりは、あなたのサプライチェーンの露出の直接の尺度で、4.9章のセキュアな開発ライフサイクルの仕事に直接つながります。

  4. 私たちのビルドは毎日どれだけのエンジニアリングの時間を費やし、それを速くするビジネスケースは何ですか。 ビルドの遅延は、すべてのエンジニアがすべての変更で払う税で、大きなチームの規模では、一回の待ちが高く感じられないので、集計は過小評価しやすいです。測ることに合意することで、漠然とした不満が、リモートキャッシュ、より良い増分性、より重いビルドツールのコストと量れる数字に変わります。ローカルとCIのビルド時間の中央値と最悪値、一日のビルドの数、遅いビルドが誰かをフローからコンテキストの切り替えに押し出す頻度の誠実な見積もりを持ち込んでください。相反する考慮は、速いビルドが無料ではないことです。リモートキャッシュと分散実行は運用して保護するインフラストラクチャを加え、より重いツールは保守チームを加えます。企業あるいは政府の組織では、多くのチームにわたる遅いフィードバックのスループットと士気のコストを数えてください。それは通常インフラストラクチャの請求を小さく見せ、まさにリーダーシップがすでに資金を出す枠づけです。

  5. 共有のビルドキャッシュに誰が書き込めて、毒された項目が本番に届くのを何が防ぎますか。 共有のキャッシュは、速度の勝利を新しい信頼の境界と交換し、一人のエンジニアの結果がフリート全体に仕えられるようにする同じ仕組みが、一つの破損したあるいは悪意ある項目が、それを取得する全員を侵害できるようにします。大きなチームでは、影響範囲は組織全体なので、これはツールの既定が偶然どうなっているかではなく、意図した決定に値します。各キャッシュに書き込みアクセスを持つ人とものの一覧、書き込みが開発者のノートパソコンではなく信頼されたCIに絞られているか、古いあるいは毒された項目が正当なものを装えないよう、キャッシュキーがすべての実際の入力をハッシュしているかを持ち込んでください。緊張は、最も厳しい統制が、開発者が自分のマシンからキャッシュ項目をプッシュする便利な道を遅くすることです。企業と政府の設定では、キャッシュの汚染をサプライチェーンのモデルの明示的な脅威として扱い、リリースにコードを注入できる他のあらゆる本番のシステムに適用するのと同じアクセス制御、記録、レビューを要求してください。

  6. どの時点で、ビルドグラフはより重いツールを正当化し、それを越えたことをどうやって知りますか。 軽いエコシステムのツールと、Bazelのようなグラフベースのシステムの選択は、この領域で最も高価で元に戻しにくい決定の一つです。大きなコードベースを細粒度のビルド定義に移行するには、数か月と専任のチームがかかるからです。閾値を事前に決めておくと、流行だからと不要な複雑さを採用することも、ビルド時間があらゆるチームを絞めてからずっと後まで軽いツールにしがみつくことも避けられます。ビルドグラフの大きさと相互依存、現在のビルドとキャッシュヒットの指標、ツールが取り戻すエンジニアリングの時間に対する、移行と継続的な保守のコストの現実的な見積もりを持ち込んでください。相反する引力は、重いツールが、規模では他に匹敵しない正確な増分性とリモート実行を届けるが、グラフが本当に元を取れるほど大きい場合に限る、ということです。大きな企業あるいは機関では、ツールの閉鎖性と出所の保証が、監査とサプライチェーンの要件を満たす助けになるかも量ってください。それは計算を、生の速度を超えて動かしえます。

セクター別の視点

スタートアップ。 小さなチームでビルドのインフラストラクチャに割く余裕がないなら、軽く保ってください。言語ネイティブのビルドツールを使い、初日からロックファイルを採用し、コンテナイメージは「latest」タグではなくダイジェストでデプロイします。それらの習慣はほとんど費用がかからず、後の「自分のマシンでは動く」という苦痛の一種類をまるごと免れさせてくれるからです。重いグラフビルドツールには抵抗してください。最も乏しい資源は、エンジニアリングの注意です。ビルドが数分を超え始めたら、手を伸ばす価値のあるアップグレードは、リモートビルドキャッシュ一つです。

小規模事業者。 専任のビルドエンジニアがいないので、自前の成果物のインフラストラクチャを動かすのではなく、マネージドなサービスに頼ってください。ホスト型のレジストリとCIプロバイダー組み込みのキャッシュが、プラットフォームチームなしに、バージョニング、保持、アクセス制御を与えます。選択を築くより買うとして枠づけ、ストレージコストが予測可能に保たれるよう自動的な失効の方針を設定し、基本が整っていることを確かめてください。ロックされた依存関係と、不変でダイジェスト固定のデプロイ。誰もパイプラインをフルタイムで見ていなくても、それらはあなたを守るからです。

大企業。 多くのチームにわたる問題は一貫性です。共有で所有されたビルドのプラットフォーム、共通の成果物リポジトリ、どのグループも信頼できないパイプラインを再発明しないよう、ロックファイル、署名、SBOM、一度構築して昇格させることの徹底された標準。リモートキャッシュに、そしてビルドグラフが正当化する所ではグラフベースのツールに投資し、キャッシュを、書き込みアクセスを絞り監査記録を伴う、統治された信頼の境界として扱います。成果物を、保持の方針と出所を備えた管理された資産群として管理し、本番のどのコンポーネントも、要求に応じてレビューされたソースまでたどれるようにします。

政府。 調達規則、透明性、公的な説明責任が、ビルド時の完全性を、あれば良いものではなくコンプライアンスの要件にします。パイプラインをSLSAのような段階的な枠組みに揃え、固定されたツールチェーンから、隔離されたネットワーク制限のある環境でビルドを走らせ、サードパーティの依存関係を、使う前にスキャンして承認する内部リポジトリ経由でプロキシします。署名されたSBOMと出所を、記録保持法が求める年数にわたって不変に保存し、署名されダイジェストで識別された成果物だけをデプロイし、本番のソフトウェアがまさにレビューされ承認されたものだと、監査人と市民に証明できるよう備えてください。

事例

スタートアップ。 小さなモノレポを動かす15人のスタートアップは、言語ネイティブのビルドツールと速いフィードバックから始め、それは彼らの規模では正しい選択です。成長するにつれ、ビルド時間が5分を超え、エンジニアは待つ間にコンテキストを切り替え始めます。重いグラフビルドツールに飛びつく代わりに、開発者のマシンとCIの間で共有されるリモートビルドキャッシュを加え、変わっていないターゲットが再構築されず取得されるので、ほとんどのビルドが数秒に削られます。すべての言語にロックファイルを採用し、コンテナイメージを「latest」タグではなくダイジェストでデプロイし、レジストリの請求が平坦に保たれるよう、プルリクエストのイメージのビルドに自動失効をオンにします。取り組み全体は数週間で済み、毎日エンジニアリングの時間を何時間も買い戻します。

大企業。 世界的な金融サービス企業は、数百人のエンジニアにまたがる大きなモノレポを動かし、リモートキャッシュとリモート実行を備えたグラフベースのビルドシステムを採用します。彼らの規模では、細粒度の増分性が、ビルドチームのコストよりはるかに多くのエンジニアリングの時間を取り戻すからです。すべての成果物は、隔離された環境で閉じてビルドされ、署名され、SBOMと署名された出所を添えて、管理されたレジストリに公開されます。デプロイはコンテンツダイジェストで行われ、ポリシーエンジンは署名が検証されないイメージの実行を拒否します。成果物はステージングから本番まで昇格され、再構築されることはないので、テストを通ったバイナリが、顧客に仕えるものだと証明できます。監査人が本番のコンポーネントをレビューされたソースまでたどるよう求めるとき、管理の連鎖は調査ではなくクエリです。

政府。 システムを近代化する国の税務当局は、ビルド時のサプライチェーンの完全性を、パイプラインをSLSAのような段階的な枠組みに揃えて、コンプライアンスの要件として扱います。ビルドは、固定されたツールチェーンとロックされた依存関係から、隔離されたネットワーク制限のある環境で走るので、出力は再現可能で独立に検証可能です。すべての成果物は署名されたSBOMと出所を持ち、記録保持法を満たすために何年も不変に保存されます。サードパーティの依存関係は、どのビルドが使う前にもスキャンして承認する内部リポジトリ経由でプロキシされ、審査されていないコードをネットワークから完全に締め出します。機関は、署名され昇格された、ダイジェストで識別される成果物だけをデプロイするので、市民の申告を処理するソフトウェアがまさにレビューされ承認されたものだと、規制当局と国民に証明できます。

ビジネスケース: 動機、ROI、TCO

ビルドと成果物の規律の見返りは、まず取り戻されたエンジニアリングの時間として現れます。遅いビルドは、すべての変更ですべてのエンジニアに課税し、そのコストは大きな組織にわたって複合します。一日に数千回走るビルドから数分を削ることは、年に何人年分も取り戻し、定量化は難しいが同じくらい本物のこととして、エンジニアをコンテキストの切り替えではなくフローに保ちます。リモートキャッシュと良い増分性は、しばしば数週間で元を取ります。再現可能で一度だけ昇格される成果物は、「ステージングでは動いた」というインシデントの一種類をまるごと減らし、リーダーがすでに見ているデリバリー指標、変更失敗率と平均復旧時間を下げます。

より大きく、見えにくい見返りは、リスクの低減です。署名された成果物、SBOM、出所は、サプライチェーンのインシデントを、数週間の緊急事態から、範囲の定まった数時間の対応に変え、監査を大慌てからクエリに変えます。規制対象と政府の文脈では、その追跡可能性は運用すること自体の前提条件なので、投資は任意ではなく構造的です。これを怠ると、総所有コストは逆に走ります。可変の成果物と再現できないビルドは、誰も完全には説明できない資産群へと積み重なり、保持の方針なしにストレージは際限なく育ち、すべての監査とすべてのインシデントが、本来よりも高くつきます。リーダーシップに論拠を示すには、ビルドの速度をエンジニアリングのスループットに、成果物の完全性を監査のコストと侵害の露出に結びつけてください。どちらも彼らがすでに資金を出しているものです。

アンチパターンと落とし穴

  • 環境ごとの再構築: ステージングと本番に新しいバイトを作り、テストされた成果物がデプロイされたものだという保証を捨てること。
  • 浮動するタグによるデプロイ: 不変のダイジェストではなく、「latest」や可変のタグを動かし、動くものが予測不能で追跡不能になること。
  • ロックファイルなし: 浮動するバージョン範囲により、ビルドが時間とともに静かに異なる、あるいは悪意ある依存関係を引き込むこと。
  • 不完全なキャッシュキー: 実際の入力をキャッシュキーから省き、デバッグの何日分も無駄にする古い結果を生むこと。
  • 保護されていない共有キャッシュ: 信頼されない書き込み者にリモートキャッシュを汚染させ、利用者が侵害された出力を取得して実行すること。
  • 非決定的なビルド: 埋め込まれたタイムスタンプ、絶対パス、固定されていないツールが出力を変え、検証を無効にすること。
  • 重いツールの早すぎる採用: ビルドグラフが正当化するほど大きくなる前に、Bazel級の複雑さを引き受けること。
  • 後付けのSBOMと出所: ビルドの中で生成するのではなく、高価で信頼できなくなる事後に、サプライチェーンのメタデータを再構成すること。
  • 無制限の保持: ストレージコストと遅い検索がうろたえた片付けを強いるまで、古い成果物を決して失効させないこと。

成熟度モデル

  • レベル1: 開始。 ビルドは、誰も所有しない、しばしば開発者のマシンから走る、その場しのぎのスクリプトです。出力は非決定的で、依存関係はロックファイルなしに浮動し、成果物は環境ごとに再構築されて可変のタグでデプロイされ、共有キャッシュも、署名も、部品表もありません。
  • レベル2: 発展。 一部のチームがビルドをチェックインされた定義からCIに移してロックファイルを採用していますが、実践は組織全体で一貫していません。成果物は基本的なバージョニングを伴う管理されたリポジトリに置かれるかもしれず、ローカルあるいは単純なリモートキャッシュが一般的なビルドを速めますが、環境ごとの再構築はまだ起こり、出所は穴だらけです。
  • レベル3: 標準化。 再現可能でおおむね閉じたビルドが、固定されたツールチェーンと、キーがすべての実際の入力をハッシュする共有のリモートキャッシュを伴って、組織全体で文書化され徹底されています。成果物は、不変でコンテンツアドレス化され、セマンティックにバージョン管理され、一度構築してあらゆる所へ昇格され、署名され、SBOMとともに出荷されます。キャッシュへのアクセスは制御され、保持の方針はチーム間で一貫して適用されます。
  • レベル4: 管理。 ビルドの資産群が、ベースラインに対して測定され制御されます。ビルド時間、キャッシュヒット率、開発者のフィードバック時間、ストレージコストが明示的な目標とともに追跡され、退行は行動を引き起こし、署名と出所の検証がデプロイ時に徹底されるので、失敗したチェックがリリースをブロックします。ビルド時のサプライチェーンの完全性はSLSAのような段階的な枠組みに対して評価され、数字が次にどこへ投資するかを駆動します。
  • レベル5: オーケストレーション。 ビルド、キャッシュ、成果物、サプライチェーンの実践が継続的に改善され、組織全体に統合されています。ツール、保持、セキュリティの姿勢は、インシデントと監査から学ぶにつれて適応し、リモート実行とキャッシュはコードベースの進化に合わせて調整され、ビルド時の完全性は、後付けではなく、より広いセキュアな開発ライフサイクルに織り込まれています。

議論のためのアイデア

  1. 現在のローカルビルド時間の中央値と最悪値は何で、リモートキャッシュはそれぞれに何をもたらしますか。
  2. 今日、可変のタグでデプロイされている成果物はどれで、すべてをダイジェストでデプロイするには何が必要ですか。
  3. あなたのビルドグラフが、より重いツールを正当化する所はどこで、そのツールが節約するより多くかかる所はどこですか。
  4. 共有のビルドキャッシュに誰が書き込めて、毒された項目が本番に届くのを何が防ぎますか。
  5. 最後に出荷したものについて、署名されたSBOMを作れますか。作れないなら、そこへの最小の一歩は何ですか。
  6. ビルドの成果物の保持方針は何で、ストレージは今日いくらかかり、いくらであるべきですか。

要点

  • ビルドはデリバリーの最初のステップです。下流のすべてがその欠陥を引き継ぐので、その速度と正しさを本番の関心事として資金を出します。
  • 監査する成果物が出荷するものだと証明できるよう、固定されたツールチェーンとロックファイルで、ビルドを再現可能にし、可能なら閉じたものにします。
  • ローカルとリモートでキャッシュと増分ビルドを行いますが、すべての実際の入力をハッシュしてキャッシュを保護します。共有キャッシュは共有の信頼の境界だからです。
  • 各成果物を一度構築し、不変でコンテンツアドレス化し、意味のあるバージョンを付け、まさにその成果物を環境にわたって昇格させます。
  • 出所、署名、SBOMをビルド時に生成し、保持とアクセス制御を伴って成果物を保存して、サプライチェーンの完全性と監査の備えを通常の仕事の副産物にします。

参考文献とさらなる読み物

  • Jez Humble and David Farley, Continuous Delivery: Reliable Software Releases through Build, Test, and Deployment Automation
  • Nicole Forsgren, Jez Humble, and Gene Kim, Accelerate: The Science of Lean Software and DevOps
  • Titus Winters, Tom Manshreck, and Hyrum Wright (eds.), Software Engineering at Google: Lessons Learned from Programming Over Time
  • Betsy Beyer, Chris Jones, Jennifer Petoff, and Niall Richard Murphy (eds.), Site Reliability Engineering: How Google Runs Production Systems
  • Peter Smith, Software Build Systems: Principles and Experience
  • The Open Source Security Foundation, SLSA: Supply-chain Levels for Software Artifacts (specification)
  • National Institute of Standards and Technology, Secure Software Development Framework (SSDF), SP 800-218
  • Tom Preston-Werner, Semantic Versioning Specification (SemVer)