Jenkins والتكامل المستمر المؤسسي

بيانات الاعتماد والأسرار في Jenkins

18 دقيقة الدرس 7 من 28

بيانات الاعتماد والأسرار في Jenkins

تُعدّ الأسرار أخطر أنواع البيانات في أي منظومة CI/CD. تسريب بيانات اعتماد في سجل بناء، أو مفتاح API مُضمَّن في Jenkinsfile، أو رمز وصول واسع النطاق مشترك بين جميع خطوط الأنابيب — كلها أسباب أفضت إلى اختراقات حقيقية في شركات من مختلف الأحجام. يأتي Jenkins مزوَّدًا بنظام بيانات اعتماد ناضج، غير أن استخدامه بأمان على نطاق المؤسسات يستلزم فهم آلية عمله وأماكن التخزين والأنماط التي تفضي إلى تسريب صامت للبيانات.

مخزن بيانات الاعتماد

يخزِّن Jenkins بيانات الاعتماد في مخزن مشفَّر من نوع مفتاح/قيمة مدعوم بالمكوِّن الإضافي Credentials Plugin (مدمج منذ Jenkins LTS 2.x). يقع مفتاح التشفير الرئيسي في $JENKINS_HOME/secrets/master.key، وتُخزَّن النصوص المشفَّرة لكل بيانات اعتماد في ملفات XML ضمن $JENKINS_HOME/credentials.xml (نطاق عام) أو داخل $JENKINS_HOME/jobs/<name>/config.xml (نطاق مجلد/عنصر).

يعتمد التشفير على طبقتين: يُستخدم المفتاح الرئيسي لاشتقاق مفتاح AES-128 خاص بكل بيانات اعتماد عبر ملف بذرة سري. هذا يعني أن نسخ Jenkins احتياطيًا دون دليل secrets/ يجعل بيانات الاعتماد غير قابلة للاسترداد — وفي المقابل، نسخ credentials.xml وحده دون المفتاح الرئيسي آمنٌ لأن المحتوى مشفَّر.

Jenkins Credential Scoping Hierarchy System Scope (Jenkins Controller) Global Credentials Store (credentials.xml) Folder Scope Pipeline A Pipeline B Folder-scoped creds (jobs only) Item / Job Scope Visible only inside that single pipeline Narrowest blast radius. Prefer for high-value secrets.
هرمية النطاق في Jenkins: النظام ← العام ← المجلد ← العنصر. النطاق الأضيق يعني نطاق تأثير أصغر عند الاختراق.

أنواع بيانات الاعتماد

يشحن Credentials Plugin بأنواع مدمجة متعددة، وتضيف المكوِّنات الإضافية للمؤسسات أنواعًا أخرى:

  • اسم مستخدم مع كلمة مرور — الأكثر شيوعًا؛ يُربط بـ usernameVariable وpasswordVariable.
  • نص سري — سلسلة نصية معتمة واحدة (رموز API، مفاتيح التوقيع).
  • SSH مع مفتاح خاص — يُدخَل المفتاح مباشرةً أو يُحمَّل من مسار ملف على العامل؛ تُخزَّن عبارة المرور منفصلةً.
  • شهادة (PKCS#12) — TLS المتبادل وتوقيع الكود. يُربط عبر KEYSTORE_FILE وKEYSTORE_PASSWORD.
  • ملف سري — بيانات ثنائية اعتباطية (kubeconfig، مفتاح GCP بصيغة JSON). تتجسَّد كملف مؤقت في مساحة عمل العامل ويحذفه Jenkins بعد اكتمال الخطوة.
  • Vault: AppRole / AWS IAM / GCP Workload Identity — توفِّرها مكوِّنات HashiCorp Vault Plugin وAWS Credentials Plugin وغيرها. لا يُخزَّن أي سرٌّ ثابت في Jenkins.

استخدام بيانات الاعتماد في خط أنابيب تصريحي

الطريقة الصحيحة لكشف بيانات الاعتماد داخل خطوة خط أنابيب هي استخدام كتلة withCredentials. يعمل Jenkins تلقائيًا على إخفاء أي متغير مرتبط بهذه الطريقة: إذا ظهرت القيمة الخام في أي سطر سجل، تُستبدَل بـ ****.

// Declarative Pipeline — ربط أنواع متعددة من بيانات الاعتماد pipeline { agent any environment { // اختصار: يربط DOCKER_HUB_CREDS_USR + DOCKER_HUB_CREDS_PSW DOCKER_HUB_CREDS = credentials('dockerhub-prod') } stages { stage('Push Image') { steps { // ربط صريح — مفضَّل لأنواع غير usernamePassword withCredentials([ usernamePassword(credentialsId: 'dockerhub-prod', usernameVariable: 'DHUB_USER', passwordVariable: 'DHUB_PASS'), string(credentialsId: 'snyk-token', variable: 'SNYK_TOKEN'), sshUserPrivateKey(credentialsId: 'deploy-key', keyFileVariable: 'SSH_KEY') ]) { sh ''' echo "$DHUB_PASS" | docker login -u "$DHUB_USER" --password-stdin docker push "$DHUB_USER/myapp:${BUILD_NUMBER}" snyk container test "$DHUB_USER/myapp:${BUILD_NUMBER}" \ --token="$SNYK_TOKEN" ssh -i "$SSH_KEY" deploy@prod.internal \ "docker pull $DHUB_USER/myapp:${BUILD_NUMBER} && systemctl restart app" ''' } } } } }
تسريب عبر echo: لا تُشغِّل أبدًا echo $SECRET أو sh 'printenv' داخل كتلة withCredentials. يُخفي Jenkins التطابقات الحرفية فقط، لكن أشكال base64 أو URL-encode للسر لا تُخفى. أي تحويل للقيمة الخام قد يُسرِّبها في السجلات دون تنبيه.

نطاقات بيانات الاعتماد عمليًا

يدعم Jenkins ثلاثة نطاقات جوهرية:

  • System — متاح لعمليات Jenkins الداخلية فقط (اتصالات العقد، خادم البريد). لا يمكن استخدامه داخل خطوات خط الأنابيب. مخصَّص لبيانات اعتماد البنية التحتية.
  • Global (نطاق: Jenkins) — مرئي لجميع المهام على المتحكم. استخدمه فقط لبيانات الاعتماد المشتركة منخفضة القيمة (مثل حساب قراءة فقط على Nexus).
  • Folder / Item — الموصى به لأي شيء حساس. بيانات الاعتماد في /team-payments/ غير مرئية للمهام في /team-platform/. هذه هي الضبطة الأساسية لنطاق التأثير في بيئة Jenkins متعددة الفرق.
التحكم في الوصول القائم على الأدوار (RBAC): النطاق وحده لا يكفي. ثبِّت Role Strategy Plugin وامنح صلاحية Credentials/View فقط لدور مالك خط الأنابيب. بدون RBAC، يستطيع أي مستخدم يمكنه تهيئة مهمة كتابة خط أنابيب من سطر واحد يطبع كل بيانات الاعتماد ضمن النطاق في سجل البناء.

التكامل مع الخزائن الخارجية

على نطاق واسع، يُعدّ تخزين الأسرار داخل Jenkins نمطًا مضادًا. النهج المقبول في المؤسسات هو التعامل مع Jenkins بوصفه مستهلِكًا لا مخزنًا. تعيش الأسرار في HashiCorp Vault أو AWS Secrets Manager أو Azure Key Vault؛ يسترجعها Jenkins في وقت التشغيل باستخدام رموز قصيرة العمر:

// HashiCorp Vault Plugin — ربط Vault AppRole // بيانات اعتماد Jenkins: 'vault-approle' (نوع Vault AppRole) pipeline { agent any stages { stage('Deploy') { steps { withVault( configuration: [ vaultUrl: 'https://vault.internal:8200', vaultCredentialId: 'vault-approle', engineVersion: 2 ], vaultSecrets: [ [path: 'secret/data/payments/stripe', secretValues: [ [envVar: 'STRIPE_KEY', vaultKey: 'api_key'], [envVar: 'STRIPE_WEBHOOK', vaultKey: 'webhook_secret'] ] ] ] ) { sh 'node deploy-payment-service.js' } // تختفي STRIPE_KEY و STRIPE_WEBHOOK هنا } } } }

بهذا النمط، لا تُحفظ الأسرار أبدًا في Jenkins: لا XML على القرص، لا صف في قاعدة البيانات، لا config.xml. تُطبِّق Vault سياسات TTL وتسجيل التدقيق والتدوير التلقائي باستقلالية تامة عن Jenkins.

سلوك الإخفاء وحدوده

يعترض إخفاء Jenkins كل عملية println / كتابة سجل ويُجري استبدالًا حرفيًا. افهم حدوده في بيئة الإنتاج:

  • الإخفاء يعمل بالقيمة لا بالتسلسل البايتي. سرٌّ مكوَّن من 3 أحرف (abc) يتطابق تافهيًا مع ضجيج السجل — تجنَّب الأسرار القصيرة.
  • الأسرار متعددة الأسطر (مفاتيح PEM) تُخفى سطرًا بسطر فقط إذا كان Mask Passwords Plugin نشطًا. الإخفاء المدمج يغطي السلسلة المرتبطة حرفيًا فقط.
  • تقارير الاختبارات المُؤرشَفة وملفات JUnit XML وHTML لـ Jacoco وغيرها من القطع الأثرية لا تُخفى أبدًا. يمكن أن يحتوي تتبُّع المكدس على سر مُمرَّر كوسيطة.
  • مخرجات وحدة التحكم للعامل المُوجَّهة إلى منظِّمات السجلات الخارجية (Splunk, ELK) تمرّ عبر إخفاء Jenkins قبل الإرسال — لكن فقط إذا كان Pipeline Logging Plugin أو ما يعادله نشطًا في المسار.
سجِّل تدقيقًا لكل استخدام لبيانات الاعتماد. فعِّل Audit Trail Plugin وهيِّئه للكتابة في حاوية S3 للكتابة مرة واحدة أو نظام SIEM. تحتاج إلى سجل ثابت يوثِّق أي خط أنابيب استخدم أي معرِّف بيانات اعتماد ومتى — ضروري للتحقيق في الاختراقات والامتثال لـ SOC 2 / ISO 27001.

تدوير بيانات الاعتماد دون توقف

أأمن استراتيجية للتدوير هي: إنشاء بيانات الاعتماد الجديدة بـمعرِّف جديد، وتحديث جميع مراجع خط الأنابيب في التحكم بالمصدر (تمرّ تغييرات Jenkinsfile عبر مراجعة طلب السحب)، ونشر خطوط الأنابيب المحدَّثة، ثم حذف بيانات الاعتماد القديمة. لا تُلغي بيانات الاعتماد في موضعها خلال تشغيل خط أنابيب نشط — تحتفظ عمليات البناء الجارية بمرجع لمعرِّف بيانات الاعتماد وستقرأ القيمة مجددًا؛ إذا كانت القيمة القديمة غير صالحة الآن، تفشل تلك عمليات البناء في منتصف التنفيذ بطريقة غير حتمية.

قائمة التحقق من مبدأ الحد الأدنى من الصلاحيات

  1. استخدم بيانات اعتماد ذات نطاق مجلد لكل حد فريق أو مشروع.
  2. امنح خطوط الأنابيب أضيق نطاق رمز ممكن (رمز نشر للقراءة فقط بدلًا من رمز مدير المستودع).
  3. فضِّل الأسرار الديناميكية قصيرة العمر من Vault أو IAM السحابي على الرموز الثابتة طويلة العمر.
  4. لا تطبع ولا تسجِّل الأسرار أبدًا، حتى في كتل catch.
  5. دوِّر جميع بيانات الاعتماد عند إنهاء عضوية أي مهندس أو عند الاشتباه في اختراق.
  6. انسخ $JENKINS_HOME/secrets/ احتياطيًا بشكل منفصل، مشفَّرًا، مع تدقيق الوصول.