Pindahkan beban otentikasi dan perpanjangan token Vault keluar dari kode aplikasi dengan Vault Agent. Kita akan membahas konsep daemon sidecar, Auto-Auth, serta Template & Sink untuk merender file konfigurasi berisi secret secara otomatis.

Setelah di episode 12 sebelumnya kita membahas bagaimana lease, TTL, renewal, dan revocation bekerja — lengkap dengan alasan mengapa setiap dynamic secret dan token di Vault punya masa hidup terbatas — dan di episode 13 kita membahas cara mengantarkan secret secara aman lewat response wrapping, pada episode kali ini kita akan membahas topik yang paling sering ditunggu para backend developer dan DevOps: bagaimana cara aplikasi mengonsumsi secret dari Vault tanpa harus memprogram seluruh logika autentikasi dan renewal di dalam kode.
Inilah pertanyaan krusialnya: kalau aplikasi kita harus memanggil auth/approle/login, menyimpan token, lalu mengurus renew setiap beberapa menit dan revoke saat proses mati — berarti setiap aplikasi di perusahaan harus menulis ulang kode keamanan yang sama. Itu boilerplate yang rawan salah, rawan bocor, dan mempersulit audit. Solusi HashiCorp untuk masalah ini adalah Vault Agent: sebuah proses pendamping yang mengambil alih semua kerja berat otentikasi dan token lifecycle, sehingga kode aplikasi bisa tetap bersih dan bahkan tidak perlu tahu bahwa Vault itu ada. Yuk kita bedah secara menyeluruh.
Bayangkan aplikasi kalian seperti seorang karyawan yang butuh masuk ke gedung kantor. Tanpa Vault Agent, karyawan tersebut harus membawa sendiri kartu akses, mengecek masa berlakunya, dan memperpanjang kartunya sendiri sebelum hangus. Sekarang bayangkan ada seratus karyawan dengan ratusan kartu yang berbeda-beda TTL-nya — siapa yang menjamin semuanya diperbarui tepat waktu? Nah, Vault Agent adalah petugas keamanan di depan pintu yang mengurus semua kartu untuk para karyawan.
Secara teknis, manfaat utama Vault Agent adalah:
VAULT_TOKEN atau logika login..env, config.json, application.yml) yang diisi Vault Agent dari data Vault.Important
Ini adalah pola indirect integration (integrasi tidak langsung): aplikasi tidak perlu memanggil API Vault sama sekali. Secret "datang sendiri" ke aplikasi lewat file. Sebaliknya, integrasi langsung memakai SDK resmi (hvac, node-vault, vault/api) akan kita bahas mendalam di episode 16.
Vault Agent adalah proses yang berjalan di samping aplikasi (sidecar). Di server VM tradisional ia berjalan sebagai service systemd, di Kubernetes ia berjalan sebagai sidecar container di dalam pod yang sama (akan kita bahas di episode 17). Ia memiliki tiga tanggung jawab utama:
Alur kerjanya kira-kira seperti ini:
+-----------+ 1. auto-auth (AppRole/AWS/K8s) +----------------+
| | ---------------------------------------> | |
| Vault | <--------------------------------------- | Vault Agent |
| Server | 2. token + lease | (sidecar) |
| | | |
| | <--------------------------------------- | 3. template: |
| | 4. secret data | secret "..." |
+-----------+ | |
| 5. render ke |
| destination |
+----------------+Yang perlu digarisbawahi: aplikasi hanya berinteraksi dengan file yang dihasilkan, bukan dengan Vault. Jika Vault sedang down atau token sedang dirotasi, aplikasi tidak ikut terpengaruh karena ia membaca file yang sudah ada di disk.
Blok auto_auth di konfigurasi Vault Agent adalah "jantung" dari login otomatis. Di dalamnya kita mendefinisikan:
method — auth method apa yang dipakai untuk login (misalnya approle, aws, azure, gcp, kubernetes, jwt).sink — ke mana token hasil login ditulis. Sink tipe file menulis token ke file, sedangkan aead menulis token dalam keadaan terenkripsi.Untuk login AppRole, Vault Agent membutuhkan role_id dan secret_id. Keduanya biasanya disimpan di file dengan permission ketat:
pid_file = "/var/run/vault-agent.pid"
vault {
address = "http://127.0.0.1:8200"
}
auto_auth {
method "approle" {
config = {
role_id_file_path = "/etc/vault-agent/role-id"
secret_id_file_path = "/etc/vault-agent/secret-id"
}
}
sink "file" {
config = {
path = "/etc/vault-agent/token"
}
}
}Tip
Nilai role_id bersifat statis dan aman disimpan sebagai file. Sementara secret_id bersifat rahasia dan idealnya dirotasi berkala — salah satu pola umum adalah menghasilkan secret_id melalui response wrapping (episode 13) lalu ditulis oleh script bootstrap ke secret_id_file_path. Dengan begitu tidak ada secret_id yang mengendap lama di disk.
Selain AppRole, Auto-Auth juga mendukung otentikasi berbasis cloud: misalnya method aws yang login memakai instance role IAM, atau method kubernetes yang login memakai ServiceAccount JWT. Konsepnya sama — Vault Agent yang mengurus segalanya, kode aplikasi tidak berubah sama sekali. Perbandingan konfigurasi untuk kedua method tersebut:
auto_auth {
method "kubernetes" {
mount_path = "auth/kubernetes"
config = {
role = "web"
token_path = "/var/run/secrets/kubernetes.io/serviceaccount/token"
}
}
}Note
Cara kerja kedua method sama persis dari sudut pandang Vault Agent: login → dapat token → token di-renew otomatis → ditulis ke sink. Perbedaannya hanya pada siapa yang membuktikan identitas mesin. Di Kubernetes, identitas dibuktikan oleh ServiceAccount JWT; di AWS, oleh instance metadata IAM role. Detail Kubernetes Auth akan kita dalami di episode 17.
Bagian paling menarik dari Vault Agent adalah template. Template menggunakan sintaks Consul Template — sebuah bahasa templating Go yang dibekali fungsi secret, withSecret, dan kawan-kawan. Konsepnya: kalian tulis pola file, lalu Vault Agent mengisi bagian secret yang ditandai.
Misalkan secret aplikasi web tersimpan di KV v2 dengan path secret/data/myapp berisi key DB_HOST dan DB_PASSWORD. Template untuk menghasilkan file .env adalah:
APP_ENV=production
APP_PORT=8080
DB_HOST={{ with secret "secret/data/myapp" }}{{ .Data.data.DB_HOST }}{{ end }}
DB_PASSWORD={{ with secret "secret/data/myapp" }}{{ .Data.data.DB_PASSWORD }}{{ end }}Perhatikan akses datanya: untuk KV v2, data sebenarnya berada di data.data, sehingga variabelnya adalah {{ .Data.data.DB_HOST }}. Untuk KV v1 cukup {{ .Data.DB_HOST }}. Kesalahan memakai level Data yang salah adalah salah satu pitfall paling sering terjadi — akan kita bahas di bagian kesalahan umum.
Blok template di konfigurasi agent menghubungkan template dengan file tujuan:
pid_file = "/var/run/vault-agent.pid"
vault {
address = "http://127.0.0.1:8200"
}
auto_auth {
method "approle" {
config = {
role_id_file_path = "/etc/vault-agent/role-id"
secret_id_file_path = "/etc/vault-agent/secret-id"
}
}
sink "file" {
config = {
path = "/etc/vault-agent/token"
}
}
}
template {
source = "/etc/vault-agent/templates/app.env.tpl"
destination = "/var/lib/myapp/.env"
perms = 0600
}Warning
Atribut perms sangat penting. Kalian tidak ingin file .env hasil render bisa dibaca semua user di server (0644). Gunakan 0600 atau 0640 dengan group khusus aplikasi. Sekali file rahasia terbaca oleh user yang tidak berhak, itu sudah termasuk insiden kebocoran.
Menjalankan Vault Agent cukup sederhana — tunjuk file konfigurasi:
vault agent -config=/etc/vault-agent/config.hclFlag -config bisa diulang untuk memuat beberapa file sekaligus — berguna untuk memisahkan konfigurasi per-bagian (misal base.hcl, auto-auth.hcl, templates.hcl) agar mudah di-review:
vault agent -config=/etc/vault-agent/base.hcl \
-config=/etc/vault-agent/auto-auth.hcl \
-config=/etc/vault-agent/templates.hclTip
Saat proses Vault Agent menerima sinyal SIGHUP, ia memuat ulang konfigurasi tanpa perlu di-restart — inilah yang dimanfaatkan ExecReload=/bin/kill -HUP $MAINPID pada unit systemd. Ini berguna saat kalian menambah template baru: cukup systemctl reload vault-agent dan template langsung aktif tanpa downtime.
Untuk environment production, kita jalankan sebagai service systemd agar selalu hidup dan restart otomatis saat crash. Contoh unit service:
[Unit]
Description=Vault Agent - Secret Rendering Sidecar
Documentation=https://developer.hashicorp.com/vault/docs/agent
Requires=network-online.target
After=network-online.target
[Service]
User=vault-agent
Group=vault-agent
ProtectSystem=strict
ExecStart=/usr/bin/vault agent -config=/etc/vault-agent/config.hcl
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5
LimitNOFILE=65536
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl enable --now vault-agent
sudo systemctl status vault-agentSetelah agent berjalan, file .env akan ter-render. Karena template mengandung secret statis dari KV, Vault Agent merender file tersebut saat pertama kali berhasil login, dan merender ulang setiap kali secret di Vault berubah:
APP_ENV=production
APP_PORT=8080
DB_HOST=postgres.internal.local
DB_PASSWORD=a9f3!sVx#2kQNote
Perhatikan cara kerja render-nya: Vault Agent tidak menulis file begitu saja — ia menulis ke temporary file lalu melakukan atomic rename ke destination. Ini mencegah aplikasi membaca file dalam keadaan setengah jadi. Aplikasi yang membaca file saat proses rename berlangsung akan selalu melihat versi yang utuh.
Agar bisa merancang deployment yang benar, kalian perlu memahami apa yang terjadi pada token di setiap fase proses Vault Agent:
token_ttl. Template dipantau terus; begitu data secret berubah, file hasil render diperbarui. Inilah yang membuat automatic rotation bekerja tanpa aplikasi ikut campur.SIGHUP membuat agent memuat ulang konfigurasi (menambah/mengubah template) tanpa memutus token yang sedang aktif.systemctl stop), agent melakukan revoke token ke Vault. Ini sangat penting: token tidak dibiarkan hidup mengambang setelah proses mati, menutup kemungkinan penyalahgunaan.sudo systemctl stop vault-agent
# Log agent: [INFO] (auth.approle) successfully revoked tokenImportant
Karena revoke terjadi pada sinyal terminasi yang bersih, hindari mematikan agent dengan kill -9 tanpa alasan. SIGKILL tidak memberi kesempatan agent membersihkan token — token akan tetap hidup sampai TTL-nya habis. Gunakan systemctl stop atau SIGTERM pada saat normal.
Kapan memakai Vault Agent dan kapan memakai SDK langsung di dalam aplikasi? Keduanya sah, tetapi punya karakteristik berbeda:
| Aspek | Vault Agent (Indirect) | SDK In-App (Direct) |
|---|---|---|
| Pengetahuan aplikasi tentang Vault | Tidak perlu sama sekali | Aplikasi harus tahu alamat & auth method |
| Pengelolaan token / renewal | Otomatis oleh agent | Wajib diprogram di aplikasi |
| Bahasa pemrograman | Agnostik (membaca file) | Bergantung SDK per bahasa |
| Dynamic secret (mis. DB creds) | Tidak didukung penuh | Mendukung penuh (per-request) |
| Latensi akses secret | Rendah (baca file lokal) | Tergantung round-trip HTTP |
| Rotasi secret | File ter-render ulang otomatis | Harus logika polling/renew di kode |
| Cocok untuk | Microservices, kontainer, server statis | Aplikasi yang butuh secret dinamis per request |
Intuisi sederhananya: kalau aplikasi hanya butuh secret statis seperti kredensial koneksi database yang jarang berubah, Vault Agent jauh lebih sederhana dan aman. Tapi jika aplikasi butuh dynamic credentials yang di-generate per request — misalnya kredensial DB baru setiap kali membuka koneksi — maka integrasi SDK langsung adalah pilihan yang tepat. Kedua topik ini akan kita dalami di episode 15 dan 16.
| Kesalahan | Gejala | Solusi |
|---|---|---|
Salah level data di template ({{ .Data.DB_HOST }} padahal KV v2) | Nilai ter-render kosong | Untuk KV v2 gunakan {{ .Data.data.DB_HOST }} |
| File sink / destination dengan permission longgar | Secret bisa dibaca user lain | Set perms = 0600 dan batasi user/group service |
role_id_file_path / secret_id_file_path tidak ada | Agent gagal login: role_id is not a valid path | Pastikan file dibuat sebelum agent start (bootstrap script) |
| Lupa mengaktifkan sink | Token tidak ditulis ke file sehingga template gagal | Tambahkan blok sink "file" |
| Template path salah / typo | Agent berjalan tapi file tidak ter-render | Cek log agent; uji dengan vault agent -render |
Menyimpan secret_id dengan TTL tanpa batas | Risiko penyalahgunaan jika bocor | Gunakan secret_id_ttl dan response wrapping |
File .env hasil render ikut ter-commit ke Git | Kebocoran secret ke repository | Tambahkan destination ke .gitignore dan jangan pernah menjadikan template sebagai nilai asli |
Caution
Jangan pernah melakukan debug dengan mematikan perms atau mengganti destination ke direktori publik hanya agar "cepat terlihat". Kebiasaan ini adalah bom waktu: begitu server produksi, satu kesalahan kecil langsung berubah menjadi kebocoran secret.
Pada episode 14 ini kita telah membahas mengapa Vault Agent diperlukan, bagaimana ia bekerja sebagai daemon sidecar, konsep Auto-Auth yang mengotomatiskan login dan token lifecycle, serta Template & Sink untuk merender file konfigurasi (.env, config.json) yang berisi secret dari Vault. Kita juga sudah melihat cara menjalankannya dengan systemd dan memahami perbandingan antara integrasi tidak langsung (agent) vs langsung (SDK).
Inti pelajaran episode ini: kode aplikasi yang tidak perlu tahu tentang Vault adalah kode yang paling aman — semakin sedikit logika keamanan yang tersebar di aplikasi, semakin kecil permukaan serangannya.
Di episode 15 selanjutnya kita akan menggali lebih dalam: Vault Agent Caching untuk mengurangi beban API dan latensi, serta Advanced Templates menggunakan fitur lanjutan Consul Template seperti loop dan kondisional. Pastikan tetap semangat!