10 تنظیمات زمینه امنیتیSecurity Context Kubernetes که باید بدانید
10 تنظیمات زمینه امنیتیSecurity Context Kubernetes که باید بدانید
اجرای ایمن بارهای کاری در Kubernetes می تواند دشوار باشد. بسیاری از تنظیمات مختلف بر امنیت Kubernetes API تأثیر میگذارند و برای پیادهسازی صحیح به دانش قابل توجهی نیاز دارند. یکی از قدرتمندترین ابزارهایی که Kubernetes در این زمینه ارائه می دهد، تنظیمات SecurityContext است که هر مانیفست Pod و Container می تواند از آن استفاده کند. در این cheatsheet، نگاهی به تنظیمات مختلف SecurityContext خواهیم انداخت، معنی آنها را بررسی خواهیم کرد و چگونه باید از آنها استفاده کنید.
- runAsNonRoot
- runAsUser / runAsGroup
- seLinuxOptions
- seccompProfile
- privileged / allowPrivilegeEscalation
- capabilities
- readonlyRootFilesystem
- procMount
- fsGroup / fsGroupChangePolicy
- sysctl
تنظیمات Pod و Container
تنظیمات Kubernetes securityContext در هر دو API PodSpec و ContainerSpec تعریف شدهاند و محدوده در این سند با حاشیهنویسی [P] و/یا [C] در کنار هر یک نشان داده میشود. توجه داشته باشید که اگر تنظیمی در هر دو حوزه موجود باشد و پیکربندی شده باشد، تنظیمات پاد اولویت خواهد داشت. اکنون، بدون ترتیب خاصی، اجازه دهید نگاهی به تنظیمات SecurityContext بیندازیم:
1. runAsNonRoot [P/C]
حتی اگر یک کانتینر از فضاهای نام و گروههای c برای محدود کردن فرآیند(های) خود استفاده میکند، تنها چیزی که لازم است یک پیکربندی نادرست در تنظیمات استقرار آن است تا به آن فرآیندها دسترسی به منابع موجود در میزبان داده شود. اگر آن فرآیند به صورت root اجرا شود، همان دسترسی اکانت ریشه میزبان به آن منابع را دارد. علاوه بر این، اگر سایر تنظیمات کانتینر برای کاهش محدودیتها (مثلاً procMount یا قابلیتها) استفاده شود، داشتن یک UID ریشه خطرات هرگونه بهرهبرداری از آنها را افزایش میدهد. مگر اینکه دلیل خیلی خوبی داشته باشید، هرگز نباید یک پاد را به عنوان root اجرا کنید.
بنابراین، اگر تصویری برای استقرار دارید که از root استفاده می کند، چه کار می کنید؟
Option 1: Use the user provided in the base image
اغلب، تصاویر پایه قبلاً یک کاربر ایجاد و در دسترس دارند، اما استفاده از آن را به تیمهای توسعه یا استقرار واگذار میکنند. به عنوان مثال، تصویر رسمی Node.js با کاربری به نام node در UID 1000 ارائه میشود که میتوانید آن را به عنوان اجرا کنید، اما آنها به صراحت کاربر فعلی را در Dockerfile خود تنظیم نمیکنند. یا باید آن را در زمان اجرا با تنظیمات runAsUser پیکربندی کنیم یا کاربر فعلی در تصویر را با استفاده از یک Dockerfile مشتق شده تغییر دهیم. اولی فرض می کند که UID 1000 می تواند فایل های موجود در فهرست برنامه را بخواند. اجازه دهید در عوض به مثالی با استفاده از Dockerfile مشتق برای ساختن تصویر خود نگاه کنیم.
بدون عمیق شدن در ساخت تصویر، بیایید فرض کنیم که یک برنامه npm از پیش ساخته شده داریم. در اینجا یک Dockerfile مینیمال برای ساختن یک تصویر بر اساس [**node:slim**](https://hub.docker.com/_/node) و اجرا به عنوان کاربر گره ارائه شده وجود دارد.
خط کلید با USER شروع می شود که گره را به کاربر پیش فرض در داخل هر کانتینر که از این تصویر شروع می شود تبدیل می کند. ما از UID به جای نام کاربر استفاده میکنیم زیرا Kubernetes نمیتواند نام کاربری پیشفرض یک تصویر را قبل از شروع کانتینر به UID آن نگاشت کند و در هنگام استقرار با runAsNotRoot: true specified یک خطا در این مورد برمیگرداند.
Option 2: Base image provides no user
بنابراین اگر تصویر پایه گره قبلاً یک کاربر برای استفاده در اختیار ما قرار نداده باشد، چه کار می کنیم؟ برای بسیاری از فرآیندها، ما به سادگی یکی را در یک Dockerfile مشتق ایجاد می کنیم و از آن استفاده می کنیم. بیایید مثال قبلی را برای این کار گسترش دهیم:
همانطور که می بینید، تنها خط RUN است که یک کاربر ایجاد می کند – نحو آن ممکن است بسته به توزیع تصویر پایه متفاوت باشد – و من کاربر و مراجع مسیر را تغییر داده ام تا با آن مطابقت داشته باشد.
توجه: این کار برای node.js و npm خوب عمل می کند، اما ممکن است ابزارهای دیگر برای ایجاد تغییرات مالکیت به عناصر مختلف فایل سیستم نیاز داشته باشند. در صورت مواجه شدن با هر گونه مشکل، به اسناد ابزار خود مراجعه کنید.
2. runAsUser / runAsGroup [P/C]
تصاویر کانتینر ممکن است دارای کاربر و/یا گروه خاصی باشند که برای اجرای فرآیند به صورت پیکربندی شده است. این را می توان با تنظیمات پیکربندی runAsUser و runAsGroup لغو کرد. اغلب اینها همراه با پایههای حجمی حاوی فایلهایی که شناسههای مالکیت یکسانی دارند، تنظیم میشوند.
استفاده از این تنظیمات خطری وجود دارد زیرا در حال تصمیم گیری در زمان اجرا برای پاد هستید که ممکن است با تصویر اصلی سازگار نباشد. برای مثال، تصویر سرور رسمی jenkins/jenkins CI به صورت group:user با نام jenkins:jenkins اجرا میشود و فایلهای کاربردی آن همگی متعلق به آن کاربر هستند. اگر کاربر دیگری را پیکربندی کنیم، راه اندازی نمی شود زیرا آن کاربر در فایل تصویر /etc/passwd وجود ندارد. حتی اگر به نحوی انجام شود، به احتمال زیاد در خواندن و نوشتن فایل های متعلق به jenkins:jenkins با مشکل مواجه خواهد شد. یک دستور ساده docker run می تواند این را برای شما بررسی کند:
همانطور که در بالا ذکر کردیم، ایده بسیار خوبی است که اطمینان حاصل شود که فرآیندهای کانتینر به عنوان کاربر اصلی اجرا نمی شوند، اما برای تضمین این موضوع به runAsUser یا runAsGroupsettings اعتماد نکنید. کسی می تواند این تنظیمات را در آینده حذف کند. حتما runAsNonRoot را نیز روی true تنظیم کنید.
3. seLinuxOptions [P/C]
SELinux یک سیستم مبتنی بر سیاست برای کنترل دسترسی به برنامهها، فرآیندها و فایلها در یک سیستم لینوکس است. این چارچوب ماژول های امنیتی لینوکس را در هسته لینوکس پیاده سازی می کند. SELinux بر اساس مفهوم برچسب ها است. این برچسب ها را به تمام عناصر موجود در سیستم که عناصر را با هم گروه بندی می کنند، اعمال می کند. این برچسبها به عنوان زمینه امنیتی شناخته میشوند – که نباید با Kubernetes SecurityContext اشتباه گرفته شود – و از یک کاربر، نقش، نوع و یک سطح فیلد اختیاری در قالب user:role:type:level تشکیل شدهاند.
سپس SELinux از سیاست هایی استفاده می کند تا تعریف کند که کدام فرآیندهای یک زمینه خاص می توانند به اشیاء برچسب گذاری شده دیگر در سیستم دسترسی داشته باشند. SELinux را می توان به شدت اجرا کرد، در این صورت دسترسی ممنوع می شود، یا می توان آن را در حالت مجاز پیکربندی کرد که در آن دسترسی ثبت شود. در کانتینرها، SELinux معمولاً فرآیند کانتینر و تصویر ظرف را به گونهای برچسبگذاری میکند که فرآیند را محدود به دسترسی به فایلهای داخل تصویر کند.
برچسبهای پیشفرض SELinux توسط زمان اجرای کانتینر هنگام نمونهسازی یک پاد اعمال میشوند. تنظیمات seLinuxOptions در SecurityContext اجازه می دهد تا برچسب های SELinux سفارشی اعمال شود. توجه داشته باشید که تغییر برچسب SELinux برای یک کانتینر به طور بالقوه می تواند به فرآیند کانتینری اجازه دهد تا از تصویر کانتینر فرار کند و به سیستم فایل میزبان دسترسی پیدا کند.
توجه داشته باشید که این قابلیت تنها در صورتی اعمال می شود که سیستم عامل میزبان از SELinux پشتیبانی کند.
4. seccompProfile [P/C]
Seccomp مخفف حالت محاسبات امن است و یکی از ویژگی های هسته لینوکس است که می تواند تماس هایی را که یک فرآیند خاص از فضای کاربر به هسته انجام می دهد محدود کند. نمایه seccomp یک تعریف JSON است که معمولاً شامل مجموعهای از syscalls و اقدام پیشفرض در صورت وقوع یکی از این syscalls است.
Kubernetes مکانیزمی برای استفاده از پروفایل های سفارشی از طریق تنظیمات seccompProfile در SecurityContext فراهم می کند.
سه مقدار ممکن برای فیلد نوع وجود دارد:
Localhost
که با تنظیمات localhostProfile مسیری را در داخل کانتینر به نمایه seccomp ارائه می دهد.
Unconfined
که در آن هیچ نمایه ای اعمال نمی شود.
RuntimeDefault
که در آن از پیشفرض زمان اجرا کانتینر استفاده میشود – اگر نوع نامشخص باقی بماند، این پیشفرض است
میتوانید این تنظیمات را در PodSecurityContext یا SecurityContext اعمال کنید. اگر هر دو تنظیم شده باشند، تنظیمات در سطح کانتینر در SecurityContext استفاده می شود. توجه داشته باشید که API پیکربندی SecurityContext در Kubernetes نسخه 1.19 منتشر شد – اگر در نسخههای قبلی استقرار میکنید، نحو متفاوتی وجود دارد. برای جزئیات و مثال ها به سایت اسناد Kubernetes مراجعه کنید. مانند اکثر تنظیمات مربوط به امنیت، اصل حداقل امتیاز در اینجا اعمال می شود. فقط به کانتینر خود اجازه دسترسی به امتیازاتی را بدهید که نیاز دارد و نه بیشتر. با ایجاد نمایهای شروع کنید که به سادگی ثبت کند که کدام syscals در حال انجام است، سپس برنامه خود را برای ساخت مجموعهای از syscals مجاز آزمایش کنید. می توانید اطلاعات بیشتری در مورد این فرآیند در آموزش های Kubernetes پیدا کنید.
5. Avoid Privileged Containers / Escalations [C]
اعطای وضعیت ممتاز کانتینر خطرناک است و معمولاً به عنوان یک راه ساده تر برای دستیابی به مجوزهای خاص استفاده می شود که در غیر این صورت می توان از طریق اعطای دسترسی به قابلیت ها کنترل کرد. زمان اجرا کانتینر اجرای دقیق پرچم ممتاز را کنترل میکند، اما به طور مؤثری تمام امتیازات و محدودیتهای اعمال شده توسط کنترلکننده cgroup دستگاه را به کانتینر اعطا میکند. همچنین ممکن است پیکربندی ماژول امنیتی لینوکس را تغییر دهد و به فرآیندهای داخل کانتینر اجازه دهد تا از ظرف خارج شوند. کانتینرها جداسازی فرآیند را در هاست فراهم میکنند، بنابراین حتی با اجرای کانتینر بهعنوان روت، قابلیتهایی وجود دارد که زمان اجرای کانتینر به کانتینر نمیدهد. با مجموعه پرچم ممتاز، زمان اجرا کانتینر تمام قابلیتهای ریشه سیستم را اعطا میکند، و آن را از منظر امنیتی بسیار خطرناک میکند زیرا امکان دسترسی کامل به سیستم میزبان اصلی را فراهم میکند. از استفاده از پرچم ممتاز خودداری کنید و اگر کانتینر شما به قابلیتهای اضافی نیاز دارد، فقط موارد مورد نیاز خود را از طریق تنظیمات قابلیتها اضافه کنید. مگر اینکه کانتینر شما نیاز به کنترل تنظیمات سطح سیستم در هسته میزبان (مانند دسترسی به سخت افزار خاص یا پیکربندی مجدد شبکه ها) داشته باشد و نیاز به دسترسی به سیستم فایل میزبان داشته باشد، پس نیازی به پرچم ممتاز privileged flag ندارد.
6. Linux kernel capabilities [C]
قابلیتها مجوزهای سطح هسته هستند که اجازه میدهند تا کنترلهای دقیقتری روی مجوزهای فراخوانی هسته به جای اجرای همه چیز بهعنوان روت انجام شود. قابلیتها شامل مواردی مانند توانایی تغییر مجوزهای فایل، کنترل زیرسیستم شبکه و انجام عملکردهای مدیریتی در سراسر سیستم است. در SecurityContext، Kubernetes پیکربندی را برای حذف یا اضافه کردن قابلیتها فراهم میکند. قابلیت های فردی یا یک لیست جدا شده با کاما ممکن است به عنوان یک آرایه رشته ای ارائه شود. همچنین، میتوانید از کوتاهنویسی -all برای افزودن یا حذف همه قابلیتها استفاده کنید. این پیکربندی به زمان اجرای کانتینر منتقل میشود و مجموعه قابلیتها را هنگام ایجاد کانتینر پیکربندی میکند. اگر هیچ بخش قابلیتی در SecurityContext وجود نداشته باشد، آن کانتینر با مجموعه قابلیتهای پیشفرض که زمان اجرا کانتینر ارائه میکند ارائه میشود.
روش توصیهشده این است که همه قابلیتها را کنار بگذارید، سپس فقط آنهایی را که برنامهتان واقعاً به آن نیاز دارد، دوباره اضافه کنید. در بسیاری از موارد، برنامهها در عمل عادی به هیچ قابلیتی نیاز ندارند، آن را با حذف همه آنها آزمایش کنید و با نظارت بر گزارشهای حسابرسی برای مشاهده اینکه کدام قابلیتها مسدود شدهاند، هر گونه خرابی را رفع اشکال کنید. توجه داشته باشید که هنگام فهرست کردن قابلیت هایی برای حذف یا اضافه کردن در SecurityContext، پیشوند CAP_ را که هسته در قابلیت های نام گذاری استفاده می کند، حذف می کنید. برای اهداف اشکالزدایی، ابزار capsh خروجی قابل خواندن توسط انسان را در اختیار شما قرار میدهد که دقیقاً کدام قابلیتها در کانتینر شما فعال هستند و برای اکثر توزیعها موجود است. این را در ظروف تولیدی در دسترس قرار ندهید، زیرا این کار را برای مهاجم آسان میکند تا بفهمد کدام قابلیتها فعال هستند! اگر واقعاً عاشق خواندن بیت مپ هستید، می توانید قابلیت های فعال شده در فایل /proc/1/status را نیز بررسی کنید.
با حذف قابلیت های پیش فرض یک کانتینر، نحوه بهبود امنیت Kubernetes را بیاموزید.
7. Run with a read-only filesystem [C]
اگر کانتینر شما به خطر بیفتد، و دارای یک سیستم فایل خواندن و نوشتن باشد، مهاجم میتواند پیکربندی آن را تغییر دهد، نرمافزار نصب کند و بهطور بالقوه اکسپلویتهای دیگری را راهاندازی کند. داشتن یک فایل سیستم فقط خواندنی با محدود کردن اقداماتی که مهاجم می تواند انجام دهد، به جلوگیری از این نوع تشدیدها کمک می کند. به طور کلی، کانتینرها نباید نیاز به نوشتن در سیستم فایل کانتینر داشته باشند. اگر برنامه شما دارای داده های حالت است، باید از یک روش ماندگاری خارجی مانند پایگاه داده، حجم یا سرویس دیگری استفاده کنید. همچنین، اطمینان حاصل کنید که همه گزارشها در stdout و/یا یک log Forwarder نوشته شدهاند، جایی که میتوان آنها را به صورت مرکزی جمعآوری کرد.
8. procMount [C]
بهطور پیشفرض، زمانهای اجرا کانتینر بخشهای خاصی از سیستم فایل proc/را از داخل یک کانتینر پنهان میکنند تا از مشکلات امنیتی احتمالی جلوگیری شود. با این حال، مواقعی وجود دارد که دسترسی به آن بخشهای /proc ضروری است. به ویژه هنگام استفاده از کانتینرهای تو در تو که اغلب به عنوان بخشی از فرآیند ساخت درون خوشه ای استفاده می شود. فقط دو گزینه معتبر برای این ورودی وجود دارد: پیشفرض، که رفتار زمان اجرای کانتینر استاندارد را حفظ میکند، یا Unmasked، که تمام پوششها را برای سیستم فایل **/proc** حذف میکند.
بدیهی است که فقط در صورتی باید از این ورودی استفاده کنید که واقعاً بدانید چه کاری انجام می دهید. اگر از آن برای اهداف ساخت تصویر استفاده می کنید، آخرین نسخه ابزار ساخت خود را بررسی کنید زیرا بسیاری دیگر به این نیاز ندارند. ارتقا دهید و به procMount پیشفرض برگردید که برای ابزاری که استفاده میکنید صادق است. در نهایت، اگر متوجه شدید که به استفاده از این نیاز دارید، این کار را فقط برای یک ظرف تودرتو انجام دهید. هرگز /procfilesystem سیستم میزبان خود را در معرض یک کانتینر قرار ندهید.
9. fsGroup / fsGroupChangePolicy [P]
تنظیم fsGroup گروهی را تعریف میکند که Kubernetes مجوزهای همه فایلها را در حجمها به زمانی تغییر میدهد که حجمها توسط یک پاد نصب میشوند. رفتار در اینجا نیز توسط fsGroupChangePolicy کنترل میشود که میتواند روی onRootMismatch یا Always تنظیم شود. اگر روی onRootMismatch تنظیم شود، مجوزها تنها در صورتی تغییر میکنند که از قبل با مجوزهای ریشه کانتینر مطابقت نداشته باشند. در استفاده از fsGroup محتاط باشید. تغییر مالکیت گروهی کل یک جلد میتواند باعث تاخیر در راهاندازی پاد برای سیستمهای فایل کند و/یا بزرگ شود. همچنین اگر فرآیندهای آنها مجوز دسترسی به GID جدید را نداشته باشند، می تواند برای سایر فرآیندهایی که حجم مشابهی دارند نیز مضر باشد. به همین دلیل، برخی از ارائه دهندگان سیستم های فایل مشترک مانند NFS این قابلیت را اجرا نمی کنند. این تنظیمات همچنین بر حجم های زودگذر تأثیر نمی گذارد.
10. sysctls [P]
Sysctls تابعی از هسته لینوکس است که به مدیران اجازه می دهد تا پیکربندی هسته را تغییر دهند. در یک سیستم عامل کامل لینوکس، اینها با استفاده از /etc/sysctl.conf تعریف می شوند و همچنین می توانند با استفاده از ابزار **sysctl** تغییر داده شوند. تنظیم sysctls در SecurityContext به sysctls خاصی اجازه میدهد تا در کانتینر اصلاح شوند. تنها یک زیرمجموعه کوچک از sysctls سیستم عامل وجود دارد که می توان آنها را بر اساس هر کانتینر تغییر داد که در فضای نام در هسته قرار دارند. از این زیر مجموعه، برخی ایمن در نظر گرفته می شوند. بسته به پتانسیل ضربه زدن به سایر غلاف ها، مجموعه بسیار بزرگتر ناامن در نظر گرفته می شود. sysctls ناامن به طور کلی در خوشه ها غیرفعال هستند و باید به طور خاص توسط مدیر خوشه فعال شوند. با توجه به پتانسیل بی ثبات کردن سیستم عامل زیربنایی، باید از اصلاح پارامترهای هسته از طریق sysctls اجتناب شود، مگر اینکه الزامات بسیار خاصی داشته باشید. همچنین باید چنین تغییراتی را با اپراتور خوشه خود بررسی کنید.
نکته ای در مورد SecurityContext در زمان اجرا
در بسیاری از موارد، تنظیمات امنیتی شرح داده شده در اینجا با کنترل پذیرش مبتنی بر سیاست ترکیب میشوند تا اطمینان حاصل شود که تنظیمات مورد نیاز در واقع قبل از راهاندازی کانتینرها در خوشه پیکربندی شدهاند. با ترکیب تنظیمات SecurityContext با PodSecurityPolicy، میتوانید اطمینان حاصل کنید که فقط کانتینرهایی که از این خطمشی پیروی میکنند با اعمال تنظیمات امنیتی خاص راهاندازی میشوند. تنظیمات SecurityContext همچنین میتواند به پیکربندی کانتینر در زمان راهاندازی ازDynamic Admission Control و استفاده از webhooks جهشیافته اضافه شود.
نتیجه :
هنگام سختتر کردن استقرار برنامهها با تنظیمات SecurityContext، موارد زیادی وجود دارد که باید در نظر داشته باشید. هنگامی که به درستی استفاده می شوند، ابزار بسیار موثری هستند و امیدواریم این لیست به تیم شما کمک کند تا گزینه های مناسب را برای حجم کاری و محیط شما انتخاب کند.
دیدگاهتان را بنویسید
برای نوشتن دیدگاه باید وارد بشوید.