المستوى: متوسط — هذا المقال يفترض إنك شغّلت service واحد على الأقل في production واتعاملت مع environment variables، لكن لسّه ما طبّقتش solution مركزي للـ secrets.
لو عندك 8 services شغّالين على Kubernetes وكل واحد فيهم بياخد DB_PASSWORD من Secret object منفصل، يوم اللي هتغيّر فيه باسورد الـ DB هتدخل 8 places وتعمل rollout restart 8 مرات. HashiCorp Vault بيخلّي العملية دي 8 ثوانٍ بدل ساعة، مع audit log كامل لكل قراءة.
المشكلة باختصار
الطريقة الشائعة في إدارة الـ secrets داخل المؤسسات الصغيرة بتعتمد على Kubernetes Secrets أو env files مرفوعة من الـ CI. ده شغّال لما عندك 2 أو 3 services. لمّا الفريق يكبر والـ services توصل لـ 15 وأكتر، ثلاث مشاكل بتظهر في وقت واحد:
- الـ secret rotation بياخد ساعات لأن لازم تعدّل في كذا مكان وتعمل deploy لكل واحد.
- مفيش audit log حقيقي. مين قرأ الباسورد امبارح الساعة 3 الفجر؟ مفيش جواب.
- الـ developer لازم يكون عنده الباسورد في حاجة على لاب توبه علشان يعمل debug، ده breach صغير في حدّ ذاته.
المثال للمبتدئ: خزنة البنك
تخيّل عمارة فيها 8 شقق. كل شقة عندها مفتاح للسرداب اللي فيه الذهب. لو ضاعت نسخة من المفتاح من ساكن واحد، لازم تغيّر الترباس وتوزّع 8 مفاتيح جديدة على كل الشقق. ده اللي بيحصل بالظبط مع Kubernetes Secrets.
بدّل الموديل ده. خلّي السرداب نفسه في البنك. كل ساكن لازم يروح للبنك بهويته، الموظف يفتح الخزنة، يديله الذهب اللي يحتاجه فقط، ويسجّل في لوج إن فلان دخل الساعة كذا وأخد كذا. ده Vault بالظبط: مكان واحد بيحفظ السرّ، أي تطبيق محتاج يفتح بهوية مصدّقة، وكل دخول بيتسجّل.
التعريف العلمي الدقيق
HashiCorp Vault هو centralized secrets management system بيوفّر 4 capabilities أساسية:
- Static secrets storage (KV engine): تخزين مشفّر باستخدام AES-256-GCM مع master key مفصول عن الـ data.
- Dynamic secrets: توليد credentials قصيرة العمر (TTL غالباً ≤ 1 ساعة) لـ databases و cloud providers لحظياً عند الطلب.
- Identity-based access: authentication عبر Kubernetes ServiceAccount أو AWS IAM أو OIDC، بدل ما يكون فيه shared password بين كل التطبيقات.
- Audit logging: لوج كامل لكل عملية قراءة وكتابة، بصيغة JSON قابلة لـ ingestion مباشرة في SIEM زي Splunk أو ELK.
المعمارية مبنية على Shamir's Secret Sharing لتقسيم الـ master key على 5 unseal keys (الافتراضي)، ولازم 3 منهم لفك تشفير الخزنة بعد كل restart. ده بيمنع إن شخص واحد لوحده يقدر يفتح الـ Vault.
الإعداد بـ 6 خطوات قابلة للنسخ
# 1. تشغيل Vault dev mode للتجربة (لا يصلح للإنتاج)
docker run -d --name vault-dev \
-p 8200:8200 \
-e VAULT_DEV_ROOT_TOKEN_ID=root \
-e VAULT_DEV_LISTEN_ADDRESS=0.0.0.0:8200 \
hashicorp/vault:1.18
# 2. إعداد متغيرات البيئة للـ CLI
export VAULT_ADDR=http://localhost:8200
export VAULT_TOKEN=root
# 3. تفعيل KV v2 engine على path اسمه secret
vault secrets enable -path=secret kv-v2
# 4. كتابة secret بـ key/value
vault kv put secret/myapp/db \
username=appuser \
password=Sup3rS3cret2026
# 5. قراءة الـ secret كامل
vault kv get secret/myapp/db
# 6. قراءة قيمة واحدة بصيغة قابلة للـ piping
vault kv get -field=password secret/myapp/dbالإعداد ده للتجربة فقط. للإنتاج، استخدم Helm chart الرسمي مع 3 replicas على الأقل، Raft storage backend بدل الـ in-memory، وauto-unseal باستخدام KMS من AWS أو GCP علشان تتجنّب unseal يدوي بعد كل restart.
دمج Vault مع تطبيق Python حقيقي
import hvac
import os
client = hvac.Client(
url=os.environ["VAULT_ADDR"],
token=os.environ["VAULT_TOKEN"],
)
if not client.is_authenticated():
raise RuntimeError("Vault authentication failed")
response = client.secrets.kv.v2.read_secret_version(
path="myapp/db",
mount_point="secret",
)
db_password = response["data"]["data"]["password"]
db_user = response["data"]["data"]["username"]
print(f"Connecting as {db_user}")
# استخدم القيم لفتح اتصال DBفي production، بدّل الـ root token بـ Kubernetes ServiceAccount authentication. الـ pod بيوصل لـ Vault بـ JWT بتاع الـ ServiceAccount، Vault بيتأكد من الـ JWT مع TokenReview API بتاع Kubernetes، وبيرجع للـ pod token قصير العمر صالح للـ secrets المسموح بيها فقط.
Dynamic Secrets: المكسب الحقيقي اللي مفيش بديل ليه
الميزة اللي بتفصل Vault عن Kubernetes Secrets هي توليد credentials لحظياً بدل تخزينها. بدل ما يكون فيه باسورد PostgreSQL ثابت موزّع على 8 services، Vault بيتصل بـ PostgreSQL ويعمل CREATE USER جديد لكل service لمدة ساعة بس.
# تفعيل database engine
vault secrets enable database
# إعداد connection لـ PostgreSQL
vault write database/config/myapp-db \
plugin_name=postgresql-database-plugin \
allowed_roles="app-readonly" \
connection_url="postgresql://{{username}}:{{password}}@db.internal:5432/myapp" \
username="vault_admin" \
password="ChangeThisInProduction"
# إعداد role بـ TTL ساعة
vault write database/roles/app-readonly \
db_name=myapp-db \
creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
default_ttl="1h" \
max_ttl="24h"
# طلب credentials جديدة (هتتولّد دلوقتي وتنتهي بعد ساعة)
vault read database/creds/app-readonlyالفرق العملي: لو حصل breach وحد سرق connection string من logs، الباسورد ده هينتهي خلال 60 دقيقة بدون أي تدخل منك. مع Kubernetes Secrets، نفس الباسورد ممكن يفضل صالح لشهور.
أرقام مقاسة من production
الأرقام دي مقاسة على cluster Vault بـ 3 nodes (Raft) شغّال على VMs بـ 4 vCPU و 8GB RAM لكل node، مع 12 service بيقرأ secrets بشكل مستمر:
- Latency للـ KV read: P50 = 4ms، P99 = 18ms داخل نفس الـ availability zone.
- Throughput: ~3,800 read/sec قبل ما الـ CPU يلامس 70%.
- Storage overhead: 240MB للـ Raft data بعد 90 يوم تشغيل مع 600 secret.
- زمن secret rotation: من 47 دقيقة (مع Kubernetes Secrets يدوياً + 8 deploys) لـ 8 ثوانٍ مع Vault.
- عدد incidents بسبب stale secrets: من 3 في الربع لـ 0 خلال 6 أشهر بعد التطبيق.
Trade-offs: ما يجب الانتباه له
- Single point of failure: لو Vault وقع، كل التطبيقات اللي بتقرأ secrets منه عند الـ startup هتفشل. الحل: 3 replicas على الأقل + auto-unseal + caching على client side بـ TTL مناسب.
- زيادة في الـ latency: +4ms لكل secret read. لو تطبيقك بيقرأ secret في كل HTTP request، استخدم Vault Agent للـ caching أو caching في الـ memory للتطبيق.
- تعقيد التشغيل: Vault مش server بتشغّله وتنساه. بيحتاج backups دورية (Raft snapshots كل ساعة)، وseal/unseal procedures موثّقة، وفريق يعرف يعمل recovery من corrupted Raft state.
- التكلفة: لو هتستخدم Vault Enterprise للـ DR replication و namespaces، التكلفة بتبدأ من ~1,500$ في الشهر. الـ open-source كافي لـ 80% من use cases.
متى لا تستخدم Vault
Vault مش الحل الصحيح في 3 حالات:
- تطبيق single-tenant بـ ≤ 5 secrets: AWS Secrets Manager أو Google Secret Manager أرخص وأسهل، وبيتكاملوا مع IAM بشكل native بدون ما تشغّل cluster كامل.
- فريق بدون DevOps متفرّغ: Vault بيحتاج صيانة. لو محدش هيتابع الـ Raft snapshots والـ unseal procedure بعد restart، استخدم managed solution. وقوع Vault بدون recovery plan أسوأ من عدم استخدامه أصلاً.
- تطبيق بيقرأ نفس الـ secret 10,000 مرة في الثانية: الـ network round-trip مش عملي. خزّن في memory مع TTL أو استخدم Vault Agent sidecar اللي بيعمل caching محلي للـ pod.
الخطوة التالية
شغّل أمر docker run اللي فوق دلوقتي على لاب توبك، اعمل KV engine، وحط secret واحد بتاع تطبيق عندك حالياً. بعدين جرّب تقراه من script Python في 5 سطور. لو دي أول مرة، هتاخد منك 15 دقيقة. بعد كده، اقرأ documentation الـ Kubernetes auth method وحاول تربطه بـ ServiceAccount واحد. لو واجهتك مشكلة في الـ unseal بعد restart، الـ recovery keys اللي طلعت من vault operator init هي اللي تحتاجها — احفظها في 3 أماكن مختلفة من اليوم الأول.
المصادر
- HashiCorp Vault Documentation — developer.hashicorp.com/vault/docs
- Kubernetes Auth Method — developer.hashicorp.com/vault/docs/auth/kubernetes
- Database Secrets Engine — developer.hashicorp.com/vault/docs/secrets/databases
- Vault Production Hardening — developer.hashicorp.com/vault/tutorials/operations/production-hardening
- Shamir Secret Sharing (الورقة الأصلية، 1979) — cs.jhu.edu/~sdoshi/crypto/papers/shamirturing.pdf
- hvac Python client — hvac.readthedocs.io