در چشم انداز همیشه در حال تحول معماری ابر، نقش رابط های برنامه نویسی کاربردی (API) به طور فزاینده ای حیاتی شده است. APIها به عنوان پلی عمل می کنند که به نرم افزارهای مختلف اجازه می دهد تا به طور یکپارچه با هم ارتباط برقرار کنند. این مقاله به بررسی اهمیت APIها در معماری ابر و تصمیم حیاتی در انتخاب درگاه API مناسب میپردازد.
کامپوننت درگاه API در یک معماری بومی ابری بسیار مهم است زیرا امنیت و خطمشی مهم API را در یک مکان مشترک تخلیه میکند و به APIها و سرویسهای بک اند اجازه میدهد بر منطق تجاری تمرکز کنند. احراز هویت API، مجوز، audit، throttling و کارهای مشابه می تواند پیچیده و دشوار باشد، بنابراین بسیاری از سازمان ها یک درگاه API را برای رسیدگی به آنها انتخاب می کنند.
آشنایی با دروازه های API
دروازه های API به عنوان واسطه بین برنامه های نرم افزاری مختلف عمل می کنند و ارتباطات و تبادل داده ها را تسهیل می کنند. این دروازهها به ویژگیهای ضروری مانند مسیریابی درخواست، ترکیب و ترجمه پروتکل مجهز هستند که آنها را در سیستمهای مبتنی بر ابر مدرن ضروری میسازد.
برای سرویس به سرویس (S2S) یا ترافیک داخلی، شرقی/غربی چطور؟ اجبار کردن ترافیک S2S به "hairpin" از طریق درگاه API باعث ایجاد پرش بیشتر، تاخیر بیشتر، افزایش ترافیک و کاهش کارایی می شود.
اما اگر از درگاه API صرف نظر کنید و مستقیماً سرویس ها را صدا بزنید، چگونه می توانید ترافیک را ایمن کنید؟ سرویس گیرنده چگونه احراز هویت می کند و می داند چه کسی آن را صدا می زند؟
دو روش متداول برای ایمن سازی ارتباطات S2S عبارتند از:
- با استفاده از امنیت لایه حمل و نقل (TLS) و گواهی های مشتری (TLS متقابل یا mTLS).
- استفاده از رمزهای وب JSON امضا شده (JWT).
مش سرویس با استفاده از گزینه یک مشکل را حل میکند تا بسیاری از بهترین شیوهها را خودکار کند و نکات منفی را کاهش دهد.
توسعهدهندگان ممکن است استفاده از JWTها را برای احراز هویت S2S انتخاب کنند، اما این کار آنچه را که از درگاه API انتظار دارید انجام دهد، آشکار میکند. یعنی تمام پیچیدگی و شکنندگی مدیریت امنیتی که در درگاه API بارگذاری کردهاید باید در هر میکروسرویس برای ارتباط S2S دوباره ایجاد و تکرار شود. این یک مشکل بزرگ است زیرا استفاده از JWT ها برای احراز هویت S2S با پیچیدگی و توجه به جزئیات همراه است.
اگرچه فریمورک ها و کتابخانه های عالی برای مدیریت JWT ها وجود دارد، و در حالی که JWT جای خود را دارد، استفاده از JWT برای احراز هویت ترافیک S2S پیچیده، سنگین است و اعتماد زیادی به توسعه دهندگان برای درست کردن کارها می کند. این پیچیدگی (یا عدم آگاهی) میتواند وضعیت امنیتی کلی را کاهش دهد، اگر توسعهدهندگان از ویژگیهای مهم چشم پوشی کنند. توسعه دهندگان همچنین باید این کار را به روشی خاص برای زبان و فریمورک ها انجام دهند (به عنوان مثال، حل آن در PHP با Go یا Node.js متفاوت است). نگهداری، patching و auditing هر پیاده سازی در تمامی پایگاه های کد هزینه بر است.
نحوه استفاده از JWT برای احراز هویت ارتباطات S2S
دو رویکرد برای ایجاد یک JWT برای احراز هویت ارتباطات S2S وجود دارد: استفاده از یک ارائهدهنده هویت (IdP) (با نام مستعار سرویس رمز امن یا STS) یا اجازه دادن به سرویسهای فردی برای امضای JWTها. (اگر تازه کار هستید یا نیاز به تجدید نظر در مفاهیم JWT دارید، AuthO نمای کلی خوبی از JWT ها ارائه می دهد.)
گزینه 1: از STS برای صدور توکن استفاده کنید
رویکرد اول از یک سرویس توکن ایمن (STS)، یک هویت یا ارائهدهنده توکن قابل اعتماد، مانند Keycloak، Okta یا Auth0 برای صدور توکنهایی استفاده میکند که نشان دهنده یک سرویس خاص هستند.
در این رویکرد، یک سرویس یک اعتبار بلندمدت (مانند نام کاربری و رمز عبور یا اعتبار مشتری OAuth2.0) را با یک JWT از STS مبادله می کند که می گوید: «من سرویس A هستم».
توجه کنید که اعتبارنامه (credential) "دراز مدت" باید به طور ایمن ذخیره شود و به صورت محدود مورد استفاده قرار گیرد. به عنوان مثال، می توانید یک بار از آن برای بوت استرپ هویت در راه اندازی استفاده کنید و دیگر هرگز از آن استفاده نکنید. علاوه بر این، این اعتبارنامه ها فقط باید در حافظه ذخیره شوند.
STS JWT را با کلید خصوصی خود امضا می کند که با کلید عمومی آن قابل تأیید است. سپس سرویس A ،JWT را در یک درخواست به سرویس B می فرستد. از اینجا، سرویس B میتواند تأیید کند که JWT توسط STS با تأیید امضای JWT با استفاده از کلید عمومی STS صادر شده است.
برای اینکه این کار عمل کند:
- ترافیک باید رمزگذاری شود.
- سرویس B باید ادعای حساب، انقضا، issued at و قبلا نداشته باشد از ادعاهای JWT را بررسی کند.
- سرویس B باید برای به روز رسانی کلید عمومی STS هنگام چرخش آماده شود.
رمزگذاری ترافیک بسیار مهم است زیرا هنگامی که JWT ها به این روش استفاده می شوند، نشان دهنده یک "bearer token" هستند، بنابراین هرکسی که رمز را داشته باشد می تواند سرویس A را جعل کند. رمزگذاری ترافیک (مانند سرور یک طرفه TLS) بین سرویس A و سرویس B به کاهش این کمک می کند.
سرویس B همچنین باید انقضا (exp)، صادر شده در (iat) و نه قبل از زمان (nbf) را بررسی کند، و به ویژه ادعای aud برای تأیید صحت توکن (منقضی نشده، در بازه زمانی خود و در نظر گرفته شده برای استفاده توسط سرویس B) بررسی شود. ). JWT ها از این قرارداد برای محافظت در برابر حملات تکراری استفاده می کنند، جایی که مهاجم جعل سرویس B را جعل می کند، رمز را از سرویس A می گیرد، سپس سرویس A را جعل می کند تا سرویس C را فراخوانی کند. یک سرویس معتبر C ادعای aud را بررسی می کند، ببینید JWT نشان دهنده سرویس A در نظر گرفته شده است. برای سرویس B، و آن را رد کنید.
برای هر صدا زدن باید از JWT متفاوتی استفاده شود زیرا ادعای aud متفاوت خواهد بود. تلاش برای استفاده از JWT بدون ادعای aud یا استفاده از یک ادعای aud با حروف عام، خطر یک JWT در معرض خطر را افزایش می دهد. از انجام این کار خودداری کنید.
در آخر، و اغلب نادیده گرفته می شود، چرخش کلیدهای عمومی STS است. در صورت چرخش برنامه ریزی شده یا لغو برنامه ریزی شده کلیدهایی که STS برای امضای JWT ها استفاده می کند، سرویس B (یا هر سرویسی که برای تأیید به STS متکی است) باید بتواند کلیدهای عمومی امضای به روز شده را مدیریت کند.
گزینه 2: از سرویس بخواهید توکن های خود را امضا کند
رویکرد دوم از کلیدهای مخصوص سرویس برای امضای JWTها استفاده می کند. می توانید از کلیدهای متقارن یا کلیدهای نامتقارن استفاده کنید.
در این مورد، سرویس A از کلیدهای خود برای امضای JWT هایی که به سرویس B (یا هر سرویس دیگری) ارسال می کند، استفاده می کند. سرویس B برای تأیید ارسال سرویس A JWT به کلید عمومی سرویس A (یا کلید متقارن که به دلیل نگرانی های مبادله کلید و جعل هویت خطرناک تر است) نیاز دارد. در واقع، سرویس B به هر کلید عمومی برای هر سرویسی که با استفاده از JWT ها به عنوان اصول احراز هویت فراخوانی می کند، نیاز دارد.
همانطور که در مثال JWT صادر شده توسط STS، ترافیک بین سرویس ها باید رمزگذاری شود، سرویس B نیز باید ادعای aud را بررسی کند، و شما به راهی برای امضای چرخش کلید عمومی نیاز دارید. همچنین باید برای هر سرویسی که تماس می گیرید از JWT متفاوتی استفاده کنید.
توسعه دهندگان باید بسیاری از چیزها را در جای خود قرار داده و پیگیری کنند تا این امر به درستی انجام شود. Certificate ها همچنین باید حداقل برای نیمی از سرویس ها (سرویس های در انتهای گیرنده) صادر شود تا حداقل TLS یک طرفه ارائه شود. همچنین کلید کل فرآیند مدیریت کلید، چرخش و حفظ اسرار است.
جایی که همه چیز ممکن است با JWT اشتباه باشد
ما راه هایی را پوشش داده ایم که از JWT ها می توان برای نشان دادن هویت سرویس و مناطق پیشنهادی مورد توجه استفاده کرد. برای جلوگیری از حفرههای امنیتی، چندین حوزه وجود دارد که باید در معماری سرویسهای خود به دقت مشاهده کنید. اگر این ها ضد حمله نباشند، به مهاجمان فرصت هایی می دهید تا سیستم شما را به خطر بیاندازند.
یکی از مهمترین تفاوتها بین استفاده از گواهیهای client/mTLS، مانند سرویس مش انجام میدهد، و JWTها برای احراز هویت این است: JWTها مواد bearer token حساس را روی سیم ارسال میکنند، در حالی که mTLSها این کار را نمیکنند. با mTLS، فقط کلید عمومی از طریق سیم ارسال می شود، نه کلید خصوصی، و کلیدهای session مذاکره می شوند. اگر JWT به بیرون درز کرد، JWT یک ماده محرمانه خصوصی است و می تواند دوباره پخش شود. با گواهیها، فقط گواهیهای عمومی از طریق سیم به اشتراک گذاشته میشوند.
برای جلوگیری از پخش مجدد bearer token، باید با تنظیم زمانهای انقضا کوتاه، در حالت ایدهآل فقط چند دقیقه، استفاده از آن را محدود کنید. این امر مسئولیت بیشتری را بر دوش سرویس ها می گذارد تا JWT های خود را برای درخواست های خود به روز کنند. تنظیم انقضا برای ساعت ها، روزها یا ماه ها اغلب اتفاق می افتد. این یک حفره امنیتی بزرگ است.
یکی دیگر از شکاف های امنیتی بزرگ این است که هنگام استفاده از STS برای دریافت مواد JWT، اعتبارنامه های طولانی مدت (مثلاً برای جریان client_credentials) را بارها از طریق سیم ارسال می کنید. این اعتبارنامههای با عمر طولانی بسیار حساس هستند و باید به اندازه کافی استفاده شوند (مثلاً هنگام راهاندازی)، نه به طور مداوم.
بهعلاوه، استفاده از ادعاهای aud با حروف عام یا کنار گذاشتن کلی aud، مشکل بزرگ دیگری است. عدم استفاده از این قراردادها به طور مداوم در سرویس ها برای احراز هویت، مشکلات قابل توجهی را ایجاد می کند. اطمینان حاصل کنید که برای هر سرویس فراخوانی شده، JWT با ادعای صحیح aud ایجاد کنید.
در نهایت، چرخش کلید به همان اندازه مهم است که انقضای کوتاه مدت و بررسی ادعای حساب. باطل کردن کلیدها آخرین تلاش برای لغو JWT ها در صورت نقض است و باید تا حد امکان سریع و کارآمد انجام شود.
پیچیدگی JWT جایی است که مش سرویس کارها را ساده می کند
مش سرویس احراز هویت سرویس به سرویس را ساده میکند و به توسعهدهندگان اجازه میدهد تا روی منطق کسبوکار خود تمرکز کنند، نه اینکه JWTها و مطالب مخفی را (امیدوارم) به درستی درگیر کنند. همانطور که یک درگاه API باید برای مدیریت امنیت برای ترافیک شمال/جنوب و ورودی استفاده شود، یک سرویس مش باید برای ترافیک شرق/غرب و S2S استفاده شود. تمرکز سرویسها و APIها بر ارزش تجاری متمایز که میتوانند ارسال کنند، داشته باشند، نه کد امنیتی boilerplate (و در عین حال بسیار مهم).
نتیجه
برای غواصی عمیق تر، مقاله ها و آموزش های ما در یوتیوب و وبسایت آنوفل را دنبال کنید، ما در لاراول API بررسی کردیم. دیدیم که موارد امنیتی را رعایت نکنیم به چه مشکلاتی مواجه خواهیم شد و برای اینکه با این مشکلات و مواجه نشیم زمان انقضای توکن ها را کمتر کنید و هر بار آن را تغییر دهید.