لقد درست المكونات الفردية: بنية Vault، والأسرار الديناميكية، والمخازن السحابية الأصيلة، وExternal Secrets في Kubernetes، وأتمتة PKI، وكتيبات تشغيل التدوير. يجمع هذا الدرس الأخير كل ذلك في تصميم متماسك شامل — النوع الذي يقدمه مهندس Staff في مراجعة تصميم داخل شركة تأخذ الأمن بجدية. الهدف ليس مثالاً نظرياً. إنه بنية مرجعية بمستوى إنتاجي يمكنك تكييفها مع أي مؤسسة تشغّل خدمات مصغّرة على Kubernetes مع pipeline لـ CI/CD.
ما يعنيه "الشمول" هنا: يولد سر في مكان واحد موثوق، ينتقل بالضبط إلى أحمال العمل التي تحتاجه عبر قنوات مُتحقق منها، يُدار تدويره تلقائياً بدون تدخل بشري، وكل وصول إليه مُسجَّل لتتمكن من الإجابة على "من قرأ هذا، متى، ومن أين؟" — لأي سر، في أي وقت.
المستويات الثلاثة لبنية الأسرار
قبل رسم المربعات والأسهم، حدّد المستويات بوضوح. كل سر يعبر ثلاثة مستويات متمايزة، والخلط بينها مصدر معظم أخطاء التصميم:
مستوى السلطة — حيث تُخزَّن الأسرار ويُدار دورة حياتها. هذا هو HashiCorp Vault (أو AWS Secrets Manager / GCP Secret Manager للأنظمة السحابية الأصيلة). إنه مصدر الحقيقة الوحيد. لا شيء يكتب أسراراً في أي مكان آخر.
مستوى التوزيع — كيف تنتقل الأسرار من السلطة إلى المستهلكين: مكونات Vault Agent الجانبية، External Secrets Operator، تبادل رمز OIDC في CI، أو Secrets Store CSI Driver. مستوى التوزيع بنية تحتية؛ لا يستدعي كود التطبيق Vault مباشرة في نظام مُصمَّم جيداً.
مستوى الاستهلاك — حيث تُستخدَم الأسرار: يقرأ تطبيق ملفاً أو متغير بيئة يُحقنه مستوى التوزيع. التطبيق لا يعلم ولا يهتم بمصدر السر أو كيفية تدويره.
هذا الفصل هو الرؤية المعمارية الأساسية. عندما تكون المستويات نظيفة، يمكنك تبديل آلية التوزيع بدون تغيير أي كود تطبيق، ويمكنك تدوير الأسرار في مستوى السلطة بدون إعادة تشغيل أي تطبيق — يتعامل مستوى التوزيع مع التجديد.
مخطط البنية المرجعية
بنية الأسرار الشاملة: مستويات السلطة والتوزيع والاستهلاك مع طبقتي السياسة والكشف الأفقيتين.
توصيل الـ CI Pipeline: لا بيانات اعتماد طويلة الأمد
الـ CI pipeline هو المصدر الأكثر شيوعاً لانتشار الأسرار في المؤسسات التي لم تستثمر بعد في إدارة الأسرار. الحالة المستهدفة هي: صفر بيانات اعتماد طويلة الأمد في CI. كل سر يحتاجه الـ pipeline يُجلب في وقت التشغيل لمدة ذلك المهمة المحددة، باستخدام رمز قصير الأمد يثبت هوية المهمة عبر OIDC. إليك النمط الكامل لـ GitHub Actions لجلب الأسرار من Vault ومن AWS Secrets Manager:
# .github/workflows/deploy.yml
# الهدف: صفر أسرار ثابتة في إعدادات مستودع GitHub.
# CI يصادق على Vault عبر OIDC JWT، Vault يعيد بيانات اعتماد AWS قصيرة الأمد.
name: Deploy
on:
push:
branches: [main]
permissions:
id-token: write # مطلوب: يسمح لـ GitHub بسك رمز OIDC لهذه المهمة
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
env:
VAULT_ADDR: https://vault.internal.example.com
steps:
- uses: actions/checkout@v4
# الخطوة 1 — تبادل رمز OIDC الخاص بـ GitHub برمز Vault
- name: Authenticate to Vault via OIDC
id: vault-auth
uses: hashicorp/vault-action@v3
with:
url: ${{ env.VAULT_ADDR }}
method: jwt
role: github-deploy # دور Vault مرتبط بهذا المستودع والفرع
secrets: |
secret/data/ci/docker registry_user | DOCKER_USER ;
secret/data/ci/docker registry_pass | DOCKER_PASS ;
aws/creds/deploy-role access_key | AWS_ACCESS_KEY_ID ;
aws/creds/deploy-role secret_key | AWS_SECRET_ACCESS_KEY
# بيانات اعتماد AWS الآن في البيئة، محدودة بهذه المهمة، TTL = 15 دقيقة (عقد Vault)
- name: Deploy to ECS
run: |
aws ecs update-service \
--cluster prod \
--service api \
--force-new-deployment \
--region us-east-1
# تكوين دور Vault المقابل (Terraform):
# resource "vault_jwt_auth_backend_role" "github_deploy" {
# backend = vault_jwt_auth_backend.github.path
# role_name = "github-deploy"
# role_type = "jwt"
# bound_claims = {
# repository = "myorg/myrepo"
# ref = "refs/heads/main"
# }
# user_claim = "actor"
# token_policies = ["ci-deploy-policy"]
# token_ttl = 900 # 15 دقيقة — تنتهي عند انتهاء المهمة
# }
ثبّت vault-action على SHA كامل بدلاً من علامة. العلامات قابلة للتغيير — يمكن لمشرف إجراء مخترق تغيير ما تشير إليه @v3 بعد مراجعتها. استخدم hashicorp/vault-action@<40-char-SHA>. طبّق نفس القاعدة على كل إجراء خارجي تستخدمه. شغّل pinact run أو ميزة "pin actions" في Dependabot لتطبيق هذا تلقائياً على جميع سير العمل.
نمطان قياسيان في بيئات Kubernetes الإنتاجية، وهما متكاملان — لا متنافسان. استخدم External Secrets Operator (ESO) للأسرار التي تحتاج للعيش كـ Kubernetes Secrets أصيلة (لأن مخطط Helm أو مشغّل يقرأها من API الكلاستر). استخدم Secrets Store CSI Driver للأسرار التي يجب ألا تلمس etcd أبداً — بيانات الاعتماد عالية القيمة حيث تحتاج ضمان وجود السر فقط في تركيب tmpfs داخل الـ pod، يختفي عند إنهاء الـ pod.
يجب إدارة تكوين Vault نفسه — المحركات والسياسات وأساليب المصادقة والأدوار — كبرمجيات في Git، يُطبَّق عبر CI، ويُراجَع في pull requests. المهندسون الذين ينقرون في واجهة Vault لتكوين السياسات يُدخلون نفس مشكلة الانجراف التي تخلقها البنية التحتية غير المُعالَجة بـ Terraform. كل سياسة Vault هي حد أمني؛ يجب مراجعتها من نظير قبل تغييرها في الإنتاج.
# terraform/vault/main.tf — إدارة تكوين Vault كبرمجيات
terraform {
required_providers {
vault = { source = "hashicorp/vault", version = "~> 4.0" }
}
}
provider "vault" {
address = var.vault_addr
# المصادقة عبر AppRole من CI، لا رمز root
}
# تفعيل محرك أسرار KV v2
resource "vault_mount" "kv" {
path = "secret"
type = "kv-options"
options = { version = "2" }
}
# تفعيل أسلوب مصادقة Kubernetes
resource "vault_auth_backend" "kubernetes" {
type = "kubernetes"
}
resource "vault_kubernetes_auth_backend_config" "main" {
backend = vault_auth_backend.kubernetes.path
kubernetes_host = "https://k8s-api.internal.example.com"
kubernetes_ca_cert = data.kubernetes_secret.vault_sa_token.data["ca.crt"]
}
# دور: pods الـ api-service في namespace 'production' تقرأ بيانات اعتماد DB
resource "vault_kubernetes_auth_backend_role" "api_service" {
backend = vault_auth_backend.kubernetes.path
role_name = "api-service"
bound_service_account_names = ["api-service-sa"]
bound_service_account_namespaces = ["production"]
token_policies = ["api-service-policy"]
token_ttl = 3600 # ساعة واحدة
}
# سياسة: أقل الصلاحيات — api-service تقرأ فقط مساراتها الخاصة
resource "vault_policy" "api_service" {
name = "api-service-policy"
policy = <<EOT
path "secret/data/production/db" {
capabilities = ["read"]
}
path "secret/data/production/cache" {
capabilities = ["read"]
}
path "pki/issue/api-service" {
capabilities = ["create", "update"]
}
EOT
}
لا تستخدم رمز root أبداً خارج الإعداد الأولي. رمز Vault root لديه وصول غير مقيد لكل سر وكل سياسة. بعد تكوين الكلاستر الأولي، ألغِه فوراً. جميع العمليات الجارية — بما فيها تطبيقات Terraform عبر CI — يجب أن تستخدم AppRole محدود النطاق أو رمز OIDC. إذا احتجت يوماً إلى وصول root للطوارئ، استخدم vault operator generate-root مع نصاب من حاملي مفاتيح الفك. عامل هذه العملية كإجراء نووي: تتطلب شخصين، مُسجَّلة، وتُلغى فوراً بعد الاستخدام.
طبقة الكشف والاستجابة
بنية الأسرار بدون كشف غير مكتملة. سجل تدقيق Vault هو أهم مصدر أمني لديك: كل قراءة وكتابة وفشل مصادقة وحرمان من سياسة يصل إليه. أعِد توجيهه إلى SIEM الخاص بك من اليوم الأول وابنِ تنبيهات على هذه الإشارات:
فشل مصادقة أكثر من 5 في 60 ثانية من IP واحد أو دور — قوة غاشمة أو تكوين خاطئ.
قراءة سر خارج ساعات العمل لمسارات الإنتاج — بيانات اعتماد بشرية مستخدمة بعملية آلية، أو تسرب بيانات اعتماد.
استخدام رمز root — دائماً تنبيه، بلا استثناءات. إما طارئ مشروع (يجب إعلامه مسبقاً) أو حادثة أمنية.
فشل التدوير — انتهت صلاحية عقد Vault لكن لم يُجدَّد. التطبيق على وشك الفشل بخطأ مصادقة.
انتهاء صلاحية شهادة خلال 7 أيام — فشلت أتمتة تجديد cert-manager أو Vault PKI بصمت؛ هذا آخر تحذير مرئي بشرياً.
تحليل ما بعد حادثة Twitch عام 2021: فقدت Twitch 125 غيغابايت من كود المصدر وبيانات الاعتماد الداخلية. سجلات تدقيق Vault كانت موجودة؛ لم تُكوَّن تنبيهات على القراءات الضخمة من IP شاذ. كان التسرب قابلاً للاكتشاف في الوقت الفعلي — لم يُكشَف حتى ظهرت البيانات على 4chan. تنبيه SIEM مُكوَّن بشكل صحيح على "حجم غير عادي من قراءات Vault من IP غير خدمي" كان سيُطلَق في غضون دقائق من بداية التسرب.
قائمة مراجعة قرارات التصميم
قبل الموافقة على أي تصميم لبنية الأسرار، تحقق من كل بند في هذه القائمة. كل منها نمط فشل إنتاجي رأيت مساره الكامل:
مصدر حقيقة واحد: مخزن واحد موثوق بالضبط لكل بيئة (كلاستر Vault أو SM السحابي). لا أسرار يُحتفظ بها في مكانين.
لا أسرار ثابتة في CI: كل سر CI يُجلب في وقت تشغيل المهمة عبر OIDC. أسرار المستودع لا تحتوي على أي بيانات اعتماد.
بيانات اعتماد ديناميكية لقواعد البيانات: لا تطبيق لديه كلمة مرور دائمة لقاعدة بيانات. محرك DB في Vault يولد بيانات الاعتماد لكل خدمة مع TTL ويدورها تلقائياً.
تشفير K8s Secrets أثناء الراحة: etcd مُشفَّر بمزود KMS. أسرار ESO المزامَنة لها RBAC مناسب لكي لا يقرأها إلا حساب الخدمة المستهدف.
جميع شهادات TLS من أتمتة PKI: cert-manager أو Vault Agent يُصدر ويجدد جميع الشهادات الداخلية. لا شهادة يدوية الإصدار أو التجديد في الكلاستر.
تكوين Vault في Git: كل سياسة Vault ودور وتركيب محرك مُعالَج بـ Terraform وخضع لمراجعة نظير. لا نقر في واجهة Vault للإنتاج.
Auto-unseal مُكوَّن: يستخدم Vault AWS KMS أو GCP Cloud KMS للفك التلقائي حتى لا يتطلب إعادة تشغيل العقدة تدخلاً يدوياً الساعة 3 صباحاً.
سجل التدقيق مُعاد توجيهه إلى SIEM: جميع أحداث تدقيق Vault مُعادة توجيهها مع تنبيهات مُعرَّفة للإشارات الخمس أعلاه.
كتيب التدوير مُختبَر: كتيب التدوير اليدوي للطوارئ (الدرس 9) نُفِّذ في بيئة مرحلية خلال آخر 90 يوماً.
نطاق الضرر موثَّق: لكل سر، يستطيع الفريق الإجابة: من يمكنه قراءته، ماذا يتعطل إذا دوّرته الآن، وكم يستغرق انتشار التدوير الكامل؟
هذه البنية ليست مثالاً نظرياً. إنها المعيار التشغيلي في الشركات التي تأخذ الأسرار بجدية — Google وNetflix وHashiCorp وStripe تشغّل كل منها ما يعادل هذا. المكونات الفردية كلها موثَّقة ومفتوحة المصدر. المميِّز هو الانضباط للحفاظ على نظافة المستويات الثلاثة، وإدارة التكوين كبرمجيات، ومعاملة كل انحراف عن أقل الصلاحيات كمشكلة P1 لا كتعليق TODO.
نستخدم ملفات تعريف الارتباط لتشغيل هذا الموقع وتحليل الزيارات وعرض إعلانات مخصّصة. يمكنك قبول كل ملفات تعريف الارتباط أو رفض غير الأساسية منها.
سياسة الخصوصية