We are still cooking the magic in the way!
التوقيع والتحقق
التوقيع والتحقق
تستغل كل هجمات سلسلة التوريد الحديثة نفس ثغرة الثقة: المستهلك — سواء كان كلاسترًا في Kubernetes أو عداء CI أو محطة عمل مطور — يجلب artifact لا يستطيع إثبات أنها قادمت من المصدر الذي تدّعيه. ربما جرى استبدالها أثناء النقل أو على مستوى السجل أو داخل منظومة البناء ذاتها. يُغلق توقيع الـ Artifacts هذه الثغرة بربط توقيع تشفيري بالـ artifact وقت البناء والتحقق من هذا التوقيع قبل أي استهلاك. يغطي هذا الدرس أحدث الأدوات مفتوحة المصدر — Sigstore / Cosign — وكيفية تطبيق التحقق على طبقة الـ Admission في Kubernetes حتى لا تعمل أي صور غير موقّعة أو غير قابلة للتحقق في بيئة الإنتاج.
لماذا تفشل إدارة المفاتيح التقليدية على نطاق واسع
قبل Sigstore، كان توقيع الـ artifacts يعني إدارة مفاتيح GPG أو OpenSSL طويلة الأمد. على النطاق الكبير للشركات التقنية الكبرى، يُفرز هذا ثلاث مشكلات متراكمة. أولاً، توزيع المفاتيح: يجب أن يتلقى كل مستهلك المفتاح العام ويثق به عبر قناة خارجية — وهو إشكال لا حل نظيف له. ثانياً، تدوير المفاتيح: يُبطل المفتاح المُخترَق جميع التوقيعات السابقة، لكن إلغاء المفاتيح وإعادة توزيعها عبر مئات الفرق مُجهِد تشغيلياً. ثالثاً، الإسناد غير واضح: يُثبت التوقيع امتلاك المفتاح الخاص، لا هوية الإنسان أو مهمة CI التي شغّلت البناء فعلاً. إذا تسرّب المفتاح، لا توجد طريقة للتمييز بين التوقيعات الشرعية والخبيثة.
معمارية Sigstore: Fulcio وRekor وCosign
توقيع صورة الحاوية باستخدام Cosign (الوضع بلا مفاتيح)
في GitHub Actions، يعمل الـ workflow برمز OIDC افتراضياً. تكتشف Cosign ذلك وتُنفّذ دورة Fulcio/Rekor بشكل شفاف. لا تحتاج إلى أي إدارة للمفاتيح:
يتجاوز الخيار --yes موجه التأكيد التفاعلي، وهو مطلوب في بيئة CI. يُفعّل COSIGN_EXPERIMENTAL=1 الوضع بلا مفاتيح (وهو الآن الافتراضي في Cosign v2، لكنه لا يزال شائعاً في الأنابيب القديمة). بعد هذه الخطوة، يُخزَّن التوقيع كـ artifact OCI منفصل في نفس نطاق السجل — تستخدم Cosign الاصطلاح sha256-<digest>.sig.
للتحقق من التوقيع محلياً أو في سكريبت:
--certificate-identity-regexp بمسار ملف workflow محدد (مثل .github/workflows/release.yml) لا بحرف بدل. سيقبل التعبير العام مثل .* التوقيعات من أي workflow في المستودع، بما فيها workflows طلبات السحب التي تُشغّل كوداً غير موثوق. قفل مُصدر OIDC بالغ الأهمية أيضاً — دوماً حدّد --certificate-oidc-issuer صراحةً.تطبيق التوقيعات في وحدة تحكم Admission في Kubernetes
التوقيع بدون تحقق إلزامي على حدود الكلاستر مجرد مسرحية أمنية. طبقة التطبيق هي admission webhook في Kubernetes يعترض كل طلب إنشاء/تحديث Pod ويرفضه إذا كانت الصورة تفتقر إلى توقيع Cosign صالح. خياران ناضجان على نطاق الشركات الكبرى:
- Policy Controller (من Sigstore) — admission webhook مستقل يقرأ موارد
ClusterImagePolicy. المسار الموصى به للإعدادات الخالصة من Sigstore. - Kyverno — محرك سياسات Kubernetes عام مع تحقق Cosign مدمج؛ يُفضَّل عند استخدام Kyverno مسبقاً لسياسات أخرى.
المثال التالي يستخدم Policy Controller من Sigstore:
بتطبيق هذه السياسة على prod-namespace، يُرفض أي Pod يشير إلى صورة من ghcr.io/my-org/** لا تحمل توقيعاً صالحاً من workflow CI المحدد بخطأ 403 Forbidden قبل بدء أي عملية حاوية. لا تتأثر namespaces غير المُصنَّفة للتطبيق — نمط شائع هو التطبيق في prod أولاً ثم التوسع إلى بيئة التدريج.
:latest أو :1.2.3) غير كافٍ لأن التاغات قابلة للتغيير. يمكن للمهاجم القادر على الدفع إلى السجل نقل التاغ إلى صورة غير موقّعة. وقّع وتحقق دوماً بالـ digest (sha256:...). في Kubernetes، اضبط أداة CD الخاصة بك (ArgoCD أو Flux) لحل وتثبيت الـ digest قبل أن تراه وحدة تحكم الـ Admission في مواصفة الـ pod. تُوقّع Cosign على digest المانيفست؛ تتحقق Policy Controller من الـ digest — ما دمت لا تستخدم تاغات قابلة للتغيير من طرف إلى طرف، أنت محمي.التحقق من الـ Attestations: ما وراء التوقيع
يمكن لـ Cosign أيضاً إرفاق والتحقق من attestations منظمة — بيانات وصفية موقّعة عن الصورة مثل وثائق SBOM وسجلات استمرارية SLSA ونتائج فحص الثغرات. هكذا تُثبت الشركات الكبرى ليس فقط "هذه الصورة موقّعة" بل "هذه الصورة بُنيت من الـ commit X، اجتازت SAST بدون ثغرات حرجة، وSBOM الخاص بها مُرفق." يتعامل الأمر cosign attest والأمر cosign verify-attestation مع هذا الـ workflow باستخدام تنسيق in-toto attestation:
authorities في ClusterImagePolicy قسم attestations يشترط predicate استمرارية SLSA صالح أو نتيجة فحص Trivy بدون ثغرات حرجة أو أي predicate مخصص. يحوّل هذا وحدة تحكم الـ Admission إلى بوابة سلسلة توريد كاملة لا مجرد خانة اختيار توقيع.أوضاع الفشل والاعتبارات التشغيلية
يُضيف التحقق من التوقيع زمن استجابة لجدولة الـ pod (يجب أن يصل الـ admission webhook إلى السجل واختيارياً إلى Rekor). على نطاق Google يكون هذا عادةً 50–200 ميلي ثانية لكل digest صورة فريد، مع تخزين مؤقت مكثف من جانب Policy Controller. ثلاثة اعتبارات تشغيلية يجب التخطيط لها:
- توافر الـ Webhook: إذا كان pod Policy Controller معطلاً، ستفشل الـ pods في الجدولة (سلوك الإغلاق عند الفشل). انشره بنسختين على الأقل وPodDisruptionBudget وتقارب نود يبقيه على نودات control-plane أو نودات نظام مخصصة.
- بيئة معزولة عن الشبكة: في البيئات المعزولة، يكون Rekor وFulcio غير متاحَين. إما تشغيل stacks Sigstore مستضافة ذاتياً (sigstore-the-hard-way أو Helm chart sigstore/scaffolding)، أو استخدام التوقيع المستند إلى مفاتيح مع Hardware Security Module (HSM) بدلاً من الوضع بلا مفاتيح.
- استثناء التمهيد: يجب استثناء صورة Policy Controller ذاتها من سياستها الخاصة لتجنب التبعية الدائرية أثناء تمهيد الكلاستر. أضف دوماً استثناء namespace أو صورة صريحاً لـ
cosign-system.