چارچوب مهار و نقطه کور آن
ابزارهای اولیه مهار — سندباکسها، ماشینهای مجازی، فیلترهای فراخوان سیستمی — در پاسخ به این پرسش که کد کجا میتواند اجرا شود عالی هستند. آنها محیط اجرا را تعریف میکنند: کدام باینریها میتوانند اجرا شوند، کدام فایلها میتوانند خوانده شوند، کدام فراخوانهای هسته مجاز هستند. این یک لایه ضروری برای هر عاملی است که کد تولیدشده یا ابزار دلخواه را اجرا میکند. با این حال، مدلی از دسترسی بیرونی نیست.
یک عامل درون یک سندباکس کاملاً مهارشده هنوز میتواند هزاران درخواست خروجی به هزاران مقصد متمایز ارسال کند. سندباکس اهمیتی نمیدهد که فرایند با یک میزبان صحبت میکند یا ده هزار؛ برایش مهم است که فرایند از جعبه فرار نکند. حالت شکستی که مدام با آن مواجه میشویم فرار نیست. دسترسی است.
عاملی مهارشده را در نظر بگیرید که از طریق یک بار تزریق پرامپت در یک سند بازیابیشده به خطر افتاده است. عامل نمیتواند فیلتر فراخوان سیستمی را بشکند. نمیتواند فایلسیستم میزبان را بخواند. اما میتواند از دسترسی شبکهای اعطاشده و اعتبارنامههای اعطاشدهاش استفاده کند تا نقاط پایانی داخلی را شمارش کند، زمینه را در تکههای کوچک بیرون بکشد، یا APIهای شخص ثالث را کاوش کند تا یکی با دادههای مفید پاسخ دهد. مهار برقرار است. شعاع انفجار هنوز بزرگ است.
گفتگوی صنعت پیرامون ایمنی عامل تا حد زیادی مدلهای تهدید خود را از امنیت کانتینر به ارث برده است، جایی که مرز، میزبان است. برای عاملها، مرز مجموعه هویتهای بیرونی، نقاط پایانی، و جریانهای دادهای است که عامل میتواند بر آنها تأثیر بگذارد. آن مجموعه توسط سندباکس محدود نمیشود. توسط سیاست خروجی محدود میشود، و سیاست خروجی بدون یک مدل هزینه فقط فهرستی از میزبانهای مجاز است.
خروجی بهعنوان یک منبع بودجهبندیشده
ما خروجی را بهعنوان یک منبع بودجهبندیشده با ابعادی که بهازای هر اقدام خروجی بدهکار میشوند در نظر میگیریم. ابعادی که مفید یافتهایم عبارتند از:

- مقصدهای متمایز. تعداد نقاط پایانی شبکهای یکتا که تماس گرفته میشود، نه تعداد فراخوانها. ده هزار فراخوان به یک میزبان، پروفایل ریسک متفاوتی از ده فراخوان به ده هزار میزبان دارد. شمارش مقصد باید در سراسر DNS، IP، و پورت نرمالسازی شود، و باید تغییرمسیرها را بهعنوان مقصدهای جدید در نظر بگیرد.
- بایتهای خروجی. حجم بار دادهای که از فرایند خارج میشود، شامل سرآیندها، رشتههای پرسوجو، و بدنههای درخواست. این امر بیرونکشی آهستهای را که زیر آستانههای تعداد فراخوان میماند میگیرد.
- دامنه اعتبارنامه. مجموعه هویتها و توکنهایی که خروجی میتواند ارائه دهد. بودجهای که یک توکن گسترده به یک مقصد باریک را مجاز میکند، هنوز یک بودجه گسترده است.
- پنجره زمانی. بازهای که بودجه در آن معتبر است. بودجهای که هر ثانیه تازه میشود، بودجه نیست.
اجرا باید در مرز شبکه باشد، نه در چارچوب عامل. بررسیهای سطح چارچوب توصیهای هستند: به همکاری عامل، به درست استفادهشدن از پوشش ابزار، و به اینکه هیچ مسیر کدی پوشش را دور نزند بستگی دارند. یک مرز شبکه — یک پروکسی، یک سایدکار مش سرویس، یک قلاب eBPF روی رابط خروجی — هر بستهای را میبیند بدون توجه به اینکه کدام کتابخانه آن را آغاز کرده است. چارچوب عامل میتواند بودجه درخواست کند؛ مرز آن را اجرا میکند.
مرز همچنین باید یک حالت پایانی منتشر کند. وقتی بودجه تمام میشود، اجرا بیصدا تنزل نمییابد یا دوباره تلاش نمیکند. با یک مسیر بازیابی تعریفشده پایان مییابد: به اپراتور اطلاع داده میشود، اجرا بهعنوان بودجهتمامشده علامتگذاری میشود، و یک انسان میتواند یک اجرای جدید با یک بودجه جدید صریح را مجاز کند. این امر تمامشدن را به یک نتیجه درجهیک تبدیل میکند نه خطایی که باید بلعیده شود.
قواعد طراحی
هر فراخوان ابزاری که از فرایند خارج میشود باید یک بودجه را بدهکار کند. این شامل فراخوانهایی میشود که داخلی به نظر میرسند، فراخوانهایی که از یک ورودی DNS کششده استفاده میکنند، و فراخوانهایی که توسط وابستگیها انجام میشوند نه توسط کد خود عامل. اگر بایتی از مرز فرایند خارج شود، خروجی است. بدهکاری با درخواست اتمی است؛ اگر بدهکاری شکست بخورد، درخواست خارج نمیشود.
بودجهها بهازای هر اجرا و بهازای هر هویت هستند، و منتقل نمیشوند. یک اجرا یک وظیفه منطقی واحد با شروع و پایان تعریفشده است. بودجه به آن اجرا تعلق دارد، نه به فرایند عامل، نه به نشست کاربر، و نه به استقرار. هویتها بهطور جداگانه دامنهبندی میشوند: عاملی که به نمایندگی از یک کاربر عمل میکند، بودجه کاربر دیگری را به ارث نمیبرد. بودجه استفادهنشده برای اجرای بعدی ذخیره نمیشود، زیرا ذخیرهسا
](/media/server-rack-closeup-3b0bfb-b5562f.jpg)
بدهکاری، کلاس مقصد، و تصمیم را ثبت کنید، نه فقط درخواست را. یک خط لاگ که فقط URL را ثبت میکند برای تحلیل پس از حادثه کافی نیست. ما مقدار بدهکاری بودجه، کلاس مقصد (برای مثال: سرویس داخلی، API شخص ثالث، وب عمومی، ناشناخته)، بودجه باقیمانده، و تصمیم سیاستی که درخواست را مجاز یا رد کرده ثبت میکنیم. رکورد تصمیم چیزی است که بودجه را قابل حسابرسی میکند. بدون آن، بودجه یک عدد است، نه یک کنترل.
یک مکانیزم مشخص
یک پیادهسازی که استفاده کردهایم یک پروکسی روبهجلو بین سندباکس عامل و شبکه قرار میدهد. پروکسی یک جدول بودجه بهازای هر اجرا را نگه میدارد که با شناسه اجرا و هویت کلیدگذاری شده است. در هر درخواست، پروکسی مقصد را حل میکند، آن را طبقهبندی میکند، هزینه بایت را از سرآیندها و بدنه درخواست محاسبه میکند، و تلاش میکند یک کاهش اتمی از بودجه اجرا در سراسر همه ابعاد انجام دهد. اگر هر بعدی منفی شود، پروکسی یک رد به عامل برمیگرداند و یک رویداد بودجهتمامشده به صفحه کنترل منتشر میکند. صفحه کنترل اجرا را به یک حالت پایانی منتقل میکند و به اپراتور اطلاع میدهد.
عامل هرگز جدول بودجه را نمیبیند. یک رد میبیند، که باید آن را بهعنوان یک شرط غیرقابلتلاشمجدد مدیریت کند. این عمدی است: عامل نباید بتواند درباره دسترسی باقیماندهاش استدلال کند، زیرا عاملی که میتواند درباره دسترسی باقیماندهاش استدلال کند میتواند حول آن برنامهریزی کند.
معامله صادقانه
اجرای بودجه تأخیر و سطح عملیاتی اضافه میکند. هر درخواست خروجی متحمل یک پرش پروکسی، یک مرحله طبقهبندی، و یک بهروزرسانی حالت میشود. برای عاملهایی که فراخوانهای پرفرکانس به یک نقطه پایانی شناختهشده واحد انجام میدهند، این سرباری با سود کم است؛ بودجه عملاً ایستا است. برای عاملهایی که به سراسر مقصدهای بسیاری پخش میشوند، سربار همان نکته است.
معامله سختتر مثبتهای کاذب است. یک اجرای مشروع که نیاز به تماس با یک کلاس مقصد جدید دارد به بودجه برخورد میکند و پایان مییابد. اپراتورها باید بتوانند سریع یک بودجه جدید اعطا کنند، و اعطا باید با همان دقت اصلی ثبت شود. اگر مسیر بازیابی کند باشد، تیمها بودجه پیشفرض را گستردهتر میکنند تا از وقفه جلوگیری کنند، و کنترل تزئینی میشود. بودجه فقط بهاندازه مسیر بازیابی خوب است.
مهار ضروری باقی میماند. کافی نیست. عاملی که میتواند از درون یک سندباکس به ده هزار مقصد برسد، به هیچ معنایی که برای دادههایی که میتواند لمس کند مهم باشد، مهار نشده است. مرز تعریف میکند کجا اجرا میشود. بودجه تعریف میکند تا کجا میرسد. هر دو باید حاضر باشند، و دومی باید جایی اجرا شود که عامل نتواند با آن بحث کند.
