İçeriğe geç
academia.sh

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 node ile 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-hatti hiçbir listede yazmadığı hâlde üç adımda rol-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.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat