Mühendislik

Rol Tabanlı Erişim Kontrolünü Doğru Kurmak: SaaS İçin Pratik Rehber

Basit yönetici/kullanıcı ayrımı, SaaS ürünleri büyüdükçe yetersiz kalır. Bu rehber; modül-eylem izinlerinin nasıl tasarlanacağını, rollerin nasıl bir araya getirileceğini, her API uç noktasında yetkinin nasıl denetleneceğini ve denetçilerin güvenebileceği bir RBAC yapısının nasıl kurulacağını anlatıyor.

Fethi UZUN Güncellendi: 10 Haziran 2026 11 dk okuma

Erişim kontrolü, bir gün çözülmediği ortaya çıkana kadar çözülmüş sanılan mühendislik problemlerinden biridir. Erken aşamadaki bir SaaS, basit bir yönetici/kullanıcı ayrımıyla idare edebilir. Ancak ürün onlarca özelliğe, birden çok ekip katmanına ve uyumluluk gereksinimleri olan kurumsal müşterilere ulaştığında bu ayrım bir yüke dönüşür: gerçek iş kurallarını ifade edemeyecek kadar kaba, denetlenemeyecek kadar kırılgan ve değiştirilemeyecek kadar pahalıdır.

Rol tabanlı erişim kontrolü (RBAC) bu sorunun standart çözümüdür; ancak "RBAC" denince akla gelen yelpaze, basit boolean bayraklardan sağlam ve denetlenebilir bir izin motoruna kadar uzanır. Bu rehber, gerçekten ölçeklenen bir RBAC'nin nasıl tasarlanacağını ele alıyor.

Erişim Kontrolü Yelpazesi

RBAC'ye geçmeden önce alternatiflerin neler olduğunu ve RBAC'nin neden çoğu SaaS ürünü için pratik açıdan en dengeli nokta olduğunu bilmek faydalıdır.

Erişim Kontrol Listeleri (ACL): İzin, her kullanıcıya her kaynak için ayrı ayrı verilir. Uygulaması kolaydır, ölçekte yönetilmesi ise imkânsızdır: 500 kullanıcının yetkisini değiştirmek 500 ayrı güncelleme gerektirir.

Rol Tabanlı Erişim Kontrolü (RBAC): Kullanıcılara roller atanır; izinleri roller taşır. Bir rolün yetkisini değiştirdiğinizde, o role sahip tüm kullanıcılar için aynı anda değişmiş olur. SaaS uygulamalarının büyük çoğunluğu için doğru model budur.

Öznitelik Tabanlı Erişim Kontrolü (ABAC): Politikalar dinamik öznitelikleri değerlendirir: kullanıcının departmanı, kaynağın sahibi, isteğin zamanı, ağ konumu. Daha ifade gücü yüksektir ancak uygulanması, üzerine akıl yürütülmesi ve denetlenmesi belirgin biçimde zordur. Bu karmaşıklığa ancak RBAC'nin gerekli politikaları ifade edemediği durumlarda değer.

İlişki Tabanlı Erişim Kontrolü (ReBAC): İzinler, varlıklar arasındaki ilişki grafiğinden türetilir; Google Zanzibar'ın ve Airbnb'nin izin sisteminin arkasındaki model budur. Sosyal uygulamalar ve ince taneli kaynak sahipliği için güçlüdür; ancak ciddi bir uygulama yatırımı ister.

Çoğu SaaS için önerimiz: RBAC, belirli politikalar için yer yer ABAC uzantılarıyla.

İzin Modelini Tasarlamak

İyi bir RBAC sisteminin temeli izin modelidir: hangi erişim birimlerini tanımladığınız ve bunları nasıl ifade ettiğiniz.

Modül + Eylem

Bakımı en kolay desen module:action biçimidir. Modül, ürünün bir özellik alanına ya da bir kaynak türüne karşılık gelir; eylem ise onunla ne yapabileceğinizdir.

projects:read
projects:write
projects:manage
issues:read
issues:write
billing:manage
team:invite
reports:export

Neden ölçeklenir: Mevcut hiçbir izin ya da rol tanımına dokunmadan yeni bir modül (yeni bir ürün özelliği) ekleyebilirsiniz. Mevcut bir modüle hiçbir şeyi bozmadan yeni bir eylem (projects:archive) ekleyebilirsiniz. İzin kümesi ürünle birlikte büyür.

Kaçının: Özellik başına boolean bayraklardan (can_access_reports: true), eylemsiz modül dizgelerinden (projects) ya da fiil-nesne tutarsızlığından (read_project, manage-billing). Adlandırmadaki tutarsızlık, yetki denetimindeki tutarsızlığa yol açar.

Eylem Hiyerarşisi

Çoğu modülde eylemler doğal bir hiyerarşi oluşturur: manage, write'ı; write da read'i kapsar. Bunu kodda açıkça tanımlayın:

const ACTION_HIERARCHY = {
  manage: ['manage', 'write', 'read'],
  write:  ['write', 'read'],
  read:   ['read'],
};

Bir kullanıcının write yapıp yapamayacağını denetlerken manage iznine de bakın. Böylece bir kaynağı "yöneten" bir yöneticinin, o kaynağın içerdiği yazma işlemlerini yapamaması gibi yaygın bir hatanın önüne geçersiniz.

Rol Tasarımı

Roller, kullanıcılara atanan, adı konmuş izin paketleridir. İyi bir rol tasarımı üç ilkeye dayanır:

En az yetki ilkesi. Bir rol, amaçlanan işlevi yerine getirmek için gereken izinleri içermeli, fazlasını değil. Böylece bir hesap ele geçirildiğinde oluşacak hasarın etki alanı sınırlı kalır.

Rol tutarlılığı. Bir roldeki her izin, o rolün amacı bağlamında anlamlı olmalıdır. "member" rolü işini yapabilmek için faturalama erişimine ihtiyaç duyuyorsa, sorun rolde değil izin modelindedir.

Rol patlamasından kaçının. Kendinizi manager_with_billing_except_delete gibi roller oluştururken buluyorsanız, izin modeliniz fazla kabadır. Daha fazla rol yerine daha ince taneli izinler ekleyin.

Tipik bir SaaS için başlangıç noktası:

RolAçıklamaTemel izinler
ownerÇalışma alanı sahibiFaturalama ve ekip yönetimi dahil her şey
adminYönetici kullanıcıTüm operasyonel izinler, faturalama hariç
managerEkip lideri / proje sahibiKendi kapsamında oluşturma, yazma, yönetme
memberStandart kullanıcıÇoğu şeyi okuma, kendisine atanan işlerde yazma
viewerSalt okunur paydaşYalnızca okuma erişimi
billing_adminFinans ekibi üyesiYalnızca faturalama modülü

Çok Rollü Kullanıcılar

Gerçek kurumlarda insanlar birden fazla şapka taşır. Bir geliştirici çoğu konuda member, harcama takibinde ise billing_admin olabilir. Bir yüklenici bir projede manager, bir diğerinde viewer olabilir.

Bunu en baştan hesaba katarak tasarlayın. Geçerli izin kümesi, atanmış tüm rollerin izinlerinin birleşimidir. Yetki denetimi mantığı aynı kalır; değişen yalnızca rol atama sorgusudur.

// Geçerli izinler = tüm rollerin izinlerinin birleşimi
const effectivePermissions = user.roles.flatMap((role) => role.permissions).map((p) => p.name);

function hasPermission(user: User, permission: string): boolean {
  return effectivePermissions.includes(permission);
}

Yetki Denetimi: Nerede, Nasıl ve Ne Sıklıkla

Her API Uç Noktasında Denetleyin

Anlamlı bir işlem yapan her rota, ilgili izni denetlemelidir. Bu denetim:

  1. Tutarlı olmalı: İstek hangi yoldan gelirse gelsin (REST, GraphQL, arka plan işi) aynı izin denetimi uygulanmalı
  2. Ucuz olmalı: İzinler kimlik doğrulamadan sonra oturumda/JWT'de önbelleğe alınmalı; her istekte veritabanı sorgulanmamalı
  3. Kapalı kalacak şekilde başarısız olmalı (fail-closed): İzin denetimi yapılamıyorsa (rol verisi eksik, token süresi dolmuş) erişim reddedilmeli; varsayılan davranış asla izin vermek olmamalı

Pratik bir middleware deseni:

const requirePermission =
  (permission: string) => (req: Request, res: Response, next: NextFunction) => {
    if (!req.user?.permissions.includes(permission)) {
      throw new ApiError(403, `Permission required: ${permission}`);
    }
    next();
  };

// Rota tanımında:
router.post('/projects', requirePermission('projects:write'), createProject);
router.delete('/projects/:id', requirePermission('projects:manage'), deleteProject);

Satır Düzeyinde Denetim

Belirli kullanıcılara ya da ekiplere ait kaynaklar için satır düzeyinde denetimler ekleyin. Kullanıcının projects:read iznine sahip olduğunu doğruladıktan sonra, projenin kullanıcının kurumuna ait olduğunu (çok kiracılı yalıtım) ya da kendisiyle açıkça paylaşıldığını doğrulayın.

Bu iki denetimi kavramsal olarak birbirinden ayırın:

  • İzin denetimi: Bu kullanıcı bu eylem sınıfını gerçekleştirebilir mi?
  • Sahiplik/kapsam denetimi: Bu kullanıcının bu belirli kaynağa erişimi var mı?

İkisini birbirine karıştırmak, iş mantığını içine gömen izin modellerine yol açar; bunlar da kırılgandır ve bakımı zordur.

Arayüzü Dürüst Tutmak

Arka uçta yetki denetimi tartışmaya kapalıdır; ancak her kullanıcıya her düğmeyi (devre dışı bırakılmış ve üzerinde bir ipucu balonuyla) gösteren bir arayüz güveni aşındırır ve kullanıcıyı bezdirir. Arayüz gerçek izinleri yansıtmalıdır.

Gezinme: Kullanıcının erişemediği modüllerin menü öğelerini gizleyin. Kullanıcı faturalamaya erişemiyorsa, faturalama menü öğesi hiç görünmemelidir.

Eylem düğmeleri: Yalnızca kullanıcının gerçekleştirebileceği eylemleri gösterin. "Sil" düğmesi bir viewer'a görünmemelidir.

Uç durumları zarifçe ele alın: Bir izin eşzamansız olarak (sayfa yüklendikten sonra) denetleniyorsa, kontrollerin önce görünüp sonra kaybolduğu bir titreme yerine iskelet (skeleton) görünüm gösterin.

Bir izin deposu (istemci tarafında, kimlik doğrulamadan sonra yüklenen) tutun ve arayüz durumunu ondan türetin. Kod tabanına dağılmış if (user.role === 'admin') gibi buyurgan mantık yerine her bileşen can('projects:write') denetimi yapsın.

Denetim Kaydı (Audit Log)

Kurumsal müşteriler ve uyumluluk gereksinimleri için, reddedilen her izin denetimi ve izinle korunan her başarılı eylem kayda geçirilmelidir.

Asgari kayıt içeriği:

  • Zaman damgası
  • Kullanıcı kimliği ve eylem anındaki rol kümesi
  • Gerçekleştirilen eylem (HTTP yöntemi + rota ya da anlamsal işlem)
  • Kaynak tanımlayıcısı
  • Denetlenen izin
  • Sonuç (izin verildi / reddedildi)

Bu sayede güvenlik olaylarını inceleyebilir, uyumluluk için denetim izi oluşturabilir, yetkisiz eylemleri tekrar tekrar deneyen kullanıcıları tespit edebilir ve izin değişikliklerinin beklenen etkiyi yaratıp yaratmadığını doğrulayabilirsiniz.

RBAC'yi Test Etmek

Erişim kontrolü, kendi test kapsamını hak eden, güvenlik açısından kritik bir özelliktir.

Her izin için: İzne sahip bir kullanıcının eylemi gerçekleştirebildiğini, izne sahip olmayanın ise gerçekleştiremediğini doğrulayan bir test yazın. Bu testler hızlı ve ucuzdur; gerilemeleri anında yakalar.

Rol matrisi testleri: Her rol ve her uç nokta kategorisi için beklenen izin/ret sonucunu doğrulayın. Bu, erişim modelinizin yaşayan bir şartnamesi olur.

Yetki yükseltme testleri: Hiçbir kullanıcının kendisine mevcut rol kümesinin ötesinde izin veremediğini doğrulayın: ne API parametreleri ne de istek sahteciliği yoluyla.

Sık Yapılan Hatalar

İzin yerine rol denetlemek. Kod tabanına dağılmış if (user.role === 'admin') ifadelerinin bakımı yapılamaz. hasPermission('projects:manage') denetleyin ve yöneticilerin neler yapabileceğini izin modeli tanımlasın.

Yalnızca ön yüzde denetim. Gizlenmiş bir düğme erişim kontrolü değildir. API, yetkiyi bağımsız olarak denetlemelidir.

Bayat izinleri önbellekte tutmak. İzinler bir JWT'ye gömülüyse, rol değişikliklerinden sonra güncelleme yapmak token'ın geçersiz kılınmasını gerektirir. Bunu en baştan tasarlayın: ya kısa token ömürleri (TTL), ya bir token engel listesi (denylist) ya da kısa TTL'li bir önbellekten çekilen izinler.

Denetim kaydının olmaması. Kayıt olmadan olayları inceleyemez, uyumluluk denetimlerinden geçemez ya da beklenmedik retlerin nedenini bulamazsınız.

Sonuç

İyi bir RBAC, olağan işleyişte görünmezdir: kullanıcılar tam olarak ihtiyaç duyduklarını görür, hassas eylemler korunur ve sistem, izinlerin yeniden yazılmasını gerektirmeden yüzlerce modüle ölçeklenir.

Yatırım iki alanda yapılır: veri modelini doğru kurmak (tutarlı module:action izinleri, tutarlı roller, ilk günden çok rol desteği) ve yetki denetiminde disiplin (her uç noktanın denetlenmesi, arayüzün izinlerden türetilmesi, en baştan denetim kaydı).

Doğru kurulduğunda RBAC, kurumsal müşteriler nezdinde bir rekabet avantajına dönüşür: ürününüzün, istisna gerektirmek yerine onların erişim kontrolü politikalarına uyum sağlayabilmesi anlamına gelir.

  • RBAC
  • Güvenlik
  • Erişim Kontrolü
  • SaaS

Bir fikriniz ya da çözülmesi gereken bir süreciniz mi var?

Bize kısaca anlatın. Size dönüp keşif sprintinin kapsamını birlikte çıkaralım.

Projenizi anlatın