Ders 11 / 15
Güvenli Varsayılanlar
Yirmi iki yapılandırma kaleminden biri unutulduğunda ne olduğu iki varsayılan altında ayrı ayrı sayılır: varsayılan açıkta açılan yol, varsayılan kapalıda duran günlük iş. Unutulan kalem sayısı taranır ve iki hata türünün görünürlük oranı karşılaştırılarak yanlış yapılandırmaya dayanıklılık ölçülür.
İçindekiler
Önceki ders iki denetimi ayırdı ve her birinin hangi isteği durdurduğunu saydı. Bütün şemalarda ortak bir varsayım vardı: kapsam listesi doğru yazılmış, kapsamda olması gereken her adım kapsamda. Gerçekte bu liste elle yazılır, ağ değiştikçe güncellenir ve bir kalem unutulur. Bu dersin sorusu unutulan kalemin ne olacağıdır.
Güvenli varsayılan (secure by default), yapılandırılmamış bir kalemin kapalı sayılmasıdır. Karşıtı, yapılandırılmamış kalemin geçirmesidir. İki seçenek yalnız hata anında ayrışır: her şey doğru yazıldığında ikisi de aynı ağı verir. Bu ders o hata anını ölçer — bir kalem unutulduğunda varsayılan açıkta kaç yol açılıyor, varsayılan kapalıda kaç meşru iş duruyor ve iki hatanın hangisi kendini gösteriyor. Yol sayımı yine kurgusal ağın modeli üzerinde yapılıyor; gerçek bir ağda yapılandırma kalemlerinin taranması yazılı yetki ve tanımlı kapsam olmadan yürütülemez.
- SI27. Yirmi iki adımın her biri bir yapılandırma kalemidir. Tam yapılandırmada her kalem yetki denetimi yapar ve ağ önceki dersin en dar şemasındaki yirmi yola iner.
- SI28. Unutulan kalem denetim yapmaz. Varsayılan açıkta herkesi geçirir; varsayılan kapalıda herkesi durdurur, meşru akış dahil.
- SI29. Kalemler birbirinden bağımsız unutulur ve unutulma olasılığı her kalem için eşittir. Gerçekte yeni eklenen kalemler daha çok unutulur; bu, açık varsayılanın bedelini büyütür.
- SI30. Örnekleme kendi yazılan doğrusal eşlemeli üreteçle yapılır. Tohum görünür ve sabittir; çıktı koşumdan koşuma aynı kalır.
- SI31. “Görünmez” sütunu, hatanın hiçbir ölçülebilir iz bırakmadığı örneklerin oranıdır: açıkta yol sayısı değişmemiş, kapalıda hiçbir meşru iş durmamış demektir.
Tek Kalemin Bedeli
Yirmi iki kalem tek tek unutuluyor ve her unutmanın iki varsayılan altındaki sonucu ayrı yazılıyor.
// ag.mjs — kurgusal bolgesel olcum aginin erisim grafigi ve mesru akislari (model) export const GIRIS = ['saha-uc', 'sube-agi', 'genel-uc', 'bakim-uc']; export const VARLIK = ['olcum-deposu', 'fatura-vt', 'abone-kayit', 'yapilandirma']; export const KENAR = [ ['saha-uc', 'toplayici'], ['saha-uc', 'is-emri'], ['sube-agi', 'toplayici'], ['sube-agi', 'is-emri'], ['sube-agi', 'yonetim'], ['genel-uc', 'toplayici'], ['bakim-uc', 'yonetim'], ['bakim-uc', 'kuyruk'], ['toplayici', 'kuyruk'], ['toplayici', 'olcum-deposu'], ['kuyruk', 'dogrulayici'], ['kuyruk', 'faturalama'], ['dogrulayici', 'olcum-deposu'], ['dogrulayici', 'fatura-vt'], ['faturalama', 'fatura-vt'], ['faturalama', 'abone-kayit'], ['is-emri', 'kuyruk'], ['is-emri', 'abone-kayit'], ['yonetim', 'toplayici'], ['yonetim', 'dogrulayici'], ['yonetim', 'is-emri'], ['yonetim', 'yapilandirma'], ]; // Mesru akis: gunluk kosan is; adim dizisi ayni grafigin kenarlarindan gecer. export const AKIS = [ ['saha-okuma', ['saha-uc', 'toplayici', 'kuyruk'], 1440], ['dogrulama', ['kuyruk', 'dogrulayici', 'olcum-deposu'], 1440], ['genel-okuma', ['genel-uc', 'toplayici', 'olcum-deposu'], 300], ['sube-sorgu', ['sube-agi', 'toplayici', 'olcum-deposu'], 210], ['fatura-yazimi', ['kuyruk', 'faturalama', 'fatura-vt'], 48], ['is-emri-acma', ['sube-agi', 'is-emri', 'abone-kayit'], 32], ['is-emri-kuyruk', ['sube-agi', 'is-emri', 'kuyruk'], 32], ['abone-guncelleme', ['faturalama', 'abone-kayit'], 6], ['yapilandirma-degisikligi', ['sube-agi', 'yonetim', 'yapilandirma'], 2], ['bakim-oturumu', ['bakim-uc', 'yonetim', 'toplayici'], 1], ['kuyruk-bakimi', ['bakim-uc', 'kuyruk'], 1], ['mutabakat', ['yonetim', 'dogrulayici', 'fatura-vt'], 1], ]; export const ad = (a, b) => `${a}>${b}`; export const adimlar = (d) => d.slice(0, -1).map((x, i) => ad(x, d[i + 1])); export function yollar(kapali = new Set()) { const komsu = new Map(); for (const [a, b] of KENAR) if (!kapali.has(ad(a, b))) komsu.set(a, [...(komsu.get(a) || []), b]); const s = []; const yuru = (d, y) => { if (VARLIK.includes(d)) return void s.push(y); for (const k of komsu.get(d) || []) if (!y.includes(k)) yuru(k, [...y, k]); }; for (const g of GIRIS) yuru(g, [g]); return s; } export const kesilen = (kapali) => AKIS.filter(([, d]) => adimlar(d).some((k) => kapali.has(k)));
// varsayilan.mjs — yapilandirilmamis kalemin varsayilan durumu ve yol sayimi import { KENAR, AKIS, GIRIS, VARLIK, ad, adimlar } from './ag.mjs'; export const KENAR_AD = KENAR.map(([a, b]) => ad(a, b)); const ORTAK = new Set(AKIS.filter(([, d]) => !GIRIS.includes(d[0])).flatMap(([, d]) => adimlar(d))); const kendi = (g) => AKIS.filter(([, d]) => d[0] === g).flatMap(([, d]) => adimlar(d)); export const YETKI = Object.fromEntries(GIRIS.map((g) => [g, new Set([...ORTAK, ...kendi(g)])])); const komsu = new Map(); for (const [a, b] of KENAR) komsu.set(a, [...(komsu.get(a) || []), b]); // Yapilandirilmis kalem yetki denetler; unutulan kalem varsayilanina gore gecirir ya da durdurur. export function yolSay(unutulan, varsayilan) { const U = new Set(unutulan); let n = 0; for (const g of GIRIS) { const yuru = (d, y) => { if (VARLIK.includes(d)) return void n++; for (const k of komsu.get(d) || []) { const e = ad(d, k); if (U.has(e)) { if (varsayilan === 'kapali') continue; } else if (!YETKI[g].has(e)) continue; if (!y.includes(k)) yuru(k, [...y, k]); } }; yuru(g, [g]); } return n; } export function uretec(tohum) { let s = tohum >>> 0; return () => { s = (Math.imul(s, 1664525) + 1013904223) >>> 0; return s / 4294967296; }; }
// kosum1.mjs — tek kalem unutulunca: varsayilan acikta acilan yol, kapalida duran is import { AKIS, adimlar } from './ag.mjs'; import { KENAR_AD, yolSay } from './varsayilan.mjs'; const tam = yolSay([], 'acik'); const duran = (k) => AKIS.filter(([, d]) => adimlar(d).includes(k)).reduce((s, [, , n]) => s + n, 0); const sat = KENAR_AD.map((k) => [k, yolSay([k], 'acik') - tam, duran(k)]); console.log(`tam yapilandirmada yol ${tam}, yapilandirma kalemi ${KENAR_AD.length}\n`); console.log('varsayilan acik — unutulunca en cok yol acan kalem'); for (const [k, a] of [...sat].sort((x, y) => y[1] - x[1]).slice(0, 5)) console.log(` ${k.padEnd(26)}+${a} yol`); console.log('\nvarsayilan kapali — unutulunca en cok is durduran kalem'); for (const [k, , c] of [...sat].sort((x, y) => y[2] - x[2]).slice(0, 5)) console.log(` ${k.padEnd(26)}${c} gunluk istek durur`); console.log(''); for (const [etiket, v] of [ ['acikta ortalama acilan yol', (sat.reduce((s, x) => s + x[1], 0) / sat.length).toFixed(2)], ['acikta hicbir yol acmayan kalem', `${sat.filter((x) => x[1] === 0).length} / ${sat.length}`], ['kapalida ortalama duran gunluk istek', Math.round(sat.reduce((s, x) => s + x[2], 0) / sat.length)], ['kapalida hicbir isi durdurmayan kalem', `${sat.filter((x) => x[2] === 0).length} / ${sat.length}`], ]) console.log(`${etiket.padEnd(40)}${v}`);
tam yapilandirmada yol 20, yapilandirma kalemi 22 varsayilan acik — unutulunca en cok yol acan kalem toplayici>kuyruk +12 yol yonetim>is-emri +5 yol toplayici>olcum-deposu +2 yol yonetim>toplayici +1 yol yonetim>yapilandirma +1 yol varsayilan kapali — unutulunca en cok is durduran kalem saha-uc>toplayici 1440 gunluk istek durur toplayici>kuyruk 1440 gunluk istek durur kuyruk>dogrulayici 1440 gunluk istek durur dogrulayici>olcum-deposu 1440 gunluk istek durur toplayici>olcum-deposu 510 gunluk istek durur acikta ortalama acilan yol 0.95 acikta hicbir yol acmayan kalem 17 / 22 kapalida ortalama duran gunluk istek 319 kapalida hicbir isi durdurmayan kalem 2 / 22
İki listenin şekli farklıdır. Açık varsayılanda dağılım son derece dengesiz: bir kalem on iki yol açıyor, bir kalem beş, üç kalem birer ikişer ve geri kalan on yedi kalem hiçbir şey açmıyor. Ortalama sıfır virgül doksan beş yol, ama ortalama burada anlamsızdır — bedel bir kalemde toplanmış durumda. Kuyruğa yazma adımının denetimi unutulursa yol sayısı yirmiden otuz ikiye çıkıyor, yani ağın altı buçuk kat daralmasını sağlayan bütün çalışmanın yarısı tek bir kalemin unutulmasıyla geri veriliyor.
Kapalı varsayılanda dağılım tersine dengelidir. Yirmi iki kalemin yirmisi unutulduğunda en az bir meşru iş duruyor; ortalama günde üç yüz on dokuz istek. Dört ayrı kalem günde bin dört yüz kırk isteği durduruyor, çünkü saha okuma ve doğrulama akışları ağın en yoğun işleridir. Bir bakıma bu, kapalı varsayılanın maliyetidir; başka bir bakıma hatanın hemen ortaya çıkmasının garantisidir.
İki listenin kesişimi de dikkat ister. Kuyruğa yazma adımı her iki listede de birinci sırada: açık varsayılanda en çok yol açan, kapalı varsayılanda en çok işi durduran kalem odur. En yoğun kullanılan adım aynı zamanda en çok yol taşıyan adımdır ve hangi varsayılan seçilirse seçilsin en pahalı kalemdir. Yapılandırma denetiminin ilk bakacağı yer, en çok trafik geçen adımdır. Bu kalem her iki varsayılanda da ayrı bir doğrulamayı hak eder; hangi varsayılan seçilmiş olursa olsun, elde edilen daralmanın yarısını tek başına taşıyan bir kalemin doğru yazıldığı ayrıca sınanmalıdır.
Kaç Kalem Unutulursa
Bir kalem gerçekçi bir hata sayısı değildir. Aynı ölçüm k kalem unutulduğunda tekrarlanıyor ve üçüncü bir sütun ekleniyor: hatanın hiç iz bırakmama oranı.
// kosum2.mjs — k kalem unutulunca iki varsayilanin bedeli ve hatanin gorunurlugu import { AKIS, adimlar } from './ag.mjs'; import { KENAR_AD, yolSay, uretec } from './varsayilan.mjs'; const TOHUM = 20260802, ORNEK = 200, tam = yolSay([], 'acik'); const r = uretec(TOHUM); const sec = (k) => { const a = [...KENAR_AD]; for (let i = a.length - 1; i > 0; i--) { const j = Math.floor(r() * (i + 1)); [a[i], a[j]] = [a[j], a[i]]; } return a.slice(0, k); }; const durus = (u) => AKIS.filter(([, d]) => adimlar(d).some((x) => u.includes(x))).reduce((s, [, , n]) => s + n, 0); console.log(`tohum ${TOHUM}, ornek ${ORNEK}, tam yapilandirmada yol ${tam}`); console.log('unutulan acik: ort yol en kotu gorunmez kapali: ort duran en kotu gorunmez'); for (const k of [1, 2, 3, 5, 8, 22]) { const say = k === 22 ? 1 : ORNEK, o = { a: 0, am: 0, ag: 0, c: 0, cm: 0, cg: 0 }; for (let i = 0; i < say; i++) { const u = k === 22 ? KENAR_AD : sec(k); const ya = yolSay(u, 'acik'), dur = durus(u); o.a += ya; o.am = Math.max(o.am, ya); if (ya === tam) o.ag++; o.c += dur; o.cm = Math.max(o.cm, dur); if (dur === 0) o.cg++; } console.log(`${String(k).padEnd(10)}${(o.a / say).toFixed(1).padEnd(13)}${String(o.am).padEnd(9)}` + `${`%${Math.round((o.ag / say) * 100)}`.padEnd(10)}${(o.c / say).toFixed(0).padEnd(19)}` + `${String(o.cm).padEnd(9)}%${Math.round((o.cg / say) * 100)}`); }
tohum 20260802, ornek 200, tam yapilandirmada yol 20 unutulan acik: ort yol en kotu gorunmez kapali: ort duran en kotu gorunmez 1 21.3 32 %73 347 1440 %9 2 22.3 37 %53 644 2880 %1 3 23.2 41 %44 969 2944 %0 5 24.9 42 %22 1343 3423 %0 8 29.4 50 %8 2050 3510 %0 22 55.0 55 %0 3513 3513 %0
Görünmez sütunları bu dersin cevabıdır. Tek bir kalem unutulduğunda açık varsayılanda hatanın yüzde yetmiş üçü hiçbir iz bırakmıyor: yol sayısı değişmiyor, kimse fark etmiyor, kayıt düşmüyor. Aynı hata kapalı varsayılanda yüzde doksan bir olasılıkla bir işi durduruyor ve durdurduğu anda görülüyor. İki hatanın büyüklüğü değil, bulunabilirliği farklıdır.
Fark unutulan kalem sayısı arttıkça kapanıyor ama yanlış yönde. Açık varsayılanda üç kalem unutulduğunda hâlâ yüzde kırk dördü sessiz; sekiz kalemde yüzde sekiz. Kapalı varsayılanda iki kalemde sessizlik yüzde bire, üç kalemde sıfıra iniyor. Yani açık varsayılanla çalışan bir sistem, biriken yanlış yapılandırmayı yıllarca taşıyabilir; kapalı varsayılanla çalışan bir sistem ikinci hatada kendini bildirir.
En kötü durum sütunları da simetrik değil. Açık varsayılanda tek bir kalemin unutulması yol sayısını otuz ikiye, sekiz kalem elliye çıkarıyor; yirmi ikisinin unutulması elli beşe, yani hiçbir savunma yokmuş gibi bir ağa. Kapalı varsayılanda aynı uçta ağ tamamen duruyor: günde üç bin beş yüz on üç isteğin tamamı. İki hatanın sonucu da felakettir, ancak biri sessiz bir açıklık, diğeri gürültülü bir kesintidir. Güvenli varsayılanın gerekçesi, ikinci tür hatanın onarılacağının bilinmesidir; birinci tür hata onarılmaz, çünkü varlığı bilinmez.
Modelin bir yanlılığı da yazılmalıdır. Kalemlerin eşit olasılıkla unutulduğu kabul edildi. Gerçekte unutulan kalem rastgele seçilmez: yeni eklenen bir servisin adımları, nadiren değişen eski adımlardan daha çok unutulur. Tabloda hiçbir işi durdurmayan iki kalem, henüz meşru trafik taşımayan adımlardır; yeni eklenen adımlar da ilk günlerinde aynı gruba düşer. Bu iki gözlem birleştiğinde açık varsayılanın gerçek bedeli tablodakinden büyük çıkar: unutmanın en olası olduğu yer, kapalı varsayılanın en sessiz kaldığı ve dolayısıyla hatanın en geç görüldüğü yerdir. Ölçümü gerçeğe yaklaştırmanın yolu, unutulma olasılığını kalemin yaşına bağlamaktır; bu ders o adımı atmıyor, ancak atıldığında sonucun hangi yöne kayacağı bellidir.
Ortalama sütunları bir denge noktası da veriyor. Beş kalem unutulduğunda açık varsayılanda ortalama yirmi beş yol açık kalıyor; tam yapılandırmadaki yirmiye göre beş yol fazla. Aynı beş kalem kapalı varsayılanda günde bin üç yüz kırk üç isteği durduruyor, yani günlük işin yüzde otuz sekizini. Kapalı varsayılanın bedeli açıkça daha büyüktür ve bu bedel doğrudan işletmeye yansır. Karar bu iki sayı arasında verilir — ama görünmez sütunu okunmadan verilen bir karar, yalnız birinci sütunu okumaktır.
Özet
- Tam yapılandırmada 22 kalemin hepsi yetki denetler ve ağ 20 yola iner. Unutulan kalemin sonucu yalnız varsayılana bağlıdır; iki varsayılan hatasız durumda aynı ağı verir.
- Açık varsayılanda tek kalem unutmanın dağılımı dengesizdir: bir kalem 12 yol açıyor, 17 kalem hiçbir şey açmıyor. Ortalama 0,95 yol, ama bedel tek bir kalemde toplanmıştır.
- Kapalı varsayılanda 22 kalemin 20’si unutulduğunda en az bir işi durduruyor; ortalama günde 319 istek, en kötü 1.440. Bu hem maliyettir hem de hatanın hemen görülmesinin güvencesidir.
- Görünmezlik oranı asıl farkı veriyor: tek kalem unutulduğunda açık varsayılanda hataların %73’ü hiç iz bırakmıyor, kapalı varsayılanda yalnız %9’u.
- Fark hata sayısı arttıkça yanlış yönde kapanıyor: 3 kalemde açık varsayılan hâlâ %44 sessiz, kapalı varsayılan %0. Açık varsayılanla çalışan sistem yanlış yapılandırmayı biriktirir.
- En kötü uçta 22 kalemin unutulması açık varsayılanda ağı 55 yola, yani hiç savunma yokmuş hâline döndürüyor; kapalı varsayılanda günlük 3.513 isteğin tamamını durduruyor.
Sonraki Adım
Altı ilke aynı yol kümesi üzerinde ölçüldü ve her birinin bedeli sayıldı. Derinlemesine savunma elli beş yolun elli ikisini kapattı ve altmış üç kalem bakım yükü getirdi; en az yetki kırk üç yolu günde on bir isteğin bedeliyle kapattı; yalıtım erişilen kalemi on üçten dört virgül sekize indirdi ve yirmi geçit istedi; sıfır güven yolu yirmiye indirdi ve istek başına iki ek adım ekledi; kimlik ile yetki ayrımı yanlış katmanda duran denetimin otuz yolu açık bıraktığını gösterdi; güvenli varsayılan bir kalemin unutulmasının açık varsayılanda yüzde yetmiş üç olasılıkla sessiz kaldığını ortaya çıkardı.
Bütün bu tablolarda sorulmayan bir soru var. Ölçümleri kim yapacak? Bir katmanın hiçbir yeni yol kapatmadığını kim fark edecek, bir geçidin gereksiz olduğunu kim sınayacak, unutulan kalemi kim tarayacak? Sayılar kendiliğinden ortaya çıkmadı; her biri, savunmayı kuran taraftan bağımsız bir sınama gerektirir. Sonraki konu bu soruyu ele alıyor: savunmayı kuran, saldıran gibi düşünen ve ikisini birleştiren rollerin işlevi nedir, bu işler hangi meslek tanımlarına dağılır ve bir sınamanın hangi yazılı sınır içinde yapılabileceğini ne belirler.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.