Cara Pipeline Mengakses Secret Tanpa Menyimpannya
Anda memiliki pipeline yang membangun, menguji, dan menyebarkan aplikasi. Di suatu titik selama proses tersebut, pipeline membutuhkan kata sandi database, kunci API, atau sertifikat. Insting alaminya adalah meletakkan secret itu ke dalam variabel pipeline, file konfigurasi, atau bahkan menuliskannya secara hardcode ke dalam skrip. Namun, hal itu menciptakan masalah: begitu secret masuk ke pipeline, ia bisa berakhir di tempat yang tidak pernah Anda inginkan.
Secret bocor ke log build. Mereka terbakar ke dalam image Docker. Mereka muncul di file artefak. Mereka bertahan di cache workspace. Begitu secret menyentuh kode pipeline Anda, Anda kehilangan kendali ke mana secret itu pergi.
Solusinya bukanlah menjauhkan secret sepenuhnya dari pipeline. Pipeline membutuhkannya untuk melakukan tugasnya. Solusinya adalah menginjeksi secret sedemikian rupa sehingga secret hanya ada di memori, hanya selama durasi tugas, dan tidak pernah bertahan di mana pun secara permanen. Ada tiga pendekatan umum, dan masing-masing memiliki trade-off sendiri.
Environment Variable: Sederhana tapi Mudah Bocor
Pendekatan yang paling umum adalah menarik secret dari vault atau penyimpanan secret dan mengaturnya sebagai environment variable di proses yang berjalan. Ketika pipeline Anda menjalankan npm test atau dotnet run, variabel DB_PASSWORD sudah tersedia di memori proses.
Pendekatan ini sederhana dan cepat. Ini bekerja dengan hampir semua alat dan kerangka kerja. Anda tidak perlu mengubah cara aplikasi Anda membaca konfigurasi. Sebagian besar bahasa dan runtime mendukung environment variable secara native.
Misalnya, menggunakan Vault CLI, Anda dapat mengambil secret dan mengekspornya sebelum menjalankan build:
# Ambil kata sandi database dari Vault dan ekspor sebagai environment variable
export DB_PASSWORD=$(vault kv get -field=password secret/db-prod)
# Jalankan perintah build yang membutuhkan secret
npm run build
Masalahnya adalah environment variable mudah bocor. Banyak aplikasi mencetak semua environment variable selama debugging. Kerangka kerja logging sering menulis environment variable ke file log secara default. Begitu secret muncul di log, siapa pun yang memiliki akses ke sistem logging dapat membacanya. Itu termasuk pengembang, staf dukungan, dan berpotensi penyerang jika sistem logging dikompromikan.
Ada risiko lain: artefak build. Ketika pipeline Anda membuat file JAR, image Docker, atau biner yang dikompilasi, environment variable dapat tertangkap jika proses build secara tidak sengaja membaca semua variabel. Build Docker yang menggunakan instruksi ARG atau ENV dapat menyematkan secret ke dalam layer image. Begitu secret ada di image, ia akan ada di sana selamanya kecuali Anda membangun ulang dan menyebarkan ulang semuanya.
Environment variable bekerja dengan baik untuk pipeline berumur pendek di mana Anda mengontrol logging dan proses build secara ketat. Mereka berbahaya di pipeline yang menghasilkan artefak atau memiliki logging yang verbose.
Mount File: Lebih Terkendali, Lebih Banyak Pembersihan
Pendekatan kedua adalah menarik secret dari vault dan menulisnya ke file sementara di dalam container atau workspace. Aplikasi membaca file tersebut saat startup. Setelah tugas selesai, file tersebut dihapus.
Pendekatan ini memberi Anda kontrol lebih. Anda dapat mengatur izin file sehingga hanya proses aplikasi yang dapat membaca file. Anda dapat me-mount file sebagai read-only. Anda dapat menghapusnya segera setelah digunakan. Banyak kerangka kerja modern mendukung pembacaan konfigurasi dari file. Spring Boot membaca dari application.properties atau file YAML. .NET membaca dari file konfigurasi JSON. Anda dapat mengarahkan kerangka kerja ini ke file sementara yang hanya berisi secret yang diperlukan untuk proses tersebut.
Risikonya adalah file dapat tertinggal. Jika pipeline Anda tidak membersihkan workspace setelah selesai, file secret tetap ada di disk. Di lingkungan container, file yang di-mount dapat dibaca oleh proses lain di container yang sama jika izin tidak diatur dengan benar. Jika pipeline Anda menggunakan caching, seperti caching layer Docker, file secret dapat di-cache dan muncul di build berikutnya.
Mount file lebih aman daripada environment variable karena Anda mengontrol masa pakai dan izin file. Tetapi mereka membutuhkan disiplin: Anda harus membersihkan setelah setiap proses, dan Anda harus memastikan bahwa mekanisme caching tidak menyimpan file.
Direct API Call: Tanpa Secret di Pipeline
Pendekatan ketiga adalah tidak pernah memberikan secret ke pipeline sama sekali. Sebaliknya, aplikasi atau skrip memanggil API vault secara langsung setiap kali membutuhkan secret. Pipeline tidak menangani secret. Ia tidak mengatur environment variable. Ia tidak menulis file. Aplikasi itu sendiri menjangkau vault dan mengambil apa yang dibutuhkan.
Misalnya, alih-alih memberikan kata sandi database sebagai environment variable, aplikasi memanggil GET /v1/secret/db-password ketika perlu terhubung ke database. Vault mengautentikasi permintaan, mengembalikan secret, dan aplikasi menggunakannya segera.
Diagram urutan berikut mengilustrasikan alur ini:
Ini adalah pendekatan yang paling aman. Secret tidak pernah ada di memori pipeline. Ia tidak pernah ditulis ke file. Ia tidak pernah muncul di log. Bahkan jika seseorang mendapatkan akses ke workspace pipeline, mereka tidak dapat menemukan secret karena secret tidak pernah ada di sana.
Trade-off-nya adalah ketersediaan. Aplikasi Anda sekarang bergantung pada vault yang dapat dijangkau. Jika vault mati atau tidak dapat dijangkau, aplikasi Anda tidak dapat dimulai. Setiap panggilan API menambah latensi dan meninggalkan jejak di log audit vault. Pendekatan ini paling baik untuk secret yang jarang digunakan atau untuk secret dinamis yang memiliki masa pakai pendek, seperti kredensial database sementara yang kedaluwarsa setelah beberapa menit.
Direct API call ideal untuk lingkungan produksi di mana persyaratan keamanan tinggi dan tim infrastruktur dapat menjamin ketersediaan vault. Mereka berlebihan untuk pipeline pengembangan atau pengujian di mana risiko kebocoran secret lebih rendah.
Memilih Pendekatan yang Tepat
Tidak ada satu metode terbaik. Pilihannya tergantung pada seberapa sering secret digunakan, seberapa ketat kontrol akses yang Anda butuhkan, dan seberapa andal infrastruktur vault Anda.
Untuk pipeline pengembangan cepat di mana secret jarang berubah, environment variable tidak masalah selama Anda mengontrol logging dan pembuatan artefak. Untuk deployment produksi di mana secret tidak boleh bocor, direct API call atau mount file dengan pembersihan ketat lebih baik. Untuk lingkungan container, mount file dengan izin read-only dan pembersihan otomatis setelah container keluar bekerja dengan baik.
Yang penting adalah memahami titik lemah dari setiap pendekatan dan merancang pipeline Anda untuk menutup celah-celah tersebut. Jangan hanya memilih metode yang paling mudah. Pilih metode yang sesuai dengan toleransi risiko dan kemampuan operasional Anda.
Checklist Praktis
Sebelum Anda memutuskan bagaimana pipeline Anda akan mengakses secret, periksa poin-poin ini:
- Apakah pipeline Anda menghasilkan artefak (image Docker, file JAR, biner yang dikompilasi) yang dapat menangkap environment variable?
- Apakah kerangka kerja logging Anda mencetak environment variable secara default?
- Dapatkah Anda mengatur izin file pada secret yang di-mount di lingkungan container Anda?
- Apakah pipeline Anda membersihkan file workspace setelah setiap proses?
- Apakah infrastruktur vault Anda cukup andal untuk direct API call dari aplikasi?
- Apakah Anda memerlukan jejak audit untuk setiap akses secret?
Tantangan Sebenarnya
Memasukkan secret ke dalam pipeline tanpa menyimpannya hanyalah setengah dari masalah. Bagian yang lebih sulit adalah memastikan secret tidak bocor ke tempat yang tidak terduga: log, artefak, version control, atau layer build yang di-cache. Setiap pendekatan memberi Anda cara untuk menginjeksi secret, tetapi tidak ada yang secara otomatis mencegah kebocoran. Itu membutuhkan disiplin yang berkelanjutan, pemeriksaan otomatis, dan pemahaman yang jelas tentang ke mana secret Anda bisa berakhir.
Tujuannya bukan untuk menemukan metode yang sempurna. Tujuannya adalah untuk memilih metode yang sesuai dengan lingkungan Anda dan kemudian membangun pengaman di sekitar titik lemahnya.