ทำไมต้อง Secrets Management
ผมเคยเจอ database password ที่ hardcode ไว้ใน source code แล้ว push ขึ้น Git เคยเจอ API keys ใน .env files ที่ share กันใน team chat เคยเจอ SSH private keys ที่เก็บใน shared drive ทุกกรณีเป็นความเสี่ยงด้าน security ที่ร้ายแรง Vault แก้ปัญหานี้ทั้งหมด
HashiCorp Vault เป็น secrets management platform ที่ทำหน้าที่เป็นศูนย์กลางจัดเก็บและจ่าย secrets ทุกประเภทตั้งแต่ passwords, API keys, certificates จนถึง dynamic database credentials ทุกการเข้าถึง secrets มี audit log ครบถ้วน
ปัญหาที่ Vault แก้ได้
Secret Sprawl — secrets กระจายอยู่ทุกที่ในระบบไม่รู้ว่ามีอะไรอยู่ที่ไหน No Audit Trail — ไม่มี log ว่าใครเข้าถึง secret อะไรเมื่อไร No Rotation — passwords ไม่เคยถูกเปลี่ยนใช้ password เดิมมาหลายปี Overprivileged Access — ทุกู้คืนเข้าถึง secrets ทุกตัว Vault แก้ทุกข้อมี centralized storage, audit logging, automatic rotation, granular policies
ติดตั้งด้วย Docker Compose
# docker-compose.yml — Vault Production Setup
services:
vault:
image: hashicorp/vault:1.17
cap_add:
- IPC_LOCK
ports:
- "8200:8200"
environment:
VAULT_ADDR: "http://0.0.0.0:8200"
volumes:
- vault-data:/vault/data
- ./vault-config:/vault/config
command: vault server -config=/vault/config/vault.hcl
restart: unless-stopped
volumes:
vault-data:
# vault-config/vault.hcl
storage "raft" {
path = "/vault/data"
node_id = "vault-1"
}
listener "tcp" {
address = "0.0.0.0:8200"
tls_disable = 0
tls_cert_file = "/vault/config/tls/cert.pem"
tls_key_file = "/vault/config/tls/key.pem"
}
api_addr = "https://vault.example.com:8200"
cluster_addr = "https://vault.example.com:8201"
ui = true
disable_mlock = true
Initialize และ Unseal
# Initialize Vault (ครั้งแรกเท่านั้น)
export VAULT_ADDR="https://vault.example.com:8200"
vault operator init -key-shares=5 -key-threshold=3
# จะได้:
# Unseal Key 1: xxxxx
# Unseal Key 2: xxxxx
# Unseal Key 3: xxxxx
# Unseal Key 4: xxxxx
# Unseal Key 5: xxxxx
# Initial Root Token: hvs.xxxxx
# เก็บ keys เหล่านี้ให้ปลอดภัย! แยกเก็บคนละที่
# Unseal (ต้องใช้ 3 จาก 5 keys)
vault operator unseal # ใส่ key 1
vault operator unseal # ใส่ key 2
vault operator unseal # ใส่ key 3
# Login ด้วย root token
vault login hvs.xxxxx
# ตรวจสอบ status
vault status
เก็บและอ่าน Secrets
# เปิด KV v2 secrets engine
vault secrets enable -path=secret kv-v2
# เก็บ secret
vault kv put secret/database/production \
username="app_user" \
password="SuperSecretPass2026!" \
host="10.10.10.201" \
port="3306"
# อ่าน secret
vault kv get secret/database/production
vault kv get -field=password secret/database/production
# อ่านเป็น JSON
vault kv get -format=json secret/database/production
# ดู version history
vault kv metadata get secret/database/production
# อ่าน version เก่า
vault kv get -version=2 secret/database/production
# ลบ secret (soft delete)
vault kv delete secret/database/production
# ลบถาวร
vault kv destroy -versions=1,2,3 secret/database/production
ใช้งานจาก Application
# Python example
import hvac
client = hvac.Client(url='https://vault.example.com:8200', token='hvs.xxx')
# อ่าน secret
secret = client.secrets.kv.v2.read_secret_version(
mount_point='secret',
path='database/production'
)
db_password = secret['data']['data']['password']
db_host = secret['data']['data']['host']
# Bash/curl example
curl -s -H "X-Vault-Token: hvs.xxx" \
https://vault.example.com:8200/v1/secret/data/database/production \
| jq -r '.data.data.password'
Dynamic Secrets สำหรับ Database
Dynamic secrets คือ feature ที่ทรงพลังที่สุดของ Vault แทนที่จะเก็บ database password แบบ static Vault สร้าง temporary credentials ที่มีอายุจำกัดให้แต่ละ application หมดอายุแล้ว Vault ลบ user ออกจาก database อัตโนมัติ
ตั้งค่า MySQL Dynamic Secrets
# เปิด database secrets engine
vault secrets enable database
# ตั้งค่า MySQL connection
vault write database/config/production-mysql \
plugin_name=mysql-database-plugin \
connection_url="{{username}}:{{password}}@tcp(10.10.10.201:3306)/" \
allowed_roles="readonly, readwrite" \
username="vault_admin" \
password="VaultAdminPass2026!"
# สร้าง role สำหรับ readonly access
vault write database/roles/readonly \
db_name=production-mysql \
creation_statements="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}'; GRANT SELECT ON production.* TO '{{name}}'@'%';" \
revocation_statements="DROP USER IF EXISTS '{{name}}'@'%';" \
default_ttl="1h" \
max_ttl="24h"
# สร้าง role สำหรับ readwrite access
vault write database/roles/readwrite \
db_name=production-mysql \
creation_statements="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}'; GRANT SELECT, INSERT, UPDATE, DELETE ON production.* TO '{{name}}'@'%';" \
revocation_statements="DROP USER IF EXISTS '{{name}}'@'%';" \
default_ttl="1h" \
max_ttl="8h"
# ขอ dynamic credentials
vault read database/creds/readonly
# username: v-token-readonly-abc123
# password: A1B2C3D4E5F6
# ttl: 1h
# หลัง 1 ชั่วโมง Vault จะ DROP USER อัตโนมัติ!
สร้าง Internal CA ด้วย Vault
# เปิด PKI secrets engine
vault secrets enable pki
vault secrets tune -max-lease-ttl=87600h pki
# สร้าง Root CA
vault write -field=certificate pki/root/generate/internal \
common_name="Example Internal CA" \
issuer_name="root-ca" \
ttl=87600h > /tmp/root-ca.pem
# สร้าง Intermediate CA
vault secrets enable -path=pki_int pki
vault secrets tune -max-lease-ttl=43800h pki_int
vault write -format=json pki_int/intermediate/generate/internal \
common_name="Example Intermediate CA" \
issuer_name="intermediate-ca" | jq -r '.data.csr' > /tmp/intermediate.csr
# Sign Intermediate CA ด้วย Root CA
vault write -format=json pki/root/sign-intermediate \
csr=@/tmp/intermediate.csr \
format=pem_bundle \
ttl=43800h | jq -r '.data.certificate' > /tmp/intermediate.pem
vault write pki_int/intermediate/set-signed \
certificate=@/tmp/intermediate.pem
# สร้าง role สำหรับ issue certificates
vault write pki_int/roles/web-server \
allowed_domains="example.com" \
allow_subdomains=true \
max_ttl=720h
# Issue certificate
vault write -format=json pki_int/issue/web-server \
common_name="web.example.com" \
ttl=720h
AppRole สำหรับ Applications
# เปิด AppRole auth
vault auth enable approle
# สร้าง role
vault write auth/approle/role/web-app \
token_policies="web-app-policy" \
token_ttl=1h \
token_max_ttl=4h \
secret_id_ttl=720h
# ดึง Role ID
vault read auth/approle/role/web-app/role-id
# สร้าง Secret ID
vault write -f auth/approle/role/web-app/secret-id
# Login ด้วย AppRole
vault write auth/approle/login \
role_id="xxx" \
secret_id="yyy"
Token Auth สำหรับ CI/CD
# สร้าง token สำหรับ CI/CD pipeline
vault token create \
-policy=ci-cd-policy \
-ttl=2h \
-display-name="gitlab-ci-deploy"
# Orphan token (ไม่ถูก revoke เมื่อ parent token หมดอายุ)
vault token create \
-policy=ci-cd-policy \
-orphan \
-ttl=24h
เขียน Policies
# web-app-policy.hcl
path "secret/data/database/production" {
capabilities = ["read"]
}
path "database/creds/readonly" {
capabilities = ["read"]
}
path "pki_int/issue/web-server" {
capabilities = ["create", "update"]
}
# ci-cd-policy.hcl
path "secret/data/deploy/*" {
capabilities = ["read", "list"]
}
path "secret/metadata/deploy/*" {
capabilities = ["list"]
}
# Upload policies
vault policy write web-app-policy web-app-policy.hcl
vault policy write ci-cd-policy ci-cd-policy.hcl
# ดู policies
vault policy list
vault policy read web-app-policy
การนำความรู้ไปประยุกต์ใช้งานจริง
แหล่งเรียนรู้ที่แนะนำ ได้แก่ Official Documentation ที่อัพเดทล่าสุดเสมอ Online Course จาก Coursera Udemy edX ช่อง YouTube คุณภาพทั้งไทยและอังกฤษ และ Community อย่าง Discord Reddit Stack Overflow ที่ช่วยแลกเปลี่ยนประสบการณ์กับนักพัฒนาทั่วโลก
Vault จำเป็นสำหรับทีมเล็กไหม?
ถ้ามีแค่ 2-3 servers อาจยังไม่จำเป็นใช้ ansible-vault หรือ sops encrypt secrets ใน Git ก็พอแต่ถ้ามี servers 10+ หรือมี multiple teams ที่ต้อง share secrets Vault คุ้มค่ามากโดยเฉพาะ dynamic secrets ที่ลดความเสี่ยงจาก password leaks ได้เกือบ 100%
Vault หยุดทำงาน (sealed) แล้ว applications จะทำยังไง?
ถ้า Vault sealed หรือ down applications ที่มี token อยู่แล้วยังใช้ secrets ที่ cache ไว้ได้จนหมดอายุแต่จะขอ secrets ใหม่ไม่ได้ดังนั้นต้องมี HA setup (cluster 3+ nodes) และ auto-unseal ด้วย cloud KMS หรือ HSM ผมใช้ Vault cluster 3 nodes กับ Raft storage ไม่เคย downtime เกิน 5 นาทีใน 4 ปี
Vault กับ Terraform ใช้ด้วยกันยังไง?
Terraform มี Vault provider สำหรับอ่าน secrets มาใช้ใน configuration เช่นอ่าน database password จาก Vault มาตั้งค่า MySQL server ทำให้ไม่ต้อง hardcode secrets ใน Terraform files และ Vault ยังสร้าง dynamic credentials สำหรับ Terraform ได้ด้วย
มี alternative อื่นนอกจาก Vault ไหม?
มีหลายตัว AWS Secrets Manager ดีถ้าอยู่ใน AWS ecosystem CyberArk Conjur open-source สำหรับ enterprise Infisical modern secrets manager ที่ UI สวย SOPS encrypt secrets ใน files สำหรับ GitOps แต่ Vault ยังเป็น gold standard สำหรับ on-premise และ multi-cloud environments เพราะ features ครบที่สุดโดยเฉพาะ dynamic secrets และ security integration
สรุป
HashiCorp Vault เป็น secrets management platform ที่สมบูรณ์ที่สุด KV secrets engine สำหรับเก็บ static secrets, dynamic secrets สำหรับ database credentials ที่มีอายุจำกัด, PKI สำหรับ internal certificate authority, granular policies สำหรับ access control ทุกการเข้าถึงมี audit log ครบถ้วน
สำหรับปี 2026 ผมแนะนำให้ทุกองค์กรที่มี servers มากกว่า 10 เครื่องใช้ Vault เริ่มจาก KV secrets engine ก่อนแล้วค่อยๆเพิ่ม dynamic secrets และ PKI ทีหลังครับ
อ่านเพิ่มเติม: สอนเทรด Forex | XM Signal | IT Hardware | อาชีพ IT