タラバガニー設計局stalins.clubNOTE/notes/lockfile-is-not-reproducible-build

lockfileで依存を固定してもreproducible buildにはならない

lockfileは再現性に重要だが、lockfileがあることとreproducible buildであることは同義ではない。

Pixiの--frozenはlockfileに定義されたenvironmentをinstallし、--lockedはmanifestとlockfileが一致していなければ中断する。これは「dependency resolutionの結果を固定する」仕組みであり、同じpackage version/buildを再選択する助けになる。

しかしReproducible Builds projectの定義では、reproducible buildとは、同じsource code・build environment・build instructionsから、誰でもbit-for-bit同一のartifactを再生成できることである。dependency versionを固定することは、その条件の一部にすぎない。

Nixのstore pathは通常content-addressedではない でも同じ区別が必要になる。Nixのinput-addressed derivationはbuild-time dependency graphをaddressへ反映するが、それだけで実際のoutput bytesがdeterministicになるわけではない。

典型的な非決定性には次がある。

  • build時刻をbinary/archiveへ埋め込む
  • filesystemから列挙したfileの順序が毎回異なる
  • localeやtimezoneでsorting・生成結果が変わる
  • random seedやgenerated identifierが毎回変わる
  • build directoryのabsolute pathがdebug info等へ埋め込まれる
  • parallel buildの実行順でoutputが変わる

Reproducible Builds projectは、timestampを最大の再現性問題の一つとして挙げ、SOURCE_DATE_EPOCHによってbuild時の「現在時刻」をsourceに由来する固定値へ置き換える方法を標準化している。またfile orderingやrandomnessも独立した問題として扱っている。

したがって「再現性」には少なくとも三段階ある。

  1. resolution reproducibility — 同じdependency/version集合を選ぶ
  2. environment reproducibility — compiler、system dependency、environment variable等も同じ条件にする
  3. artifact reproducibility — 最終的なbytesまでbit-for-bit一致する

lockfileが直接保証するのは主として1であり、package formatやsolverによっては2の一部まで記録できる。3にはbuild process自体のdeterminismが必要になる。

この区別はbinary cacheのtrustにも関係する。binary cacheの公開鍵を追加することはbuilderを信頼することに近い のcacheから取得したartifactが本当にsourceから再生成できるかを第三者が確認したい場合、単に同じderivationやlockfileを持っているだけでは足りず、独立rebuildで同じbytesを得られる必要がある。

一方、checksum・signature・provenanceは別の保証をする のprovenanceは「どう作られたか」を記録するが、それ自体もreproducibilityではない。SLSA Build Provenanceはrebuildに必要な情報を提供し得るが、同じinputsから必ず同一bytesが生成されることを要求する概念とは分けて考えるべきである。

package managerの比較では、「lockfileあり」「hermetic build」「content addressed」「reproducible build」を一つの再現性スコアにまとめず、どの段階を保証しているのかを確認する必要がある。

#ツールチェーン #security

出典

▸ ノート一覧に戻る