Ders 04 / 21
Rol Üstlenme
Geçici kimlik bilgisiyle erişim, uzun ömürlü anahtarla karşılaştırılır: sızıntı penceresi, üstlenme zincirinin uzunluğu, güven ilişkisinin kimin üstlenebileceğini belirlemesi ve denetim kaydında asıl öznenin kaç adım sonra kaybolduğu sayılır.
İçindekiler
Önceki üç ders izni daralttı ve iki yönü birlikte okumayı öğretti, ama her özne hâlâ kalıcı bir kimlikti ve her kalıcı kimliğin uzun ömürlü bir kimlik bilgisi vardı. İlk derste bu yüzeyin boyu sayılmıştı: yirmi dokuz saklama yeri, en eskisi sekiz yüz seksen günlük. Politika belgesi ne kadar dar yazılırsa yazılsın, anahtarı ele geçiren o belgenin verdiği her şeyi alır.
Rol üstlenme erişimi kalıcı kimlikten ayırır. Özne kendi kimliğiyle doğrulanır, sonra bir rolü üstlenir ve o rolün yetkisiyle çalışan geçici bir kimlik bilgisi alır. Kimlik bilgisinin dinamik üretilmesi ve ömrünün kısalması daha önce sır yönetimi ekseninde ölçülmüştü; buradaki ölçüm o değil. Burada sayılan üç şey var: pencerenin ne kadar daraldığı, üstlenmenin zincirlenmesi ve zincirin denetim kaydında bıraktığı iz.
- BI19. Model beş kalıcı kimlik, altı rol ve dokuz üstlenme zinciri taşır. Gerçek bir hesap
koşturulmuyor; ölçülen şey
nodeile kurulan güven grafiğidir. - BI20. Kimlik bilgisi ömürleri ve saatlik üstlenme sınırı kurgudur, ders içinde tanımlıdır. Bir sağlayıcının değerleri değildir.
- BI21. Sızıntının fark edilme süresi yirmi bir gün kabul edildi. Uzun ömürlü anahtarın penceresi bu süreyle sınırlandı; gerçekte fark edilmeyen sızıntıda pencere daha uzundur, bu yüzden ölçülen kat bir alt sınırdır.
- BI22. Sızıntının kimlik bilgisinin geçerlilik aralığında düzgün dağıldığı varsayıldı; beklenen pencere bu yüzden ömrün yarısıdır.
- BI23. Otuz günlük iz elle yazıldı ve dokuz zincirden oluşuyor. Zincirlerin güven ilişkisine uyduğu kod içinde denetleniyor.
- BI24. Denetim kaydı iki kalem taşıyor sayılır: son rol ve oturum adı. Üstlenme kaydı ayrıca çağıranın oturum adını taşır. Kayıt saklama süresi modele girmedi.
Güven Grafiği ve Ömürler
// ustlenme.mjs — guven iliskisi ve ustlenme zinciri; gercek bir hesap degil, node ile kurulan modeldir export const KIMLIK = ['toplama-hizmeti', 'analitik-is', 'saha-bakim', 'yayin-hatti', 'nobetci-insan']; export const GUVEN = { // rol -> onu ustlenebilecekler (kimlik ya da rol) 'rol-okuma': ['toplama-hizmeti', 'analitik-is', 'rol-koprusu'], 'rol-yayin': ['yayin-hatti'], 'rol-bakim': ['saha-bakim', 'rol-yayin'], 'rol-yonetim': ['nobetci-insan', 'rol-bakim'], 'rol-denetim': ['*'], 'rol-koprusu': ['nobetci-insan', 'yayin-hatti'], }; export const ROL = Object.keys(GUVEN); // Otuz gunluk iz: hangi zincir kac islem uretti; elle yazildi export const IZ = [ ['toplama-hizmeti', ['rol-okuma'], 1200], ['analitik-is', ['rol-okuma'], 800], ['saha-bakim', ['rol-bakim'], 260], ['yayin-hatti', ['rol-yayin', 'rol-bakim'], 340], ['nobetci-insan', ['rol-koprusu', 'rol-okuma'], 90], ['nobetci-insan', ['rol-yonetim'], 40], ['yayin-hatti', ['rol-yayin', 'rol-bakim', 'rol-yonetim'], 25], ['saha-bakim', ['rol-denetim'], 60], ['analitik-is', ['rol-denetim'], 30], ]; export const guvenir = (rol, ustlenen, g = GUVEN) => g[rol].includes('*') || g[rol].includes(ustlenen); export function zincirGecerli(basla, adimlar, g = GUVEN) { let su = basla; for (const r of adimlar) { if (!guvenir(r, su, g)) return false; su = r; } return true; } // Bir kimlikten ulasilan roller ve en kisa zincir uzunlugu (genislik oncelikli arama) export function ulasim(basla, g = GUVEN) { const uzaklik = new Map(); let sinir = [basla]; for (let d = 1; sinir.length; d++) { const yeni = []; for (const r of Object.keys(g)) { if (uzaklik.has(r)) continue; if (sinir.some((s) => guvenir(r, s, g))) { uzaklik.set(r, d); yeni.push(r); } } sinir = yeni; } return uzaklik; } export const OMUR = [ // ad, gecerlilik suresi (dakika) ['uzun omurlu anahtar', null], ['rol ustlenme 12 saat', 720], ['rol ustlenme 1 saat', 60], ['rol ustlenme 15 dk', 15], ]; export const TESPIT_DK = 21 * 24 * 60; // sizintinin fark edilme suresi, kurgu export const SINIR_SAAT = 500; // saatte en cok ustlenme cagrisi, kurgu
Güven ilişkisi rolün kendi üstünde durur ve bir liste taşır: bu rolü kim üstlenebilir. Listede
kalıcı bir kimlik olabileceği gibi başka bir rol de olabilir — zincir buradan doğar. rol-denetim
satırındaki * bu listenin en geniş hâlidir ve kendi başına bir ölçüm konusudur.
Sızıntı Penceresi
// kosum1.mjs — sizinti penceresi: uzun omurlu anahtar ile rol ustlenme import { KIMLIK, OMUR, TESPIT_DK, SINIR_SAAT } from './ustlenme.mjs'; const AY = 30 * 24 * 60; // otuz gunluk pencere, dakika const uzun = TESPIT_DK; // uzun omurlude pencere = fark edilme suresi console.log(`otuz gun ${AY} dk; sizintinin fark edilme suresi ${TESPIT_DK} dk (kurgu)`); console.log(`${KIMLIK.length} kalici kimlik, saatlik ustlenme siniri ${SINIR_SAAT} cagri (kurgu)\n`); console.log('kimlik bilgisi omur (dk) otuz gunde adet beklenen pencere en kotu pencere kat'); for (const [ad, t] of OMUR) { const adet = t ? AY / t : 1; const beklenen = t ? Math.min(t / 2, uzun) : uzun; const enKotu = t ? Math.min(t, uzun) : uzun; console.log(`${ad.padEnd(21)} ${String(t ?? 'sinirsiz').padEnd(10)} ${String(adet).padEnd(16)} ` + `${String(beklenen).padEnd(17)} ${String(enKotu).padEnd(16)} ${Math.round(uzun / beklenen)}`); } console.log('\nyenileme maliyeti ve sinir:'); for (const [ad, t] of OMUR.filter(([, t]) => t)) { const saatlik = (60 / t) * KIMLIK.length; console.log(` ${ad.padEnd(21)} saatlik cagri ${saatlik.toFixed(2).padEnd(6)} ` + `sinira kalan ${(SINIR_SAAT - saatlik).toFixed(2).padEnd(7)} ayni hizda sigan kimlik ${Math.floor(SINIR_SAAT / (60 / t))}`); }
otuz gun 43200 dk; sizintinin fark edilme suresi 30240 dk (kurgu) 5 kalici kimlik, saatlik ustlenme siniri 500 cagri (kurgu) kimlik bilgisi omur (dk) otuz gunde adet beklenen pencere en kotu pencere kat uzun omurlu anahtar sinirsiz 1 30240 30240 1 rol ustlenme 12 saat 720 60 360 720 84 rol ustlenme 1 saat 60 720 30 60 1008 rol ustlenme 15 dk 15 2880 7.5 15 4032 yenileme maliyeti ve sinir: rol ustlenme 12 saat saatlik cagri 0.42 sinira kalan 499.58 ayni hizda sigan kimlik 6000 rol ustlenme 1 saat saatlik cagri 5.00 sinira kalan 495.00 ayni hizda sigan kimlik 500 rol ustlenme 15 dk saatlik cagri 20.00 sinira kalan 480.00 ayni hizda sigan kimlik 125
Uzun ömürlü anahtarın penceresi ömründen değil, sızıntının fark edilmesinden gelir: otuz bin iki yüz kırk dakika, yani üç haftadır. Bu sürede anahtar hâlâ geçerlidir ve kimse durumu bilmez. Bir saatlik geçici kimlik bilgisinde beklenen pencere otuz dakikaya iner — bin sekiz kat daha kısa — çünkü sızan şeyin ömrü, fark edilmeye kadar geçen süreden bağımsızdır. Kimse bir şey yapmasa bile kimlik bilgisi kendiliğinden geçersizleşir.
Maliyet ikinci sütunda. Bir saatlik ömür otuz günde yedi yüz yirmi ayrı kimlik bilgisi demektir; on beş dakikalık ömürde iki bin sekiz yüz seksen. Bunların her biri bir üstlenme çağrısıdır ve çağrı sayısı kotaya çarpar. Beş kalıcı kimlikle on beş dakikalık ömür saatte yirmi çağrı ediyor ve kurgu beş yüzlük sınıra dört yüz seksen çağrı kalıyor; aynı hızda çalışan yüz yirmi beş kimlik sığar. Pencereyi dört kat daraltmanın bedeli, sığan kimlik sayısının dörtte bire inmesidir.
Zincir ve Güven Listesi
// kosum2.mjs — guven iliskisi kimin ustlenebilecegini belirler; zincir ne kadar uzuyor import { KIMLIK, ROL, GUVEN, IZ, ulasim, zincirGecerli } from './ustlenme.mjs'; console.log(`${KIMLIK.length} kalici kimlik, ${ROL.length} rol; izdeki zincir ${IZ.length}`); console.log(`izdeki zincirlerin hepsi guven iliskisine uyuyor: ${IZ.every(([b, a]) => zincirGecerli(b, a))}\n`); console.log('kalici kimlik dogrudan zincirle toplam en uzun zincir izde kullandigi'); let dogrudanT = 0, toplamT = 0; for (const k of KIMLIK) { const u = ulasim(k); const d = [...u.values()].filter((x) => x === 1).length; const kullanilan = new Set(IZ.filter(([b]) => b === k).flatMap(([, a]) => a)).size; dogrudanT += d; toplamT += u.size; console.log(`${k.padEnd(18)} ${String(d).padEnd(9)} ${String(u.size - d).padEnd(9)} ${String(u.size).padEnd(7)} ` + `${String(Math.max(...u.values())).padEnd(15)} ${kullanilan}`); } console.log(`toplam ${String(dogrudanT).padEnd(9)} ${String(toplamT - dogrudanT).padEnd(9)} ${toplamT}`); // rol-denetim'in genis guveni ize gore daraltilirsa const izdeUstlenen = (rol) => KIMLIK.filter((k) => IZ.some(([b, a]) => b === k && a.includes(rol))); const dar = { ...GUVEN, 'rol-denetim': izdeUstlenen('rol-denetim') }; const cift = (g) => KIMLIK.reduce((a, k) => a + ulasim(k, g).size, 0); const mesru = (g) => IZ.filter(([b, a]) => zincirGecerli(b, a, g)).reduce((s, [, , n]) => s + n, 0); console.log('\n' + 'guven listesi'.padEnd(36) + ' (kimlik, rol) cifti duran zincir duran islem/gun'); for (const [ad, g] of [['rol-denetim: *', GUVEN], [`rol-denetim: ${dar['rol-denetim'].join(', ')}`, dar], ['rol-denetim kaldirildi', { ...GUVEN, 'rol-denetim': [] }]]) { const kalan = IZ.filter(([b, a]) => !zincirGecerli(b, a, g)).length; console.log(`${ad.padEnd(36)} ${String(cift(g)).padEnd(20)} ${String(kalan).padEnd(13)} ${mesru(GUVEN) - mesru(g)}`); }
5 kalici kimlik, 6 rol; izdeki zincir 9 izdeki zincirlerin hepsi guven iliskisine uyuyor: true kalici kimlik dogrudan zincirle toplam en uzun zincir izde kullandigi toplama-hizmeti 2 0 2 1 1 analitik-is 2 0 2 1 2 saha-bakim 2 1 3 2 2 yayin-hatti 3 3 6 3 3 nobetci-insan 3 1 4 2 3 toplam 12 5 17 guven listesi (kimlik, rol) cifti duran zincir duran islem/gun rol-denetim: * 17 0 0 rol-denetim: analitik-is, saha-bakim 14 0 0 rol-denetim kaldirildi 12 2 90
Beş kimlik ve altı rol otuz olası çift kurar; güven listeleri bunun on yedisini açıyor. On ikisi
doğrudan üstlenme, beşi zincir üzerinden. Zincir en çok yayin-hatti için iş görüyor: doğrudan üç
role üstlenebiliyor, zincirle üç role daha ulaşıyor ve en uzun zinciri üç adım. Bu kimliğe
rol-yonetim yetkisi hiçbir yerde verilmemiştir; rol-yayin üzerinden rol-bakima, oradan
rol-yonetime ulaşıyor. Güven listelerine tek tek bakan biri bunu göremez, çünkü hiçbir listede
yayin-hatti ile rol-yonetim yan yana yazılı değil.
Alt tablo geniş güven listesinin bedelini ölçüyor. rol-denetim her özneye açık olduğu için beş
çift buradan geliyor; listeyi izde gerçekten üstlenen iki adla değiştirmek çifti on yediden on
dörde indiriyor ve duran meşru iş sıfır. Üç çift, hiç kullanılmadığı hâlde açık duran üstlenme
hakkıydı. Bir kademe ileri gidip rolü tamamen kapatmak iki zinciri durduruyor ve günde doksan
işlem kaybediyor. Daraltmanın ilk kademesi bedava, ikincisi değil — önceki derste kaynak temelli
belge için çıkan sonucun aynısı, başka bir eksende.
Denetim Kaydında Asıl Özne
// kosum3.mjs — denetim kaydinda asil ozne gorunuyor mu, kac adim sonra kayboluyor import { ROL, IZ } from './ustlenme.mjs'; function kayitlar(adlandir) { // otuz gunluk izden kayit uretilir const ustlenme = [], islem = []; for (const [asil, adimlar, gunluk] of IZ) { let su = asil, onceki = null, oturum = null; for (const [n, r] of adimlar.entries()) { oturum = adlandir(asil, r, n); ustlenme.push({ ustlenen: su, rol: r, oturum, cagiran: onceki }); onceki = oturum; su = r; } islem.push({ rol: adimlar.at(-1), oturum, gunluk, asil, uzunluk: adimlar.length }); } return { ustlenme, islem }; } // Geri izleme: (rol, oturum) anahtarindan olasi asil ozneler function olasiAsil(ustlenme, rol, oturum) { const kume = new Set(); for (const u of ustlenme.filter((x) => x.rol === rol && x.oturum === oturum)) { if (!ROL.includes(u.ustlenen)) kume.add(u.ustlenen); else for (const a of olasiAsil(ustlenme, u.ustlenen, u.cagiran)) kume.add(a); } return kume; } const ADLANDIRMA = [ // ad, son kayittan okunur mu, uretici ['rol adina gore', false, (a, r) => `${r}-oturum`], ['yalniz ilk adimda asil', false, (a, r, n) => (n === 0 ? `${a}@${r}` : `${r}-oturum`)], ['her adimda asil', true, (a, r) => `${a}@${r}`], ]; const toplamIslem = IZ.reduce((a, [, , n]) => a + n, 0); console.log(`otuz gunluk izde ${IZ.length} zincir, gunde ${toplamIslem} islem kaydi\n`); console.log('oturum adlandirmasi son kayitta asil cozulen islem/gun yuzde okunacak kayit en cok aday'); const sonuc = new Map(); for (const [ad, okunur, f] of ADLANDIRMA) { const { ustlenme, islem } = kayitlar(f); const adayi = islem.map((k) => ({ ...k, aday: olasiAsil(ustlenme, k.rol, k.oturum).size })); sonuc.set(ad, adayi); const tek = adayi.filter((k) => k.aday === 1); const cozulen = tek.reduce((a, k) => a + k.gunluk, 0); const derinlik = okunur ? '0' : (cozulen ? (tek.reduce((a, k) => a + k.gunluk * k.uzunluk, 0) / cozulen).toFixed(2) : '-'); console.log(`${ad.padEnd(23)} ${(okunur ? 'evet' : 'hayir').padEnd(17)} ${String(cozulen).padEnd(18)} ` + `%${((100 * cozulen) / toplamIslem).toFixed(1).padEnd(6)} ${derinlik.padEnd(15)} ${Math.max(...adayi.map((k) => k.aday))}`); } console.log('\nzincir uzunlugu zincir islem/gun rol adina gore cozulen ilk adimda asil ile cozulen'); for (const u of [1, 2, 3]) { const secili = (ad) => sonuc.get(ad).filter((k) => k.uzunluk === u); const c = (ad) => secili(ad).filter((k) => k.aday === 1).reduce((a, k) => a + k.gunluk, 0); console.log(`${String(u).padEnd(16)} ${String(secili('rol adina gore').length).padEnd(7)} ` + `${String(secili('rol adina gore').reduce((a, k) => a + k.gunluk, 0)).padEnd(10)} ` + `${String(c('rol adina gore')).padEnd(23)} ${c('yalniz ilk adimda asil')}`); } const adim = IZ.reduce((a, [, ad]) => a + ad.length, 0); console.log(`\nustlenme adimi ${adim}; bir saatlik gecici kimlik bilgisiyle gunde ${adim * 24} ustlenme kaydi`);
otuz gunluk izde 9 zincir, gunde 2845 islem kaydi oturum adlandirmasi son kayitta asil cozulen islem/gun yuzde okunacak kayit en cok aday rol adina gore hayir 0 %0.0 - 3 yalniz ilk adimda asil hayir 2845 %100.0 1.17 1 her adimda asil evet 2845 %100.0 0 1 zincir uzunlugu zincir islem/gun rol adina gore cozulen ilk adimda asil ile cozulen 1 6 2390 0 2390 2 2 430 0 430 3 1 25 0 25 ustlenme adimi 13; bir saatlik gecici kimlik bilgisiyle gunde 312 ustlenme kaydi
İşlem kaydı iki kalem taşıyor: hangi rol ve hangi oturum. Rol adına göre isimlendirilmiş bir
oturumda asıl özne hiçbir yerde görünmüyor ve geri izleme de kurtarmıyor — günde iki bin sekiz yüz
kırk beş kaydın sıfırı tek bir asıl özneye bağlanabiliyor. Nedeni ikinci tabloda: bir adımlık
zincirlerde bile sonuç sıfır. rol-okuma rolüne üç ayrı kimlik ulaşıyor ve üçü de aynı oturum
adını kullandığı için bir okuma kaydının hangisinden geldiği ayırt edilemiyor. En kötü durumda üç
aday var.
Oturum adı yalnız ilk adımda asıl özneyi taşıdığında bütün kayıtlar çözülüyor, ama kaydın kendisi hâlâ asıl özneyi göstermiyor: ortalama bir virgül on yedi üstlenme kaydını birleştirmek gerekiyor ve üç adımlık zincirde bu sayı üçe çıkıyor. Asıl özne her adımda taşındığında birleştirme sıfıra iniyor — soru doğrudan kaydın kendisinden cevaplanıyor.
Aradaki fark bir arıza sırasında ölçülür. Üç kayıt kümesini birleştirmek, ilgili kayıtların üçünün de elde olmasını ve zaman aralıklarının örtüşmesini gerektirir; oturum adı seçimi ise üstlenmeyi yapan tarafın elindedir. Son satır hacmi veriyor: on üç üstlenme adımı, bir saatlik ömürle günde üç yüz on iki üstlenme kaydı. Pencereyi daraltmak denetim kaydını da büyütüyor.
Özet
- Uzun ömürlü anahtarın sızıntı penceresi fark edilme süresine eşittir (30240 dk); bir saatlik geçici kimlik bilgisinde beklenen pencere 30 dk, yani 1008 kat kısa.
- Pencerenin bedeli üretim hacmidir: 15 dakikalık ömür otuz günde 2880 kimlik bilgisi ve saatte 20 çağrı ister; kurgu 500’lük sınıra 480 çağrı kalıyor, aynı hızda 125 kimlik sığar.
- Beş kimlik ve altı rol 30 çift kurar, güven listeleri 17’sini açar: 12 doğrudan, 5 zincirle.
yayin-hattihiçbir listede yazmadığı hâlde üç adımdarol-yonetime ulaşıyor. rol-denetimin*güven listesini ize göre yazmak çifti 17’den 14’e indiriyor ve hiçbir meşru işi durdurmuyor; rolü kapatmak 2 zinciri ve günde 90 işlemi durduruyor.- Oturum adı role göre verildiğinde günde 2845 işlem kaydının sıfırı tek bir asıl özneye bağlanabiliyor; bir adımlık zincirlerde bile sonuç sıfır, en kötü durumda 3 aday var.
- Asıl özne yalnız ilk adımda taşındığında bütün kayıtlar çözülür ama ortalama 1,17 üstlenme kaydını birleştirmek gerekir; her adımda taşındığında birleştirme sıfıra iner.
Sonraki Adım
Bu dersin beş öznesinden dördü bir program, biri insandı ve hepsi aynı biçimde ele alındı. Kalıcı kimlik ile geçici kimlik bilgisi arasındaki fark ölçüldü, ama bir sorunun cevabı verilmedi: bir program ilk kimliğini nereden alıyor. Rol üstlenmek için önce bir kimlikle doğrulanmak gerekiyor ve o ilk kimlik bir yerde duruyorsa zincirin başında yine uzun ömürlü bir sır var demektir. Sonraki ders bu ilk adımı ölçer: bir iş yüküne kimlik verilmesinin kaç ayrı yolu var, her yol kaç sır saklamayı gerektiriyor ve saklanan sır sayısı sıfıra indiğinde yerine hangi kalem geçiyor.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.