Ders 01 / 09
Denetim Kaydı Tasarımı
On altı soruluk bir soru kümesi üç kayıt kaynağıyla eşleştirildiğinde altısı cevaplanıyor, onu cevaplanamıyor: dördü yazılmayan alan, beşi kaynaklar arasında kurulmayan bağ, biri saklama penceresi yüzünden. Beş ek alan cevaplananı 13'e çıkarıyor, ama aynı alanlar günlük hacmi 1,45 kata çıkarıp sabit bütçedeki saklamayı 65 günden 45 güne indiriyor ve 60 günlük denetim dönemine uzanan beş soruyu yeniden cevapsız bırakıyor.
İçindekiler
Çalışma Zamanı Güvenliği ve Sır Yönetimi kursu katmanları kurdu ve her katmanın neyi kaçırdığını yazdı. Kaçırılan kalemin varlığı orada modelin doğrusundan okunuyordu. Gerçek bir kurumda böyle bir doğru yoktur: kaçırılanın kaçırıldığı ancak bir kayıttan anlaşılır. Bu kurs o kaydı ölçer ve tek soru sorar — olaydan sonra sorulacak soruların kaçı cevaplanabiliyor.
Ölçü birimi cevaplanamayan sorudur. Bir kayıt tasarımı “kapsamlı” ya da “yetersiz” diye nitelenmez; önüne bir soru kümesi konur, eşleştirme koşturulur ve cevapsız kalan soru sayılır. Aynı ölçünün ikinci yarısı bedeldir: cevaplanabilir kılmak kaç ek alan, kaç kat hacim ve kaç kişisel veri kalemi getiriyor. Bu ders ikisini birlikte koşturur. Kaydın nasıl yazıldığı, değiştirilemez biçimde tutulduğu ve bütünlüğünün korunduğu Arka Uç Güvenliği kursunda ölçülmüştü; burada tekrarlanmaz, girdi olur.
- UM1. Örnek ağ kurgudur: bölgesel bir ölçüm ağının abone portalında bir yetkisiz erişim ihlali, dokuz servis, üç kayıt kaynağı ve 60 günlük bir denetim dönemi. Bütün sayılar bir modelin çıktısıdır.
- UM2. Soru kümesi, olaydan sonra sorulacak soruların veri yapısı olarak modellenmiş hâlidir. Her sorunun iki niteliği vardır: cevaplamak için gereken alanlar ve kaç gün geriye uzandığı.
- UM3. Bir soru ancak gereken alanlarının tamamı tek bir eşlenebilir kaynak kümesi içinde bulunuyorsa cevaplanır. İki ayrı kaynaktaki alan, aralarında ortak bir bağ alanı yoksa birleştirilemez; iki kayıt yan yana durur ama aynı olaya ait olduğu gösterilemez.
- UM4. Cevaplanamama üç nedene ayrılır: alan yok (hiçbir kaynak yazmıyor), bağ yok (alanlar var ama eşleşmiyor), pencere (alanlar ve bağ var ama kayıt o kadar geriye saklanmıyor).
- UM5. Saklama süresi kararla değil aritmetikle belirlenir: sabit bir saklama bütçesi günlük hacme bölünür. Bütçe modelde 600 GB, günlük olay sayısı 42 milyondur; 1 GB 10⁹ bayt sayılır.
- UM6. Kişisel veri tür olarak sayılır: istemci adresi, oturum tanımlayıcısı ve değişiklik öncesi alan değeri birer kalemdir. Her kalem saklama süresine ayrı bir üst sınır getirir.
Soru Kümesini Şemayla Eşleştirmek
// kayit-esleme.mjs — soru kumesi kayit semasiyla eslestirilir; cevaplanamayan soru // bu kursun olcu birimidir. MODELDIR: ag, kayitlar ve sorular kurgudur. export const BUTCE_B = 600e9, GUN_OLAY = 42e6; // sabit saklama butcesi ve gunluk olay // Kaynak = bir kayit akisi. `iz` alani olan kaynaklar birbirine eslenebilir; // olmayan kaynak tek basina kalir ve alanlari baska alanla birlestirilemez. export const KAYNAK = [ { ad: "uygulama denetim kaydi", pay: 0.18, bayt: 240, alan: ["zaman", "iz", "aktor", "eylem", "sonuc"] }, { ad: "ag gecidi erisim kaydi", pay: 0.62, bayt: 180, alan: ["zaman", "iz", "yol", "yontem", "durum", "istemci_ip"] }, { ad: "veritabani degisiklik kaydi", pay: 0.20, bayt: 320, alan: ["zaman", "tablo", "nesne", "islem"] }, ]; // Soru = [metin, gereken alanlar, kac gun geriye uzandigi]. Denetim donemi 60 gundur. export const SORU = [ ["hangi hesap hangi abone kaydini okudu", ["aktor", "nesne", "eylem"], 30], ["okuma kabul mu edildi ret mi", ["aktor", "eylem", "sonuc"], 30], ["istek hangi istemci adresinden geldi", ["istemci_ip", "iz"], 7], ["hangi hesap hangi tabloyu degistirdi", ["aktor", "tablo", "islem"], 30], ["degisiklik oncesi deger neydi", ["tablo", "once_deger"], 30], ["hangi uygulama surumu calisiyordu", ["aktor", "eylem", "surum"], 30], ["ayni oturumda baska ne yapildi", ["oturum", "eylem"], 7], ["yetki karari neydi ve neye dayandi", ["aktor", "eylem", "yetki_karari"], 30], ["donem basindaki ilk ret ne zaman", ["aktor", "eylem", "sonuc"], 60], ["donem boyunca kac abone kaydi okundu", ["nesne", "eylem"], 60], ["hangi uc noktalar cagrildi", ["yol", "yontem", "durum"], 30], ["hangi istek hangi satiri degistirdi", ["iz", "tablo", "nesne"], 60], ["ayni adresten kac hesap denendi", ["istemci_ip", "aktor"], 30], ["olaydan onceki ceyrekte ayni hesap ne yapti", ["aktor", "eylem"], 90], ["disari yazilan kayit kumesi neydi", ["aktor", "eylem", "nesne", "sonuc"], 60], ["donem boyunca kac satir degisti", ["tablo", "islem"], 60], ]; // Bir soru ancak gereken alanlarinin tamami TEK bir eslenebilir kume icindeyse // cevaplanir; ayri kumelerdeki alanlar birlestirilemez. export function kumeler(k) { const bagli = k.filter((s) => s.alan.includes("iz")); const tekil = k.filter((s) => !s.alan.includes("iz")); const birlesik = [...new Set(bagli.flatMap((s) => s.alan))]; return [birlesik, ...tekil.map((s) => s.alan)].filter((a) => a.length); } export function esle(k, saklama) { const kume = kumeler(k), tum = new Set(k.flatMap((s) => s.alan)); return SORU.map(([metin, alanlar, gun]) => { const eksik = alanlar.filter((a) => !tum.has(a)); if (eksik.length) return { metin, gun, durum: "alan yok", eksik: eksik[0] }; if (!kume.some((c) => alanlar.every((a) => c.includes(a)))) return { metin, gun, durum: "bag yok", eksik: "-" }; if (gun > saklama) return { metin, gun, durum: "pencere", eksik: "-" }; return { metin, gun, durum: "cevaplanir", eksik: "-" }; }); } export const gunlukBayt = (k) => k.reduce((t, s) => t + GUN_OLAY * s.pay * s.bayt, 0); export const saklamaGun = (k) => Math.floor(BUTCE_B / gunlukBayt(k)); export const gen = (B) => (h) => h.map((v, j) => (j ? String(v).padStart(B[j]) : String(v).padEnd(B[0]))).join(""); if (import.meta.url === `file://${process.argv[1]}`) { const gb = gunlukBayt(KAYNAK) / 1e9, saklama = saklamaGun(KAYNAK); console.log(`model: ${KAYNAK.length} kaynak, ${SORU.length} soru, gunluk ` + `${gb.toFixed(2)} GB, ${BUTCE_B / 1e9} GB butce -> ${saklama} gun saklama`); console.log(`eslenebilir alan kumeleri: ` + kumeler(KAYNAK).map((c) => c.length).join(" ve ") + " alan"); const y = gen([44, 6, 13, 13]); console.log("\n" + y(["soru", "gun", "durum", "eksik alan"])); for (const s of esle(KAYNAK, saklama)) console.log(y([s.metin, s.gun, s.durum, s.eksik])); const d = esle(KAYNAK, saklama); const say = (t) => d.filter((s) => s.durum === t).length; console.log(`\ncevaplanir ${say("cevaplanir")}, cevaplanamaz ` + `${SORU.length - say("cevaplanir")}: alan yok ${say("alan yok")}, ` + `bag yok ${say("bag yok")}, pencere ${say("pencere")}`); }
model: 3 kaynak, 16 soru, gunluk 9.19 GB, 600 GB butce -> 65 gun saklama eslenebilir alan kumeleri: 9 ve 4 alan soru gun durum eksik alan hangi hesap hangi abone kaydini okudu 30 bag yok - okuma kabul mu edildi ret mi 30 cevaplanir - istek hangi istemci adresinden geldi 7 cevaplanir - hangi hesap hangi tabloyu degistirdi 30 bag yok - degisiklik oncesi deger neydi 30 alan yok once_deger hangi uygulama surumu calisiyordu 30 alan yok surum ayni oturumda baska ne yapildi 7 alan yok oturum yetki karari neydi ve neye dayandi 30 alan yok yetki_karari donem basindaki ilk ret ne zaman 60 cevaplanir - donem boyunca kac abone kaydi okundu 60 bag yok - hangi uc noktalar cagrildi 30 cevaplanir - hangi istek hangi satiri degistirdi 60 bag yok - ayni adresten kac hesap denendi 30 cevaplanir - olaydan onceki ceyrekte ayni hesap ne yapti 90 pencere - disari yazilan kayit kumesi neydi 60 bag yok - donem boyunca kac satir degisti 60 cevaplanir - cevaplanir 6, cevaplanamaz 10: alan yok 4, bag yok 5, pencere 1
Üç kaynak da düzenli yazılıyor, hiçbiri kapalı değil, günde 9,19 GB kayıt üretiliyor. Buna rağmen on altı sorunun onu cevapsız. Bu tablonun asıl bilgisi cevaplanamayan sayısı değil, üçüncü sütundaki nedenlerin dağılımıdır; çünkü üç neden üç ayrı işle çözülür ve bedelleri farklıdır.
En büyük yığın bağ yok satırlarındadır: beş soru. Bu sorularda gereken alanların hepsi
yazılıyor. “Hangi hesap hangi tabloyu değiştirdi” sorusunun ihtiyacı olan aktor uygulama
denetim kaydında, tablo ve islem veritabanı değişiklik kaydında duruyor. İki kayıt aynı
saniyede yazılmış olabilir, ama veritabanı kaydında iz alanı olmadığı için hangi isteğin hangi
satır değişikliğini doğurduğu gösterilemez. Yoğun bir dönemde aynı saniyede yüzlerce istek ve
yüzlerce satır değişikliği vardır; zaman damgasına dayanan bir eşleme iddia üretir, kanıt
üretmez. Bağ alanı olmayan iki kayıt kaynağı, toplamı kadar değil, ayrı ayrı topladıkları
kadar soru cevaplar.
İkinci yığın alan yok: dört soru. Bunlar tasarım eksiğidir ve yeni alan yazmakla kapanır.
Üçüncüsü tek satırdır ama en sinsisidir: pencere. “Olaydan önceki çeyrekte aynı hesap ne yaptı”
sorusunun bütün alanları var, bağı da var; 90 gün geriye uzandığı için cevapsız kalıyor. Bu soru
şemaya bakılarak asla bulunamaz. Şema doğru, alanlar tam, bağ kurulmuş görünür — cevaplanamama
saklama aritmetiğinden gelir ve ancak soru kümesi pencereyle birlikte modellendiğinde ortaya
çıkar.
Cevaplanabilir Kılmanın Bedeli
Dört eksik alan ile bir bağ alanı yazılabilir. Her ek alan her kayda girer ve günlük hacmi büyütür; bütçe sabit olduğu için hacim doğrudan saklama gününe dönüşür.
// ekleme.mjs — her ek alan cevaplanan soruyu artirir ama gunluk hacmi buyutur; // sabit butcede hacim saklama gunune, saklama gunu de cevaba geri doner. MODELDIR. import { KAYNAK, SORU, esle, gunlukBayt, saklamaGun, gen } from "./kayit-esleme.mjs"; // Her ekleme: hangi kaynaklara hangi alan, kayit basina kac bayt, kisisel veri mi. const EKLEME = [ { alan: "iz", hedef: ["veritabani degisiklik kaydi"], bayt: 18, kisisel: false }, { alan: "yetki_karari", hedef: ["uygulama denetim kaydi"], bayt: 16, kisisel: false }, { alan: "surum", hedef: ["uygulama denetim kaydi"], bayt: 12, kisisel: false }, { alan: "oturum", hedef: ["uygulama denetim kaydi", "ag gecidi erisim kaydi"], bayt: 26, kisisel: true }, { alan: "once_deger", hedef: ["veritabani degisiklik kaydi"], bayt: 340, kisisel: true }, ]; const uygula = (k, e) => k.map((s) => e.hedef.includes(s.ad) ? { ...s, bayt: s.bayt + e.bayt, alan: [...s.alan, e.alan] } : { ...s }); const TABAN_GB = gunlukBayt(KAYNAK) / 1e9; const y = gen([16, 10, 6, 9, 12, 14, 9]); console.log(y(["eklenen alan", "gunluk GB", "kat", "saklama", "cevaplanir", "cevaplanamaz", "kisisel"])); let k = KAYNAK.map((s) => ({ ...s })), kisisel = 1; // istemci_ip zaten kisisel const satir = (ad) => { const gb = gunlukBayt(k) / 1e9, sak = saklamaGun(k); const c = esle(k, sak).filter((s) => s.durum === "cevaplanir").length; console.log(y([ad, gb.toFixed(2), (gb / TABAN_GB).toFixed(2), sak, c, SORU.length - c, kisisel])); return { sak, c }; }; const iz = [satir("(taban sema)")]; for (const e of EKLEME) { k = uygula(k, e); if (e.kisisel) kisisel++; iz.push(satir(e.alan)); } const enIyi = iz.reduce((a, b) => (b.c > a.c ? b : a)), son = iz.at(-1); console.log(`\nen cok cevap veren sema ${enIyi.sak} gun saklamali olan: ${enIyi.c} soru`); console.log(`son sema ${enIyi.c - son.c} soru daha az cevapliyor, cunku saklama ` + `${enIyi.sak} gunden ${son.sak} gune indi ve denetim donemi 60 gun`); console.log(`taban semadan son semaya: cevaplanan ${iz[0].c} -> ${son.c}, ` + `hacim ${(gunlukBayt(k) / 1e9 / TABAN_GB).toFixed(2)} kat, kisisel veri 1 -> ${kisisel} kalem`);
eklenen alan gunluk GB kat saklama cevaplanir cevaplanamaz kisisel (taban sema) 9.19 1.00 65 6 10 1 iz 9.34 1.02 64 11 5 1 yetki_karari 9.46 1.03 63 12 4 1 surum 9.55 1.04 62 13 3 1 oturum 10.43 1.13 57 9 7 2 once_deger 13.28 1.45 45 10 6 3 en cok cevap veren sema 62 gun saklamali olan: 13 soru son sema 3 soru daha az cevapliyor, cunku saklama 62 gunden 45 gune indi ve denetim donemi 60 gun taban semadan son semaya: cevaplanan 6 -> 10, hacim 1.45 kat, kisisel veri 1 -> 3 kalem
İlk ekleme tabloda en ucuz olanıdır ve en çok kazandırandır: veritabanı kaydına 18 baytlık bir
iz alanı, günlük hacmi yüzde iki büyütüp cevaplanan soruyu 6’dan 11’e çıkarıyor. Tek başına
hiçbir yeni olgu kaydetmez; yalnız zaten yazılan iki kaydı birbirine bağlar. Bir kayıt
tasarımında en yüksek getirili alan, çoğu zaman yeni bir olguyu değil, var olan iki olgunun aynı
işe ait olduğunu yazan alandır.
Sonraki iki ekleme doğrusal ilerliyor: yetki_karari ve surum, hacmi yüzde dört büyütüp cevabı
13’e çıkarıyor. Bu satır tablonun en iyi noktasıdır ve tabloya bakmadan bulunamaz. Ek alanların
sırası da rastgele değildir: listedeki her alan, kayıt başına baytının o kaynağın günlük
payıyla çarpımı kadar hacim getirir. surum alanı 12 baytlıktır ama yalnız olayların yüzde
18’ini taşıyan kaynağa girer; oturum 26 baytlıktır ve yüzde 80’ine girer. İkincisi birincinin
iki katından biraz fazla yer kaplar gibi görünür, gerçekte dokuz katından fazlasını kaplar.
Bir alanın bedeli baytıyla değil, baytının yazıldığı kayıt sayısıyla ölçülür.
Dördüncü satır kırılmayı gösteriyor. oturum alanı iki yüksek hacimli kaynağa girer ve günlük
hacim 10,43 GB’ye çıkar; sabit bütçede saklama 62 günden 57 güne iner. Bu ekleme bir soruyu
cevaplanır kılar ve 60 güne uzanan beş soruyu birden cevapsız bırakır: cevaplanan 13’ten
9’a düşer. Beşinci satırda değişiklik öncesi değerin yazılması hacmi 1,45 kata çıkarır, saklamayı
45 güne indirir ve tablo 10’da kapanır — taban şemadan yalnız dört soru daha iyi, en iyi
şemadan üç soru daha kötü.
Bu, tabloda tek bir eğri olarak duran şeyin adıdır: daha çok kayıt, sabit bütçede daha az cevap. Kırılma kayıt hacmi arttığı için değil, saklama penceresi soru kümesinin uzandığı sürenin altına indiği için olur. Denetim dönemi 60 gündür; 57 günlük saklama, kaydın kendisi kusursuz olsa bile dönemin ilk üç gününü cevapsız bırakır.
Bedelin üçüncü sütunu tabloda tek haneli görünür ama en uzun ömürlüsüdür. Kişisel veri kalemi 1’den 3’e çıkar: oturum tanımlayıcısı ile değişiklik öncesi alan değeri, abonenin doğrudan kimliğine bağlanabilen kalemlerdir. Bu iki alan yalnız hacim getirmez; kayda erişimi kısıtlar, saklamaya ayrı bir üst sınır koyar ve dışarı verilen her kanıt kopyasında ayıklanmasını gerektirir. Bir alanı “her ihtimale karşı” yazmanın bedeli bu üç sütunda birden okunur.
Özet
- Bir kayıt tasarımı nitelemeyle değil, önüne konan soru kümesiyle ölçülür; ölçü birimi cevaplanamayan sorudur. Modelde 16 sorunun 10’u taban şemayla cevapsızdır.
- Cevaplanamama üç ayrı nedene ayrılır ve üçü ayrı işle çözülür: alan yok (4 soru), bağ yok (5 soru), saklama penceresi yetmiyor (1 soru).
- En yüksek getirili alan yeni bir olguyu değil, iki kaydın aynı işe ait olduğunu yazan bağ alanıdır: 18 bayt hacim karşılığında cevaplanan soru 6’dan 11’e çıkar.
- Sabit saklama bütçesinde her ek alan saklama gününe dönüşür: beş alan hacmi 1,45 kata çıkarır, saklamayı 65 günden 45 güne indirir.
- Daha çok kayıt daha az cevap verebilir: en iyi şema 62 günlük saklamayla 13 soru cevaplarken, iki alan daha eklenmiş şema 45 günle 10 soruda kalır, çünkü denetim dönemi 60 gündür.
- Bedelin kalıcı sütunu kişisel veri kalemidir: 1’den 3’e çıkan bu sayı erişim kısıtı, ayrı saklama sınırı ve her kanıt kopyasında ayıklama yükü doğurur.
Sonraki Adım
Bu dersin bütün ölçümü olaydan sonra yapıldı: soru zaten sorulmuştu ve kayıtta cevabı olup olmadığına bakıldı. Aynı kayıtların ikinci bir işi daha vardır — soruyu doğuran olayı, olay sürerken haber vermek. Ama uygulama düzeyinde bir kötüye kullanım, protokol düzeyinde bir saldırıya benzemez: istekler geçerli, oturum açık, yetki kararı çoğu zaman olumludur ve tek anormallik iş kuralının ölçtüğü bir sayıdadır. Sonraki ders bu sayılar üzerine kurulan tespit senaryolarını olay akışında koşturur ve eşik seçiminin iki bedelini birlikte ölçer: kaç kötüye kullanım oturumu kaçıyor ve kaç kez boşuna uyandırılıyor.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.