Pengelolaan dependensi

Dokumen ini menjelaskan dependensi aplikasi dan praktik terbaik untuk mengelolanya, termasuk pemantauan kerentanan, verifikasi artefak, mengurangi jejak dependensi, dan mendukung build yang dapat direproduksi.

Dependensi software adalah bagian software yang diperlukan aplikasi Anda untuk berfungsi seperti library software atau plugin. Penyelesaian dependensi dapat terjadi saat Anda mengompilasi kode, mem-build, menjalankan, mendownload, atau menginstal software.

Dependensi dapat mencakup komponen yang Anda buat, software pihak ketiga eksklusif, dan software open source. Pendekatan yang Anda lakukan untuk mengelola dependensi dapat memengaruhi keamanan dan keandalan aplikasi Anda.

Spesifikasi untuk menerapkan praktik terbaik dapat bervariasi menurut format artefak dan alat yang Anda gunakan, tetapi prinsip umum tetap berlaku.

Dependensi langsung dan transitif

Aplikasi Anda dapat menyertakan dependensi langsung dan transitif:

Dependensi langsung
Komponen software yang dirujuk aplikasi secara langsung.
Dependensi transitif
Komponen software yang secara fungsional diperlukan oleh dependensi langsung aplikasi. Setiap dependensi dapat memiliki dependensi langsung dan tidak langsungnya sendiri, sehingga membuat hierarki rekursif dependensi transitif yang semuanya memengaruhi aplikasi.

Bahasa pemrograman yang berbeda menawarkan tingkat visibilitas yang berbeda terhadap dependensi dan hubungannya. Selain itu, beberapa bahasa menggunakan pengelola paket untuk me-resolve hierarki dependensi saat menginstal atau men-deploy paket.

Dalam ekosistem Node.js, pengelola paket npm dan yarn menggunakan file kunci untuk mengidentifikasi versi dependensi guna mem-build modul dan versi dependensi yang didownload pengelola paket untuk penginstalan modul tertentu. Di ekosistem bahasa lain seperti Java, ada dukungan yang lebih terbatas untuk introspeksi dependensi. Selain itu, sistem build harus menggunakan pengelola dependensi tertentu untuk mengelola dependensi secara sistematis.

Sebagai contoh, pertimbangkan modul npm glob versi 8.0.2. Anda mendeklarasikan dependensi langsung untuk modul npm dalam file package.json. Dalam file package.json untuk glob, bagian dependencies mencantumkan dependensi langsung untuk paket yang dipublikasikan. Bagian devDepdencies mencantumkan dependensi untuk pengembangan dan pengujian lokal oleh pengelola dan kontributor glob

  • Di situs npm, halaman glob mencantumkan dependensi langsung dan dependensi pengembangan, tetapi tidak menunjukkan apakah modul ini juga memiliki dependensi sendiri.

  • Anda dapat menemukan informasi dependensi tambahan tentang glob di situs Open Source Insights. Daftar dependensi untuk glob mencakup dependensi langsung dan dependensi tidak langsung (transitif).

    Dependensi transitif dapat memiliki beberapa lapisan dalam hierarki dependensi. Contoh:

    1. glob 8.0.2 memiliki dependensi langsung pada minimatch 5.0.1.
    2. minimatch 5.0.1 memiliki dependensi langsung brace-expression 2.0.1.
    3. brace-expression 2.0.1 memiliki dependensi langsung pada balanced-match 1.0.2.

Tanpa visibilitas ke dependensi tidak langsung, sangat sulit untuk mengidentifikasi dan merespons kerentanan serta masalah lainnya yang berasal dari komponen yang tidak direferensikan secara langsung oleh kode Anda.

Saat Anda menginstal paket glob, npm akan me-resolve seluruh hierarki dependensi dan menyimpan daftar versi tertentu yang didownload dalam file package.lock.json sehingga Anda memiliki catatan semua dependensi. Penginstalan berikutnya di lingkungan yang sama akan mengambil versi yang sama.

Alat untuk insight dependensi

Anda dapat menggunakan alat berikut untuk membantu memahami dependensi open source dan mengevaluasi postur keamanan project Anda. Alat ini memberikan informasi di seluruh format paket.

Insight keamanan di konsol Google Cloud
Google Cloud memberikan insight keamanan untuk artefak Anda di Cloud Build, Cloud Run, dan GKE, termasuk kerentanan, informasi dependensi, bill of materials software (SBOM), dan asal build. Layanan Google Cloud lainnya juga menyediakan fitur yang meningkatkan postur keamanan Anda di seluruh siklus proses pengembangan software. Untuk mempelajari lebih lanjut, lihat ringkasan keamanan supply chain software.
Alat open source

Sejumlah alat open source tersedia, termasuk:

  • Open Source Insights: Situs yang memberikan informasi tentang dependensi langsung dan tidak langsung yang diketahui, kerentanan yang diketahui, dan informasi lisensi untuk software open source. Project Open Source Insights juga menyediakan data ini sebagai Set Data Google Cloud. Anda dapat menggunakan BigQuery untuk menjelajahi dan menganalisis data.

  • Database Open Source Vulnerabilities: Database kerentanan yang dapat ditelusuri yang menggabungkan kerentanan dari database lain ke dalam satu lokasi.

  • Kartu skor: Alat otomatis yang dapat Anda gunakan untuk mengidentifikasi praktik supply chain software yang berisiko dalam project GitHub Anda. Alat ini melakukan pemeriksaan terhadap repositori dan memberikan skor dari 0 hingga 10 untuk setiap pemeriksaan. Kemudian, Anda dapat menggunakan skor tersebut untuk mengevaluasi postur keamanan project Anda.

  • Allstar: Aplikasi GitHub yang terus-menerus memantau organisasi atau repositori GitHub untuk kepatuhan terhadap kebijakan yang dikonfigurasi. Misalnya, Anda dapat menerapkan kebijakan ke organisasi GitHub yang memeriksa kolaborator di luar organisasi yang memiliki akses administrator atau push.

Pendekatan untuk menyertakan dependensi

Ada beberapa metode umum untuk menyertakan dependensi dengan aplikasi Anda:

Menginstal langsung dari sumber publik
Instal dependensi open source langsung dari repositori publik, seperti Docker Hub, npm, PyPI, atau Maven Central. Pendekatan ini praktis karena Anda tidak perlu mengelola dependensi eksternal. Namun, karena Anda tidak mengontrol dependensi eksternal ini, supply chain software Anda lebih rentan terhadap serangan supply chain open source.
Menyimpan salinan dependensi di repositori sumber
Pendekatan ini juga dikenal sebagai vendoring. Daripada menginstal dependensi eksternal dari repositori publik selama build, Anda mendownloadnya dan menyalinnya ke hierarki sumber project. Anda memiliki kontrol yang lebih besar atas dependensi vendor yang Anda gunakan, tetapi ada beberapa kelemahan:
  • Dependensi vendor meningkatkan ukuran repositori sumber Anda dan menyebabkan lebih banyak churn.
  • Anda harus menyediakan dependensi yang sama ke setiap aplikasi terpisah. Jika repositori sumber atau proses build tidak mendukung modul sumber yang dapat digunakan kembali, Anda mungkin perlu mempertahankan beberapa salinan dependensi.
  • Mengupgrade dependensi vendor dapat menjadi lebih sulit.
Menyimpan dependensi di registry pribadi

Registry pribadi, seperti Artifact Registry, memberikan kemudahan penginstalan dari repositori publik serta kontrol atas dependensi Anda. Dengan Artifact Registry, Anda dapat:

  • Sentralisasi artefak build dan dependensi untuk semua aplikasi Anda.
  • Konfigurasikan klien paket bahasa dan Docker Anda untuk berinteraksi dengan repositori pribadi di Artifact Registry dengan cara yang sama seperti yang dilakukan dengan repositori publik.
  • Memiliki kontrol yang lebih besar atas dependensi Anda di repositori pribadi:

    • Batasi akses ke setiap repositori dengan Identity and Access Management.
    • Gunakan repositori jarak jauh untuk meng-cache dependensi dari sumber publik upstream dan memindainya untuk menemukan kerentanan (pratinjau pribadi).
    • Gunakan repositori virtual untuk mengelompokkan repositori jarak jauh dan pribadi di balik satu endpoint. Tetapkan prioritas di setiap repositori untuk mengontrol urutan penelusuran saat mendownload atau menginstal artefak (pratinjau pribadi).
  • Gunakan Artifact Registry dengan layanan Google Cloud lainnya, termasuk Cloud Build, Cloud Run, dan Google Kubernetes Engine. Gunakan pemindaian kerentanan otomatis di seluruh siklus proses pengembangan software, buat provenans build, kontrol deployment, dan lihat insight tentang postur keamanan Anda.

Jika memungkinkan, gunakan registry pribadi untuk dependensi Anda. Jika Anda tidak dapat menggunakan registry pribadi, pertimbangkan untuk membuat dependensi menjadi vendor sehingga Anda memiliki kontrol atas konten dalam supply chain software.

Versi disematkan

Penyematan versi berarti membatasi dependensi aplikasi ke versi atau rentang versi tertentu. Idealnya, Anda menyematkan satu versi dependensi.

Menyematkan versi dependensi membantu memastikan bahwa build aplikasi Anda dapat direproduksi. Namun, hal ini juga berarti bahwa build Anda tidak menyertakan update pada dependensi, termasuk perbaikan keamanan, perbaikan bug, atau peningkatan.

Anda dapat memitigasi masalah ini menggunakan alat pengelolaan dependensi otomatis yang memantau dependensi di repositori sumber untuk rilis baru. Alat ini melakukan update pada file persyaratan untuk mengupgrade dependensi sesuai kebutuhan, sering kali menyertakan informasi log perubahan atau detail tambahan.

Penyematan versi hanya berlaku untuk dependensi langsung, bukan dependensi transitif. Misalnya, jika Anda menyematkan versi paket my-library, sematkan akan membatasi versi my-library, tetapi tidak membatasi versi software yang memiliki dependensi my-library. Anda dapat membatasi hierarki dependensi untuk paket dalam beberapa bahasa menggunakan file kunci.

Verifikasi tanda tangan dan hash

Ada sejumlah metode yang dapat Anda gunakan untuk memverifikasi keaslian artefak yang Anda gunakan sebagai dependensi.

Verifikasi hash

Hash adalah nilai yang dihasilkan untuk file yang berfungsi sebagai ID unik. Anda dapat membandingkan hash artefak dengan nilai hash yang dihitung oleh penyedia artefak untuk mengonfirmasi integritas file. Verifikasi hash membantu Anda mengidentifikasi penggantian, modifikasi, atau kerusakan dependensi, melalui serangan man-in-the-middle atau penyusupan repositori artefak.

Menggunakan verifikasi hash memerlukan kepercayaan bahwa hash yang Anda terima dari repositori artefak tidak disusupi.

Verifikasi tanda tangan

Verifikasi tanda tangan menambahkan keamanan tambahan ke proses verifikasi. Repositori artefak, pengelola software, atau keduanya dapat menandatangani artefak.

Layanan seperti sigstore memberikan cara bagi pengelola untuk menandatangani artefak software dan bagi konsumen untuk memverifikasi tanda tangan tersebut.

Otorisasi Biner dapat memverifikasi bahwa image container yang di-deploy ke lingkungan runtime Google Cloud ditandatangani dengan pengesahan untuk berbagai kriteria.

File kunci dan dependensi yang dikompilasi

File kunci adalah file persyaratan yang di-resolve sepenuhnya, yang menentukan dengan tepat versi setiap dependensi yang harus diinstal untuk aplikasi. Biasanya dihasilkan secara otomatis oleh alat penginstalan, file kunci menggabungkan penyematan versi dan verifikasi tanda tangan atau hash dengan hierarki dependensi lengkap untuk aplikasi Anda.

Alat penginstalan membuat hierarki dependensi dengan me-resolve sepenuhnya semua dependensi transitif downstream dari dependensi level teratas, lalu menyertakan hierarki dependensi dalam file kunci Anda. Akibatnya, hanya dependensi ini yang dapat diinstal, sehingga build lebih dapat direproduksi dan konsisten.

Menggabungkan dependensi pribadi dan publik

Aplikasi modern berbasis cloud sering kali bergantung pada kode open source dan pihak ketiga, serta library internal dengan sumber tertutup. Artifact Registry memungkinkan Anda membagikan logika bisnis di beberapa aplikasi, dan menggunakan kembali alat yang sama untuk menginstal library eksternal dan internal.

Namun, saat mencampurkan dependensi pribadi dan publik, rantai pasokan software Anda lebih rentan terhadap serangan kebingungan dependensi. Dengan memublikasikan project dengan nama yang sama dengan project internal Anda ke repositori open source, penyerang mungkin dapat memanfaatkan penginstal yang salah dikonfigurasi untuk menginstal kode berbahaya mereka, bukan dependensi internal Anda.

Untuk menghindari serangan kebingungan dependensi, Anda dapat melakukan sejumlah langkah:

  • Verifikasi tanda tangan atau hash dependensi Anda dengan menyertakannya dalam file kunci.
  • Pisahkan penginstalan dependensi pihak ketiga dan dependensi internal menjadi dua langkah yang berbeda.
  • Secara eksplisit, buat duplikat dependensi pihak ketiga yang Anda perlukan ke repositori pribadi, baik secara manual maupun dengan proxy pull-through. Repositori jarak jauh Artifact Registry adalah proxy pull-through untuk repositori publik upstream.
  • Gunakan repositori virtual untuk menggabungkan repositori Artifact Registry standar dan jarak jauh di balik satu endpoint. Anda dapat mengonfigurasi prioritas untuk repositori upstream sehingga versi artefak pribadi Anda selalu diprioritaskan daripada artefak publik dengan nama yang sama.
  • Gunakan sumber tepercaya untuk paket publik dan image dasar.

Menghapus dependensi yang tidak digunakan

Seiring kebutuhan Anda berubah dan aplikasi berkembang, Anda dapat mengubah atau berhenti menggunakan beberapa dependensi. Terus menginstal dependensi yang tidak digunakan dengan aplikasi Anda akan meningkatkan jejak dependensi dan meningkatkan risiko Anda disusupi oleh kerentanan dalam dependensi tersebut.

Setelah aplikasi berfungsi secara lokal, praktik umum adalah menyalin setiap dependensi yang Anda instal selama proses pengembangan ke dalam file persyaratan untuk aplikasi Anda. Kemudian, Anda men-deploy aplikasi dengan semua dependensi tersebut. Pendekatan ini membantu memastikan bahwa aplikasi yang di-deploy berfungsi, tetapi juga cenderung akan memperkenalkan dependensi yang tidak Anda perlukan dalam produksi.

Berhati-hatilah saat menambahkan dependensi baru ke aplikasi Anda. Setiap hal memiliki potensi untuk memperkenalkan lebih banyak kode yang tidak sepenuhnya Anda kontrol. Sebagai bagian dari pipeline linting dan pengujian reguler, integrasikan alat yang mengaudit file persyaratan untuk menentukan apakah Anda benar-benar menggunakan atau mengimpor dependensi.

Beberapa bahasa memiliki alat untuk membantu Anda mengelola dependensi. Misalnya, Anda dapat menggunakan Plugin Dependensi Maven untuk menganalisis dan mengelola dependensi Java.

Pemindaian kerentanan

Merespons kerentanan dalam dependensi dengan cepat akan membantu Anda melindungi supply chain software.

Pemindaian kerentanan memungkinkan Anda menilai secara otomatis dan konsisten apakah dependensi Anda menyebabkan kerentanan dalam aplikasi. Alat pemindaian kerentanan menggunakan file kunci untuk menentukan dengan tepat artefak yang Anda andalkan, dan memberi tahu Anda saat kerentanan baru muncul, terkadang bahkan dengan jalur upgrade yang disarankan.

Misalnya, Artifact Analysis mengidentifikasi kerentanan paket OS dalam image container. Alat ini dapat memindai image saat diupload ke Artifact Registry dan terus memantaunya untuk menemukan kerentanan baru hingga 30 hari setelah image dikirim.

Anda juga dapat menggunakan Pemindaian On-Demand untuk memindai image container secara lokal untuk menemukan kerentanan OS, Go, dan Java. Hal ini memungkinkan Anda mengidentifikasi kerentanan sejak awal sehingga Anda dapat mengatasinya sebelum menyimpannya di Artifact Registry.

Langkah selanjutnya