1 poin oleh GN⁺ 2023-10-30 | 1 komentar | Bagikan ke WhatsApp
  • ISO instalasi minimal NixOS berhasil dibangun ulang secara independen dan identik hingga tingkat bit dengan artefak distribusi Hydra, menunjukkan bahwa kecocokan antara biner distribusi dan source dapat diverifikasi
  • Verifikasi kali ini mereproduksi bukan hanya paket yang disertakan di dalam ISO, tetapi juga proses pembuatan ISO itu sendiri, sehingga cakupannya lebih luas daripada sekadar reproduksi paket
  • Rebuild dimulai dari appliance VirtualBox NixOS 20.03, menggunakan revisi nixpkgs 63678e9f3d3a, dan dengan --option substitute false untuk menonaktifkan ketergantungan pada binary cache
  • Jika OVA tahun 2020 atau git yang diunduh memiliki backdoor canggih, itu masih bisa menjadi vektor serangan, sehingga verifikasi berbasis sistem yang sepenuhnya di-bootstrap masih menjadi pekerjaan yang tersisa
  • Rebuild ISO minimal adalah tonggak penting, tetapi penghapusan workaround sementara, reproduksi lebih banyak media instalasi, infrastruktur rebuild independen berkala, dan alat build attestation masih menjadi tugas berikutnya

Reproducibility yang terverifikasi pada ISO minimal

  • Build ISO nixos-minimal yang dipublikasikan Hydra dibangun ulang secara independen dan menghasilkan artefak identik hingga tingkat bit
  • Cakupan reproduksi terbagi dalam dua sumbu
    • Semua paket yang masuk ke dalam ISO
    • Proses build itu sendiri yang membuat ISO
  • Paket yang diperlukan untuk build ISO tetapi tidak disertakan di dalam ISO juga ikut dibangun, tanpa bergantung pada binary yang di-cache
  • Build reproducible menyediakan jalur kepercayaan untuk memeriksa apakah binary distribusi setia pada source dan tidak dimodifikasi di pipeline build seperti Hydra

Prosedur rebuild dan keterbatasannya

  • Rebuild dilakukan dengan memulai NixOS 20.03 dari appliance VirtualBox baru
    • CPU dan memori dialokasikan secara memadai, dan disk diperluas menjadi sekitar 65GB
    • Setelah menginstal git, nixpkgs di-clone lalu revisi 63678e9f3d3a di-checkout
    • Dengan --option substitute false, item yang dibutuhkan tidak diambil dari binary cache dan dibangun di mesin lokal
  • Prosedur ini mencakup langkah sementara untuk mengatasi isu yang sudah diketahui
  • Dari sisi kepercayaan rantai pasok, keterbatasan masih ada
    • Jika OVA tahun 2020 atau git yang diunduh memiliki backdoor canggih, itu masih bisa menjadi vektor serangan
    • Akan lebih baik jika rebuild dilakukan dari sistem yang sepenuhnya bootstrapped, tetapi tahap itu belum tercapai
    • Perkembangan terkait berlanjut di thread proyek keamanan supply-chain nixpkgs

Perbedaan antara pengumuman 2021 dan hasil kali ini

  • Pada 2021, ada pengumuman bahwa ISO minimal 100% reproducible, tetapi saat itu yang direproduksi hanya paket-paket yang diperlukan untuk build ISO secara terpisah, sementara rebuild ISO yang sebenarnya masih menyisakan perbedaan
    • Penyebabnya adalah masalah yang tersisa pada cache Hydra dan cara pembuatan ISO
    • Setelah masalah itu diperbaiki, sempat muncul regresi seperti isu upstream pada Python 3.10, dan baru minggu ini kondisi kembali memungkinkan verifikasi seluruh rantai
  • Langkah berikutnya mencakup penghapusan workaround sementara, reproduksi lebih banyak paket, dan reproduksi media instalasi lain seperti ISO Gnome
  • Infrastruktur rebuild independen berkala dan alat untuk berbagi serta mengonsumsi build attestation seperti trustix juga diperlukan

1 komentar

 
GN⁺ 2023-10-30
Opini Hacker News
  • Membangun ulang ISO minimal dari sumber adalah tonggak yang mengesankan dalam perjalanan menuju sistem yang dapat dibangun secara reproducible dari sumber
    Guix juga baru-baru ini meraih pencapaian yang ortogonal namun sama mengesankannya dalam perjalanan yang sama: mem-bootstrap seluruh toolchain compiler dari satu biner 357 byte yang reproducible, tanpa blob compiler biner lain
    Mungkin suatu hari nanti keduanya akan digabungkan, sehingga seluruh distribusi bisa dibangun secara reproducible dari sumber
    https://guix.gnu.org/en/blog/2023/the-full-source-bootstrap-...

    • Luar biasa, dan menyenangkan melihat ada orang-orang yang terus memperjuangkan hal baik meski ada reaksi seperti “kalau ada backdoor, bukankah semua orang tetap mendapat backdoor yang sama?”
      Poin penting yang tidak dipahami banyak orang bukanlah membuktikan bahwa hasil akhirnya 100% dapat dipercaya, melainkan membuktikan bahwa hasil akhirnya 100% setia pada sumbernya
      Artinya, jika ada hal mencurigakan seperti backdoor tersembunyi ditemukan, hal itu selalu bisa direproduksi secara deterministik
      Dari sudut pandang pihak jahat, itu berarti tidak ada tempat untuk kabur atau bersembunyi
    • Belum sejauh stage0 milik Guix, tetapi di NixCon ada presentasi menarik tentang mem-bootstrap Nix dari TinyCC: https://media.ccc.de/v/nixcon-2023-34402-bootstrapping-nix-a...
    • Fakta bahwa biner compiler bootstrap hanya 357 byte benar-benar mengesankan
    • Kalau hanya 357 byte, rasanya apakah perlu biner yang reproducible?
      Sepertinya seluruh 357 byte kode mesin itu bisa didokumentasikan secara manual agar dapat dipahami manusia
  • Mungkin ini pertanyaan bodoh karena saya belum pernah mencoba hal seperti ini, tetapi saya penasaran kenapa reproducibility bukan perilaku bawaan
    Jika kita mengompilasi dua salinan software dari sumber yang sama, saya tidak begitu paham apa yang mencegahnya selalu menjadi persis sama
    Saya tahu ada banyak bagian yang bergerak, tetapi saya tetap kurang memahami bagaimana perbedaannya bisa muncul

    • Penyebab spesifiknya banyak, dan mungkin timestamp adalah masalah yang paling umum
      Daftar masalah umum bisa dilihat di sini: https://reproducible-builds.org/docs/
      Inti besarnya adalah developer tidak menguji apakah build tersebut reproducible
      Jika dimasukkan ke pengujian rilis, biasanya build akan terus dipertahankan dalam kondisi reproducible
    • Penyebabnya sangat banyak
      Contoh umum yang secara eksplisit membuatnya tidak reproducible adalah timestamp dan informasi penulis
      Ada juga tempat yang secara implisit merusak reproducibility bawaan; misalnya banyak runtime tidak mendefinisikan urutan item hashmap, dan compiler bisa saja menelusuri hashmap itu untuk membuat biner
    • Bisa jadi karena paralelisme
      Ada pekerjaan yang mungkin tidak independen terhadap urutan, dan tergantung kondisi CPU, biner yang keluar bisa sedikit berbeda tetapi semuanya tetap hasil yang benar
    • Tim Go baru-baru ini menulis tentang apa yang mereka lakukan untuk membuat toolchain Go sepenuhnya reproducible: https://go.dev/blog/rebuild
    • Terkadang penyebabnya algoritma acak, terkadang masalah performa, misalnya ketika tidak mengurutkan sesuatu lebih cepat
      Terkadang juga metadata yang bergantung pada waktu atau lingkungan, urutan eksekusi thread, dan sebagainya
  • Maaf kalau saya kurang paham, tetapi saya kira salah satu alasan utama NixOS ada adalah reproducibility
    Saya pikir masalah-masalah seperti ini sudah terselesaikan
    Saya hanya memakai NixOS sekitar 2 jam dan ingin mencoba Hyprland; karena Hyprland perlu sedikit konfigurasi, saya pikir akan lebih mudah memakai konfigurasi orang lain di NixOS dibanding distro lain
    Namun mencari konfigurasinya pun sulit, dan dari sekitar 3 yang saya temukan di gist GitHub acak, tidak ada yang berfungsi, jadi saya menyerah

    • Keunggulan NixOS adalah semuanya dibangun di dalam sandbox sendiri, hanya dengan dependensi yang dideklarasikan secara eksplisit dan di-hash
      Karena tidak bergantung pada seluruh lingkungan sistem seperti distro biasa, dalam banyak kasus biner yang dihasilkan sudah sama setiap kali
      Namun proses build itu sendiri bisa nondeterministik pada berbagai paket, jadi ini saja tidak langsung memberikan reproducibility yang sepenuhnya sempurna
    • Reproducibility punya dua makna
      Makna yang Anda pikirkan adalah ketika paket biner dapat dengan mudah dibangun ulang dengan versi dependensi dan opsi build yang sama, dan sebagainya
      Artinya tidak boleh ada ruang untuk munculnya error kompilasi baru seperti “di laptop saya jalan”
      Makna yang dibahas di sini adalah semua artefak build menjadi biner yang identik byte demi byte
      Tidak boleh bergantung pada nama mesin, waktu kompilasi, urutan selesainya kompilasi file dalam build paralel, dan sebagainya; yang ini jauh lebih sulit
    • Nix adalah alat yang sulit dipelajari
      Jika belum terbiasa, hampir bukan alat yang dipilih ketika situasinya “saya ingin sesuatu yang langsung jalan sekarang”
      Di NixOS, istilah “reproducible” lebih dekat artinya dengan “mendapatkan perilaku program yang sama dari kode Nix yang sama”
      Ini mirip dengan apa yang diharapkan orang dari Dockerfile, dan levelnya adalah menyelesaikan masalah seperti “di mesin saya jalan” atau “terakhir kali jalan”
      Sebaliknya, “reproducible build” bertujuan agar artefak yang dibuat di mesin berbeda identik bit demi bit
      Dengan begitu, kita bisa memverifikasi apakah kode dibangun dari kumpulan sumber tertentu, sehingga ada satu lapisan keamanan tambahan
      Saya juga penasaran kata kunci pencarian apa yang Anda pakai saat mencari konfigurasi
      Jika mencari “nixos configuration”, ada hasil seperti https://github.com/search?q=nixos%20configuration&type=repos..., dan untuk Hyprland saja pun terlihat cukup banyak seperti https://github.com/search?q=wayland.windowManager.hyprland&t...
  • Ada baiknya melihat https://github.com/donovanglover/nix-config
    Konfigurasinya berbasis Flake dan berisi Hyprland serta beberapa hal bagus lainnya
    Saat ini NixOS bukan alat yang cocok untuk orang yang kurang tangguh atau yang kekurangan waktu
    Saya berharap suatu hari nanti itu berubah, tetapi jika bisa bertahan dan melewatinya, ada manfaat yang bisa didapat

  • Perlu diingat bahwa reproduktibilitas Nix / NixOS / Nixpkgs adalah reproduktibilitas sumber
    Jika sumber berubah, Anda akan mendapat peringatan, tetapi itu berbeda dari reproduktibilitas biner yang bisa berubah setiap kali dibangun
    Reproduktibilitas biner Nix / NixOS / Nixpkgs, setidaknya secara sistematis, cenderung belum diuji dengan baik
    Guix, Arch Linux, dan Debian menangani reproduktibilitas biner lebih baik daripada Nix / NixOS / Nixpkgs
    Referensi: https://r13y.com/ (Nix*) / https://tests.reproducible-builds.org/debian/reproducible.ht... (Debian) / https://tests.reproducible-builds.org/archlinux/archlinux.ht... (Arch Linux) / https://data.guix.gnu.org/repository/1/branch/master/latest-... (Guix, pemuatannya bisa lambat dan salinan cache ada di https://archive.is/lTuPk)

    • Dalam konteks ini, “reproduktibilitas” memiliki dua definisi
      Reproduktibilitas input berarti “invalidasi cache yang sempurna terhadap input”
      Nix dan Guix melakukannya secara sempurna berdasarkan desain, dan kadang malah memicu terlalu banyak rebuild
      Debian dan Arch Linux tidak menjadikannya perhatian utama, dan menangani masalah paket mana yang harus dibangun ulang ketika file sumber tertentu diperbarui dengan cara sementara seperti pemicu rebuild manual
      Reproduktibilitas output berarti “proses build bersifat deterministik dan selalu menghasilkan biner yang sama”, dan inilah topik tulisan aslinya
      Nix membangun paket di dalam sandbox, jadi itu membantu, tetapi bukan solusi serba guna
      Dalam hal ini Nix berada di perahu yang sama dengan Debian dan Arch Linux
      Dalam praktiknya, distro-distro sering mengirim patch yang meningkatkan reproduktibilitas ke upstream, dan distro lain ikut mendapat manfaatnya
      Dalam konteks ini https://reproducible.nixos.org adalah padanan dari tautan-tautan lain yang disebutkan, dan saya setuju laporan Nix kurang rinci, tetapi itu bukan berarti reproduktibilitas biner Nix lebih buruk
      Jika dibaca sebagai “Nix hanya bagus dalam reproduktibilitas input dan buruk dalam reproduktibilitas biner”, itu keliru
      Tonggak inilah yang sedang dirayakan di sini
    • Sepertinya sebaiknya membaca tulisannya
      Tulisan ini bukan hanya tentang biner, tetapi juga tentang mereproduksi secara bit-per-bit cara biner-biner itu dipaketkan menjadi ISO
      r13y.com sudah usang, dan kurang dari 1% yang hilang itu, seingat saya, juga disebabkan regresi upstream Python
      Reproduktibilitas biner itu sendiri, jika mengecualikan pemaketan ISO, sudah dicapai beberapa tahun lalu
      Jika masuk ke paket-paket di luar ISO inti, perbandingannya menjadi rumit
      Cara paket ditangani bersifat halus tetapi berbeda secara penting dalam konteks ini, dan banyak paket yang kemungkinan ada di AUR milik Arch masuk sebagai paket biasa di Nix, sementara sebagian besar paket upstream -bin juga pada dasarnya tidak diperlukan di Nix
      Secara umum Nix memudahkan pembuatan build yang dapat direproduksi, tetapi tidak selalu mungkin terlepas dari Nix dan sering kali membutuhkan patch
      Ditambah lagi repositori paket dasar Nix berisi lebih dari 80 ribu paket, sedangkan Arch kurang dari 15 ribu jika AUR dikecualikan, sehingga perbandingan persentase tidak terlalu berguna
      Salah satu kesalahpahaman yang sangat umum adalah mengira hash pada jalur Nix store berbasis output build, padahal sebenarnya hash itu didasarkan pada seluruh sumber dan input yang digunakan untuk membangun biner di lingkungan terisolasi, terlepas dari apakah input tersebut biner atau bukan
      Jadi manfaat keamanan yang orang harapkan tidak muncul begitu saja, tetapi sebagai gantinya ini memungkinkan software yang tidak dibangun secara reproducible tetap dapat digunakan dalam bentuk distribusi yang cukup reproducible dengan fitur, pengaturan compiler, versi dependensi, pengguna, konfigurasi, dan sebagainya yang sama
    • Sepertinya justru itulah yang dibahas oleh referensi pertama dan tulisan aslinya
      Yaitu memeriksa apakah biner yang dibangun dari sumber yang sama di mesin berbeda hasilnya sama
      Intinya adalah biner tidak berubah setiap kali dibangun
      Metode pengujiannya juga disebut menjalankan setiap build dua kali pada waktu berbeda, hardware berbeda, dan kernel berbeda
    • Saya tidak tahu bahwa Arch Linux menguji reproduktibilitas
      Tampaknya tertulis 85,6% dapat direproduksi: https://reproducible.archlinux.org
      Saya penasaran berapa banyak pekerjaan yang diperlukan di NixOS, yang punya lebih dari 80 ribu paket di repositori resmi
  • Dilihat dari tujuan maupun realitas nixpkgs, itu sama sekali tidak benar
    Tulisan aslinya membahas reproduksi ISO minimal biner yang berisi berbagai paket biner

  • Ironis sekaligus lucu bahwa proyek OpenBSD justru bergerak keras ke arah yang berlawanan
    OpenBSD memiliki offset alamat yang unik dan diacak pada setiap instalasi
    Saya paham bahwa dua tujuan, build yang dapat direproduksi dan instalasi yang unik, saling ortogonal dan bisa dicapai bersamaan, tetapi dualitas ini tetap saja lucu

    • Jika offset alamat bisa diacak dengan seed yang diberikan, pembuktian reproduktibilitas tetap mungkin dilakukan
      Atau bisa juga menggunakan cara mengacak offset saat program dimulai, yang mempertahankan reproduktibilitas sekaligus meningkatkan keamanan
      Dengan begitu offset berubah setiap kali dijalankan
    • OpenBSD melakukan linking yang diacak saat boot
      Paketnya sendiri masih bisa saja dapat direproduksi
      Semua pengacakan dilakukan secara lokal setelah paket diunduh dan checksum diverifikasi
  • Sekarang tinggal berharap para maintainer menandatangani paket, seperti yang sudah dilakukan hampir semua distro Linux lain sejak tahun 90-an
    Dengan begitu semua orang bisa punya sedikit kepastian bahwa kode yang mereka build adalah kode yang sama yang diajukan dan ditinjau oleh orang-orang yang diketahui
    Sebelum penandatanganan distandarkan, sulit membayangkan memakai Nix untuk penggunaan produksi yang melindungi sesuatu yang bernilai

    • Saya melihat para maintainer paket Nix lebih sebagai pihak yang menyediakan antarmuka berguna agar perangkat lunak mudah dikomposisikan
      Kebanyakan dari mereka tidak memberi jaminan apa pun atas isi paket
      Mengharapkan jaminan bermakna dari tanda tangan mereka terasa mirip dengan mengharapkan dukungan produk dari kurir pengiriman
      Kita juga tidak perlu percaya bahwa paket tersebut tidak dipaketkan secara berbahaya
      Karena Nix melakukan build yang dapat direproduksi, jika tidak ingin bergantung pada cache biner, cukup lihat derivation dan build sendiri
      Apakah isi dasarnya berbahaya atau tidak pada akhirnya adalah urusan antara pengembang dan pengguna
      Jika distro lain membuat orang percaya sebaliknya, menurut saya itu mendekati penyesatan
      Pengecualian yang terlintas mungkin Tails, tetapi Tails tidak seluas Nix
    • Saya penasaran distro mana yang melakukan itu
      Sejauh yang terlihat, Debian sudah tidak melakukannya lagi dan sistem build-lah yang menandatangani build; Fedora juga tidak; Arch saya tidak yakin, tetapi sepertinya tidak
      Sistem build NixOS menandatangani semua artefak build dengan kuncinya sendiri dan memverifikasi tanda tangan saat diunduh
      Jika ingin sangat paranoid, Nix setidaknya memudahkan untuk membangun semuanya langsung dari sumber
  • Ini tonggak yang sangat mengesankan, dan selamat untuk orang-orang yang memungkinkannya
    Disebutkan bahwa saat ISO benar-benar dibuild ulang, masih ada perbedaan, dan penyebabnya adalah masalah yang tersisa di cache Hydra serta cara ISO dibuat
    Saya penasaran apakah ada yang bisa menjelaskan bagaimana mereka memperbaiki “cara ISO dibuat”
    Dulu saya pernah mencoba membuat ISO yang dapat direproduksi, tetapi tidak bisa membuat sistem berkas menentukan extent secara deterministik

    • Untuk NixOS, itu ada di bagian “bagaimana kami mereproduksinya” dalam tulisan tersebut
      Langkah terakhir proses itu menghasilkan ISO di direktori ./result/iso
      Sepertinya yang dicari adalah perintah yang dipanggil oleh build itu, tetapi saya tidak yakin langkah mana yang dimaksud
      Misalnya pemanggilan xorriso ada di sini: https://github.com/NixOS/nixpkgs/blob/master/nixos/lib/make-...
  • Bukankah untuk melakukan ini kita harus memalsukan waktu sistem?
    Waktu sering masuk ke dalam biner dengan berbagai cara

    • Memang, timestamp kemungkinan adalah salah satu penyebab nondeterminisme yang paling umum
      Saking umumnya, banyak compiler telah mengimplementasikan variabel de facto standar untuk memalsukan timestamp, yaitu SOURCE_DATE_EPOCH: https://reproducible-builds.org/docs/source-date-epoch/
    • Saya penasaran apakah ada contoh bagaimana dan mengapa hal seperti itu terjadi
    • Cukup jangan sertakan timestamp sama sekali di semua build, atau setel ke 0 sehingga tanggal build di mana pun menjadi 1970
  • Bukankah ini membantu menyelesaikan masalah yang ditulis Ken Thompson dalam “Reflections on Trusting Trust”?
    Jika seluruh sistem bisa sepenuhnya dibootstrap dari kode sumber, rasanya akan lebih sulit menyisipkan sesuatu seperti compiler yang ditanami backdoor

    • Memang membantu, tetapi bukan “solusi” lengkap
      Secara teori, bisa saja ada backdoor canggih di dalam lingkungan tempat ISO dibuild
      Jika benar-benar ingin menyelesaikan masalah itu, bisa melihat Diverse Double Compiling(https://dwheeler.com/trusting-trust/) atau bootstrap lingkungan secara penuh(https://bootstrappable.org/)
      Bagian “apakah pendekatan di atas tidak punya masalah bootstrap?” dalam tulisan itu juga relevan
      Meski begitu, sekadar mereproduksi build sudah sangat membantu membuat serangan seperti itu semakin kecil kemungkinannya
  • Belakangan ini saya berada di dalam ekosistem Red Hat karena pekerjaan
    Saya penasaran bagaimana ini dibandingkan dengan hal-hal seperti Fedora Silverblue, Ansible, atau Fedora Silverblue + Ansible

    • Di ekosistem Fedora, yang paling dekat dengan builder ISO NixOS dan reproduktibilitasnya adalah osbuild / imagebuilder: https://www.osbuild.org/guides/introduction.html
      Imagebuilder mengklaim reproduktibilitas, tetapi setahu saya sebagian besar memasang paket rpm sebagai biner, bukan dari sumber
      Jadi itu bukan reproduktibilitas yang ketat kecuali semua paket input juga dapat direproduksi
      Jika penjelasan tentang membangun paket dari sumber, membuat image distro, dan menangani reproduktibilitas tidak terasa relevan, kemungkinan Anda memang bukan pembaca sasaran utamanya
    • Nix adalah OS deklaratif, yang mendeskripsikan seperti apa OS seharusnya
      Sementara Ansible menetapkan langkah-langkah yang harus diikuti OS

Silverblue dan Nix bersifat ortogonal satu sama lain selain sama-sama merupakan distribusi Linux
Silverblue adalah upaya untuk mengubah cara penyampaian perangkat lunak dengan hanya menggunakan container di atas host yang immutable
Jika mencari alternatif Ansible yang sampai batas tertentu meniru Nix dengan menggunakan Jsonnet dan pelacakan status, Etcha layak dilihat: https://etcha.dev

  • Ansible menerapkan perubahan mutable ke OS dalam satuan tugas
    Nix bersifat immutable
    Perubahan baru dibuat sepenuhnya dari awal, dan baru setelah build berhasil semua paket “di-symlink” ke sistem saat ini
    Fedora Silverblue berbasis ostree https://github.com/ostreedev/ostree
    Ia bekerja mirip git terhadap pohon root, tetapi untuk menerapkan perubahan perlu me-reboot seluruh sistem
    Karena Nix menggunakan cara menautkan paket dengan symbolic link, sistem tidak perlu di-reboot
    Penjelasan lebih rinci ada di sini: https://dataswamp.org/~solene/2023-07-12-intro-to-immutable-...