Ders 23 / 30
Rol Tabanlı Erişim Denetimi
Bir özne × fiil × nesne × ad alanı yetki matrisi kurulur ve geniş yetkiden en az yetkiye inince kaç işlemin düştüğü sayılır: izinli işlem, rol tanımının satır maliyeti ve bir öznenin başka bir öznenin yetkisine ulaşabildiği yükseltme yolları ölçülür.
İçindekiler
Önceki iki dersin denetleyicileri kümede kısıtsız iş gördü. Dağıtım denetleyicisi sürüm nesnesini değiştirdi, kapsül sildi, havuz üyeliğini yazdı; sağlık denetimleri süreç öldürdü. Aynı arayüzü insanlar ve öteki otomatik süreçler de kullanıyor ve şimdiye kadar hiçbiri “bunu yapmaya yetkin var mı” sorusuyla karşılaşmadı. Kimlik ve en az yetki daha önce ölçüldü; buranın farkı, yetkinin küme nesneleri üzerinde tanımlanması ve her nesnenin başka nesnelere ulaşma imkânı taşımasıdır.
Devredilen karar şudur: bir isteğin yürütülüp yürütülmeyeceğine, isteği yapanın kim olduğuna bakarak küme arayüzü karar verir. Bunun için bilmesi gereken üç kalem vardır — kim, ne yapmak istiyor, neyin üstünde — ve bu üçüne bir dördüncüsü eklenir: hangi ad alanında. Kalemlerin çarpımı, sistemin doldurması gereken tablodur. Bu dersin ölçüsü o tablonun boyu, doldurmanın maliyeti ve boş bırakmanın bedelidir.
- OI13. Model kurgusal bölgesel ölçüm ağının sekiz öznesini, yedi fiili, sekiz nesne türünü ve
üç ad alanını taşır. Gerçek bir küme koşturulmuyor; ölçülen şey
nodeile kurulan modeldir. - OI14. İşlem izi otuz günlük bir kayıttan çıkarılmış sayılır ve elle yazılmıştır. İzde görünmeyen işlem “gerekmiyor” kabul edilir. Seyrek koşan bakım işleri böyle bir izde görünmez; en az yetki onları da düşürür ve ilk koşumlarında engellenirler.
- OI15. Buradaki ad alanı kümenin ad alanıdır: nesnelerin gruplandığı ve yetkinin sınırlandığı bölme. Tek makinedeki yalıtımın görünürlük eşlemesi anlamındaki ad alanıyla aynı sözcüktür, farklı nesnedir.
- OI16. Yetki yükseltme iki kurala indirgendi: rol tanımı yazabilen özne o ad alanındaki her yetkiyi kendine verebilir; sır nesnesini okuyabilen özne o ad alanındaki bir öznenin kimliğini ele geçirebilir. Gerçekte daha çok yol vardır, bu yüzden sayılan değer bir alt sınırdır.
- OI17. Rol tanımı satırı kendi küçük şemamızla sayılır; şema ders içinde tanımlıdır. Satır sayısı biçim seçimine bağlıdır, büyüklük sırası değil.
- OI18. Aynı yetki kümesine sahip özneler tek role indirilir. Rol adları üretilmiştir; okunur adlar satır sayısını değiştirmez.
Yetki Matrisi
// yetki.mjs — ozne x fiil x nesne x ad alani yetki matrisi; gercek kume degil, bir modeldir export const OZNE = ['okuma-toplayici', 'dogrulayici', 'faturalama', 'is-emri', 'gecelik-toplu-is', 'yayin-denetleyicisi', 'nobetci', 'pano-okuyucu']; export const FIIL = ['oku', 'listele', 'izle', 'olustur', 'guncelle', 'sil', 'yetkilendir']; export const NESNE = ['kapsul', 'surum-nesnesi', 'servis-nesnesi', 'yapilandirma-nesnesi', 'sir-nesnesi', 'kota', 'rol-tanimi', 'dugum']; export const ALAN = ['gelistirme', 'hazirlik', 'uretim']; const U = ['uretim'], H = ['hazirlik', 'uretim'], T = ALAN; // Otuz gunluk kayittan cikarilan islem izi; elle yazildi, rastgelelik yok. export const IZ = [ ['okuma-toplayici', 'oku', 'yapilandirma-nesnesi', U], ['okuma-toplayici', 'listele', 'kapsul', U], ['dogrulayici', 'oku', 'yapilandirma-nesnesi', H], ['dogrulayici', 'oku', 'sir-nesnesi', H], ['dogrulayici', 'listele', 'servis-nesnesi', H], ['faturalama', 'oku', 'yapilandirma-nesnesi', U], ['faturalama', 'oku', 'sir-nesnesi', U], ['is-emri', 'oku', 'yapilandirma-nesnesi', U], ['is-emri', 'listele', 'servis-nesnesi', U], ['gecelik-toplu-is', 'oku', 'sir-nesnesi', U], ['gecelik-toplu-is', 'olustur', 'kapsul', U], ['gecelik-toplu-is', 'listele', 'kapsul', U], ['yayin-denetleyicisi', 'guncelle', 'surum-nesnesi', T], ['yayin-denetleyicisi', 'listele', 'kapsul', T], ['yayin-denetleyicisi', 'sil', 'kapsul', T], ['yayin-denetleyicisi', 'izle', 'kapsul', T], ['nobetci', 'oku', 'kapsul', T], ['nobetci', 'listele', 'kapsul', T], ['nobetci', 'izle', 'kapsul', T], ['nobetci', 'oku', 'sir-nesnesi', U], ['pano-okuyucu', 'listele', 'kapsul', T], ['pano-okuyucu', 'listele', 'servis-nesnesi', T], ]; export const anahtar = (o, f, n, a) => `${o}|${f}|${n}|${a}`; export function enAz() { const s = new Set(); for (const [o, f, n, alanlar] of IZ) for (const a of alanlar) s.add(anahtar(o, f, n, a)); return s; } export function genis() { // her ozneye her fiil, her nesne, her alan const s = new Set(); for (const o of OZNE) for (const f of FIIL) for (const n of NESNE) for (const a of ALAN) s.add(anahtar(o, f, n, a)); return s; } // Yukseltme: rol tanimi yazabilen o alandaki her yetkiyi kendine verebilir; sir nesnesini // okuyabilen o alandaki bir oznenin kimligini ele gecirebilir. export function yukseltme(izin) { const var_ = (o, f, n, a) => izin.has(anahtar(o, f, n, a)); const alanOzne = (a) => OZNE.filter((o) => [...izin].some((k) => k.startsWith(`${o}|`) && k.endsWith(`|${a}`))); const kenar = new Set(); for (const o of OZNE) for (const a of ALAN) { const rolYazar = ['olustur', 'guncelle', 'yetkilendir'].some((f) => var_(o, f, 'rol-tanimi', a)); const sirOkur = var_(o, 'oku', 'sir-nesnesi', a); if (!rolYazar && !sirOkur) continue; for (const t of alanOzne(a)) if (t !== o) kenar.add(`${o}->${t}`); } let n = kenar.size, once; // gecisli kapanis do { once = n; for (const k1 of [...kenar]) for (const k2 of [...kenar]) { const [a1, b1] = k1.split('->'), [a2, b2] = k2.split('->'); if (b1 === a2 && a1 !== b2) kenar.add(`${a1}->${b2}`); } n = kenar.size; } while (n !== once); return kenar; }
İzin listesi ile matris arasındaki fark şudur: matris bütün hücreleri taşır, iz yalnız dolu
olanları. genis işlevi bütün hücreleri doldurur — hiçbir soru sormadan her özneye her şeyi
verir. enAz yalnız izde görüneni doldurur. İkisi arasındaki bütün fark, otuz günlük kayda
bakmanın maliyetidir.
Geniş Yetkiden En Az Yetkiye
// kosum5.mjs — genis yetki ile en az yetki karsilastirilir import { OZNE, FIIL, NESNE, ALAN, IZ, enAz, genis } from './yetki.mjs'; const g = genis(), e = enAz(); console.log(`ozne ${OZNE.length} x fiil ${FIIL.length} x nesne ${NESNE.length} x ad alani ${ALAN.length}` + ` = ${OZNE.length * FIIL.length * NESNE.length * ALAN.length} olasi islem`); console.log(`gozlenen iz: ${IZ.length} satir, ad alanlarina acilinca ${e.size} ayri islem\n`); console.log('olcut genis yetki en az yetki fark'); const satir = (ad, x, y) => console.log(`${ad.padEnd(29)} ${String(x).padEnd(12)} ${String(y).padEnd(12)} ${x - y}`); satir('izinli islem', g.size, e.size); satir('yetkili ozne', OZNE.length, new Set([...e].map((k) => k.split('|')[0])).size); const ff = (s) => new Set([...s].map((k) => k.split('|').slice(0, 2).join('|'))).size; satir('ozne-fiil cifti', ff(g), ff(e)); const nn = (s) => new Set([...s].map((k) => k.split('|')[2])).size; satir('dokunulan nesne turu', nn(g), nn(e)); const sir = (s) => [...s].filter((k) => k.split('|')[1] === 'oku' && k.split('|')[2] === 'sir-nesnesi').length; satir('sir nesnesi okuma izni', sir(g), sir(e)); const rol = (s) => [...s].filter((k) => k.split('|')[2] === 'rol-tanimi').length; satir('rol tanimina dokunan izin', rol(g), rol(e));
ozne 8 x fiil 7 x nesne 8 x ad alani 3 = 1344 olasi islem gozlenen iz: 22 satir, ad alanlarina acilinca 43 ayri islem olcut genis yetki en az yetki fark izinli islem 1344 43 1301 yetkili ozne 8 8 0 ozne-fiil cifti 56 18 38 dokunulan nesne turu 8 5 3 sir nesnesi okuma izni 24 5 19 rol tanimina dokunan izin 168 0 168
Bin üç yüz bir işlem düştü — matrisin yüzde doksan yedisi. Geriye kalan kırk üç işlem, sekiz öznenin otuz gün boyunca gerçekten yaptığı her şeydir. İkinci satır bu düşüşün hangi eksende olmadığını gösteriyor: yetkili özne sayısı sekizden sekize, yani hiç değişmedi. En az yetki kimseyi kümeden çıkarmıyor; herkesin ne yapabildiğini daraltıyor.
Daralma nesne ekseninde en sert. Sekiz nesne türünden beşine dokunuluyor; üç tür — kota, rol tanımı ve düğüm — otuz gün boyunca hiçbir özne tarafından kullanılmadı. Bunların iki tanesi kümenin kendi işletimine ait nesnelerdir ve iş yükü öznelerinin bunlara erişmesi için bir neden yoktur. Son satır bunun sayısını veriyor: geniş yetkide rol tanımına dokunan yüz altmış sekiz izin vardı, en az yetkide sıfır. Yüz altmış sekiz iznin tamamı, hiç kullanılmadığı hâlde açık duran ve her biri kendisini genişletmeye yarayan izinlerdi.
Sır nesnesi satırı ise düşüşün durduğu yeri gösteriyor: yirmi dörtten sıfıra değil, beşe indi. Dört özne sırlara gerçekten erişiyor — doğrulayıcı iki ad alanında, faturalama, gecelik toplu iş ve nöbetçi üretimde. Bu beş izin izde vardır, dolayısıyla en az yetki onları düşüremez.
Yazma Bedeli ve Yükseltme Yolları
En az yetkinin ikinci bedeli ilk tabloda görünmüyor: matrisin doldurulmayan hücreleri bedava, doldurulanların her biri yazılmak zorunda. Bunu saymak için yetki kümesi kendi şemamızla metne dökülür.
// kosum6.mjs — iki modelin rol tanimi kendi semamizla yazilir ve satiri sayilir import { OZNE, enAz, genis, yukseltme } from './yetki.mjs'; // Sema: "rol <ad>" / " <nesne>: <fiil>,<fiil>" / "bag <rol> -> <ozne> @ <alan>" function yaz(izin) { const kume = new Map(); // (ozne, alan) -> nesne:fiiller for (const k of izin) { const [o, f, n, a] = k.split('|'); const m = kume.get(`${o}|${a}`) ?? new Map(); m.set(n, (m.get(n) ?? new Set()).add(f)); kume.set(`${o}|${a}`, m); } const rol = new Map(), bag = []; // ayni yetki kumesi tek role indirilir for (const [oa, m] of kume) { const govde = [...m].sort().map(([n, fs]) => ` ${n}: ${[...fs].sort().join(',')}`).join('\n'); if (!rol.has(govde)) rol.set(govde, `rol-${rol.size + 1}`); const [o, a] = oa.split('|'); bag.push(`bag ${rol.get(govde)} -> ${o} @ ${a}`); } const metin = [...rol].map(([g, ad]) => `rol ${ad}\n${g}`).concat(bag).join('\n'); return { metin, rol: rol.size, bag: bag.length, satir: metin.split('\n').length }; } const g = yaz(genis()), e = yaz(enAz()); console.log('model rol bag toplam satir izinli islem islem/satir'); for (const [ad, y, izin] of [['genis yetki', g, genis()], ['en az yetki', e, enAz()]]) { console.log(`${ad.padEnd(12)} ${String(y.rol).padEnd(4)} ${String(y.bag).padEnd(4)} ` + `${String(y.satir).padEnd(13)} ${String(izin.size).padEnd(13)} ${(izin.size / y.satir).toFixed(1)}`); } console.log('\nen az yetki tanimindan iki rol ve iki bag:'); console.log(e.metin.split('\n').slice(0, 6).join('\n')); console.log(e.metin.split('\n').filter((l) => l.startsWith('bag')).slice(0, 2).join('\n')); // Sir nesnesi okuma izni kaldirilirsa yukseltme yollari ne oluyor const kis = new Set([...enAz()].filter((k) => !(k.split('|')[1] === 'oku' && k.split('|')[2] === 'sir-nesnesi'))); console.log('\nyukseltme yolu sayisi ve her ozneye ulasan ozne:'); for (const [ad, s] of [['genis yetki', genis()], ['en az yetki', enAz()], ['sir okuma kaldirildi', kis]]) { const k = yukseltme(s); const tam = OZNE.filter((o) => [...k].filter((x) => x.startsWith(`${o}->`)).length === OZNE.length - 1).length; console.log(` ${ad.padEnd(22)} yol ${String(k.size).padEnd(4)} tam yetkiye ulasan ${tam} izinli islem ${s.size}`); }
model rol bag toplam satir izinli islem islem/satir genis yetki 1 24 33 1344 40.7 en az yetki 9 15 42 43 1.0 en az yetki tanimindan iki rol ve iki bag: rol rol-1 kapsul: listele yapilandirma-nesnesi: oku rol rol-2 servis-nesnesi: listele sir-nesnesi: oku bag rol-1 -> okuma-toplayici @ uretim bag rol-2 -> dogrulayici @ hazirlik yukseltme yolu sayisi ve her ozneye ulasan ozne: genis yetki yol 56 tam yetkiye ulasan 8 izinli islem 1344 en az yetki yol 28 tam yetkiye ulasan 4 izinli islem 43 sir okuma kaldirildi yol 0 tam yetkiye ulasan 0 izinli islem 38
Yazma bedeli otuz üç satırdan kırk iki satıra çıktı — yüzde yirmi yedi artış, dokuz satır. Bu, bin üç yüz bir işlemi düşürmenin bütün maliyetidir. Son sütun ikisinin arasındaki ilişkiyi tek sayıya indiriyor: geniş yetkide yazılan her satır kırk işlem açıyor, en az yetkide tam olarak bir. Geniş yetkinin ucuzluğu yazmadığı satırlardan gelir; en az yetkide izin verilen her işlem ayrı ayrı yazılmak zorundadır, çünkü genelleme yapan hiçbir kural yoktur. Kırk iki satırın bakımı da buradan doğar: iz değiştiğinde tanım değişmek zorundadır.
Alt tablo bu dersin asıl sonucudur. Geniş yetkide elli altı yükseltme yolu var ve sekiz öznenin sekizi de her özneye ulaşıyor — beklenen sonuç. En az yetkide izinli işlem kırk üçe indi ama yükseltme yolu yalnız yarıya, yirmi sekize düştü ve dört özne hâlâ her özneye ulaşıyor. İzinli işlemin yüzde doksan yedisini düşürmek, yükseltme yolunun yalnız yüzde ellisini düşürdü. İki sayı aynı şeyi ölçmüyor.
Üçüncü satır nedeni veriyor. Sır nesnesi okuma izni kaldırıldığında izinli işlem kırk üçten otuz sekize iniyor — beş işlem — ve yükseltme yolu yirmi sekizden sıfıra düşüyor. Yirmi sekiz yolun tamamını beş izin taşıyordu. Kalan otuz sekiz iznin hiçbiri bir özneyi başka bir öznenin yerine geçirmiyor.
Bu beş izin gereksiz değildi; izde vardılar, yani o süreçler sırlara gerçekten erişiyordu. Sayının söylediği şey iznin kaldırılması değil, sırrın kümeden okunmak yerine sürece başka bir yolla ulaştırılması gerektiğidir. Karar burada bir ölçüye bağlanabilir hâle geliyor: bir izni kaldırmanın işlem maliyeti beş, yükseltme kazancı yirmi sekiz. Aynı hesap kota, rol tanımı ve düğüm için yapılsaydı kazanç sıfır çıkardı, çünkü o izinler zaten kapalıydı.
Sistemin Bilmediği
Küme arayüzü bir isteği değerlendirirken tek bir soruya cevap arar: bu dörtlü tabloda var mı. Niyeti, bağlamı, zamanı ve sırayı bilmez. Nöbetçinin üretimde sır nesnesi okuması, bir arıza sırasında da olağan bir salı sabahı da aynı hücreye düşer; tablo ikisini ayırt edemez çünkü ayırt edecek kalemi taşımıyor. Aynı nedenle “bu izni son ne zaman kullandı” sorusu da tablodan cevaplanamaz — kırk üç iznin hangilerinin hâlâ canlı olduğu, ancak izin yeniden toplanmasıyla bilinir. Bu, devredilen kararın sürekli beslenmesi gereken bir bilgi kalemi olduğu anlamına gelir: tablo bir kez doğru kurulduğunda doğru kalmaz, iz değiştikçe eskir.
Eskimenin iki yönü var ve bedelleri simetrik değil. İz genişlediğinde — yeni bir servis, yeni bir bakım işi — tablo dar kalır ve sistem meşru bir işlemi reddeder; bu hemen görünür, çünkü birileri engellendiğini bildirir. İz daraldığında — bir süreç emekliye ayrılır, bir fiil kullanılmaz olur — tablo geniş kalır ve sistem gereksiz bir işlemi kabul etmeye devam eder; bu hiç görünmez, çünkü kimse şikâyet etmez. Yüz altmış sekiz rol tanımı izni geniş yetkide tam olarak böyle duruyordu: kullanılmıyorlardı, kimseyi rahatsız etmiyorlardı ve elli altı yükseltme yolunun büyük bölümünü taşıyorlardı. Otuz günlük izden türetilen en az yetkinin değeri, bu ikinci yönü bir kereliğine kapatmasıdır; kapalı tutması için iz ölçümünün sürmesi gerekir.
Özet
- Sekiz özne, yedi fiil, sekiz nesne türü ve üç ad alanı 1344 hücrelik bir matris kurar; otuz günlük iz bunun 43’ünü dolduruyor, en az yetkiye inmek 1301 işlem düşürüyor.
- Düşüş özne ekseninde değil: yetkili özne sayısı sekizden sekize sabit kaldı, daralan şey her öznenin ne yapabildiğidir.
- Rol tanımına dokunan 168 izin en az yetkide sıfıra iniyor; hiçbiri otuz gün boyunca kullanılmamıştı.
- En az yetkinin yazma bedeli 33 satırdan 42 satıra, yüzde yirmi yedi artıştır; geniş yetkide yazılan satır başına 40,7 işlem açılırken en az yetkide tam olarak 1 işlem açılır.
- İzinli işlem sayısı ile yükseltme yolu sayısı aynı şeyi ölçmez: işlemlerin yüzde doksan yedisi düştüğünde yollar yalnız yarıya indi ve dört özne hâlâ her özneye ulaşıyordu.
- Kalan 28 yolun tamamını beş sır okuma izni taşıyordu; o beş izin kapandığında yol sayısı sıfıra iniyor. İzin kaldırmanın maliyeti ve kazancı ayrı ayrı ölçülebilir.
Sonraki Adım
Bu dersin matrisi kimin küme arayüzü üzerinden ne yapabileceğini sınırlıyor. İki kapsül arasındaki trafik bu matristen geçmez: doğrulayıcı, faturalama servisinin ucuna doğrudan bağlanır ve küme arayüzüne hiç uğramaz. Yetki matrisinde birbirine ulaşamayan iki özne, ağ üzerinde birbirine serbestçe ulaşabilir. Sonraki ders erişilebilirlik matrisini politika ile kurar ve varsayılan açık ile varsayılan kapalı arasındaki farkı sayar: kaç yol kapanıyor, kaç meşru yol yanlışlıkla kapanıyor, politika kaç kural istiyor ve yeni bir servis eklendiğinde kaç kural güncelleniyor.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.