Pelajari cara mengimplementasikan HashiCorp Vault untuk centralized secret management, dynamic credential, dan audit trail dalam environment produksi. Panduan praktis untuk DevOps dan backend engineer.

Secret ada di mana-mana dalam sistem produksi—database password, API key, TLS certificate, encryption key. Namun sebagian besar tim masih mengelolanya dengan buruk: hardcoded dalam repository, tersebar di file config, atau disimpan dalam plaintext environment variable.
Di sinilah HashiCorp Vault masuk. Ini bukan hanya sistem penyimpanan secret; ini adalah platform centralized secret management yang menangani credential generation, rotation, dan audit trail secara otomatis.
Dalam panduan ini, kami akan mengeksplorasi cara kerja Vault, mengapa penting untuk sistem produksi, dan cara mengimplementasikannya dengan benar. Baik Anda menjalankan Kubernetes, traditional VM, atau hybrid infrastructure, Vault menyediakan pendekatan unified untuk secret management yang scale.
Sebelum menggali Vault, mari kita pahami mengapa secret management sulit:
Pendekatan tradisional gagal karena:
Vault menyelesaikan masalah ini dengan centralize secret management dan automate credential lifecycle.
Sebelum mengakses secret, client harus authenticate ke Vault. Vault mendukung multiple auth method:
Anggap auth method sebagai cara berbeda untuk membuktikan "Saya adalah siapa yang saya katakan" ke Vault.
Secrets engine adalah backend system Vault yang generate, store, atau manage secret:
Perbedaan kunci: static secret (disimpan sekali) vs. dynamic secret (di-generate on-demand dengan automatic rotation).
Policy mendefinisikan apa yang dapat dilakukan authenticated client. Mereka mengikuti path-based access control model:
path "secret/data/app/*" {
capabilities = ["read", "list"]
}
path "database/creds/app-role" {
capabilities = ["read"]
}
path "auth/token/renew-self" {
capabilities = ["update"]
}Policy adalah principle of least privilege dalam aksi—setiap aplikasi mendapat akses hanya ke secret yang dibutuhkan.
# Download Vault
wget https://releases.hashicorp.com/vault/1.15.0/vault_1.15.0_linux_amd64.zip
unzip vault_1.15.0_linux_amd64.zip
sudo mv vault /usr/local/bin/
# Verifikasi instalasi
vault versionInisialisasi Vault (generate unseal key dan root token):
vault operator init \
-key-shares=5 \
-key-threshold=3Ini membuat 5 unseal key di mana 3 apa pun dapat unseal Vault. Simpan ini dengan aman—mereka critical untuk recovery.
Vault dimulai dalam sealed state. Unsealing memerlukan threshold number unseal key:
vault operator unseal <unseal-key-1>
vault operator unseal <unseal-key-2>
vault operator unseal <unseal-key-3>Setelah threshold key disediakan, Vault unseal dan menjadi operational.
Vault memerlukan persistent storage. Opsi umum:
storage "raft" {
path = "/opt/vault/data"
node_id = "vault-1"
}
listener "tcp" {
address = "0.0.0.0:8200"
tls_cert_file = "/opt/vault/tls/vault.crt"
tls_key_file = "/opt/vault/tls/vault.key"
}
api_addr = "https://vault.example.com:8200"
cluster_addr = "https://vault-1.example.com:8201"
ui = trueUntuk produksi, gunakan Integrated Storage (Raft) untuk high availability atau external backend seperti Consul, S3, atau PostgreSQL.
Salah satu fitur paling powerful Vault adalah dynamic database credential. Alih-alih static password, Vault generate temporary credential on-demand.
vault secrets enable databaseKonfigurasi koneksi ke database Anda:
vault write database/config/postgresql \
plugin_name=postgresql-database-plugin \
allowed_roles="app-role" \
connection_url="postgresql://{{username}}:{{password}}@postgres.example.com:5432/postgres" \
username="vault_admin" \
password="vault_admin_password"Definisikan role yang generate credential:
vault write database/roles/app-role \
db_name=postgresql \
creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; GRANT SELECT, INSERT, UPDATE ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
default_ttl="1h" \
max_ttl="24h"Sekarang aplikasi request credential:
vault read database/creds/app-roleResponse:
{
"lease_id": "database/creds/app-role/abc123",
"lease_duration": 3600,
"data": {
"username": "v-token-app-role-abc123",
"password": "A1b2C3d4E5f6G7h8I9j0"
}
}Credential bersifat temporary, automatically rotated, dan revoked ketika lease expire.
Vault terintegrasi native dengan Kubernetes melalui Kubernetes auth method:
vault auth enable kubernetesKonfigurasi Kubernetes connection:
vault write auth/kubernetes/config \
kubernetes_host="https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT" \
kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
token_reviewer_jwt=@/var/run/secrets/kubernetes.io/serviceaccount/tokenBuat role untuk aplikasi Anda:
vault write auth/kubernetes/role/app-role \
bound_service_account_names=app \
bound_service_account_namespaces=production \
policies="app-policy" \
ttl=1hDeploy Vault Agent sebagai sidecar untuk inject secret:
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
serviceAccountName: app
containers:
- name: app
image: myapp:latest
volumeMounts:
- name: vault-token
mountPath: /vault/secrets
- name: vault-agent
image: vault:latest
args:
- agent
- -config=/vault/config/agent.hcl
volumeMounts:
- name: vault-config
mountPath: /vault/config
- name: vault-token
mountPath: /vault/secrets
volumes:
- name: vault-config
configMap:
name: vault-agent-config
- name: vault-token
emptyDir: {}Konfigurasi Vault Agent:
vault {
address = "https://vault.vault.svc.cluster.local:8200"
}
auto_auth {
method {
type = "kubernetes"
config = {
role = "app-role"
}
}
sink {
type = "file"
config = {
path = "/vault/secrets/.vault-token"
}
}
}
template {
source = "/vault/config/app-config.tpl"
destination = "/vault/secrets/app-config.json"
}Untuk database credential, Vault menangani rotation secara otomatis:
vault write database/roles/app-role \
db_name=postgresql \
creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}';" \
rotation_statements="ALTER ROLE \"{{name}}\" WITH PASSWORD '{{password}}';" \
default_ttl="1h" \
max_ttl="24h"Vault merotasi credential sebelum expiration, memastikan aplikasi selalu memiliki valid credential.
Untuk static secret, implementasikan rotation policy:
# Generate key baru
NEW_KEY=$(openssl rand -hex 32)
# Update dalam Vault
vault kv put secret/api-keys/external-service key=$NEW_KEY
# Update external service
curl -X POST https://api.example.com/keys \
-H "Authorization: Bearer $OLD_KEY" \
-d "{\"new_key\": \"$NEW_KEY\"}"
# Revoke old key
curl -X DELETE https://api.example.com/keys/$OLD_KEY \
-H "Authorization: Bearer $NEW_KEY"Vault mempertahankan comprehensive audit log dari semua secret access:
vault audit enable file file_path=/var/log/vault-audit.logAudit log capture:
Contoh audit log entry:
Audit trail ini essential untuk compliance (SOC 2, PCI-DSS, HIPAA) dan security investigation.
Masalahnya: Unseal key disimpan dalam plaintext atau di lokasi yang sama dengan Vault.
Mengapa terjadi: Tim rush deployment dan skip key management.
Cara menghindarinya:
Masalahnya: Secret tetap static selama berbulan-bulan atau bertahun-tahun.
Mengapa terjadi: Manual rotation membosankan; tim lupa atau deprioritize.
Cara menghindarinya:
Masalahnya: Aplikasi memiliki akses ke secret yang tidak dibutuhkan.
Mengapa terjadi: Tim menggunakan wildcard policy untuk convenience.
Cara menghindarinya:
Masalahnya: Single Vault instance menjadi single point of failure.
Mengapa terjadi: Setup HA kompleks; tim skip untuk environment "non-critical".
Cara menghindarinya:
Masalahnya: Vault issue tidak terdeteksi sampai aplikasi gagal.
Mengapa terjadi: Vault diperlakukan sebagai "set and forget" infrastructure.
Cara menghindarinya:
Deploy Vault dalam HA mode dengan multiple node:
storage "raft" {
path = "/opt/vault/data"
node_id = "vault-1"
retry_join {
leader_api_addr = "https://vault-2.example.com:8200"
}
retry_join {
leader_api_addr = "https://vault-3.example.com:8200"
}
}
listener "tcp" {
address = "0.0.0.0:8200"
tls_cert_file = "/opt/vault/tls/vault.crt"
tls_key_file = "/opt/vault/tls/vault.key"
}
api_addr = "https://vault-1.example.com:8200"
cluster_addr = "https://vault-1.example.com:8201"Selalu gunakan TLS untuk Vault communication:
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /opt/vault/tls/vault.key \
-out /opt/vault/tls/vault.crt \
-subj "/CN=vault.example.com"
chmod 600 /opt/vault/tls/vault.keyGunakan auth method berbeda untuk workload berbeda:
# Kubernetes pod
vault auth enable kubernetes
# CI/CD pipeline
vault auth enable jwt
# Human operator
vault auth enable oidc
# Service-to-service
vault auth enable approleSet TTL yang sesuai untuk tipe secret berbeda:
# Short-lived credential untuk sensitive operation
vault write database/roles/sensitive-role \
default_ttl="15m" \
max_ttl="1h"
# Longer TTL untuk less sensitive operation
vault write database/roles/app-role \
default_ttl="24h" \
max_ttl="720h"Backup Vault data secara regular:
vault operator raft snapshot save vault-backup-$(date +%Y%m%d).snapSimpan backup dengan aman dan test restoration secara regular.
Vault powerful tetapi tidak selalu tool yang tepat:
HashiCorp Vault mengubah secret management dari security liability menjadi controlled, auditable process. Dengan centralize secret, automate rotation, dan provide comprehensive audit trail, Vault memungkinkan tim untuk meet compliance requirement sambil improve security posture.
Takeaway kunci:
Mulai dengan pilot deployment dalam non-critical environment, pahami operational model, kemudian expand ke produksi. Investasi dalam proper secret management membayar dividen dalam security, compliance, dan operational peace of mind.