تنفيذ التعليمات البرمجية في بيئة معزولة

توفر حزمة adk-sandbox تنفيذًا معزولًا للتعليمات البرمجية لوكلاء ADK، مع مستويين من العزل:

  1. عزل العمليات — عمليات فرعية مع عزل البيئة وفرض مهلة زمنية
  2. ملفات تعريف العزل على مستوى نظام التشغيل — قيود على مستوى النواة لنظام الملفات والشبكة وإنشاء العمليات

الواجهات الخلفية

الواجهة الخلفيةمستوى العزلاللغاتعلامة الميزة
ProcessBackendالبيئة + المهلةRust، Python، JS، TS، الأوامرprocess (افتراضي)
ProcessBackend + وضع الحمايةعلى مستوى النواةنفس ما سبقprocess + sandbox-native
WasmBackendكامل (الذاكرة، fs، الشبكة)WASM فقطwasm

ما مستوى العزل الذي تحصل عليه؟

يُبلغ عنه ProcessBackend::isolation()، لذا فهذا ليس شيئًا ينبغي استنتاجه من اسم الحزمة:

النتيجةالمعنى
IsolationClass::SubprocessOnlyعملية فرعية ببيئة تمت تهيئتها، ومهلة زمنية، ومجموعة عمليات خاصة بها. لا يطبّق نظام التشغيل أي قيود إضافية: يمكن للتعليمة البرمجية قراءة نظام ملفات المضيف والوصول إلى الشبكة. هذا ما يمنحك إياه ProcessBackend::default().
IsolationClass::OsEnforcedتم إرفاق منفّذ وسياسة، ولذلك يقيّد نظام التشغيل العملية الفرعية.

هناك أمران جديران بالمعرفة حول خلفية العمليات:

  • يتم حل البرامج قبل مسح البيئة. يتم البحث عن python3 أو node أو rustc غير المسبوق بمسار على PATH الخاص بالمتصل، ثم يُمرَّر إلى العملية التابعة باعتباره مسارًا مطلقًا. وهذا يعني أن العملية التابعة لا تحتاج إلى PATH خاص بها لبدء التشغيل — إذ كان يتعين سابقًا على المتصل وضع PATH في ExecRequest::env، مما كان يتيح أيضًا للتعليمات البرمجية المنفَّذة إنشاء أي شيء آخر باستخدامه.
  • يتم التجميع عبر الحدّ الفاصل نفسه المستخدم في التنفيذ. كان مصدر Rust يُجمَّع سابقًا باستخدام أمر يُبنى خارج المسار المشترك، ولذلك لم يكن للتجميع غلاف إنفاذ، ولا مهلة زمنية، ولا مجموعة عمليات. وهذا مهم لأن التجميع ليس خاملًا: يقرأ include_str! الملفات، وتشغّل وحدات الماكرو الإجرائية تعليمات برمجية عشوائية قبل وجود الملف الثنائي الناتج. وتتلقى مرحلة التجميع قائمة سماح لسلسلة الأدوات خاصة بالمنصة؛ وفي Windows، يشمل ذلك مسارات MSVC وWindows SDK، التي يتم اكتشافها من سلسلة الأدوات المثبّتة عندما لا يكون المتصل موجودًا مسبقًا في جلسة Developer. يستخدم التجميع رابط سلسلة أدوات Rust، وهو rust-lld، ولذلك لا يمكن اختيار link.exe غير ذي الصلة الموجود في موضع أسبق على PATH. ويفرض مُنفِّذ على مستوى نظام التشغيل القيود على تلك المرحلة.

أسبقية البيئة

يوفّر SandboxPolicy::env الإعدادات الافتراضية لكل عملية تنفيذ، ويتجاوزها ExecRequest::env لكل استدعاء. وكان يتم تجاهل متغيرات السياسة بالكامل في السابق.

ملفات تعريف عزل نظام التشغيل

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

دعم المنصات

المنصةأداة الإنفاذكيفية عملها
macOSSeatbelt (sandbox-exec)قواعد على مستوى استدعاءات النظام: «السماح افتراضيًا، وحظر الخطِر» — تحظر عمليات الكتابة، والشبكة، وfork؛ ولا تقيّد عمليات القراءة
Linuxbubblewrap (bwrap)عزل مساحة أسماء نظام الملفات (عمليات تركيب مدرجة في القائمة البيضاء)
WindowsAppContainerغير مُنفّذ — يُبلغ المُنفِّذ عن عدم توفره

البدء السريع

use adk_sandbox::{
    ProcessBackend, ProcessConfig, SandboxBackend,
    SandboxPolicyBuilder, get_enforcer,
};

// 1. Define what the sandboxed process can do
let policy = SandboxPolicyBuilder::new()
    .allow_read("/usr")           // Read system libraries
    .allow_read_write("/tmp/work") // Write to work directory
    .allow_process_spawn()         // Python needs to exec
    // Network is denied by default
    .env("PATH", "/usr/bin:/usr/local/bin")
    .build();

// 2. Get the platform-appropriate enforcer
let enforcer = get_enforcer()?;

// 3. Create a sandboxed backend
let backend = ProcessBackend::with_sandbox(
    ProcessConfig::default(),
    enforcer,
    policy,
);

// 4. Execute code — network is blocked, writes restricted
let result = backend.execute(request).await?;

علامات الميزات

[dependencies]
# Auto-detect platform enforcer
adk-sandbox = { version = "2.1.0", features = ["process", "sandbox-native"] }

# Or pick a specific platform
adk-sandbox = { version = "2.1.0", features = ["process", "sandbox-macos"] }
adk-sandbox = { version = "2.1.0", features = ["process", "sandbox-linux"] }

SandboxPolicy

تحدد السياسة ما يُسمح للعملية المعزولة بتنفيذه:

الحقلالافتراضيالوصف
allowed_paths[] (رفض الكل)مسارات نظام الملفات التي تتمتع بوصول للقراءة فقط أو للقراءة والكتابة
allow_networkfalseما إذا كان الوصول إلى الشبكة مسموحًا
allow_process_spawnfalseما إذا كان يُسمح بإنشاء عمليات فرعية
env{}متغيرات البيئة للعملية المعزولة

الاختلافات بين المنصات

macOS (Seatbelt): يستخدم نهج «السماح افتراضيًا، وحظر الخطِر» — يبدأ بوصول كامل، ثم يحظر الشبكة وعمليات كتابة الملفات وإنشاء العمليات. لا ينجح نهج القائمة البيضاء الخالصة لأن Python يحتاج إلى عشرات الفئات الخاصة بـ macOS من استدعاءات النظام عند بدء التشغيل.

Linux (bubblewrap): يستخدم قائمة بيضاء قائمة على مساحات الأسماء — لا يوجد شيء افتراضيًا، ولا تقوم بتركيب سوى ما هو مطلوب. ثبّته باستخدام apt install bubblewrap أو dnf install bubblewrap.

Windows (AppContainer): غير مُنفّذ. يعتمد التصميم على قوائم ACL المستندة إلى الرموز — معرّف SID مقيّد لا يملك أي وصول افتراضيًا، ثم تُمنح قوائم ACL لمسارات محددة — لكن إنشاء الحاويات وقوائم ACL والإمكانات وتنظيف كائنات المهام غير متوفرة، لذلك يعيد probe() القيمة EnforcerUnavailable. شغّله دون أداة فرض على Windows، أو استخدم macOS أو Linux حيث يكون الفرض فعليًا.

مثال

راجع examples/sandbox_agent/ للاطلاع على مثال كامل مدفوع بواسطة LLM ينفّذ تعليمات Python البرمجية في بيئة معزولة مع حظر الوصول إلى الشبكة بواسطة نواة نظام التشغيل.

تنفيذ التعليمات البرمجية في بيئة معزولة - وثائق ADK-Rust | ADK-Rust