İçeriğe geç
academia.sh

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.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat