آموزش اجرای Docker Containers به عنوان کاربر Non-Root
به طور پیش فرض کانتینرهای Docker به صورت UID 0 یا root اجرا میشوند؛ یعنی اگر کانتینر Docker در معرض خطر قرار گیرد، مهاجم دسترسی rootدر سطح میزبان به تمام منابع تخصیص داده شده به کانتینر خواهد داشت. با استفاده از یک کاربر Non-Root، حتی اگر مهاجم بتواند از برنامه در حال اجرا در کانتینر خارج شود، اگر کانتینر به عنوان کاربر Non-Root در حال اجرا باشد، مجوزهای محدودی خواهد داشت.در این مطلب، مراحل دقیق اجرای کانتینرهای Docker را به عنوان کاربر Non-Root با ایجاد یک کاربر سفارشی در Dockerfile توضیح دادهایم.
کاربر Non-Root چیست؟
کاربر Non-Root یک کاربر استاندارد با مجوزهای محدود در منابع سیستم است. آنها هیچ امتیازی جز مجوزهای داده شده، ندارند.
به عنوان مثال، بر خلاف یک کاربر root، یک کاربر Non-Root پس از اینکه در دایرکتوری اصلی خود مجوز دریافت کرد، نمیتواند فایلها و پوشهها را در دایرکتوری اصلی کاربر دیگر ایجاد، ویرایش یا حذف کند.
به طور پیشفرض، کاربران Non-Root نمیتوانند از sudo استفاده کنند، اما میتوان آنها را برای استفاده از sudo برای دستورات خاص پیکربندی کرد.
اجرای برنامهها با کاربر Non-Root
قبل از اینکه به مثال عملی نگاه کنیم، بیایید الزامات و تنظیمات برای اجرای برنامهها در داخل کانتینر با استفاده از یک کاربر Non-Root را درک کنیم.
منظور از برنامهها، میتواند جاوا، Node.js، روبی، پایتون و غیره باشد
یک نکته کلیدی که باید به خاطر بسپارید این است که کاربر Non-Root باید به کد برنامه و فایلهای مرتبط دسترسی داشته باشد. این شبیه به اجرای یک برنامه به عنوان یک کاربر Non-Root در یک سیستم لینوکس است.
به عنوان مثال، فرض کنید میخواهید یک برنامه جاوا را در یک کانتینر Docker اجرا کرده و کد برنامه جاوا و تنظیمات مربوطه در پوشه app/ قرار می گیرد.
در این حالت، کاربر Non-Root که ایجاد میکنید باید مجوزهای خواندن/نوشتن لازم را مستقیم برای برنامه داشته باشد.
کاربر Non-Root هیچ دسترسی خاص دیگری به فایلهای مربوط به سیستم نخواهد داشت مگر اینکه به طور خاص مجوزهایی را اضافه کنید.
اکنون که اصول اولیه را درک کردیم، بیایید به یک مثال عملی از ایجاد یک ایمیج Docker با یک کاربر Non-Root نگاه کنیم.
خرید سرور مجازی لینوکس در پنج موقعیت جغرافیایی ایران، ترکیه، هلند، آلمان و آمریکا با قابلیت تحویل آنی در پارسدو فراهم است.
آیا میدانید در پارسدو میتوان سرور مجازی Docker بر بستر دبیان سفارش داد؟
یک Docker Image با یک کاربر Non-Root ایجاد کنید
برای نشان دادن کاربران Non-Root، یک ایمیج داکر Nginx ایجاد میکنیم.
ما یک Dockerfile با یک کاربر Non-Root سفارشی ایجاد و مجوزهای لازم را برای آن کاربر اضافه میکنیم تا سرویس Nginx را در کانتینر اجرا کند.
یک Dockerfile ایجاد و محتوای Dockerfile زیر را کپی نمائید:
FROM nginx:alpine
RUN addgroup -g 1001 -S nginxgroup && adduser -u 1001 -S -G nginxgroup nginxuser
RUN mkdir -p /var/run/nginx /var/cache/nginx/client_temp /var/cache/nginx/proxy_temp /var/cache/nginx/fastcgi_temp /var/cache/nginx/scgi_temp /var/cache/nginx/uwsgi_temp \
&& chown -R nginxuser:nginxgroup /var/cache/nginx /var/run/nginx /var/log/nginx /etc/nginx /usr/share/nginx/html
RUN sed -i 's/listen 80;/listen 8080;/g' /etc/nginx/conf.d/default.conf
RUN sed -i 's/\/var\/run\/nginx.pid/\/var\/run\/nginx\/nginx.pid/g' /etc/nginx/nginx.conf
USER nginxuser
EXPOSE 8080
CMD ["nginx", "-g", "daemon off;"]
بیایید این Dockerfile و تنظیمات کلیدی مربوط به ایجاد یک کاربر Non-Root را درک کنیم.
- این Dockerfile از nginx به عنوان ایمیج اصلی استفاده میکند.
- یک گروه nginxgroup با GID 1001 و یک کاربر nginxuser با UID 1001 ایجاد نموده و مالکیت کاربر Non-Root دایرکتوریهای Nginx را میدهد. ایجاد کاربر و گروه با آیدیها به ویژه هنگامی که این ایمیج را در Kubernetes اجرا میکنید مفید است. با تنظیم صریح UID و GID در ایمیج داکر، میتوانید این شناسهها را با تنظیمات SecurityContext در Kubernetes تراز کنید.
- سپس دایرکتوریهای موقت (temporary ) مورد نیاز را برای Nginx ایجاد میکند و آنها را به کاربر Non-Root اختصاص میدهد تا Nginx بتواند دادههای خود را روی دایرکتوریهای مورد نیاز بنویسد.
- به عنوان مثال، دایرکتوری /var/cache/nginx/client_temp دادههای درخواست موقت HTTP ارسال و دریافت شده توسط Nginx را ذخیره میکند. /var/run/nginx PID ایجاد شده توسط Nignx را در حین راه اندازی نگه می دارد (در مرحله 6 توضیح داده شده است).
- دستور SED پورت Nginx را برای گوش دادن به 8080 تغییر میدهد زیرا پورتهای زیر 1024 پورتهای ممتاز (privileged ports) هستند، به این معنی که فقط کاربرانی که مجوز root دارند میتوانند به طور پیشفرض از آنها استفاده کنند.
- در حین راه اندازی، Nginx به طور پیش فرض PID خود را در پوشه /var/run مینویسد. دستور دوم SED مکان فایل PID را به /var/run/nginx تغییر میدهد زیرا کاربر Non-Root هیچ مجوزی در پوشه/var/run ندارد. با ایجاد و تغییر مجوز دایرکتوری /var/run/nginx به یک کاربر Non-Root ، Nginx می تواند فایل PID را در آن ذخیره کند.
- سپس، کاربر را به یک کاربر غیر روت nginxuser سوئیچ میکند، زیرا اگر به non-user سوئیچ نکنیم، بهطور پیشفرض بهعنوان یک کاربر root اجرا میشود.
- و پورت 8080 را برای دسترسی خارجی در معرض دید قرار می دهد.
- در نهایت، دستور CMD به داکر میگوید Nginx را در پیشزمینه راهاندازی کند. daemon off Nginx را در حال اجرا نگه میدارد و مطمئن میشود که به پسزمینه نمیرود، که باعث توقف کانتینر میشود.
حال از دستور زیر برای ساخت ایمیج داکر استفاده کنید.
docker build -t nginx-non-root:1.0.0
توجه: اگر میخواهید این کانتینر را در Kubernetes بهعنوان کاربر Non-Root با استفاده از SecurityContext اجرا کنید، معمولا اختصاص یک شناسه خاص به کاربر و گروه مفید است.
همچنین، اگر شناسهای مشخص نکنید، یک شناسه تصادفی به کاربر و گروه اختصاص میدهد که در صورت عدم تعیین شناسه صحیح، هنگام استقرار در Kubernets با خطا مواجه میشود.
همچنین، راههایی مانند setcap برای استفاده از پورتهای ممتاز توسط کاربران Non-Root با اختصاص دادن قابلیت CAP_NET_BIND_SERVICE به یک فایل اجرایی وجود دارد، اما به دلیل نگرانیهای امنیتی توصیه نمیشود.
Docker Container را به عنوان کاربر Non-Root اجرا کنید
اکنون که ایمیج ساخته شده است، کانتینر را اجرا و آن را آزمایش میکنیم تا ببینیم به عنوان یک کاربر Non-Root اجرا می شود یا خیر.
از دستور زیر برای اجرای ایمیج داکر در یک کانتینر استفاده کنید.
docker run -d -p 8080:8080 nginx-non-root:1.0.0
دستور زیر را برای بررسی اینکه آیا کانتینر در حال اجرا است را اجرا کنید
docker ps
اگر کانتینر شما در حال اجرا است، کاربر فعلی را با استفاده از دستور docker inspect بررسی کنید
docker inspect -f '{{.Config.User}}' 9638a5772391
آیدی کانتینر Docker خود را جایگزین 9638a5772391 کنید.
این دستور کاربر فعلی کانتینر را به شما نشان می دهد
یا می توانید از دستور exec برای دسترسی به شل کانتینر نیز استفاده کنید
docker exec -it 9638a5772391
سپس از دستور whoami برای بررسی کاربر فعلی مانند شکل زیر استفاده کنید
میتوانید ببینید که کانتینر بهعنوان یک کاربر Non-Root nginxuser در حال اجرا است
حال اگر می خواهید کانتینر Non-Root را به عنوان کاربر root اجرا کنید، دستور زیر را اجرا کنید
برای این کار، Docker image را در یک کانتینر در حالت تعاملی اجرا می کنیم
docker run -u 0 -it nginx-non-root:1.0.0 /bin/sh
گزینه u 0- به کانتینر میگوید که به عنوان کاربر root اجرا شود، 0 UID کاربر root است.
UID 0 به معنی (User ID 0) برای کاربر root محفوظ است که سوپر یوزر یا مدیر با دسترسی کامل به تمام دستورات و فایلهای سیستم است.
نتیجه گیری
در این مطلب با کاربر غیر روت و نحوه ایجاد کاربر non-root برای یک اپلیکیشن آشنا شده و در مورد اهمیت آن و چگونگی کاهش خطرات امنیتی یاد گرفتهاید.