
(مقتبس من معلومات حول دليل إضافة Template في دليل إضافات CloudBees)
تتطلب العديد من إضافات Jenkins من المستخدمين تعريف سكربتات مخصصة، غالبًا بلغة Groovy، لتخصيص سلوك Jenkins. إذا كان كل من يكتب هذه السكربتات مسؤولًا عن Jenkins— وتحديدًا إذا كان لديهم صلاحية Overall/RunScripts، المستخدمة على سبيل المثال من رابط Script Console— فيمكنهم كتابة أي سكربتات يريدونها. قد تشير هذه السكربتات مباشرةً إلى كائنات Jenkins الداخلية باستخدام نفس واجهة البرمجة المقدمة للإضافات. يجب الوثوق بهؤلاء المستخدمين تمامًا، لأنهم يستطيعون فعل أي شيء بـ Jenkins (حتى تغيير إعداداته الأمنية أو تشغيل أوامر shell على الخادم).
ومع ذلك، إذا كان بعض مؤلفي السكربتات "مستخدمين عاديين" بصلاحيات محدودة فقط، مثل Job/Configure، فمن غير المناسب السماح لهم بتشغيل سكربتات عشوائية. لدعم مثل هذا التقسيم للأدوار، يمكن دمج إضافة مكتبة Script Security في إضافات الميزات المختلفة. وهي تدعم نظامين مترابطين: الموافقة على السكربتات، وعزل Groovy.
النظام الأمني الأول والأبسط هو السماح بتشغيل أي نوع من السكربتات، ولكن فقط بموافقة المسؤول. توجد قائمة عامة يتم الحفاظ عليها من السكربتات المعتمدة والتي يتم الحكم بأنها لا تنفذ أي إجراءات ضارة.
عندما يقوم مسؤول بحفظ نوع من التكوين (مثل وظيفة)، فإن السكربتات التي عدّلها المسؤول تتم الموافقة عليها تلقائيًا وتكون جاهزة للتشغيل دون أي تدخل إضافي. أما السكربتات المقدمة من مستخدمين بصلاحيات أقل، فستظهر تحذيرات مناسبة تشير إلى أن الموافقة مطلوبة. يمكن للمسؤولين الموافقة على تلك السكربتات باستخدام صفحة إعدادات الموافقة على السكربتات أو عن طريق تعديل السكربت وحفظه. في الإصدارات السابقة من إضافة Script Security، كان بإمكان المسؤولين الموافقة تلقائيًا على السكربتات المقدمة من مستخدمين غير مميزين عن طريق حفظها دون إجراء أي تغييرات، ولكن هذه الوظيفة عُطّلت لمنع الهجمات القائمة على الهندسة الاجتماعية. ("الحفظ" عادةً يعني من واجهة الويب، ولكنه قد يعني أيضًا رفع تكوين XML جديد عبر REST أو CLI.)
عندما يحفظ مستخدم غير مسؤول تكوين قالب، يتم التحقق مما إذا كانت أي سكربتات مضمّنة قد عُدّلت عن نص معتمد. (بشكل أكثر دقة، ما إذا كان المحتوى المطلوب قد تمت الموافقة عليه من قبل.) إذا لم تتم الموافقة عليه، تتم إضافة طلب الموافقة على هذا السكربت إلى قائمة انتظار. (يتم أيضًا عرض تحذير في واجهة شاشة التكوين عندما لا يكون النص الحالي للسكربت معتمدًا حاليًا.)
يمكن للمسؤول الآن الانتقال إلى إدارة Jenkins » الموافقة على السكربتات أثناء التشغيل حيث ستظهر قائمة بالسكربتات المنتظرة الموافقة. بافتراض عدم طلب أي شيء يبدو خطيرًا، فقط انقر على "موافقة" للسماح بتشغيل السكربت من الآن فصاعدًا.
إذا حاولت تشغيل سكربت غير معتمد، فسيفشل ببساطة، عادةً مع رسالة توضح أنه قيد الانتظار للموافقة. يمكنك إعادة المحاولة بعد الموافقة على السكربت. قد تختلف تفاصيل هذا السلوك وفقًا لإضافة الميزة التي تدمج هذه المكتبة.
الانتظار حتى يوافق المسؤول على كل تغيير في سكربت، مهما بدا تافهًا، قد يكون غير مقبول في فريق موزّع عبر مناطق زمنية أو خلال مواعيد ضيقة. كخيار بديل، يتيح نظام Script Security تشغيل سكربتات Groovy دون موافقة طالما أنها تقتصر على العمليات التي تُعتبر آمنة بطبيعتها. تسمى بيئة التنفيذ المحدودة هذه بالعزل (sandbox). (لا تتوفر حاليًا أي تطبيقات عزل للغات أخرى، لذا يجب الموافقة على كل هذه السكربتات إذا تم تكوينها بواسطة غير المسؤولين.)
للتبديل إلى هذا الوضع، ما عليك سوى تحديد خانة "استخدام عزل Groovy" أسفل حقل إدخال سكربت Groovy. يمكن لأي شخص تشغيل السكربتات المعزولة فورًا. (حتى المسؤولون، على الرغم من أن السكربت يخضع لنفس القيود بغض النظر عمن كتبه.) عند تشغيل السكربت، يتم فحص كل استدعاء أسلوب، وإنشاء كائن، والوصول إلى حقل مقابل قائمة بيضاء بالعمليات المعتمدة. إذا تمت محاولة عملية غير معتمدة، يتم إيقاف السكربت ولا يمكن استخدام ميزة Jenkins المقابلة بعد.
تأتي إضافة Script Security مع قائمة بيضاء افتراضية صغيرة، ويمكن للإضافات المدمجة إضافة عمليات إلى تلك القائمة (عادةً أساليب خاصة بتلك الإضافة).
ولكنك لست مقيدًا بالقائمة البيضاء الافتراضية: في كل مرة يفشل فيها سكربت قبل تشغيل عملية غير مدرجة بعد في القائمة البيضاء، تتم إضافة تلك العملية تلقائيًا إلى قائمة انتظار موافقة أخرى. يمكن للمسؤول الانتقال إلى نفس الصفحة الموصوفة أعلاه للموافقة على السكربتات بأكملها، ورؤية قائمة بعمليات الموافقة المعلقة. إذا تم النقر على "موافقة" بجوار توقيع عملية ما، تتم إضافتها فورًا إلى القائمة البيضاء وتصبح متاحة للسكربتات المعزولة.
معظم التوقيعات تكون بالشكل method class.Name methodName arg1Type arg2Type…،
تشير إلى استدعاء أسلوب Java بفئة "مستقبل" محددة (this)، واسم أسلوب، و
قائمة من أنواع الوسائط (أو المعاملات). (سيتم عرض التوقيع الأكثر عمومية لاستدعاء الأسلوب
المحاول للموافقة، حتى عندما كان الكائن الفعلي الذي سيتم استدعاؤه عليه
من نوع أكثر تحديدًا يتجاوز ذلك الأسلوب.) قد ترى أيضًا staticMethod للأساليب
الثابتة (الفئوية)، وnew للمنشئات، وfield للوصول إلى الحقول (get أو
set).
يجب على المسؤولين في البيئات الحساسة أمنيًا النظر بعناية في العمليات
التي سيتم إدراجها في القائمة البيضاء. العمليات التي تغير حالة الكائنات المحفوظة (مثل
وظائف Jenkins) يجب رفضها عمومًا. معظم أساليب getSomething غير ضارة.
انتبه مع ذلك إلى أن بعض أساليب "getter" مصممة للتحقق من صلاحيات
محددة (باستخدام ACL: قائمة التحكم بالوصول)، بينما يتم غالبًا تشغيل السكربتات بواسطة مستخدم
نظام شبه افتراضي تُمنح له جميع الصلاحيات. لذا على سبيل المثال method hudson.model.AbstractItem getParent (الذي يحصل على المجلد أو جذر Jenkins الذي يحتوي على
وظيفة) غير ضار بحد ذاته، لكن الاستدعاء اللاحق المحتمل method hudson.model.ItemGroup getItems (الذي يسرد الوظائف بالاسم داخل مجلد) يتحقق من
Job/Read. سيكون هذا الاستدعاء الثاني خطيرًا إذا تمت الموافقة عليه دون شروط، لأنه سيعني
أن المستخدم الممنوح صلاحية Job/Create في مجلد سيكون قادرًا على قراءة بعض
المعلومات على الأقل من أي وظائف في ذلك المجلد، حتى تلك التي يُفترض إخفاؤها
وفقًا لاستراتيجية تفويض قائمة على المشروع؛ سيكون كافيًا إنشاء وظيفة في
المجلد تتضمن سكربت Groovy مثل هذا (ستختلف التفاصيل وفقًا للإضافة
المدمجة):
println("I sniffed ${thisjob.getParent().getItems()}!");
عند التشغيل، سيعرض مخرج السكربت على الأقل أسماء المشاريع التي يُفترض أنها سرية.
يمكن للمسؤول بدلاً من ذلك النقر على "موافقة" بافتراض التحقق من صلاحية
getItems؛ سيسمح هذا بالاستدعاء عند التشغيل كمستخدم فعلي (إذا كانت الإضافة
المدمجة تفعل ذلك أبدًا)، بينما يمنعه عند التشغيل كمستخدم النظام (وهو الأكثر
شيوعًا). في هذه الحالة، يتم تنفيذ getItems فعليًا لإرجاع فقط الوظائف التي
يستطيع المستخدم الحالي الوصول إليها، لذا إذا تم تشغيله في الحالة الأولى (كمستخدم محدد)،
فسيعرض الوصف فقط تلك الوظائف التي يمكنه رؤيتها على أي حال. هذا الزر الأكثر تقدمًا
يظهر فقط لاستدعاءات الأساليب (والمنشئات)، ويجب استخدامه فقط عندما تعرف
أن Jenkins يقوم بالتحقق من الصلاحيات.
للتكامل النموذجي مع Groovy، حيث تقدم للمستخدم خيار استخدام إما
الموافقة على السكربت أو العزل، غيّر حقل السكربت ذا القيمة النصية في كائن الوصف الخاص بك إلى
حقل SecureGroovyScript. في المُنشئ، قبل تخزين القيمة، استدعِ
configuringWithKeyItem (إذا كان يمكن أن يكون هناك سكربت واحد فقط من هذا القبيل لكل عنصر من المستوى الأعلى) أو
configuringWithNonKeyItem (إذا كان قد يكون هناك عدة سكربتات). يجب أن يستخدم نموذج التكوين
<f:property field="…"/> لالتقاط السكربت وإعدادات العزل. عندما تريد
تشغيل السكربت، فقط استدعِ evaluate.
(من أجل التوافق مع البيانات القديمة، اختر اسم حقل مختلفًا واعتبر الحقل الأصلي مهملًا.
ثم يمكنك تعريف أسلوب readResolve يضبط الحقل الجديد على SecureGroovyScript
مع إيقاف العزل، ويستدعي configuring(ApprovalContext.create()) عليه لإخطار
النظام بأن سكربتًا غير معتمد قد تم تحميله، ويلغي تعيين الحقل القديم.)
تُستخدم إذا كنت بحاجة إلى تحكم أكبر مما يقدمه SecureGroovyScript:
أدخل حقل sandbox منطقيًا في تكوينك.
عند عدم التعيين، تحتاج إلى استدعاء ScriptApproval.configuring في @DataBoundConstructor.
استخدم ApprovalContext.withCurrentUser، وأيضًا withItemAsKey حيثما ينطبق (عندما
يوجد سكربت واحد فقط لكل وظيفة)؛ وإلا فاستخدم على الأقل withItem حيثما ينطبق، و/أو
withKey عندما يمكنك تحديد هذا الاستخدام بشكل فريد من السياق
(StaplerRequest.findAncestorObject مفيد هنا). هذا يتيح للنظام معرفة أن
سكربتًا (ربما) جديدًا قد تم تكوينه بواسطة شخص معين. ستحتاج أيضًا إلى
readResolve يستدعي configuring لإخطار النظام عندما يتم تحميل عنصر قابل للتكوين مع سكربت
من القرص (وبالتالي يكون المكوِّن غير معروف). استدعِ
ScriptApproval.using عند تشغيل السكربت، والتقط UnapprovedUsageException إذا
لزم الأمر. يجب أن يستخدم الواصف التحقق من صحة النموذج على حقل السكربت واستدعاء
ScriptApproval.checking (عمومًا يجب أن يقوم الواصف بالفعل بإجراء فحص
بناء جملة على الأقل لهذا الحقل).
عند تعيين حقل العزل، تحتاج فقط إلى إعداد بيئة Groovy shell باستخدام
GroovySandbox.createSecureCompilerConfiguration ثم استدعاء GroovySandbox.run؛ وكن
مستعدًا لالتقاط RejectedAccessException واستدعاء ScriptApproval.accessRejected.
للموافقة المسبقة على بعض استدعاءات الأساليب المعينة، ما عليك سوى تعليقها باستخدام @Whitelisted إذا كانت داخل
إضافتك؛ وإلا يمكنك تسجيل (باستخدام @Extension) ProxyWhitelist يفوض إلى
StaticWhitelist.from وتحميل ملف نصي يسرد الأساليب المسموح بها.
عند إنشاء GroovyShell لتقييم سكربت، أو استدعاء
ecureGroovyScript.evaluate، يجب تمرير ClassLoader يمثل مسار الفئات الفعلي
للسكربت. يمكنك استخدام مُحمّل Jenkins الأساسي، أو إضافتك، أو
Jenkins.getInstance().getPluginManager().uberClassLoader.
أيًا كان ما تختاره، لا تسمح لمستخدم غير مميز بإضافة إدخالات مسار فئات عشوائية
عن طريق إنشاء URLClassLoader! هذا سيجعل تجاوز كل الأمان عند استخدام
العزل أمرًا تافهًا. (يكفي أن يجعل المستخدم هذه الوظيفة أو وظيفة أخرى تؤرشف JAR يحتوي على
فئة بأسلوب ثابت معلَّم بـ @Whitelisted ويفعل ما يشاء، ثم يستدعي
الأسلوب من سكربته.) لم يتم إثبات أي هجوم بعد عند استخدام الموافقة على السكربت بأكمله —
URLClassLoader مع التفويض العادي من الأصل إلى الفرع لن يسمح بإخفاء تافه
للواجهات البرمجية ذات المظهر البريء بواسطة إصدارات مخترقة — ولكن من المرجح أن بعض
الاستخدام الذكي لـ META-INF/services/org.codehaus.groovy.transform.ASTTransformation أو ما شابه
يمكن أن يتسبب في تصرف سكربت آمن بخلاف ذلك بطريقة غير متوقعة وغير مصرح بها.
يقترح JENKINS-22834 بديلًا قياسيًا
آمنًا.
عند كتابة اختبارات للإضافات التي تستخدم إضافة Script Security قد تواجه بعض الأخطاء في اختباراتك.
إذا كانت اختباراتك تستدعي، بشكل مباشر أو غير مباشر، أسلوب ScriptApproval.get()، فيجب أن
تستخدم اختبارات الوحدة JenkinsRule حتى لا يُرجع Jenkins.getInstance() قيمة null. من
المحتمل أن الاختبارات التي كانت تعمل ستبدأ الآن في الفشل إذا لم تكن تستخدم العزل.
يحدث ذلك لأنها تُدرج في قائمة انتظار الموافقة. في حال احتجت إلى تنفيذ
سكربتات بغض النظر عن الموافقات، فإن ScriptApproval.get().preapprove(script, GroovyLanguage.get()) سيضمن الموافقة على جميع السكربتات المكونة. بدلاً من ذلك،
يمكنك جعل اختباراتك تشغل السكربتات باستخدام العزل. في هذه الحالة قد تحتاج إلى
إدراج الأساليب المستخدمة في اختباراتك في القائمة البيضاء -- إما بشكل عام للمستخدمين الحقيقيين، أو باستخدام
@TestExtension للحصول على قائمة بيضاء للاختبارات فقط.
انظر سجل التغييرات