امنیت در میکروسرویس‌ها - قسمت اول

1. مقدمه تاریخچه، نحوه امن کردن نرم‌افزارهای یکپارچه

یک نرم‌افزار یکپارچه تعداد کمی درگاه ورودی دارد. درگاه ورودی برای یک نرم‌افزار حکم درب یک ساختمان را دارد. همانطور که درب ورودی امکان وارد شدن به یک ساختمان را می‏دهد (احتمالا بعد از بررسی‏های امنیتی)، درگاه ورودی یک اپلیکیشن هم امکان درخواست دادن را مهیا می‏کند.

یک نرم‌افزار تحت وب را تصور کنید (تصویر 1 را ببینید) که روی درگاهپیشفرض HTTP یعنی درگاه شماره 80 یک سرور با آدرس 192.168.0.1 در حال اجراست. درگاه 80 سرور 192.168.0.1 روی این سرور بعنوان مدخل ورودی نرم‌افزار ما است. اگر همین نرم‌افزار درخواست‏های HTTPS روی درگاه 443 همین سرور را هم بپذیرد، اکنون یک درگاه ورودی دیگر هم داریم. هرچقدر درگاه ورودی بیشتری داشته باشید، مکان‏های بیشتری برای نگرانی داریم. بعنوان مثال، زمانیکه مرز بیشتری برای محافظت دارید، سربازهای بیشتری هم نیاز دارید، یا باید دیواری مستحکم برای تمام درگاه‎های ورودی بسازید. درگاه‎های ورودی بیشتر یک اپلیکیشن به معنای مرزهایی هستند که مورد حمله قرار میگیرند.

عمده نرم‌افزارهای یکپارچه، تعداد کمی درگاه ورودی بیشتر ندارند. هر جزء یک نرم‌افزار یکپارچه که به دنیای خارج سرویس میدهد، بطور مستقیم درخواست را قبول نمی‌کنند.

در بستر معمول جاوا (وب اپلیکیشن‏های نسخه‌‏ی سازمانی Java EE که در تصویر 1 آماده است)، تمام درخواست‏های ورودی در سطح نرم‌افزار به واسطه‏ی servlet filter بررسی می‏شوند. در این غربالگری امنیتی بررسی می‏شود که آیا درخواست جاری مرتبط به یک نشست معتبر است و اگر نیست این درخواست را به سمت احراز هویت سوق دهد.

تصویر 1 نمونه نرم‌افزار یکپارچه با دو درگاه ورودی
تصویر 1 نمونه نرم‌افزار یکپارچه با دو درگاه ورودی

در مرحله بعد کنترل دسترسی‏های بیشتر بررسی می‌کنند که آیا طرف درخواست کننده اجازه یا صلاحیت‏های مورد نیاز برای آنچه که می‌خواهد را دارد یا نه. تمامی این کارها را بازرس بطور مرکزی انجام می‌دهد تا مطمئن شود درخواست‏های مشروع و مورد قبول به اجزای مربوطه برسد. اجزای درونی اهمیتی به مشروعیت درخواست نمی‌دهند، و همواره چنین پیشفرضی دارند که اگر درخواستی که به این مرحله رسیده است حتما موارد امنیتی آن بررسی شده است.

در مواردی که اجزا‏ نیاز داشته باشند که بدانند طرف درخواست کننده (یا کاربر) کیست یا اطلاعاتی مرتبط با طرف درخواست کننده داشته باشند، چنین اطلاعاتی را می‌توانند از نشست وب که در سطح اپلیکیشن و برای تمام اجزا مشترک است، بازیابی کنند (عکس 2 را ببینید). Servlet filter در فرایند غربالگری اولیه بعد از فرایند احراز هویت و احراز مجوزها، اطلاعات طرف درخواست کننده را به نشست وب تزریق می‌کند.

هنگامی که درخواست به لایه اپلیکیشن رسید، دیگر نباید نگرانی‌ای درخصوص ارتباط یک جزء با دیگری داشت. بعنوان مثال، زمانیکه زیرسیستم Order Processing با زیرسیستم Inventory صحبت می‏کند، الزامی به بررسی‏های امنیتی بیشتر نیست (البته این به این معنا نیست که شما نمی‌توانید به ازای هر جز، در سطح کامپوننت کنترل دسترسی داشته باشید). این عملیات فراخوانی‏های داخلی هستند و در غالب اوقات شنود آن برای شخص ثالث کار دشواری خواهد بود.

تصویر 2 اشتراک نشست توسط بازرس مرکزی برای اجزا داخلی سیستم
تصویر 2 اشتراک نشست توسط بازرس مرکزی برای اجزا داخلی سیستم

در اکثر نرم‌افزار‏های یکپارچه، امنیت در یک بخش مرکزی قرار دارد و تک تک اجزا نیازی به بررسی‏های بیشتر ندارند مگر در موارد بخصوص بسته به نوع نیاز داخلی یک قسمت از برنامه. به همین دلیل مدل امنیتی نرم‌افزار‏های یکپارچه به مراتب سر راست‌تر از میکروسرویس‌ها است.

2. مبانی کلیدی امنیت:

پایبندی به اصول در همه طرح‌های امنیتی مهم است. هیچ امنیت بی‎‌نقص و یا غیرقابل شکستنی وجود ندارد. باید این نکته را نیز در نظر بگیرید که میزان نگرانی شما در رابطه با امنیت صرفا یک کار فنی نبوده و تاثیرات اقتصادی نیز دارد. برای مثال برای امن کردن یک گاراژ خالی استفاده از یک دزدگیر فوق پیشرفته بی‌فایده است. بسته به دارایی که از آن‌ها محافظت می‌کنیم، سطح امنیت نیز تغییر می‌کند. به طور یقین طرح امنیتی برای یک فروشگاه اینترنتی با یک نرم‌افزار مالی متفاوت است.

پایبندی به اصول امنیتی مهم است. حتی اگر برخی تهدیدات امنیتی را پیشبینی نکنید، پیروی از اصول امنیتی به شما برای در امان ماندن از این تهدیدات کمک خواهد. در این قسمت، ما اصول امنیتی را گام به گام با شما بررسی می‌کنیم و به ارتباط آن‎ها با امنیت میکروسرویس‎ها خواهیم پرداخت.

2.1. جلوگیری از کلاهبرداری به کمک احراز هویت:

شناسایی طرف درخواست کننده به‌منظور حفاظت از سیستم در برابر کلاهبرداری را احراز هویت می‌نامیم. طرف درخواست کننده می‌تواند یک سیستم باشد (یک میکروسرویس) یا یک سیستمی که توسط کاربر انسانی یا یک سیستم دیگر کنترل میشود (تصویر 3 را ببینید). این نوع دسترسی با دسترسی مستقیم کاربر انسانی به یک میکروسرویس متفاوت است. پیش از ایجاد یک طرح امنیتی برای سیستمی که درباره آن صحبت کردیم، باید شرکت‌کنندگان را بشناسیم. روش احراز هویتی که استفاده می‌کنید وابسته به شرکت کنندگان است.

تصویر 3 اتصال سرویس‌ها به یکدیگر با و یدون عامل انسانی
تصویر 3 اتصال سرویس‌ها به یکدیگر با و یدون عامل انسانی

اگر نگران دسترسی یک سیستم به میکروسرویس هستید که در پشت صحنه توسط یک کابر هدایت می‌شود باید به این موضوع فکر کنید که چگونه آن سیستم می‌تواند مانند یک کاربرا در سیستم احراز هویت شود. در عمل ممکن است یک وب اپلیکیشن داشته باشیم که کاربری انسانی در آن احراز هویت شده و آن سیستم به میکروسرویس متصل می‌شود. در شرایطی، که یک سیستم درخواست دسترسی از طرف یک سیستم دیگر که قبل از آن یک عامل انسانی در آن احراز هویت شده است دارد، OAuth 2.0 استاندارد امنیتی مناسبی است.

برای احراز هویت کاربرانسانی به سیستم ( برای مثال، یک وب اپلیکیشن)،در روش‌های مبتنی بر چند روش احراز هویت، باید درخواست نام کاربری و رمز عبور به همراه عنصر دیگر برای احرازهویت داشته باشید (Multi-Factor Authentication یا MFA). در اغلب موارد MFA یک تصمیم تجاری است که با توجه به میزان اهمیت دارایی‎های تجاری و یا میزان حساسیت داده‎هایی که میخواهید به کاربران منتقل کنید گرفته می‌شود. مشهورترین نوع استفاده از MFA کدعبور یکبار مصرف است (One time password یا OTP) که معمولا از طریق پیامک (SMS) ارسال می‌شود. شاید این راه در دنیای امنیت بهترین روش نباشد، اما پراستفاده‎‌ترین شکل از بکارگیری MFA می‌باشد، چرا که عمدتا جمعیت کثیری از جهان به تلفن‌های موبایل دسترسی دارند که الزاما نیازی هم نیست تلفن های هوشمند باشند. MFA به کاهش 99.99 درصدی رخنه‌‎های مربوط به حساب کاربری منجر شده است. انواع مطمئن‏‌تری از MFA وجود داند که از علائم حیاتی، گواهینامه‎‌ها و Fast Identity Online (FIDO) استفاده میکند.

چندین راه برای احرازهویت یک سیستم وجود دارد که محبوب‎ترین گزینه‏‌ها استفاده از گواهینامه‎‌ها و JWTها می‌باشد.

2.2. جلوگیری از تغییر غیرمجاز داده‌ها به کمک یکپارچگی:

هنگامی که داده ها بین دو سرویس انتقال پیدا می‌کند، با توجه به قدرت کانال ارتباطی که مورد استفاده قرار می‌گیرد، ممکن است داده‌ها توسط فردی نفوذی در مسیر انتقال تغییر پیدا کند. برای مثال ممکن است پیامی که بین دو سیستم انتقال پیدا می‌کند مربوط به آدرس ارسال یک سفارش اینترنتی باشد و فرد نفوذی آدرس خود را با آدرس دریافت کننده حقیقی جایگزین کند. در حقیقت سیستم‌های مبتنی بر یکپارچگی راهکاری جهت جلوگیری از این دسترسی ارائه نمی‌کنند، بلکه راهکارهایی ایجاد می‌کنند که به کمک آن از تغییر داده‌ها در بین راه مطلع شوید.

یکی از راهکارهای معمول برای پیاده سازی یکپارچگی داده، امضا کردن آن‌ها است. هر داده‌ای که انتقال پیدا می‌کند به کمک TLSمحافظت می‌شود. اگر از HTTPS برای انتقال داده‌ها بین سرویس‌ها استفاده کنید، پیام‌های شما به کمک TLSحفاظت می‌شود.

2.3. انکار ناپذیری:

انکارناپذیری یکی از اصول امنیت نرم‌افزار است که مانع از عدم پذیرش مسئولیت کارهایی که انجام داده‌ایم می‌شود. در دنیای واقعی نیز چنین شرایطی وجود دارد. برای مثال فرض کنید زمانی‌که شما یک آپارتمان اجاره می‌کنید، برای مدت و هزینه‌ای معین، یک قرارداد امضا می‌کنید که با امضای آن قرارداد تصریح می‌کنید که به تمامی مفاد آن قرار داد پایبند هستید. شما نمی‌توانید اجاره ماهانه را پرداخت نکنید یا اگر بخواهید زود تر منزل را ترک کنید، یا باید اجاره ماه‌های باقی مانده را پرداخت کنید یا ناچارید شخص جایگزینی برای اجاره منزل بیابید. این انکارناپذیری در دنیای واقعی است. در دنیای دیجیتال نیز امضا همین حکم را دارد و مانع از انکار حقایق می‌شود. فقط به جای امضای حقیقی با امضای دیجیتال سر و کار داریم.

فرض کنید یک فروشگاه اینترنتی دارید، اگر سفارشی در فروشگاه ثبت شود، میکروسرویس مدیریت سفارشات باید به سراغ میکروسرویس انبار برود و موجودی آن کالا را کسر کرده و برای ارسال آماده کند. در صورتی که برای این تراکنش امضای دیجیتال در نظر گرفته شده باشد، در آینده میکروسرویس مدیریت سفارشات نمی‌تواند انجام این تراکنش را انکار کند. در روش امضای دیجیتال، مالک امضا یک کلید خصوصی دارد که تنها به کمک آن امکان ایجاد امضا‌های کاملا مشابه وجود دارد و سایرین به کمک کلید عمومی این امضا را تایید می‌کنند. حفظ و نگهداری کلید خصوصی بسیار اهمیت دارد.

2.4. محرمانگی و جلوگیری از انتشار داده‌های خصوصی:

هنگامی که درخواست ثبت یک سفارش از نرم‌افزار مشتری به میکروسرویس ثبت سفارشات ارسال می‌شود، شما توقع دارید که به جز بخش ثبت سفارشات سایر قسمت‌ها به اطلاعات در حال جابجایی دسترسی نداشته باشند. با توجه به سطح امنیتی که کانال ارتباطی شما رعایت می‌کند، یک متجاوز می‌تواند به داده‌های در حال انتقال دسترسی داشته باشد. به جز داده‌هایی که روی کانال‌های ارتباطی در حال انتقال هستند، داده‌های داخلی برنامه نیز باید از دسترسی غیرمجاز حفظ شوند. اگر یک فرد متجاوز به محل ذخیره‌سازی فایل‌ها یا پایگاه‌های داده شما دسترسی پیدا کند، به سادگی به تمامی داده‌های حیاتی کسب و کار شما دسترسی خواهد داشت، مگر اینکه آن‌ها را برای چنین روزهایی در سطح محرمانگی خوبی قرار داده باشی.

برای حفظ محرمانگی داده‌های در حال جابجایی معمولا از رمزگذاری داده‌ها استفاده می‌کنند. یک روال رمزگذاری خوب این اطمینان را به ما می‌دهد که اطلاعاتی که رمزنگاری شده است، تنها توسط اهدافی که قرار است به داده‌ها دسترسی داشته باشند قابل مشاهده است. اساسا TLS یکی از روش‌های اطمینان از محرمانگی هنگام انتقال داده‌ها است. اگر میکروسرویس‌های ما برای برقراری ارتباط از HTTPS استفاده کنند، می‌توانیم اطمینان حاصل کنیم که تنها دریافت کننده صحیح توانایی مشاهده داده‌ها را خواهد داشت.

باید به این نکته دقت داشته باشید که این سطح از حفظ محرمانگی صرفا برای جابجایی داده‌ها کاربرد دارد. یعنی داده‌های خام در اختیار مالک اطلاعات است و هنگامی که اقدام به ارسال می‌کند TLS داده‌ها را رمزگذاری کرده و در بستری امن منتقل می‌کند، درست در لحظه ای که انتقال به پایان می‌رسد و داده‌ها به مقصد می‌رسند، مجدد از حالت رمزنگاری خارج شده و به صورت کاملا خام و واضح در اختیار دریافت کننده قرار می‌گیرند.

در صورتی که نیاز داشته باشیم داده‌ها در مقصد نیز باید مجددا رمزگذاری شوند. یعنی هنگامی که اطلاعات را روی دیسک‌های سخت ذخیره می‌کنیم، سایر سیستم‌هایی که به فضای دیسک‌ها دسترسی دارند نباید بتوانند خارج از فرایند میکروسرویس‌های ما به اطلاعات دسترسی داشته باشند و اگر داده‌ای نیاز دارند باید از طریق نرم‌افزار درخواست دسترسی به آن داده‌ها را ارسال کنند. اغلب نرم‌افزارهای پایگاه داده این امکان را به صورت توکار پیاده‌سازی کرده‌اند و برای داده‌های حساس خود می‌توانیم از این امکانات توکار استفاده کنیم.

2.5. دسترسی پذیری ویژگی مهم نرم‌افزار:

یکی از نکاتی که هنگام طراحی سیستم‌های نرم‌افزاری باید به آن توجه کرد این است که سیستم باید دائما در دسترس باشد. از دسترس خارج شدن یک سیستم نرم‌افزاری می‌تواند ضرر هنگفتی را به کسب و کار وارد کند. در ماه مارچ سال 2016 وبسایت آمازون برای 20 دقیقه از دسترس خارج شد و ضرر این سایت برای این 20 دقیقه چیزی در حدود 3.75 میلیون دلار براورد می‌شود. در تابستان سال 1399 وب سایت سفارشات یک کارگزار ایرانی برای 1 روز کاری از دسترس خارج شد و ضرری در حدود 20 میلیارد تومانی برای این کارگزاری و سهامداران عضو آن براورد گردید.

دسترسی‌پذیری یک سامانه‌نرم افزاری صرفا یک ویژگی و کارکرد امنیتی نیست، بلکه مبحثی عمومی و مربوط به معماری کل سیستم می‌شود. برای مثلا یک خطای بحرانی در قلب سورس‌کدهای کسب و کار ممکن است منجر به از دسترس خارج شدن آن شود. اما در بین ویژگی‌های مختلفی که موجود دسترسی‌پذیری سیستم می‌شود، رعایت نکات امنیتی از اهمیت ویژه‌ای برخوردار است.

در یک سیستم که زیرساخت‌های امنیتی خوبی نداشته باشند، حمله کنندگان ممکن است با حملات Dos یا DDos تلاش کنند سیستم را برای ارائه خدمات نا‌توان کنند . مقابله با این حملات در سطوح مختلفی قابل انجام است. در سطح نرم‌افزار بهترین راه مقابله با این حملات این است که به محض یافتن درخواست‌های نامشروع آن‌ها را از چرخه پردازش خارج کنید. طراحی یک نرم‌افزار به صورت چند لایه این امکان را فراهم می‌کند که در هر لایه مراقب برخی تهدیدات امنیتی بود و با یافتن آن‌ها، از ایجاد خسارت توسط آن تهدید جلوگیری کنیم. در یک نرم‌افزار میکروسرویس همه درخواست ها از طریق یک دروازه به APIها می‌رسند. اگر بخواهیم در مورد حملات DDos تصمیم گیری کنیم بهترین محل جلوگیری از آن‌ها ابتدا در لایه شبکه است. اگر از این لایه عبور کرد بهترین راهکار استفاده از دیواره‌آتش است. بعد از آن درخواست‌ها به API Gatewayمی‌رسد که آنجا نیز می‌توانیم با بررسی درخواست‌ها، موارد غیرقانونی را از چرخه حیات خارج کنیم.

2.5. احراز مجوز و تعیین محدوده اختیارات:

احراز هویت به ما می‌گوید که چه فردی با سیستم می‌خواهد کار کند و احراز مجوز تعیین می‌کند که کاربر در چه محدوده‌ای از نرم‌افزار می‌تواند کار خود را انجام دهد . برای مثال در یک سیستم فروشگاه اینترنتی ما ابتدا با احراز هویت مشتری را شناسایی می‌کنیم و پس از آن با احراز مجوز تعیین می‌کنیم که مشتری به چه قسمت‌هایی از نرم‌افزار دسترسی دارد. برای مثلا امکان ثبت سفارش دارد، ‌می‌تواند کالاها را مورد بررسی قرار دهد و می‌تواند سفارشات پیشین خود را مشاهده کند، اما نمی‌تواند قیمت یک کالا را تغییر دهد یا کالای جدید ثبت کند. در یک سیستم توسعه داده شده بر مبنای میکروسرویس این احراز مجوز معمولا در مرزهایبیرونی که همان API Gateway است اتفاق می‌افتد. در اصل ارتباط اگر از بیرون سیستم باشد در سطح مرز و API Gateway احراز مجوز می‌شود. ولی ممکن است در هنگام ارتباط داخلی بین سرویس‌ها نیز نیاز به احراز هویت و مجوز داشته باشیم که در این سطح دیگر داخل سرویس‌ها این عملیات انجام می‌شود.

3. جمع بندی:

در این مطلب که در چندین قسمت منتشر خواهد شد به بحث و بررسی موارد امنیتی در حوزه نرم‌افزارهای توزیع شده می پردازیم. مطالبی که در قسمت اول عنوان شد اغلب به حوزه عمومی برنامه‌ها و معماری یک‌پارچه نیز مرتبط است که در قسمت‌های بعد این مباحث را در نرم‌افزارهای توزیع شده با جزئیات بیشتری بررسی خواهیم کرد.

در صورتی که دوست داشتید با این مفاهیم بهتر و دقیق‌تر آشنا بشید منابع زیر کمک بسیار کمک کننده خواهند بود:

1. Christudas, B. (2019). Practical Microservices Architectural Patterns. Berkeley, CA: APress.

2. Fowler, m., Lewis, J. (2014). Microservice A Definitioin of This New Architecture Term. https://martinfowler.com/articles/microservices.html

3. Gilman, E., Barth, D. (2017). Zero Trust Networks: Building Secure Systems in Untrusted Networks. Cambridge, England: O’Reilly.

4. IDC. (2018). Enterprise Adoption of Microservices Architecture Push ISVs to Modernize. https://www.idc.com/getdoc.jsp?containerId=US44929819

5. J.Fowler, S. (2017). Production-Ready Microservices. Cambridge, England: O’Reilly.

6. Kamaraju, A. (2012). Database encryption demystified: Four common misconceptions. https://www.zdnet.com/article/database-encryption-demystified-four-common-misconceptions/

7. Joseph. C, Chandrasekaran .K, (2019). Straddling the crevasse: A review of microservice software architecture foundations and recent advancements. Software: Practive and Experience, 49(10), 1448–1484.

8. Lepofsky, R. (2014). The Manager’s Guide to Web Application Security. Berkeley, CA: APress.

9. Lu. D, Huang .D, Walenstein .A & , Medhi .D, (2017). A Secure Microservice Framework for IoT. 2017 11th IEEE Symposium on Service-Oriented System Engineering (SOSE), 1, 9–18.

10. McDonald, M. (2020). Web Security for Developers Real Threats, Practical Defense. San Francisco, US: No Starch Press.

11. Mauro, T. (2015). Adopting Microservices at Netflix: Lessons for Architectural Design. https://www.nginx.com/blog/microservices-at-netflix-architectural-best-practices/

12. Newman, S. (2015). Building Microservices Designing Fine-Grained System. Cambridge, England: O’Reilly.

13. Newman, S. (2018). Monolith to Microservices Evolutionary Patterns to Transform Your Monolith. Cambridge, England: O’Reilly.

14. Rafe. V, Hosseinpouri. R, (2015). A security framework for developing service‐oriented software architectures. Security And Communication Networks, 8(17), 2957–2972.

15. Siriwardena, P. (2020). Advanced API Security: OAuth 2.0 and Beyond Berkeley, CA: APress.

16. Siriwardena, P., & Dias, N. (2020). Microservices Security in Action. Ny, USA: Manning.

17. Yarygina. T, Bagge. A, (2018). Overcoming Security Challenges in Microservice Architectures. 2018 IEEE Symposium on Service-Oriented System Engineering (SOSE), 1, 11–21.

18. Yu. D, Jin. Y, Zhang. Y& Zheng. X, (2018). A survey on security issues in services communication of Microservices‐enabled fog applications. Concurrency and Computation Practive and Experience.