İçeriğe geç
academia.sh

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.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat