المجتمع Active Directory

اختبار Workload Identity Federation في Entra: كيف تتحول ثقة CI/CD إلى صلاحية سحابية، وش تراجع في OIDC؟

فريق التطوير يقول لك: «ارتاح، ما عندنا Client Secret في GitHub، الدخول على Azure كله OIDC». هذي خطوة جيدة، لكنها ما تجيب عن السؤال الأمني كاملًا. من يقدر يشغّل المهمة التي تثق بها السحابة؟ وأي مستودع وبيئة وفرع يمثلها الرمز؟ وبعد ما تقبل Entra الهوية، وش الموارد التي تقدر المهمة تقرأها أو تغيرها؟

في اختبار Workload Identity Federation أنت تراجع انتقال الثقة من منصة بناء إلى هوية سحابية. الموضوع مب بحثًا عن كلمة مرور مخفية؛ هو قراءة شروط قبول الهوية وربطها بصلاحيات حقيقية. خلنا نفكك المسار بمثال مشروع يملك بيئتي تطوير وإنتاج، ونبني اختبارًا مصرحًا يعتمد على قراءة الإعدادات ومهام تجريبية محدودة.

وش تغير لما شلنا Client Secret؟

في المصادقة التقليدية يحتفظ نظام البناء بسر أو شهادة تخص تطبيقًا في Entra. إذا امتلك شخص السر، قد يستطيع استخدام الهوية إلى أن تنتهي صلاحية السر أو يسحب. الاتحاد يغير طريقة إثبات الهوية: منصة خارجية تصدر رمزًا موقّعًا يصف المهمة، وتقبل Entra هذا الرمز إذا طابق علاقة ثقة مسجلة، ثم تصدر رمز وصول للهوية السحابية.

الفرق مهم؛ ما عاد فيه سر طويل العمر يحتاج الفريق نسخه بين المتغيرات. لكن صلاحيات التطبيق أو Managed Identity تبقى موجودة. إذا كانت هوية النشر تملك دورًا واسعًا على الاشتراك، قبول مهمة غير مقصودة ما زال يعطي أثرًا واسعًا. مدة رمز قصيرة لا تصلح قاعدة ثقة تسمح للجهة الخطأ بالحصول على رمز جديد كل مرة.

افصل في ورقة العمل بين ثلاثة أشياء: الجهة الخارجية التي تثبت سياق المهمة، علاقة الاتحاد التي تقبل هذا الإثبات، وتفويض الهوية داخل المورد. هذا الفصل يمنع تقريرًا يقول «OIDC آمن» لمجرد غياب السر، ويمنع العكس أيضًا: وجود صلاحية إنتاجية مقصودة لهوية نشر معزولة مب ثغرة وحده. الحكم يعتمد على من يستطيع تشغيلها وبأي شروط.

اقرأ issuer وsubject وaudience قبل أسماء الأدوار

في علاقة الاتحاد التقليدية تكون المطابقة على issuer وsubject وaudience. فكر فيها كأسئلة: من أصدر الإثبات؟ أي مهمة أو سياق يمثل؟ ولأي جهة صدر؟ توضح Microsoft أن مطابقة هذه القيم حساسة لحالة الأحرف؛ اختلاف صغير قد يفسر رفضًا يبدو لك غريبًا، بدل أن يكون خللًا في Azure RBAC.

الـ issuer عنوان جهة الإصدار، وليس عنوان التطبيق الذي ستنشر إليه. والـ subject وصف للسياق الذي تسمح به، وليس اسم المستخدم الذي ضغط زر التشغيل بالضرورة. أما audience في رمز الإثبات الخارجي فتخص الجهة المقصودة باستبداله؛ لا تخلطها مع audience في رمز الوصول النهائي الموجه إلى خدمة سحابية. أنت تقرأ رمزين في مرحلتين مختلفتين.

اطلب نسخة من الإعدادات عبر مالك المشروع، واقرأ claims لرمز تجريبي محليًا داخل المختبر. لا تنسخ الرموز إلى مواقع فك JWT العامة؛ ظهور الحمولة بشكل مقروء لا يلغي حساسية الرمز. يكفي في الدليل الاحتفاظ بالحقول المتعلقة بالمطابقة مع إخفاء الرمز نفسه. سجّل القيمة المتوقعة والقيمة الفعلية ومرحلة الرفض، بدل رفع ملف سجلات كامل فيه بيانات اعتماد.

subject في GitHub يتغير حسب سياق المهمة

من الأخطاء الشائعة افتراض أن اسم الفرع يشرح كل شيء. في GitHub قد يعتمد subject الافتراضي على Environment مرتبطة بالمهمة، أو على سياق Pull Request، أو على الفرع عند غياب تلك السياقات. إذا ربطت المهمة ببيئة إنتاج، لازم تقرأ subject الذي صدر فعلًا؛ لا تبني الاختبار على سلسلة تتوقعها من اسم المستودع.

وهنا معلومة مرتبطة بالوقت: وثائق GitHub الحالية تذكر أن المستودعات الجديدة بعد 15 يوليو 2026 تستخدم صيغة subject تضم معرّفات ثابتة للمالك والمستودع. المستودعات السابقة لها قواعد انتقال مختلفة، كما تؤثر بعض عمليات النقل أو إعادة التسمية. هذا الوصف لا يشمل GitHub Enterprise Server بنفس الصورة. لذلك نسخ مثال قديم من مدونة يمكن يسبب فشلًا في الاختبار أو ثقة مبنية على أسماء قابلة للتغير.

في مختبرك اكتب السياق بجانب كل نتيجة: منصة الاستضافة، عمر المستودع، هل توجد بيئة، وهل التشغيل من فرع أو طلب دمج. اسأل عن تخصيص claims أيضًا. وجود repository_id في الحمولة مفيد للمراجعة، لكن وجود claim لا يعني أن علاقة الاتحاد التقليدية تفحصه تلقائيًا؛ لازم تعرف القاعدة التي يستخدمها الطرف الذي يقبل الإثبات.

الشروط المرنة مفيدة، بس لا توسعها وأنت تصلح مشكلة دخول

تدعم Entra كذلك Flexible Federated Identity Credentials، وهي موصوفة حاليًا كميزة Preview في الوثائق المشار إليها. هنا قد تستخدم claimsMatchingExpression بدل subject ثابت، وفق لغة تعبير محددة ودعم يختلف بحسب جهة الإصدار. لا تتعامل مع الاسم كأنه محرك قواعد عام يفهم أي شرط تكتبه.

في المراجعة اقرأ التعبير حرفيًا ثم ترجمه إلى جملة عربية: «نقبل مهام هذه الجهة، من هذا المستودع، ضمن هذا السياق». إذا احتجت أكثر من جملة لتشرح الاستثناءات، غالبًا تحتاج حالات اختبار منفصلة. توضح الوثائق أن subject والتعبير المرن بديلان في الاعتماد نفسه؛ جمعهما في تصورك يعطي نتيجة غير دقيقة عن شروط القبول.

خلنا نفترض أن الفريق وسّع شرطًا لحل تعطل نشر التطوير، فصار يقبل سياقات أكثر مما كان مقصودًا. النتيجة ليست أن التعبيرات المرنة ضعيفة بطبيعتها؛ المشكلة أن إصلاح التوافق غيّر حد الثقة. قارن القاعدة السابقة والجديدة مع هوية المورد المرتبطة بهما، واطلب إثباتًا أن مهمة الإنتاج المقصودة تنجح وأن مهمة المختبر غير المطابقة تُرفض. لا تكتفِ بعبارة «النشر رجع يشتغل».

من يقدر يغير workflow؟ هذا جزء من صلاحية السحابة

النقطة المهمة أن التحكم في YAML أو ملف بناء قد يصبح تحكمًا في العمل الذي ينفذ بهوية النشر. لذلك تراجع حماية الفروع، صلاحية تعديل Workflow، مراجعة التغييرات، ومن يوافق على Environment. ترتيب الموافقات له قيمة: موافقة على تشغيل مهمة لا تعني دائمًا أن محتوى المهمة الذي سيعمل تمت مراجعته بالشكل المتوقع.

مثالنا فيه مستودع تطبيق وبيئة إنتاج. المطور يستطيع تعديل فرع تطوير، لكن النشر الإنتاجي مفترض أنه يمر بمراجعة وقبول مستقلين. بدل افتراض وجود تجاوز، ارسم سلسلة القرار: أي نسخة من الملف تُقرأ؟ من يستطيع اعتمادها؟ هل توجد خطوة تستدعي مكونًا خارجيًا؟ ومن يغير مرجع ذلك المكون؟ كل سؤال يحدد مالكًا وحدًا يمكن اختباره بأثر صغير.

اختبارك المصرح يستخدم مهمة قراءة معتمدة على مورد تجريبي، ويقارن بين سياق مسموح وآخر غير مسموح. لا تحتاج مهمة تنشر ملفًا ضارًا أو تجلب أسرار الإنتاج لإثبات اتساع الثقة. نجاح إثبات الهوية في السياق غير المتوقع، مع توثيق تفويض الهوية، يكفي لبناء فرضية قوية ثم الاتفاق مع المالك على أقل تحقق إضافي مطلوب.

بعد قبول OIDC تبدأ مراجعة تفويض المورد

الهوية قد تنجح في الحصول على رمز ثم تفشل عند قراءة مورد. هذا متوقع إذا لم يوجد تفويض مناسب، ولا يثبت أن الاتحاد مكسور. والعكس صحيح: وجود دور في Azure لا يعني أن أي مهمة في GitHub تستطيع استخدامه. مرحلة قبول الإثبات ومرحلة تنفيذ العملية على المورد سؤالان مختلفان.

اقرأ نطاق إسناد الدور: مورد واحد، مجموعة موارد، اشتراك، أو نطاق أعلى. ثم اقرأ العمليات الفعلية التي يسمح بها الدور، بما فيها تفويض بيانات الخدمة إذا كان منفصلًا عن إدارة المورد. أسماء مثل Reader أو Contributor تختصر كلامًا كثيرًا، لكنها لا تغني عن فهم العملية التي تختبرها. بعض الخدمات تفرق بين إنشاء المورد وقراءة المحتوى الموجود داخله.

في المثال قد تكون هوية التطوير قادرة على تعديل خدمة إنتاجية بسبب إسناد واسع قديم. لو كان شرط الاتحاد مضبوطًا، النتيجة الرئيسية هنا تفويض مورد زائد. ولو كانت صلاحيات المورد ضيقة لكن شرط الاتحاد يقبل مستودعًا آخر، النتيجة الرئيسية حدود ثقة CI/CD. تقدر تربطهما في سيناريو واحد، لكن احتفظ بدليل مستقل لكل حلقة حتى ما يتحول التقرير إلى قصة بلا إثبات.

الأسماء القديمة وعلاقات الثقة التي ما عاد لها مالك

علاقة اتحاد مرتبطة باسم مستودع أو مالك تحتاج مراجعة دورة حياة، خصوصًا عند النقل أو الإغلاق أو إعادة التنظيم. الوثائق الرسمية تناقش خطر subjects المبنية على أسماء قابلة للتغير. المراجعة المهنية تبدأ بجرد العلاقات الباقية وملاكها، وليس بمحاولة امتلاك أسماء خارجية أو استعادة مساحات أسماء تركها فريق سابق.

اسأل: هل المشروع ما زال يعمل؟ هل انتقل إلى منظمة ثانية؟ هل هوية السحابة أصبحت مشتركة بين أكثر من خط نشر؟ وهل بقي اعتماد قديم بعد الانتقال إلى صيغة معرّفات ثابتة؟ وجود اعتماد لا يستخدم منذ فترة يستحق تحققًا، لكن انعدام نشاط ظاهر لا يثبت أنه غير مطلوب؛ قد يخص استعادة طوارئ أو مهمة شهرية.

اجمع تاريخ الاستخدام المتاح مع مسؤول المنصة، وحدد علاقة كل اعتماد بالمهمة التي يحتاجها. أثناء التصحيح يفضل المالك إزالة الثقة المتقادمة ضمن تغيير قابل للمراجعة، ثم تنفيذ اختبار تشغيل للمهمة المتبقية. سحب علاقة واحدة بدون معرفة مستخدميها قد يعطل النشر، بينما ترك العلاقات كلها بحجة الخوف من التعطل يحافظ على مساحة قبول لا يملكها أحد.

Reusable Workflows وRunners: حدود ثانية حول نفس الهوية

قد يعتمد المستودع على Reusable Workflow موجودة في مشروع مركزي. هذا يساعد توحيد النشر، لكنه ينقل جزءًا من قرار التنفيذ إلى مالك آخر. اقرأ المرجع المستخدم ومن يستطيع تحديثه، وهل القيود في علاقة الثقة تتحقق من السياق المقصود فعلًا. وجود claim مثل job_workflow_ref مفيد، لكن تطبيق شرط عليه يعتمد على المنصة والآلية المستخدمة.

ثم اسأل عن Runner. من يديره؟ هل يستخدم لمشروعات بدرجات ثقة مختلفة؟ وهل توجد ملفات أو إعدادات باقية بين الوظائف وفق نمط التشغيل الفعلي؟ لا تفترض أن كل Runner ذاتي الاستضافة يعيد استخدام نفس الحالة، ولا تفترض أنه معزول لمجرد أن كل مهمة تظهر في صفحة منفصلة. وصف البنية من المالك أهم من الاسم التسويقي.

ما تحتاج توسع اختبار الاتحاد إلى اختراق Runner كامل. سجّل اعتماد المسار على هذه الحدود، وراجع إعدادات العزل مع الفريق ضمن النطاق المتفق عليه. إذا كان الإثبات يتطلب تشغيلًا خارج البيئات المسموحة، توقف عند هذا الحد واطلب من المالك نتيجة اختبار مشتركة. قوة النتيجة تأتي من وضوح ما ثبت وما بقي افتراضًا، مب من طول سلسلة احتمالات.

تمرين عملي: حالتا تشغيل وقراءة واحدة تكشفان موقع المشكلة

جهّز في المختبر موردًا يحتوي معلومة اختبارية غير حساسة، وهوية ذات صلاحية قراءة ضيقة عليه. دوّن إعداد اعتماد الاتحاد كما هو، ثم شغّل المهمة المعتمدة من السياق الذي صمم له. احتفظ بوقت التشغيل، معرف المهمة، نتيجة استبدال الرمز، ونتيجة القراءة. هذه الحالة المرجعية تمنع تفسير فشل عام على أنه نجاح أمني.

الحالة الثانية تغير شرطًا واحدًا فقط: بيئة مختلفة أو مستودع اختبار آخر وفق التصريح. المطلوب أن يرفض الطرف السحابي السياق غير المطابق قبل قراءة المورد. إذا فشلت المهمة بسبب نقص الشبكة أو تركيب الأداة، فلا تسجل «تم منع الهوية». وإذا قُبل الإثبات ورفض المورد القراءة، فوثق نجاح المصادقة ورفض التفويض بشكل منفصل.

كرّر حالة إيجابية بعد التصحيح حتى تعرف أن العمل المسموح ما زال يعمل. اربط كل نتيجة بالسياق الفعلي في claims، لا باسم الزر الذي ضغطته. المثال ما يطلب استخراج أسرار أو تغيير إنتاج؛ مع ذلك يعطيك جدولًا واضحًا يميز عدم تطابق issuer، اختلاف subject، audience غير مناسب، ورفض المورد. هذا النوع من الأدلة يختصر ساعات نقاش بين فريق التطوير وفريق السحابة.

كيف تكتب نتيجة يفهمها صاحب خط النشر؟

عنوان النتيجة الأفضل يصف الحد الذي اتسع: «اعتماد هوية النشر يقبل سياقًا خارج بيئة الإنتاج المعتمدة». في الوصف اذكر السياق المقبول، شرط الثقة المسؤول، والهوية السحابية الناتجة. بعده اذكر المورد والنطاق الذي يسمح به تفويضها. لا تكتب «السيطرة على السحابة» إذا تحققك اقتصر على قراءة مورد تجريبي محدود.

التوصية تجمع طرفي العلاقة: تضييق شرط قبول المهمة بما يلائم المنصة الحالية، وحماية الجهة التي تستطيع تعديل المهمة أو الموافقة عليها، وتقليل تفويض هوية النشر إلى الموارد المطلوبة. استخدام هوية منفصلة للتطوير والإنتاج قد يسهل المراجعة، لكنه لا يعوض شروط قبول سيئة على الاثنين. اربط كل اقتراح بمالك واضح حتى ما يضيع التصحيح بين GitHub وEntra وAzure.

أثناء إعادة الاختبار راجع أن الاعتماد القديم سحب فعلًا إذا كان سبب المشكلة، وأن وظيفة الإنتاج المعتمدة تنجح. النتائج المقنعة تشرح لماذا صار السياق الخارجي مرفوضًا وتثبت ذلك، بدل الاكتفاء بصورة أن لوحة الاعتماد تغيّرت. هنا يبدأ الفرق بين مراجعة إعدادات سطحية واختبار انتقال الثقة من منصة التطوير إلى المورد.

مراجع تفتحها وأنت تراجع إعدادات مشروعك

لشرح الاتحاد ومطابقة القيم في Microsoft Entra:
https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation

لتفاصيل claims وسياقات subject الحالية في GitHub، بما فيها تغييرات المعرّفات الثابتة:
https://docs.github.com/en/actions/reference/security/oidc

لشروط الاتحاد المرنة وحالة الميزة ودعم جهات الإصدار:
https://learn.microsoft.com/en-us/entra/workload-id/workload-identities-flexible-federated-identity-credentials

إذا احتجت ترتب الفرق بين تعريف التطبيق والهوية التي تحصل على التفويض، ارجع لمقال App Registration وService Principal داخل المجتمع:
https://courses.cyberpts.com/community/151/akhtbar-ttbyqat-entra-alfrq-byn-app-registration-wservice-principal-wlysh-mlkyh-

خلاصة المسار: اسأل من يثبت هوية المهمة، وما الشرط الذي يقبلها، ومن يملك تغيير التنفيذ، ثم ماذا تسمح الهوية أن تفعل. غياب Client Secret يحسن طريقة المصادقة، لكن الحكم على أمان النشر يحتاج قراءة السلسلة كاملة.