İçeriğe geç
academia.sh

Ders 18 / 23

Öznitelik Tabanlı Erişim Denetimi

Kararın özne, nesne, eylem ve bağlam öznitelikleriyle verilmesi, ret önceliğinin kural birleştirmedeki rolü, aynı senaryo kümesinde öznitelik tabanlı modelin doğru ve yanlış kararları ve özniteliğin nereden okunduğunun sonucu.

İçindekiler

Önceki dersin sekiz senaryosunda dört karar yanlış çıktı ve üçünün nedeni aynıydı: rol tabanlı model isteğin bağlamını göremiyor. Kaydın sahibinin kim olduğu, personelin hangi şubede çalıştığı, isteğin hangi saatte geldiği — bunların hepsi karar anında bilinen bilgilerdir, ama izin adının içinde onlara yer yoktur.

Öznitelik tabanlı erişim denetimi (attribute-based access control) bu bilgileri kararın girdisi hâline getirir. Kararı veren şey artık bir izin listesindeki üyelik değil, öznitelik değerleri üzerinde çalışan bir kuraldır.

Dört Öznitelik Kümesi

Model, karar anında dört kaynaktan öznitelik toplar.

Özne öznitelikleri, isteği yapanın kendisine aittir: kod, rol, çalıştığı şube, kıdem, kimlik doğrulamanın hangi etmenlerle yapıldığı.

Nesne öznitelikleri, erişilmek istenen kayda aittir: türü, sahibi, ait olduğu şube, gizlilik sınıfı, oluşturulma tarihi.

Eylem, yapılmak istenen işlemdir; rol tabanlı modeldekiyle aynı anlamı taşır.

Bağlam öznitelikleri ne özneye ne nesneye aittir; isteğin kendisine aittir: saat, ağ konumu, isteğin geldiği aygıt, oturumun yaşı.

Kural, bu dört kümenin değerleri üzerinde bir koşuldur. “Kendi kaydını görüntüleyebilir” kuralı, özne kodunun nesne sahibine eşitliğidir; şube kuralı iki şube özniteliğinin eşitliğidir. Rol tabanlı modelde ifade edilemeyen şey bu eşitliklerdi, çünkü orada karar kayda hiç bakmıyordu.

Kuralların Birleştirilmesi

Birden çok kural aynı isteğe uyabilir ve sonuçları çelişebilir. Birleştirme kuralı bu durumda ne olacağını söyler. Yerleşik seçim ret önceliğidir: eşleşen kurallardan biri ret diyorsa karar rettir, izin diyen kuralların sayısı önemsizdir. Hiçbir kural eşleşmezse karar yine rettir — izin, açıkça verilmesi gereken bir şeydir.

Aşağıdaki değerlendirici dört kuralı bu birleştirmeyle uyguluyor ve önceki dersin sekiz senaryosunu yeniden karara bağlıyor. Son sütun, kararı hangi kuralın verdiğini gösteriyor.

cat > abac.mjs <<'EOF'
const OZNE = {
  "U-1001": { rol: "uye", sube: "S-02" }, "U-1002": { rol: "uye", sube: "S-02" },
  "U-1005": { rol: "uye", sube: "S-01" }, "P-2001": { rol: "gorevli", sube: "S-02" },
  "Y-3001": { rol: "sube_yoneticisi", sube: "S-02" },
};

// Onceki dersteki ortak senaryo kumesi.
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],
];

const mesaiIci = (saat) => saat >= "08:30" && saat <= "18:00";
const YAZAN = new Set(["guncelle", "olustur", "sil"]);

const KURALLAR = [
  { ad: "K1 kendi kaydi", etki: "izin",
    kosul: (o, e, n) => e === "goruntule" && n.sahip === o.kod },
  { ad: "K2 sube gorevlisi", etki: "izin",
    kosul: (o, e, n) => ["gorevli", "sube_yoneticisi"].includes(o.rol) &&
      n.sube === o.sube && ["goruntule", "guncelle", "olustur"].includes(e) },
  { ad: "K3 ceza silme", etki: "izin",
    kosul: (o, e, n) => o.rol === "sube_yoneticisi" && n.sube === o.sube &&
      e === "sil" && n.tur === "ceza" },
  { ad: "K4 mesai disi yazma", etki: "ret",
    kosul: (o, e, n, b) => YAZAN.has(e) && !mesaiIci(b.saat) && o.rol !== "sube_yoneticisi" },
];

function abac(ozneKod, eylem, nesneAdi, nesneOzn, saat) {
  const o = { kod: ozneKod, ...OZNE[ozneKod] };
  const n = { tur: nesneAdi.split(":")[0], ...nesneOzn };
  const b = { saat };
  const eslesen = KURALLAR.filter((k) => k.kosul(o, eylem, n, b));
  const ret = eslesen.find((k) => k.etki === "ret");
  const izin = eslesen.find((k) => k.etki === "izin");
  if (ret) return [false, `${ret.ad} (ret onceliklidir)`];
  if (izin) return [true, izin.ad];
  return [false, "eslesen kural yok"];
}

console.log("senaryo | ABAC | dogru | uyum | karari veren kural");
console.log("--------|------|-------|------|----------------------------");
let uyan = 0;
for (const [ad, ozne, eylem, nesne, ozn, saat, dogru] of SENARYOLAR) {
  const [karar, gerekce] = abac(ozne, eylem, nesne, ozn, saat);
  if (karar === dogru) uyan++;
  console.log(`${ad}      | ${(karar ? "izin" : "ret").padEnd(4)} | ` +
    `${(dogru ? "izin" : "ret").padEnd(5)} | ${(karar === dogru ? "+" : "-").padEnd(4)} | ${gerekce}`);
}
console.log(`\nABAC dogru karar: ${uyan}/${SENARYOLAR.length}`);
EOF
node abac.mjs
senaryo | ABAC | dogru | uyum | karari veren kural
--------|------|-------|------|----------------------------
S1      | izin | izin  | +    | K1 kendi kaydi
S2      | ret  | ret   | +    | eslesen kural yok
S3      | izin | izin  | +    | K2 sube gorevlisi
S4      | ret  | ret   | +    | eslesen kural yok
S5      | ret  | ret   | +    | K4 mesai disi yazma (ret onceliklidir)
S6      | izin | izin  | +    | K3 ceza silme
S7      | ret  | izin  | -    | eslesen kural yok
S8      | ret  | ret   | +    | eslesen kural yok

ABAC dogru karar: 7/8

Rol tabanlı modelde yanlış çıkan dört karardan üçü düzeldi. S2 ve S4, sahiplik ve şube özniteliklerinin karşılaştırılmasıyla; S5, bağlam özniteliğiyle. S8’in kararı da artık doğru nedenle veriliyor: liste U-1005’in değil, dolayısıyla hiçbir kural eşleşmiyor.

Gerekçe sütunu modelin ikinci kazancıdır. Her karar, onu veren kuralın adıyla birlikte üretilebilir; “neden reddedildi” sorusunun yanıtı kütüğe yazılabilir. Rol tabanlı modelde bu yanıt “rolde o izin yoktu” cümlesinden ibaretti.

Modelin Ulaşamadığı Yer

S7 hâlâ yanlış. U-1001, dokuz numaralı okuma listesini U-1002 ile paylaşmış; U-1002 bu listeyi görebilmeli. Öznitelik tabanlı modelde bu kısıtı yazmanın yolu, paylaşımı bir öznitelik hâline getirmektir: nesneye bir paylasilanlar alanı eklenir ve kural, özne kodunun o listede olup olmadığına bakar.

Bu yol küçük ölçekte çalışır, iki yerde tıkanır. Birincisi geçişkenliktir: U-1002 listeyi kendi çalışma grubuyla paylaşırsa, grubun üyeleri de erişmelidir. Öznitelik listesi bunu ancak grubun tüm üyelerini tek tek içine alarak ifade eder ve grup değiştikçe her nesnenin özniteliği güncellenmelidir. İkincisi dolaylılıktır: “şube yöneticisinin yönettiği şubede çalışan personelin açtığı ödünç kayıtları” gibi bir kısıt, iki adım uzaklıktaki bir bağa dayanır ve tek bir öznitelik alanına sığmaz.

Bu iki durum, kısıtın öznitelik değil ilişki olduğunun işaretidir. Sonraki dersin konusu budur.

Özniteliğin Kaynağı ve Tazeliği

Öznitelik tabanlı modelin işletimdeki asıl sorusu kuralların nasıl yazıldığı değil, özniteliklerin nereden okunduğudur. İki seçenek vardır: değerler kimlik belirtecinin içinde taşınır ya da karar anında kaydından okunur.

Belirteçten okumak hızlıdır ve ek sorgu gerektirmez. Bedeli, değerin belirtecin üretildiği andaki değer olmasıdır. Aşağıdaki örnek, şube değiştiren bir görevlinin iki isteğini iki kaynakla karara bağlıyor.

cat > tazelik.mjs <<'EOF'
const KAYIT = { "P-2001": { rol: "gorevli", sube: "S-01" } };   // 12:00'de S-02'den S-01'e gecti
const BELIRTEC = { kod: "P-2001", rol: "gorevli", sube: "S-02", uretim: "09:00" };

const kural = (o, n) => o.rol === "gorevli" && n.sube === o.sube;

const istekler = [
  ["odunc:502 (sube S-02)", { sube: "S-02" }, false],   // artik gormemeli
  ["odunc:503 (sube S-01)", { sube: "S-01" }, true],    // artik gormeli
];

console.log("oznitelik kaynagi        | " + istekler.map((i) => i[0]).join(" | "));
console.log("-------------------------|-----------------------|-----------------------");
for (const [ad, o] of [["belirtecten (09:00)", { ...BELIRTEC }],
                       ["kayittan (istek ani)", { kod: "P-2001", ...KAYIT["P-2001"] }]]) {
  const hucreler = istekler.map(([, n, dogru]) => {
    const karar = kural(o, n);
    return `${karar ? "izin" : "ret"} ${karar === dogru ? "(dogru)" : "(YANLIS)"}`.padEnd(21);
  });
  console.log((ad.padEnd(24) + " | " + hucreler.join(" | ")).trimEnd());
}
EOF
node tazelik.mjs
oznitelik kaynagi        | odunc:502 (sube S-02) | odunc:503 (sube S-01)
-------------------------|-----------------------|-----------------------
belirtecten (09:00)      | izin (YANLIS)         | ret (YANLIS)
kayittan (istek ani)     | ret (dogru)           | izin (dogru)

Belirteçteki eski değer iki yönde birden yanlış karar üretiyor: görevlinin artık görmemesi gereken kayda izin veriyor, görmesi gereken kaydı reddediyor. İkincisi bir destek talebi olarak görünür ve düzeltilir; birincisi hiç görünmez.

Karar kuralı şudur: kararı değiştiren öznitelik, değişebiliyorsa karar anında okunur. Belirteçte yalnız değişmeyen ya da belirteç ömrü içinde değişmesi kabul edilebilir öznitelikler taşınır. Belirteç ömrü kısaldıkça bu ayrımın önemi azalır — yenileme belirteçleri dersindeki ömür kararı, buradaki tazelik kararıyla aynı ödünleşimin iki yüzüdür.

Kayıttan okumanın bedeli her istekte bir sorgudur. Bu maliyet, öznitelikleri istek başına bir kez okuyup istek boyunca önbelleğe almakla sınırlanır; önbelleğin ömrü isteğin ömrünü aşmamalıdır.

Kuralların Denetlenebilirliği

Öznitelik tabanlı modelin kazandırdığı ifade gücü, bir maliyetle gelir: kuralların bir arada ne yaptığını görmek zorlaşır. Rol tabanlı modelde bir hesabın etkin izin kümesi hesaplanabiliyordu; öznitelik kurallarında böyle bir küme yoktur, çünkü karar isteğin kendisine bağlıdır.

Bunun yerine iki denetim yordamı kullanılır.

Senaryo kümesi. Bu dersteki tablonun kendisi bir denetim aracıdır: bilinen istekler ve beklenen yanıtlar bir küme hâlinde tutulur, kural her değiştiğinde küme yeniden çalıştırılır. Uyum sütununda eksi çıkması, kuralın metnine bakmayı gerektirir.

Kural kapsamı. Hiçbir senaryoda eşleşmeyen bir kural ya gereksizdir ya da yanlış yazılmıştır; her senaryoda eşleşen bir kural büyük olasılıkla fazla geniştir. Kuralların kaç kez eşleştiği sayılabilir ve bu sayı kuralın yazılışı hakkında bilgi verir.

Üçüncü bir kural yazım disiplinidir: kurallar yan etkisiz olmalı, aynı girdide her zaman aynı kararı üretmelidir. Karar sırasında kayıt yazan, dış servis çağıran ya da rastgele değer kullanan bir kural, yeniden çalıştırılamaz ve denetlenemez.

Özet

  • Öznitelik tabanlı erişim denetimi kararı özne, nesne, eylem ve bağlam özniteliklerinden üretir; rol tabanlı modelde ifade edilemeyen sahiplik ve şube kısıtları burada eşitlik koşulu olarak yazılır.
  • Kural birleştirmede ret önceliklidir ve hiçbir kural eşleşmezse karar rettir.
  • Model her kararın gerekçesini üretebilir; bu, reddin nedeninin kütüğe yazılmasını mümkün kılar.
  • Geçişken ve dolaylı bağlar öznitelik alanına sığmaz; bu kısıtlar öznitelik değil ilişki niteliğindedir.
  • Kararı değiştiren öznitelik değişebiliyorsa karar anında okunur; belirteçte taşınan eski değer iki yönde birden yanlış karar üretir.

Sonraki Adım

S7 iki derstir yanlış karara bağlanıyor. Paylaşılmış bir listenin erişilebilirliği, ne özneye ne nesneye ait bir özelliktir; ikisi arasındaki bağdır. Sonraki ders bu bağları birinci sınıf veri hâline getiren ilişki tabanlı erişim denetimini ele alıyor: nesneler ve özneler bir çizge oluşturuyor, erişim sorusu da o çizge üzerinde bir ulaşılabilirlik sorgusuna dönüşüyor.

İ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