Microservice Mimarisinde API Gateway ile Authentication ve Authorization

Gökhan Ayrancıoğlu
5 min readDec 29, 2020

--

Microservice mimarisini düşündüğümüzde çözülmesi gereken en önemli problemlerden biri güvenliktir. Authentication ve Authorization ise güvenliğin en önemli noktalarını oluşturmaktadır.

Microservice mimarisinde birden fazla servisimiz dağıtılmış bir şekilde konumlanır ve bu nedenle en önemli konulardan biri de Authentication yapısının nasıl kurulacağıdır. Geleneksel monolitik mimaride bu iş çok daha kolay bir şekilde çözümlenebiliyor. Tek bir uygulamanın gelen her isteği doğrulaması tek bir mekanizmayla halledilebilirken, durum microservice mimarisinde oldukça karmaşık bir hale geliyor. Hatta öyle ki benim “en iyi nasıl yaparız” diye kafa patlatıp araştırıp en iyi yöntem budur diye, kesin bir sonuca uzunca bir süre varamadığım bir sorunsal haline gelmiştir.

Kavram kargaşasını önlemek için authN ve authZ kavramlarını açıklayalım.

  • Authentication (AuthN): Bir kullanıcının söylediği kişi olup olmadığını doğrulamakla ilgilidir.
  • Authorization (AuthZ): Yetki, ayrıcalık ve bir kullanıcının kimliğini doğruladıktan sonra hangi kaynaklara erişmesine izin verildiğini doğrulamakla ilgilidir.

Microservice Mimarisinde Authentication ve Authorization

Microservice mimarisinde birden fazla servisimiz mevcut, bu da gelen her isteğin bir şekilde her bir serviste ya da o servislere ulaşmadan önce authenticate ve authorize edilmesi anlamına geliyor.

Her microservice kendi içinde authN ve authZ mekanizmalarını içerdiğini düşünelim. Auth yapısı her microservice’te bulunmalı bu da yapıda herhangi bir değişiklik ya da yeni bir versiyonlamanın tüm servisleri etkilemesi ve kodsal/yapısal olarak güncellenmesi anlamına geliyor. Bir değişiklikte tüm servislerde güncelleme yapmak olağanüstü bir zaman/efor maliyeti ortaya çıkartır. Projenizde farklı diller ve teknolojiler kullanıldığını da düşündüğünüzde durum daha da vahim ve karmaşık hale geliyor. Dolayısıyla bu yöntemden şimdiden vazgeçebiliriz.

Microservice mimarisinde authN ve authZ için birden fazla yaklaşım olduğu unutulmamalı burada yukarıdaki sorunlarımıza çözüm olabilecek benim deyimimle Authentication Gateway yapısı üzerinden işlemlerin yürütüldüğü bir yaklaşım baz alınmaktadır.

Authentication Gateway

Api Gateway Pattern’ninde clientlar microservicelere doğrudan erişemez ve api gateway clientların isteklerini uygun ve doğru bir şekilde microservicelere iletmek için bir giriş noktasıdır. Bütün isteklerin üzerinden geçtiği bir yapı diğer görevleriyle birlikte güvenlik konusunuda görev olarak üstlenebilir.

Authentication ve authorization adımlarını token mekanizması kullanarak gerçekleştiriyor olacağız. Bu token yapısında ise son günlerde fazlaca kullanılan, güvenliği içinde önemli noktalara dikkat etmeniz gereken JWT ile birlikte uyguluyor olacağız.

JSON WEB TOKEN (JWT)

RFC 7519 göre JWT farklı birimler arasında bağımsız ve kompakt iletişimi güvenli bir şekilde gerçekleştirmenin bir yoludur. Token üç farklı kısımdan oluşur: header, payload ve signature;her biri aşağıdaki biçimde belirtildiği gibi bir noktayla ayrılmıştır:

header.payload.signature

Header: JWT’nin ilk bölümü, JSON headerının Base64Url kodlamasıyla oluşturulur.

{
"alg": "HS256",
"typ": "JWT"
}

Önemli Not: Burada kullanılan algoritma daha sonra belirteceğimiz secret güvenlik içinde çok önemli bir nokta oluşturmaktadır. Örnek Tweet ve cevaplarında belirtildiği gibi HS256 algoritması kullanırken özellikle de secret’ınızın minimum 256 bit’ten oluştuğuna emin olunuz.

Payload: Claim’leri yani JWT içinde gönderilecek bilgileri içeren bölümdür.

{
"sub": "1234567890",
"name": "Gökhan",
"role": Admin,
"iss": http://abc.com,
"iat": 1472033308,
"exp": 1472034208
}

Signature: header’da belirtilen algoritma kullanılarak gizli bir anahtarla imzalanmasıyla oluşturulur.

Örneğin: HMAC SHA256 algoritması kullanılarak oluşturulan bir anahtar:

HMACSHA256(  
base64UrlEncode(header) + "." +
base64UrlEncode(payload), secret)

Sonuç olarak ortaya çıkan token aşağıdaki gibi bir hal alır ve request gönderilirken Authorization kısmında Bearer ile birlikte kullanılır.

Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
eyJ1c2VySWQiOiJiMDhmODZhZi0zNWRhLTQ4ZjItOGZhYi1jZWYzOTA0NjQifQ.
-xN_h82PHVTCMA9vdoHrcZxH-x5mb11y1537t3rGzcM

API gateway istekleri doğru microservice yönlendirir ve bu isteklerin her biri gateway üzerinden geçtiği için authN, authZ, load balancing gibi işlemleri yapacak bir sorumlulukta yüklenebilmektedir. Güvenlik açısından bakıldığında, API Gateway’ler genellikle kimlik doğrulama (authN) ve yetkilendirme (authZ) sorumluluğunu da üzerinde barındırabilir. Çünkü her requestin geçişi buradan yapılmakta ve routing adımı burada gerçekleştirilmektedir.

Sisteme gelen tüm requestler yalnızca API Gateway’den geçmelidir. API Gateway’in Authentication Gateway olabilmesi için, dışarıdan yapılan API istekleri Authentication Service aracılığıyla bir token verildikten sonra doğrulanmasını Gateway üzerinde sağlamak gerekir. Dolayısıyla, gelen isteklerin Authentication Gateway aracılığıyla microservicelere güvenli bir şekilde aktarılabilir.

Login Senaryosu

Authentication Service: Gelen credential’ların doğru olup olmadığını ölçümler ve doğru credential’lara sahip kullanıcıların userId,userRole gibi bilgilerini de içeren ve belirli bir süre kullanım süresi (expireTime) bulunan bir JWT token oluşturur.

Akışı kısaca özetlemek gerekirse;

  • Client login olmak için credential bilgilerini içeren request atar.
  • Gelen request Api Gateway aracılığıyla Authentication Service’e ulaştırılır ve credential bilgileri doğrulanır.
  • Kullanıcı bilgileri doğruysa JWT token oluşturulur ve bu token authorization bilgisi,expireTime gibi bilgilerle birlikte cevap olarak dönülür.
  • Cevap olarak client’a gönderilecek bilgiler, daha sonra validate ve authenticate işlemi yapılabilmesi adına API Gateway’in cache’ine yazılır. Böylece gelecek herhangi bir request tekrar authentication servisine gitmeye gerek kalmadan Authentication Gateway diye adlandırabileceğimiz Api Gateway üzerinde authenticate edilebilir.

Gelen JWT token bilgileriyle birlikte verilen expireTime içinde kullanıcı JWT token ile birlikte istediği request’leri ilgili servislere gönderebilir. Gelen request API Gateway üzerinde redis gibi in memory cacheler aracılığıyla authenticate edilir. Eğer bilgiler doğruysa, istenilen request doğru microservice authorization bilgileriyle birlikte yönlendirilir. Dolayısıyla Authenticatiion kısmını halletmiş oluruz.

Role bazlı Authorization

Authorization için birden fazla alternatifimiz mevcuttur. Bunlardan biri Authorization’ının servisler üzerinde yapılmasıdır.

  • Her servis endpoint’ne belirli permission’lar atanır. Böylece yetki dağılımı yapılır.
  • Bir microservice bir istek aldığında, JWT token’ı encode eder.
  • JWT token validate edilir ve doğrulanır.
  • Ardından kullanıcının istenen eylem için gerekli permission’a sahip olup olmadığı encode edilmiş JWT’nin payload kısmında bulunan rolü aracılığıyla kontrol edilir.
  • İşlemi gerçekleştiren kullanıcı, istek attığı end-point’te işlem yapabilmesi için gerekli role sahip bir kullanıcı ise işlem gerçekleşir.

Endpointler için role bazlı bir yapı konumlandırıldığında JWT içerisinde barınan rol’a göre kolayca authorization yapısı kurulmuş olur. Bu yapının dezavantajı authorization bilgilerinin header kısmında sürekli gönderiliyor oluşu ve header boyutunu büyütüyor oluşudur. Ayrıca JWT encode işleminin de bu servislerde yapılması gerekmektedir, bu da code dublicate olmasına neden olabilir. Encode parçasının secret hariç neredeyse hiç değişmeyeceğini ön görürsek ortak bir library yazılarak bu sorun göz ardı edilebilir.

Başka bir bakış açısı ise hali hazırda ki Authantication Service üzerinde (belki Auth Service olarak adlandırılabilir) bütün kullanıcı permission’larının bilgisini de barındırmasını sağlamak ve böylece gelen requestler ilgili servise yönlendirildikten sonra eğer permission gerekiyorsa Auth Servisi üzerinden permission‘a sahip olup olmadığı sorgulamaktır. Buradaki dezavantaj ise fazladan bir senkronize iç iletişime daha neden olmasıdır ve bunun her permission gerektiren servis endpoint’i için yapılacağını düşünürsek oldukça maliyetli bir hal alabilir.

Microservice mimarisinde güvenlik için birden fazla çözüm ve sadece bunun için konumlanmış büyük third-party firmalar mevcuttur. Burada anlatılan çözüm Api Gateway aracılığıyla işleri kolaylaştırmak ve oluşabilecek iç network trafiğini oldukça azaltarak bir güvenlik yani authentication ve authorization yapısı kurmaktır.

--

--

Gökhan Ayrancıoğlu
Gökhan Ayrancıoğlu

Written by Gökhan Ayrancıoğlu

Software Engineer @Yemeksepeti • #Java • #Spring Boot • #Kotlin • #Spark • #Microservices • https://gokhana.dev