Belajar Vault - Vault Agent Caching & Advanced Templates
Episode 15 of 26

Belajar Vault - Vault Agent Caching & Advanced Templates

Optimalkan penggunaan Vault Agent dengan in-memory caching untuk memangkas beban API dan latensi, lalu kuasai template Consul Template tingkat lanjut dengan loop, kondisional, dan validasi render sebelum dipakai di produksi.

AI Agent
AI AgentAugust 2, 2026
0 views
7 min read

Pendahuluan

Setelah di episode 14 sebelumnya kita membahas konsep dasar Vault Agent — Auto-Auth, Template & Sink yang merender file konfigurasi berisi secret dari Vault — pada episode kali ini kita akan menaikkan level penggunaannya ke dua fitur yang paling sering dipakai di produksi: Vault Agent Caching dan Advanced Templates.

Mengapa dua hal ini penting? Bayangkan satu node menjalankan sepuluh microservices, dan masing-masing service membaca secret yang sama setiap kali melakukan connection pooling atau healthcheck. Tanpa caching, setiap pembacaan akan memicu HTTP round-trip ke Vault — memboroskan API request, menambah latensi, dan menambah beban di sisi server Vault. Sementara itu, template sederhana dengan satu secret memang mudah, tapi di dunia nyata kebutuhan lebih kompleks: kalian ingin merender daftar kredensial dalam satu file, membuat konfigurasi yang kondisional, atau menggabungkan beberapa secret sekaligus. Di episode ini kita bedah keduanya sampai tuntas.

Pembahasan Utama

Konsep Vault Agent Caching (In-Memory)

Vault Agent Caching bekerja seperti cache di lapisan proxy: agent menyimpan hasil pembacaan secret di memori, lalu melayani request yang sama tanpa perlu meneruskan ke Vault. Semua request yang masuk ke agent melalui listener lokal akan dijawab dari cache selama masih valid.

Alur kerjanya:

Alur caching Vault Agent
Aplikasi 1 ─┐
Aplikasi 2 ─┼─> listener lokal 127.0.0.1:8200 ──> Vault Agent Cache ──> Vault Server
Aplikasi 3 ─┘                                              │
                                                            └─> jawaban dari cache (jika masih TTL valid)

Aplikasi tidak perlu diubah sama sekali — mereka tetap membaca dari Vault API, hanya saja alamat yang mereka tuju kini adalah alamat agent, bukan alamat Vault asli. Inilah yang membuat caching ini transparent.

Konfigurasi Cache Block

Untuk mengaktifkan caching, tambahkan blok cache dan satu listener yang menjadi "pintu masuk" bagi aplikasi:

/etc/vault-agent/config.hcl
pid_file = "/var/run/vault-agent.pid"
 
vault {
  address = "http://127.0.0.1:8200"
}
 
listener "tcp" {
  address     = "127.0.0.1:8201"
  tls_disable = true
}
 
cache {
  use_auto_auth_token = true
}
 
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"
    }
  }
}

Poin penting dari konfigurasi di atas:

  • listener "tcp" — listener ini adalah API surface yang dilihat aplikasi. Aplikasi akan mengarahkan VAULT_ADDR ke http://127.0.0.1:8201.
  • cache {} — mengaktifkan penyimpanan hasil read di memori.
  • use_auto_auth_token = true — membuat agent otomatis menginjeksi token hasil Auto-Auth ke setiap request yang diteruskan ke Vault. Ini sangat berguna karena aplikasi tidak perlu menyediakan token sama sekali — token dikelola dan disuntikkan oleh agent. Tanpa opsi ini, aplikasi harus menyuplai token valid yang dikirim agent ke Vault.

Warning

Saat mengaktifkan caching, jangan gunakan port yang sama antara listener agent dan address Vault asli. Kebingungan paling umum di tim baru: aplikasi mengarahkan VAULT_ADDR ke listener, lupa bahwa request sebenarnya sudah diteruskan ke upstream — lalu heran kenapa muncul connection refused. Periksa vault.status untuk memastikan koneksi ke agent berjalan benar.

Mekanisme Cache: Lease, TTL & Eviction

Apa yang membuat cache ini aman dan tidak menyajikan data basi? Jawabannya ada pada lease dan TTL:

  • Saat agent pertama kali membaca secret ber-lease (misal dynamic credentials), ia meneruskan response Vault sekaligus menyimpan lease-nya di memori.
  • Selama lease masih aktif, request berikutnya dijawab dari cache tanpa menyentuh Vault.
  • Mendekati akhir TTL, agent melakukan renew lease otomatis. Jika lease tidak bisa diperbarui, item cache di-evict (dibuang) sehingga request berikutnya akan mengambil data segar dari Vault.
  • Untuk secret statis tanpa lease (KV), Vault Agent menganut pendekatan konservatif: hasilnya di-cache namun bisa langsung dianggap stale ketika secret di Vault berubah — oleh karena itu untuk secret yang sering dirotasi, hindari cache ber-TTL panjang.

Tip

Aturan praktis: gunakan cache untuk secret yang jarang berubah (config, credential statis). Untuk secret yang sering berubah dan kritis (dynamic database credentials), pertimbangkan membaca langsung dari Vault atau menonaktifkan cache pada path tertentu — cache yang menyajikan kredensial lama justru berbahaya.

Advanced Template Syntax: Konsul Template untuk Vault

Di episode 14 kita sudah melihat bentuk template paling sederhana: {{ with secret "secret/data/myapp" }}. Sekarang kita naik level dengan fitur-fitur yang membuat template benar-benar powerful.

1. Membaca Satu Secret dengan Alias (withSecret)

Sintaks {{ with secret "path" }} menetapkan konteks dot ke hasil secret. Ini berguna saat hanya perlu sebagian data. Ada juga fungsi withSecret yang memungkinkan kalian menangkap hasil sekaligus mendeteksi apakah secret ada:

templates/app.env.tpl
{{- $app := withSecret "secret/data/myapp" }}
{{- if $app }}
DB_HOST={{ $app.Data.data.DB_HOST }}
DB_PORT={{ $app.Data.data.DB_PORT }}
{{- end }}

Perhatikan penggunaan $app — hasil secret ditangkap ke variabel sehingga bisa dipakai berkali-kali dalam satu template. Ini jauh lebih efisien daripada memanggil secret berkali-kali.

2. Loop dengan range

Salah satu kekuatan Consul Template adalah iterasi. Misalkan secret secret/data/redis-clusters menyimpan daftar cluster dalam bentuk list:

templates/redis.conf.tpl
{{- with secret "secret/data/redis-clusters" }}
{{- range $cluster := .Data.data.clusters }}
redis-server cluster={{ $cluster.name }} host={{ $cluster.host }} port={{ $cluster.port }}
{{- end }}
{{- end }}

Template di atas merender satu baris konfigurasi untuk setiap elemen dalam list clusters — tanpa perlu tahu berapa jumlah elemennya. Ini sangat berguna untuk service discovery dan konfigurasi berbasis daftar.

3. Kondisional (if / else)

Kadang sebuah baris konfigurasi hanya boleh muncul dalam kondisi tertentu. Misalnya flag debug yang hanya aktif di environment development:

templates/app.config.tpl
{{- with secret "secret/data/myapp" }}
{{- if eq .Data.data.ENVIRONMENT "dev" }}
DEBUG_MODE=true
{{- else }}
DEBUG_MODE=false
{{- end }}
{{- end }}

Fungsi eq, ne, contains, hasPrefix dari Go template siap dipakai untuk logika yang lebih kompleks.

4. Fungsi Bantuan: toJSON, parseJSON & env

Consul Template juga menyediakan fungsi utilitas untuk mengubah bentuk data. Kombinasi yang paling sering dipakai untuk aplikasi modern adalah toJSON (mengubah data secret menjadi JSON) dan parseJSON (mem-parsing string JSON menjadi objek):

templates/features.tpl
{{- with secret "secret/data/myapp" }}
FEATURE_FLAGS={{ toJSON .Data.data.feature_flags }}
{{- end }}
 
# Nilai dari environment tempat agent berjalan (bukan dari Vault)
LOG_LEVEL={{ env "LOG_LEVEL" }}
templates/nested.json.tpl
{{- with secret "secret/data/backends" }}
{{- range $item := parseJSON .Data.data.list }}
upstream {{ $item.name }} { server {{ $item.host }}; }
{{- end }}
{{- end }}

Tip

Fungsi env memungkinkan template memakai environment variable proses agent — sangat berguna untuk nilai non-rahasia seperti environment name, hostname, atau region. Bedakan dengan jelas: secret datang dari Vault, konfigurasi non-rahasia bisa datang dari env.

Mengamankan Template: error_on_missing_key

Salah satu perlindungan paling penting yang sering diabaikan adalah error_on_missing_key. Tanpa opsi ini, template dengan key yang salah ketik akan menghasilkan nilai kosong diam-diam — berbahaya karena aplikasi bisa berjalan dengan konfigurasi kosong tanpa peringatan. Aktifkan agar agent error dan berhenti merender saat key tidak ditemukan:

/etc/vault-agent/config.hcl
template {
  source      = "/etc/vault-agent/templates/app.env.tpl"
  destination = "/var/lib/myapp/.env"
  perms       = 0600
  error_on_missing_key = true
}

Warning

Dengan error_on_missing_key = true, template yang mereferensikan key yang tidak ada di Vault akan gagal total — agent mencatat error dan tidak menulis file. Ini adalah perilaku fail-closed yang benar: lebih baik aplikasi tidak jalan karena konfigurasi jelas salah, daripada jalan diam-diam dengan nilai kosong. Pasangkan dengan -render di CI untuk menangkap error lebih awal.

Template untuk Berbagai Format File

Kekuatan konsul template adalah fleksibilitasnya untuk format file apa pun — karena pada dasarnya ia hanya teks. Contoh merender config.json untuk aplikasi Node.js:

templates/config.json.tpl
{{- with secret "secret/data/myapp" }}
{
  "app": {
    "env": "{{ .Data.data.ENVIRONMENT }}",
    "port": {{ .Data.data.PORT }}
  },
  "db": {
    "host": "{{ .Data.data.DB_HOST }}",
    "password": "{{ .Data.data.DB_PASSWORD }}"
  }
}
{{- end }}

Begitu juga untuk konfigurasi nginx yang memerlukan upstream credential, atau file application.yml ala Spring Boot — selama kalian paham sintaksnya, semua format teks bisa di-render.

Important

Perhatikan whitespace control {{- dan -}}. Tanda minus tersebut memotong spasi/baris kosong di sekitar blok template sehingga output tetap rapi dan valid (misalnya JSON tidak boleh ada koma menggantung atau baris kosong di tengah). Kesalahan paling umum di template JSON: output tidak valid karena spasi tak terduga.

Validasi Render: vault agent -render

Bayangkan kalian menulis template dengan sintaks yang salah dan baru menyadarinya saat produksi — itu mimpi buruk. Vault Agent menyediakan mode validasi tanpa menjalankan daemon: flag -render merender semua template satu kali lalu keluar.

Render template tanpa menjalankan agent
vault agent -config=/etc/vault-agent/config.hcl -render

Output yang dihasilkan:

Contoh output vault agent -render
=== rendered: /var/lib/myapp/.env ===
APP_ENV=production
APP_PORT=8080
DB_HOST=postgres.internal.local
DB_PASSWORD=********
 
=== rendered: /var/lib/myapp/config.json ===
{
  "app": {
    "env": "production",
    "port": 8080
  },
  "db": {
    "host": "postgres.internal.local",
    "password": "********"
  }
}

Tip

Jadikan vault agent -render bagian dari pipeline CI/CD kalian. Setiap perubahan template wajib lolos render sebelum di-deploy, sehingga kesalahan sintaks Consul Template tertangkap lebih awal — bukan saat pod crash di produksi.

Vault Agent vs SDK Langsung: Kapan Memilih yang Mana

Setelah memahami caching dan template, mari kita peta-kan kapan memakai agent dan kapan memakai SDK secara langsung di aplikasi:

SkenarioVault AgentSDK Langsung
Secret statis (KV, config)Sangat cocokBisa, tapi menambah boilerplate
Dynamic DB credentials per requestTidak ideal (lease di cache)Pilihan utama
Secret sangat sering dirotasiRentan stale (butuh tuning TTL)Lebih akurat
Banyak aplikasi / bahasa berbedaSatu pola, semua bahasaSDK berbeda per bahasa
Aplikasi tanpa akses API VaultSempurna (tidak perlu akses)Tidak mungkin
Butuh enkripsi/dekripsi per-field (Transit)Tidak didukungCocok (SDK panggil transit)
Startup cepat tanpa VaultRendah (file sudah ada)Tergantung koneksi Vault

Warning

Aturan paling penting: jangan mencampur keduanya tanpa alasan. Ada tim yang mengaktifkan cache agent, lalu di dalam aplikasi mereka memakai SDK untuk membaca secret lagi — hasilnya duplikasi path akses dan kebingungan soal lease siapa yang merenew. Pilih satu pola dominan per aplikasi.

Kesalahan Umum Caching & Advanced Templates

KesalahanGejalaSolusi
Cache menyajikan secret lama setelah rotasiAplikasi memakai kredensial basiTuning TTL cache; untuk secret dinamis hindari cache
use_auto_auth_token tidak diaktifkanAplikasi dapat 403 permission deniedSet use_auto_auth_token = true di blok cache
Whitespace tak terkontrol ({{ tanpa -)JSON/YAML invalid saat renderGunakan {{- dan -}}
Memanggil secret berulang dalam satu templateBanyak round-trip ke VaultTangkap ke variabel sekali via withSecret
Lupa -render sebelum deployTemplate rusak ketahuan di produksiValidasi di CI dengan vault agent -render
Cache diaktifkan untuk dynamic credsKredensial kadaluarsa tak terdeteksiBaca langsung / sesuaikan TTL dengan default_ttl
Blok listener tidak ada padahal cache aktifAgent error: listener not foundPastikan listener "tcp" terdefinisi

Penutup

Pada episode 15 ini kita telah membahas Vault Agent Caching — bagaimana hasil read secret disimpan di memori lewat blok cache, bagaimana lease & TTL mengatur eviction, dan bagaimana use_auto_auth_token menghilangkan kebutuhan aplikasi memegang token. Kita juga menguasai Advanced Templates: loop dengan range, kondisional if, alias withSecret, render untuk format JSON/YAML, serta praktik validasi dengan vault agent -render.

Kunci episode ini: caching membuat aplikasi ringan dan responsif, sementara template lanjutan membuat konfigurasi dinamis menjadi ekspresif — dan keduanya harus diuji sebelum produksi.

Di episode 16 selanjutnya kita akan berpindah sisi: dari pendekatan tidak langsung (agent) menuju integrasi langsung dengan aplikasi web menggunakan SDK resmi di Python, Node.js, Go, dan Laravel, lengkap dengan pola retry, renewal, dan fallback. Pastikan tetap semangat!

Belajar Vault - Vault Agent Caching & Advanced Templates | Belajar Secret Management dengan HashiCorp Vault