Skrip backup tengah malam butuh password database — dan cara paling mudah, menaruhnya sebagai argumen perintah, juga cara tercepat membocorkannya: ps menampilkan argumen semua proses, history shell menyimpan baris yang pernah kita ketik, dan repository yang terdorong ke tempat umum menyimpannya bertahun-tahun. Chapter ini menyusun tangga penanganan kredensial dari kesadaran itu: mengapa environment variable lebih baik dari argumen, mengapa file ber-permission 600 lebih aman lagi, bagaimana openssl mengenkripsi data rahasia yang terpaksa tidur di disk, dan kapan waktunya menyerahkan urusan ke secret manager. Semua latihan bisa dijalankan di mesin kita hari ini — tanpa root, tanpa service tambahan.
Tiga Lubang Kebocoran Klasik #
Kebocoran paling sering bukan hasil peretasan canggih, melainkan tiga kebiasaan: password di argumen perintah, password di history, dan password ter-commit ke repository. Lubang pertama bisa kita lihat langsung — dan begitu pula celah penyelamatnya:
printf '#!/usr/bin/env bash\n# simulasi backup database; berjalan 5 menit lalu selesai\nsleep 300\n' > cadangkan-db.sh
chmod +x cadangkan-db.sh
echo '== password sebagai argumen =='
./cadangkan-db.sh -pCONTOH_PASSWORD_KUAT >/dev/null 2>&1 & pid=$!
ps -o args= -p $pid
kill $pid
echo '== password sebagai environment variable =='
DB_PASSWORD=CONTOH_PASSWORD_KUAT ./cadangkan-db.sh >/dev/null 2>&1 & pid=$!
ps -o args= -p $pid
tr '\0' '\n' < /proc/$pid/environ | grep DB_PASSWORD
kill $pidOutput yang Dihasilkan:
== password sebagai argumen ==
bash ./cadangkan-db.sh -pCONTOH_PASSWORD_KUAT
== password sebagai environment variable ==
bash ./cadangkan-db.sh
DB_PASSWORD=CONTOH_PASSWORD_KUATKita bedah demonstrasi di atas:
- Baris 1-2: skrip simulasi yang “bekerja” lima menit — laporan kerjanya kita redam dengan
>/dev/null 2>&1karena yang kita butuhkan hanya prosesnya yang hidup sebentar. - Baris 4-6 (
-pCONTOH_PASSWORD_KUAT): password ditautkan ke argumen — danps -o args=menampilkannya ke semua user di mesin itu. Program klien database yang memakai bentuk-pmengalami persis ini;kill $pidlalu mematikan simulasi. - Baris 8-11 (
DB_PASSWORD=... ./cadangkan-db.sh): password dipindah ke environment variable. Argumen yang tampak dipskini bersih, tetapi variabel itu terbaca lewat/proc/PID/environoleh root atau proses lain yang berjalan sebagai user yang sama — lebih baik, bukan aman.
Lubang kedua, history, menyimpan setiap baris yang kita ketik — password yang pernah diketik telanjang tinggal di sana sampai dihapus. Untuk skrip interaktif, read -rs password membaca ketikan tanpa menggema ke layar maupun history. Lubang ketiga, repository, dijaga dengan .gitignore yang menyebut nama file rahasia sejak commit pertama.
Environment Variable dan File .env #
Pola yang populer dari dunia container adalah file .env: daftar KUNCI=nilai yang disimpan bersebelahan dengan proyek, dibaca skrip saat mulai. Kuncinya ada dua — isi dan permission:
printf 'DB_USER=budi\nDB_HOST=192.0.2.10\nDB_PASSWORD=CONTOH_PASSWORD_KUAT\n' > .env
chmod 600 .env
stat -c '%a %n' .env
set -a
. ./.env
set +a
printf 'terhubung ke %s sebagai %s\n' "$DB_HOST" "$DB_USER"Output yang Dihasilkan:
600 .env
terhubung ke 192.0.2.10 sebagai budiKita bedah blok di atas:
- Baris 1-2 (
printf,chmod 600): file dibuat lalu dikunci —600berarti hanya owner yang bisa membaca dan menulis; user lain di mesin itu sama sekali tidak bisa. - Baris 3 (
stat -c '%a %n'): memverifikasi permission dalam bentuk oktal —600itulah yang harus terlihat. - Baris 4-6 (
set -a,. ./.env,set +a):set -amembuat semua variabel yang didefinisikan ikut diekspor, sehingga sourcing file.envmembuatDB_PASSWORDtersedia untuk proses anak;set +amenutup kembali perilaku itu. - Baris 7 (
printf ...): skrip memakai variabel lewat nama — password tidak pernah muncul di argumen, di history, atau di layar.
Enkripsi File Rahasia dengan openssl #
Untuk rahasia yang harus tidur di disk — cadangan konfigurasi, file yang dikirim ke storage luar — enkripsi sebelum disimpan. Chapter Backup Strategies
memperkenalkan openssl enc; di sini kita lengkapi dua kebiasaannya yang benar: passphrase dibaca dari file, bukan argumen, dan hasilnya diverifikasi:
printf 'DB_PASSWORD=CONTOH_PASSWORD_KUAT\nDB_USER=budi\n' > rahasia.env
printf 'kunci-pembuka-brankas\n' > kunci.txt
chmod 600 rahasia.env kunci.txt
openssl enc -aes-256-cbc -pbkdf2 -iter 60000 -salt -in rahasia.env -out rahasia.env.enc -pass file:kunci.txt
openssl enc -d -aes-256-cbc -pbkdf2 -iter 60000 -in rahasia.env.enc -out pulih.env -pass file:kunci.txt
sha256sum rahasia.env pulih.env
echo '== coba dekripsi dengan kunci salah =='
printf 'kunci-yang-salah\n' > kunci-salah.txt
openssl enc -d -aes-256-cbc -pbkdf2 -iter 60000 -in rahasia.env.enc -out gagal.env -pass file:kunci-salah.txt 2>/dev/null
printf 'kode keluar: %s\n' "$?"Output yang Dihasilkan:
fcc4003248376cbfbbb8209de0b914c5f4e5dc250df5879e19a2b719ef43692a rahasia.env
fcc4003248376cbfbbb8209de0b914c5f4e5dc250df5879e19a2b719ef43692a pulih.env
== coba dekripsi dengan kunci salah ==
kode keluar: 1Kita bedah blok di atas:
- Baris 1-3: data rahasia dan file kunci sama-sama
600— kunci jangan sampai lebih longgar dari data yang diamankannya. - Baris 4 (
openssl enc -aes-256-cbc -pbkdf2 -iter 60000 -salt): enkripsi AES-256-CBC;-pbkdf2 -iter 60000menurunkan passphrase menjadi kunci lewat fungsi yang sengaja lambat, dan-saltmembuat setiap enkripsi menghasilkan hasil berbeda meski isinya sama. - Baris 5-6 (dekripsi +
sha256sum): mendekripsi ke file lain lalu membandingkan hash keduanya — dua baris dengan hash sama berarti siklus utuh, persis teknik verifikasi Chapter File Integrity . - Baris 8-10 (kunci salah): pesan error
openssldiredam2>/dev/null, tetapi kode keluarnya tetap1— passphrase yang salah ditolak saja, tidak dikoreksi. Opsi-pass file:membaca baris pertama file, sehingga passphrase juga tidak pernah menyentuh argumen perintah.
Secret Manager dan systemd-credentials #
Tangga di atas berhenti di satu masalah: file .env dan kunci openssl tetap ada utuh di disk. Untuk service produksi, alat berikutnya mengambil rahasia dari luar sistem file saat service dinyalakan. systemd-credentials mengenkripsi kredensial dengan kunci TPM2 mesin — service yang dinyalakan menerima isinya terdekripsi lewat direktori khusus, dan service lain tidak melihat apa-apa. Docker Swarm dan Kubernetes menyediakan objek secret yang didistribusikan ke container yang berhak; alat tim seperti Vault menambah rotasi otomatis, masa hidup token pendek, dan audit siapa mengakses apa. Pemilihan metodenya mengikuti kebutuhannya:
| Kebutuhan | Pilihan yang pas | Alasannya |
|---|---|---|
| Skrip pribadi sekali jalan | read -rs saat dijalankan | tidak menyentuh disk sama sekali |
| Cron di satu mesin | .env ber-permission 600 | sederhana, cukup untuk satu pengelola |
| File rahasia yang disimpan | openssl enc + kunci 600 | terenkripsi saat istirahat |
| Service systemd | systemd-credentials | didekripsi TPM hanya untuk service itu |
| Banyak mesin dan tim | Vault / secret manager | rotasi, audit, token berumur pendek |
Kredensial kini jarang beredar telanjang: tidak di argumen, tidak di history, tidak di repository. Tetapi semua rahasia itu masih menunggu di disk — dan laptop yang dicuri atau image VM yang disalin membaca disk apa adanya. Pertahanan terakhir untuk itu adalah enkripsi seluruh disk: LUKS, chapter berikutnya.
Referensi lanjut: systemd.io tentang credentials untuk konsep dan alurnya, systemd-credentials(1) untuk sintaksnya, serta docker secrets untuk pola serupa di container.