Di episode ini kita akan membahas dua teknik Vault untuk mengirimkan secret secara aman tanpa transit plaintext: response wrapping dengan wrap token satu-kali-pakai, dan cubbyhole untuk penyimpanan per-token. Kalian akan membangun pola zero-trust bootstrap dari nol.

Setelah di episode 12 sebelumnya kita membahas lease, TTL, renewal, dan revocation — siklus hidup secret yang bisa dihancurkan seketika — kita masih menyisakan satu pertanyaan operasional yang sering menyulitkan tim di dunia nyata: bagaimana cara mengirimkan secret ke pihak lain dengan aman?
Bayangkan skenario ini: kalian baru saja memprovision sebuah server baru, dan server tersebut butuh SecretID AppRole untuk bisa login ke Vault. Opsi yang umum dipakai — dan semuanya buruk — adalah mengirim SecretID via email, chat, atau menuliskannya di dokumen onboarding. Secret transit di media yang tidak aman, tercatat di log, dan tidak pernah kedaluwarsa dari sisi pengirim. Ini persis pola secret sprawl yang kita perangi sejak episode 1.
Pada episode kali ini kita akan membahas Response Wrapping dan Cubbyhole — dua fitur Vault yang memungkinkan pengiriman secret dengan prinsip zero-trust: secret tidak pernah transit dalam bentuk plaintext, hanya bisa dibuka satu kali oleh penerima yang tepat, dan mati otomatis dalam hitungan menit. Ini adalah pola yang akan kalian pakai berkali-kali dalam karir DevOps kalian.
Mari kita mulai dari konsep wrapping.
Response wrapping adalah fitur Vault yang membungkus seluruh response sebuah request ke dalam token khusus — disebut wrap token — yang hanya bisa dibuka satu kali (one-time use) dan punya TTL sangat pendek (biasanya menit, bukan jam).
Bayangkan analogi surat diplomatik: alih-alih mengirim surat berisi rahasia yang bisa dibaca siapa pun yang mencegatnya di perjalanan, kalian mengirim amplop tertutup dengan segel. Amplop itu tidak berisi rahasia langsung; ia berisi kunci untuk membuka brankas — dan segelnya rusak setelah satu orang membukanya. Jika amplop dicuri, pencuri tidak mendapat apa-apa karena amplop hanya bisa dibuka sekali oleh orang yang tepat, dan masa berlakunya sangat singkat.
Cara kerjanya di Vault:
-wrap-ttl=....hvs.CAES...) dengan TTL sesuai permintaan.vault unwrap <wrap-token> — response secret yang tersimpan akhirnya dikeluarkan, dan wrap token mati seketika (tidak bisa dipakai lagi).Pengirim Vault Penerima
│ read + wrap-ttl=5m │ │
├──────────────────────────────────────► │
│ wrap_token: hvs.CAES... │ │
◄──────────────────────────────────────┤ │
│ │ kirim wrap token │
├──────────────────────────────────────────────────────────────────────►
│ │ unwrap (hvs.CAES...) │
│ ◄──────────────────────────────┤
│ ├── secret dikeluarkan, │
│ │ wrap token mati │Mari kita coba langsung. Skenarionya: kalian ingin mengirim kredensial dynamic database ke teman kalian, tanpa pernah mengirim password mentah.
1. Bungkus response secret.
vault read -wrap-ttl=5m database/creds/app-dbKey Value
--- -----
token hvs.CAESIJ1...
token_accessor 9fQk... # untuk lookup/revoke wrap token
token_duration 5m
token_renewable false
token_policies [""]Perhatikan: tidak ada satupun field credential (username/password) yang muncul di output. Yang dikembalikan hanyalah sebuah wrap token dengan TTL 5 menit, dan token_renewable: false — memang tidak bisa diperpanjang. Ini menegaskan bahwa credential sebenarnya disimpan aman di Vault, dan yang transit hanyalah "tanda terima" sekali pakai.
2. Kirim wrap token ke penerima. Token ini bebas dikirim lewat media apa pun — itulah keindahannya. Karena satu-kali pakai, mencegatnya tidak ada gunanya kecuali secepat mungkin dipakai.
3. Penerima membuka (unwrap) wrap token.
vault unwrap hvs.CAESIJ1...Key Value
--- -----
lease_id database/creds/app-db/Z9wXc8Kv...7Gq
lease_duration 1h
lease_renewable true
Data
----
password Vp5mQ8sZ...
username v-app-db-AJ4kLp3R...4. Coba buka lagi — pasti gagal.
vault unwrap hvs.CAESIJ1...Error un-wrapping: Error making API request.
URL: PUT http://127.0.0.1:8200/v1/sys/wrapping/unwrap
Code: 400. Errors:
* wrapping token is not valid or does not existPersis seperti janji kita: satu kali buka, token mati. Bahkan pengirimnya sendiri tidak bisa membuka ulang.
Important
Wrap token adalah artefak satu-kali-pakai. Setelah vault unwrap, ia tidak bisa digunakan lagi — bukan hanya oleh orang lain, tapi bahkan oleh pemilik aslinya. Inilah yang membuatnya aman untuk transit di media yang tidak tepercaya. Bedakan dengan token biasa yang bisa dipakai berulang kali hingga kedaluwarsa.
Pertanyaan yang wajar: "bukankah kalau wrap token dicuri, penyerang tinggal unwrap?" Jawabannya: secara teori ya, tapi jendela peluangnya sangat kecil dan biaya/risikonya tidak sebanding. Perhatikan tiga lapisan perlindungan:
Ditambah lagi, wrap token bisa di-lookup dan di-revoke oleh admin sebelum sempat dibuka:
vault token lookup -accessor 9fQk...vault token revoke -accessor 9fQk...Konsep kedua di episode ini adalah Cubbyhole — secrets engine bawaan Vault yang sering disebut private vault-in-a-vault. Prinsipnya sederhana namun kuat: setiap token punya ruang penyimpanan pribadi yang hanya bisa diakses oleh token itu sendiri.
| Karakteristik | Cubbyhole | KV (episode 4) |
|---|---|---|
| Cakupan | Per token (private) | Global (shared) |
| Siapa yang bisa baca | Hanya token pembuat data | Semua yang punya policy akses path |
| TTL | Terikat token | Terikat secret (jika dynamic) |
| Persistensi | Hilang saat token mati | Tetap sampai dihapus |
| Policy path | Tidak dibutuhkan | Dibutuhkan |
Kenapa ini berguna? Karena cubbyhole memungkinkan transfer data yang aman antar proses selama masih dalam "silsilah token" yang sama. Contoh klasiknya adalah secure delegation: sebuah proses yang memegang token bisa menyimpan data rahasia di cubbyhole-nya, lalu menerbitkan token turunan yang mewarisi akses cubbyhole untuk di-unwrap.
1. Tulis data di cubbyhole token sendiri.
vault kv put cubbyhole/bootstrapping secret-id="<secret-id>" server-ip="10.20.30.40"2. Baca kembali — hanya token yang sama yang bisa.
vault kv get cubbyhole/bootstrapping3. Token lain tidak bisa mengakses cubbyhole milik token ini.
Jika kalian mencoba membacanya dengan token berbeda, hasilnya adalah data tidak ditemukan — bukan 403, melainkan sekadar kosong. Ini disengaja: cubbyhole token lain adalah dunia yang terpisah total.
Sekarang mari kita rangkai keduanya (wrapping + cubbyhole) dalam satu skenario nyata yang akan kalian jumpai terus-menerus: server baru harus menerima SecretID AppRole tanpa pernah secret transit dalam bentuk plaintext.
Alur lengkapnya:
Orchestrator (Ansible/Terraform) Vault Server Node Baru (app-server-07)
│ │ │
│ 1. Minta SecretID untuk role app-backend │ │
├───────────────────────────────────────────────► │
│ 2. Response di-wrap dengan TTL 2m │ │
◄───────────────────────────────────────────────┤ │
│ 3. Kirim wrap_token via metadata cloud / env │ │
├─────────────────────────────────────────────────────────────────────────────────────►
│ │ 4. Unwrap wrap_token │
│ ◄─────────────────────────────────────┤
│ ├── SecretID dikeluarkan, token mati │
│ │ 5. Login AppRole → token Vault │
│ ◄─────────────────────────────────────┤Langkah 1 — Orchestrator meminta SecretID yang dibungkus.
vault write -wrap-ttl=2m auth/approle/role/app-backend/secret-idKey Value
--- -----
token hvs.CAESQr3...
token_accessor 3dHx...
token_duration 2m
token_renewable false
token_policies [""]Langkah 2 — Orchestrator mengirim wrap token ke node baru.
Wrap token ini bisa dikirim lewat user-data cloud provider, environment variable saat provisioning, atau parameter eksekusi — selama tidak tertulis permanen di disk. TTL 2 menit menjamin ia hampir pasti sudah dipakai sebelum sempat dipakai orang lain.
Langkah 3 — Node baru membuka wrap token.
vault unwrap hvs.CAESQr3...Key Value
--- -----
secret_id f7f9b3b6-...
secret_id_accessor 3a4d5c6e-...
secret_id_ttl 48h
secret_id_num_uses 0Langkah 4 — Node baru login AppRole menggunakan RoleID + SecretID.
vault write auth/approle/login \
role_id="<role-id-app-backend>" \
secret_id="f7f9b3b6-..."Key Value
--- -----
token hvs.CAESLp9...
token_duration 1h
token_policies ["app-backend"]Langkah 5 — Node baru menyimpan secret bootstrap di cubbyhole-nya sendiri untuk proses boot berikutnya, sehingga tidak perlu minta SecretID baru setiap kali restart:
vault kv put cubbyhole/approle secret-id="f7f9b3b6-..."Dari sudut pandang attacker, seluruh alur ini tidak pernah mengekspos SecretID mentah di transit. Yang terkirim hanyalah wrap token sekali pakai berumur 2 menit, dan SecretID pun tersimpan di cubbyhole yang hanya bisa dibaca token node itu sendiri.
Warning
Jangan tertukar antara wrap token dan SecretID. Wrap token adalah "amplop" sekali pakai yang menyimpan response (termasuk SecretID). SecretID adalah kredensial itu sendiri. Jika kalian salah mengirim SecretID mentah dan mengira sudah aman karena "di-wrap", maka kalian hanya memindahkan masalah. Pastikan yang dikirim selalu wrap token (vault write -wrap-ttl=...), bukan hasil unwrap-nya.
Kedua fitur ini sering dianggap sama padahal berbeda peran:
| Aspek | Response Wrapping | Cubbyhole |
|---|---|---|
| Fungsi | Mengantarkan response secret ke pihak lain | Menyimpan secret untuk token itu sendiri |
| Konsumen | Pihak lain (transfer) | Token itu sendiri (delegasi antar proses) |
| Umur data | Sesuai TTL wrap (menit) | Selama token masih hidup |
| One-time use | Ya, setelah unwrap | Tidak, bisa dibaca berulang kali |
| Use case utama | Bootstrap, distribusi SecretID, onboarding | Sink agent, cache per-proses, delegation |
Aturan praktisnya: perlu mengirim secret ke orang/komponen lain → wrapping. Perlu menyimpan rahasia sementara yang hanya milik proses ini → cubbyhole. Keduanya sering dipakai bersama — contoh klasiknya adalah mekanisme internal Vault Agent ketika melakukan auto-auth (akan dibahas di episode 14).
| Kesalahan | Gejala | Solusi |
|---|---|---|
| Mengira wrap token bisa dipakai berulang | Error wrapping token is not valid | Ingat: sekali unwrap, mati |
| Mengirim SecretID mentah "biar aman" | Secret terpapar di transit | Selalu wrap dulu dengan -wrap-ttl=... |
| Mengira cubbyhole bisa diakses token lain | Data "hilang" padahal tidak ada | Pahami scoping per-token cubbyhole |
| TTL wrap terlalu lama | Jendela ekspos membesar | Set TTL sesuai durasi pengiriman (menit) |
| Menyimpan secret sensitif permanen di cubbyhole | Hilang saat token mati | Cubbyhole untuk data transien, bukan storage permanen |
Tidak set -wrap-ttl saat write secret-id | SecretID kembali plaintext | Selalu sertakan -wrap-ttl untuk kredensial onboarding |
| Lupa membedakan wrapping vs KV | Policy ditulis untuk path yang salah | Wrapping tidak butuh policy; unwrap pakai token itu sendiri |
Tip
Biasakan mengetik -wrap-ttl=5m secara mental setiap kali kalian membaca secret yang akan "dikirim ke tempat lain". Sekalipun tujuannya hanya logika manual, membungkus response adalah kebiasaan keamanan yang menutup banyak celah transit secret tanpa biaya apa pun.
Pada episode ini kita telah membahas Response Wrapping — teknik membungkus response secret ke dalam wrap token satu-kali-pakai dengan TTL pendek, yang membuat secret tidak pernah transit dalam bentuk plaintext; Cubbyhole — brankas pribadi per-token untuk penyimpanan sementara yang hanya bisa diakses token pembuatnya; serta pola zero-trust bootstrap yang menggabungkan keduanya untuk mengirimkan SecretID AppRole ke server baru secara aman.
Inti dari episode ini: wrapping dan cubbyhole adalah jawaban Vault atas masalah "bagaimana mengirimkan rahasia tanpa pernah mengirim rahasia." Dengan menutup bab terakhir FASE 3 (Authentication, Authorization, Identity & Leases), kalian sekarang menguasai seluruh rantai keamanan Vault: siapa (auth), boleh apa (policy), siapa sebenarnya (identity), berapa lama (lease), dan bagaimana dikirim (wrapping).
Di episode 14 selanjutnya, kita masuk ke FASE 4: Vault Agent & Vault Agent Auto-Auth — bagaimana menghilangkan beban pengelolaan token dan renewal dari dalam kode aplikasi dengan daemon pendamping. Pastikan tetap semangat!