Ders 17 / 23
Rol Tabanlı Erişim Denetimi
İzinlerin kişiye değil göreve bağlanması, rol devralmasının etkin izin kümesini nasıl gizlediği, ortak senaryo kümesinde rol tabanlı kararın nerede doğru nerede yanlış olduğu ve rol patlamasının ölçülmesi.
İçindekiler
Önceki konu “karşımdaki kim” sorusuna verilen yanıtları kurdu. Oturum silme sorgusundaki
AND uye = ? koşulu ise ikinci soruyu açtı: kim olduğu bilinen birinin neyi yapabileceği.
Bu konu o soruyla ilgili ve dört ayrı modelle yanıtlıyor. Modeller birbirinin yerine geçmez;
her biri belirli bir kısıt türünü ifade edebilir, başka bir türü edemez.
Karşılaştırmanın anlamlı olması için dört model aynı senaryo kümesini değerlendirecek. Küme kütüphane ödünç servisinden alınmış sekiz istekten oluşuyor ve her senaryonun bir de doğru yanıtı var — kütüphanenin iş kuralının verdiği yanıt. Modellerin başarısı, kendi kararlarının bu yanıtla uyuşmasıyla ölçülüyor.
Rol, İzin ve Devralma
Rol tabanlı erişim denetimi (role-based access control), izinleri kişilere değil görevlere bağlar. Bu model İlişkisel Veritabanı Yönetimi kursunda veritabanı hesapları için kurulmuştu; buradaki fark katmandır. Orada denetlenen şey bir bağlantının hangi tabloya dokunabildiğiydi; burada denetlenen şey bir isteğin hangi işlemi yürütebildiğidir. İki katman ayrı ayrı bulunur ve biri diğerinin yerine geçmez: uygulama katmanındaki denetim atlanırsa veritabanı katmanı son savunmadır.
İzin (permission), bir eylem ile bir kaynak türünün birleşimidir: goruntule:odunc,
sil:ceza. Rol, izinlerin adlandırılmış bir kümesidir. Rol devralması (role
inheritance) bir rolün başka bir rolün izinlerini kapsamasıdır; şube yöneticisi görevlinin
her şeyini yapabilsin diye görevli rolünü devralır.
Devralmanın bedeli şudur: bir rolün gerçek izin kümesi yazıldığı yerde görünmez, devralma zincirinin kapanışı alınarak hesaplanır. Aşağıdaki betik bu kapanışı üretiyor ve ortak senaryo kümesini değerlendiriyor.
cat > rbac.mjs <<'EOF' const ROL_IZIN = { uye: ["goruntule:odunc", "goruntule:liste"], gorevli: ["guncelle:odunc", "olustur:odunc"], sube_yoneticisi: ["sil:ceza", "sil:odunc"], }; const ROL_DEVRAL = { uye: [], gorevli: ["uye"], sube_yoneticisi: ["gorevli"] }; const OZNE_ROL = { "U-1001": ["uye"], "U-1002": ["uye"], "U-1005": ["uye"], "P-2001": ["gorevli"], "Y-3001": ["sube_yoneticisi"], }; // Ortak senaryo kumesi: bu konudaki dort model ayni kumeyi degerlendirir. // [ad, ozne, eylem, nesne, nesne ozellikleri, saat, dogru yanit] const SENARYOLAR = [ ["S1", "U-1001", "goruntule", "odunc:501", { sahip: "U-1001", sube: "S-02" }, "10:15", true], ["S2", "U-1001", "goruntule", "odunc:502", { sahip: "U-1002", sube: "S-02" }, "10:16", false], ["S3", "P-2001", "goruntule", "odunc:502", { sahip: "U-1002", sube: "S-02" }, "10:20", true], ["S4", "P-2001", "goruntule", "odunc:503", { sahip: "U-1005", sube: "S-01" }, "10:21", false], ["S5", "P-2001", "guncelle", "odunc:502", { sahip: "U-1002", sube: "S-02" }, "22:40", false], ["S6", "Y-3001", "sil", "ceza:77", { sahip: "U-1002", sube: "S-02" }, "11:05", true], ["S7", "U-1002", "goruntule", "liste:9", { sahip: "U-1001", sube: "S-02" }, "12:00", true], ["S8", "U-1005", "goruntule", "liste:9", { sahip: "U-1001", sube: "S-02" }, "12:01", false], ]; function etkinIzinler(rol, gorulen = new Set()) { if (gorulen.has(rol)) return new Set(); // devralma dongusune karsi gorulen.add(rol); const kume = new Set(ROL_IZIN[rol] ?? []); for (const ust of ROL_DEVRAL[rol] ?? []) { for (const izin of etkinIzinler(ust, gorulen)) kume.add(izin); } return kume; } const ozneIzinleri = (ozne) => { const k = new Set(); for (const rol of OZNE_ROL[ozne] ?? []) for (const i of etkinIzinler(rol)) k.add(i); return k; }; const rbac = (ozne, eylem, nesne) => ozneIzinleri(ozne).has(`${eylem}:${nesne.split(":")[0]}`); console.log("rol | etkin izin kumesi"); console.log("----------------|-----------------------------------------------------"); for (const rol of Object.keys(ROL_IZIN)) { console.log(rol.padEnd(15) + " | " + [...etkinIzinler(rol)].sort().join(", ")); } console.log("\nsenaryo | ozne | eylem | nesne | RBAC | dogru | uyum"); console.log("--------|--------|-----------|------------|--------|--------|------"); let uyan = 0; for (const [ad, ozne, eylem, nesne, , , dogru] of SENARYOLAR) { const karar = rbac(ozne, eylem, nesne); if (karar === dogru) uyan++; console.log( `${ad} | ${ozne} | ${eylem.padEnd(9)} | ${nesne.padEnd(10)} | ` + `${(karar ? "izin" : "ret").padEnd(6)} | ${(dogru ? "izin" : "ret").padEnd(6)} | ` + (karar === dogru ? "+" : "-") ); } console.log(`\nRBAC dogru karar: ${uyan}/${SENARYOLAR.length}`); EOF node rbac.mjs
rol | etkin izin kumesi ----------------|----------------------------------------------------- uye | goruntule:liste, goruntule:odunc gorevli | goruntule:liste, goruntule:odunc, guncelle:odunc, olustur:odunc sube_yoneticisi | goruntule:liste, goruntule:odunc, guncelle:odunc, olustur:odunc, sil:ceza, sil:odunc senaryo | ozne | eylem | nesne | RBAC | dogru | uyum --------|--------|-----------|------------|--------|--------|------ S1 | U-1001 | goruntule | odunc:501 | izin | izin | + S2 | U-1001 | goruntule | odunc:502 | izin | ret | - S3 | P-2001 | goruntule | odunc:502 | izin | izin | + S4 | P-2001 | goruntule | odunc:503 | izin | ret | - S5 | P-2001 | guncelle | odunc:502 | izin | ret | - S6 | Y-3001 | sil | ceza:77 | izin | izin | + S7 | U-1002 | goruntule | liste:9 | izin | izin | + S8 | U-1005 | goruntule | liste:9 | izin | ret | - RBAC dogru karar: 4/8
Modelin Doğru ve Yanlış Kararları
Sekiz senaryonun dördünde karar doğru, dördünde yanlış. Yanlışların hepsi aynı yöndedir: model gereğinden fazla izin veriyor. Bu yön rastlantı değildir ve modelin yapısından gelir.
S2 en açık olanıdır. U-1001 kendi ödünç kaydını görüntüleyebilir, ama başka bir üyenin
kaydını göremez. Rol tabanlı model bu ikisini ayırt edemez, çünkü kararı yalnız özne ve
kaynak türü üzerinden verir. odunc:501 ile odunc:502 aynı türdendir; hangisinin kime
ait olduğu modelin göremediği bir bilgidir.
S4 aynı sorunun personel tarafıdır. Görevli ödünç kayıtlarını görüntüleyebilir; hangi şubenin kayıtlarını görüntüleyebileceği izin adında yazılı değildir.
S5 zamanla ilgilidir. Ödünç kaydının mesai saatleri dışında değiştirilmemesi bir iş kuralıdır ve rol tabanlı modelde ifade edilecek bir yeri yoktur — izinler isteğin bağlamını görmez.
S8, S7 ile birlikte okunmalıdır. İkisinde de model “izin” diyor; S7’de bu doğru, S8’de yanlış. Doğru olanı da yanlış nedenle doğrudur: model, listenin U-1002 ile paylaşılmış olup U-1005 ile paylaşılmamış olduğunu bilmiyor, yalnız her üyenin liste görüntüleyebildiğini biliyor. Doğru kararın doğru nedenle verilmesi, sonraki iki dersin konusu.
Bu dörtlünün ortak adı vardır: rol tabanlı model kaba taneli bir modeldir. Kaynağın türüne kadar iner, örneğine inemez.
Rol Patlaması
Eksik ayrımları rol tabanlı model içinde çözmenin bir yolu vardır: eksik olan koşulu rolün
adına yazmak. Şube ayrımı için gorevli_S01, gorevli_S02; mesai ayrımı için bunların
mesai içi ve mesai dışı sürümleri. Bu yolun maliyeti hesaplanabilir.
cat > rol-patlamasi.mjs <<'EOF' const boyutlar = [ ["gorev", 4, "okuyucu, gorevli, katalogcu, sube yoneticisi"], ["sube", 12, "kutuphanenin sube sayisi"], ["mesai", 2, "mesai ici / mesai disi"], ["kayit sahipligi", 2, "kendi kaydi / baskasinin kaydi"], ]; console.log("eklenen kosul | carpan | gereken rol sayisi | ornek"); console.log("--------------------|--------|--------------------|--------------------------------"); let rol = 1; for (const [ad, carpan, ornek] of boyutlar) { rol *= carpan; console.log(ad.padEnd(19) + " | " + String(carpan).padStart(6) + " | " + String(rol).padStart(18) + " | " + ornek); } console.log(`\nrol adlarinin ornegi: gorevli_S02_mesai_ici_baskasinin_kaydi`); console.log(`atama sayisi: her personel icin ${rol} rolden dogru olani secilir`); EOF node rol-patlamasi.mjs
eklenen kosul | carpan | gereken rol sayisi | ornek --------------------|--------|--------------------|-------------------------------- gorev | 4 | 4 | okuyucu, gorevli, katalogcu, sube yoneticisi sube | 12 | 48 | kutuphanenin sube sayisi mesai | 2 | 96 | mesai ici / mesai disi kayit sahipligi | 2 | 192 | kendi kaydi / baskasinin kaydi rol adlarinin ornegi: gorevli_S02_mesai_ici_baskasinin_kaydi atama sayisi: her personel icin 192 rolden dogru olani secilir
Dört görev, bir şube eklendiğinde kırk sekiz role çıkıyor; iki koşul daha eklendiğinde yüz doksan iki. Sayının kendisinden çok, büyüme biçimi önemlidir: her yeni koşul rol sayısını çarpar. On üçüncü şube açıldığında on altı yeni rol tanımlanması gerekir ve bunların her biri elle bakılan bir kayıttır.
İkinci maliyet okunabilirliktir. gorevli_S02_mesai_ici_baskasinin_kaydi adlı bir rolün ne
anlama geldiği adından çıkarılabilir, ama böyle yüz doksan iki adın arasında bir yanlışın
fark edilmesi çıkarılamaz. Bir personelin yanlış role atanması, yetki çizelgesine bakarak
görülemez hâle gelir.
Buradaki sınır rol tabanlı modelin kusuru değil, kapsamıdır. Model, görevin sabit olduğu ve kararın isteğin bağlamına bağlı olmadığı durumlarda yalın ve denetlenebilirdir.
Modelin Doğru Kullanıldığı Yer
Rol tabanlı modelin bırakılması gerekmiyor; sınırının bilinmesi gerekiyor. Sağlam kurulum şu ayrımı yapar.
Kaba taneli karar rolle verilir. “Bu istek türü bu göreve açık mı?” sorusunun yanıtı roldedir. Personel olmayan birinin ödünç kaydı güncelleme uç noktasına hiç ulaşmaması, rol denetiminin işidir ve isteğin en başında yapılır.
İnce taneli karar ayrı bir katmanda verilir. “Bu belirli kayıt bu kişiye açık mı?” sorusu, sonraki derslerin konusudur ve rolle değil, kaydın kendisiyle ilgilidir.
Roller görevden türetilir, kişiden değil. Bir role “şu kişi de erişebilsin” diye izin eklemek, rolün adını yalanlar. Gerek varsa yeni bir rol tanımlanır.
Rol atamaları düzenli denetlenir. Bir kişinin taşıdığı etkin izin kümesi ile görevinin gerektirdiği küme arasındaki fark ölçülür. Bu denetimin veritabanı tarafındaki karşılığı İlişkisel Veritabanı Yönetimi kursunda kurulmuştu; uygulama tarafında da aynı yordam uygulanır.
Özet
- Rol tabanlı erişim denetimi izinleri göreve bağlar; izin, bir eylem ile bir kaynak türünün birleşimidir.
- Rol devralması etkin izin kümesini yazıldığı yerde görünmez kılar; küme, devralma zincirinin kapanışı alınarak hesaplanır.
- Model kaba tanelidir: kaynağın türüne iner, örneğine inemez. Ortak senaryo kümesinde sekiz karardan dördü yanlış çıkmıştır ve dördü de gereğinden fazla izin yönündedir.
- Eksik koşulları rol adına yazmak rol sayısını her koşulda çarpar; on iki şube ve iki koşul yüz doksan iki rol üretir.
- Rol tabanlı karar isteğin başında kaba taneli süzgeç olarak kalır; kayıt düzeyindeki karar ayrı bir katmanda verilir.
Sonraki Adım
Yanlış çıkan dört kararın üçü aynı eksikten geliyor: model, isteğin bağlamını görmüyor. Kaydın sahibi kim, personel hangi şubede çalışıyor, istek hangi saatte geldi — bunların hepsi karar anında bilinen ama izin adında yeri olmayan bilgiler. Sonraki ders bu bilgileri kararın girdisi hâline getiren öznitelik tabanlı erişim denetimini ele alıyor ve aynı sekiz senaryoyu bu modelle yeniden değerlendiriyor.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.