İçeriğe geç
academia.sh

Ders 02 / 22

Günlük Toplama ve Normalleştirme

Üç ayrı biçimdeki kurgu günlük tek şemaya normalleştirilir ve eşlenemeyen alan sayılır: 24 kaynak alanının 15'i sekiz alanlık şemaya oturuyor, 9'u artık kalıyor; ağ akışı kaydında dört şema alanı boş ve 404 kaydın hiçbirinde aktör yok. Kaynaklar aynı olayı 1, 5 ve 8 dakika sonra yazıyor. Aktör alanını iki ara tablo dolduruyor: 139 yönetim düzlemi kaydının 115'i hesaba çevriliyor, 24'ü çevrilemiyor; beş dakikalık pencerede 404 akış kaydının 190'ına aktör atanıyor, 212'si boş kalıyor, altmış dakikada atama 208'e çıkarken belirsiz kayıt 2'den 39'a fırlıyor. İki kaynakta iz bırakan 26 olayın 21'i toplanıyor, bir dakikalık pencerede hiçbiri toplanmıyor.

İçindekiler

Bir önceki dersin devir notu, analistin belleğindeki bağı yazıya geçiriyordu. O bağın en baştan kayıtta bulunması, yani iki uyarının aynı aktöre ait olduğunun makine tarafından görülebilmesi, önceki derste varsayılmıştı. Bu ders varsayımı kaldırır ve kursun ölçü birimini kurar.

Ölçü şudur: bir kaydın hangi alanı ortak şemaya oturuyor, hangi alanı oturmuyor ve oturmayan alanın yerine ne konuyor. Kaynak envanteri Uç Nokta ve Sistem Sertleştirme kursunda sayılmıştı; burada envanter bir girdidir. Sayılan şey kaynağın varlığı değil, birbirine bağlanabilirliğidir.

  • TA7. Bölgesel ölçüm ağında üç günlük kaynağı vardır: bir bulut yönetim düzlemi kaydı, uç noktaların süreç oluşturma kaydı ve ağ akış verisi. Üçü de kurgudur; adresler yönlendirilmeyen kurgu bloklardandır.
  • TA8. Hedef şema sekiz alanlıdır: zaman, kaynak, konak, adres, aktör, eylem, hedef, sonuç. Bir kaynağın dolduramadığı alan null kalır ve sayılır.
  • TA9. Bir kaynak alanı üç durumdan birindedir: şemaya eşlenir, şemada karşılığı olmadığı için artık kalır, ya da şema alanı hiçbir kaynak alanından doldurulamadığı için boş kalır.
  • TA10. Kayıt, olayın gerçekleştiği anda değil, kaynağın yazdığı anda oluşur. Model bu farkı kaynak başına veri olarak verir: uç noktada 1, ağ akışında 5, yönetim düzleminde 8 dakika.
  • TA11. Otuz kurgu olay birden çok kaynakta iz bırakır. Bu bağ modelin bilgisidir; hiçbir günlük satırına yazılmaz.
  • TA12. Aktör kimliği üç kaynakta üç biçimdedir: portal kimliği, etki alanı hesabı ve yalnız adres. Ara tablolar günlükte değil, varlık envanterindedir.

Üç Biçim, Tek Şema

// kaynak.mjs — uc ayri bicimdeki kurgu gunluk uretilir ve tek semaya normallestirilir.
// MODELDIR. Adresler RFC1918 kurgu bloklarindandir; gercek kurum ve konak yoktur.
export const TOHUM = 20260402;
const uretec = (t) => { let s = t >>> 0;
  return () => (s = (s * 1664525 + 1013904223) >>> 0) / 4294967296; };
const r = uretec(TOHUM);
const tam = (n) => Math.floor(r() * n);
const sec = (d) => d[tam(d.length)];

export const KONAK = Array.from({ length: 60 }, (_, i) => `uc-${101 + i}`);
export const HESAP = Array.from({ length: 40 }, (_, i) => `sh-${201 + i}`);
export const ADRES = KONAK.map((_, i) => `10.40.${1 + (i % 3)}.${10 + i}`);
// Portal kimligi: 28 hesabin karsiligi var, alti tanesinin (servis kimligi) hic yok.
const PORTAL = [...HESAP.slice(0, 28).map((_, i) => `ab-${4401 + i}`),
                ...Array.from({ length: 6 }, (_, i) => `ab-${4429 + i}`)];
const EYLEM = ["nesne.oku", "nesne.yaz", "yetki.degistir", "anahtar.kullan"];
const YOL = ["/opt/olcum/toplayici", "/usr/bin/arsivle", "/opt/olcum/dogrulayici"];

// Hedef sema: sekiz alan. Her kaynak bunun bir bolumunu doldurur.
export const SEMA = ["t", "kaynak", "konak", "adres", "aktor", "eylem", "hedef", "sonuc"];
// [kaynak, bicim, kaynak alani, semaya eslenen kaynak alani, varis gecikmesi dk, cozunurluk]
export const KAYNAK = [["yonetim-duzlemi", "json", 8, 6, 8, "1 ms"],
                       ["uc-nokta", "anahtar=deger", 8, 5, 1, "1 s"],
                       ["ag-akisi", "csv", 8, 4, 5, "1 s"]];

const GUN = Date.UTC(2026, 3, 2);
const iso = (ms) => new Date(GUN + ms).toISOString();
export const yd = [], un = [], aa = [];      // uc ham gunluk, uc ayri bicim
const etiketli = { yd: [], un: [], aa: [] }; // modelin dogrusu; gunluk satirina YAZILMAZ

// Ortak olay: ayni is kalemi birden cok kaynakta iz birakir. Model bunu bilir, hat bilmez.
export const ORTAK = [];
for (let k = 0; k < 30; k++) {
  const i = tam(KONAK.length), h = HESAP[tam(28)];
  ORTAK.push({ t: 3600e3 + tam(50000e3), konak: KONAK[i], adres: ADRES[i], hesap: h,
    portal: PORTAL[HESAP.indexOf(h)], uc: r() < 0.8, ag: r() < 0.9, yd: r() < 0.7 });
}
const yaz = (o, e) => {
  if (o.yd) { yd.push({ ts: iso(o.t + 480e3 + tam(9000)), actor: { id: o.portal,
      type: "kullanici" }, op: sec(EYLEM), target: `kova/olcum/${tam(900)}`,
    result: r() < 0.9 ? "izin-verildi" : "reddedildi", srcIp: o.adres,
    requestId: `q${tam(1e5)}` }); etiketli.yd.push(e); }
  if (o.uc) { un.push(`zaman=${Math.floor((GUN + o.t + 60e3 + tam(9000)) / 1000)} ` +
    `konak=${o.konak} olay=surec-olusturma kullanici=${o.hesap} pid=${1000 + tam(9000)} ` +
    `ust=${400 + tam(600)} yol=${sec(YOL)} ` +
    `karma=${tam(1e9).toString(16).padStart(8, "0")}`); etiketli.un.push(e); }
  if (o.ag) { aa.push([Math.floor((GUN + o.t + 300e3 + tam(9000)) / 1000), 1 + tam(60),
    o.adres, `10.90.2.${10 + tam(40)}`, sec([443, 8443, 5671]), "giden", 400 + tam(9e5),
    5 + tam(900)].join(",")); etiketli.aa.push(e); }
};
ORTAK.forEach((o, i) => yaz(o, i));
// Arka plan trafigi: ortak olayla iliskisiz kayitlar.
for (let k = 0; k < 480; k++) {
  const i = tam(KONAK.length);
  yaz({ t: tam(86400e3), konak: KONAK[i], adres: ADRES[i], hesap: sec(HESAP),
    portal: sec(PORTAL), uc: r() < 0.45, ag: r() < 0.75, yd: r() < 0.25 }, -1);
}

// Normallestirme: her kaynak icin bir eslestirici. Doldurulamayan alan null kalir.
export const normal = {
  "yonetim-duzlemi": (s) => { const o = JSON.parse(s);
    return { t: Date.parse(o.ts), kaynak: "yonetim-duzlemi", konak: null, adres: o.srcIp,
      aktor: o.actor.id, eylem: o.op, hedef: o.target, sonuc: o.result }; },
  "uc-nokta": (s) => { const a = Object.fromEntries(s.split(" ").map((p) => p.split("=")));
    return { t: Number(a.zaman) * 1000, kaynak: "uc-nokta", konak: a.konak, adres: null,
      aktor: a.kullanici, eylem: a.olay, hedef: a.yol, sonuc: null }; },
  "ag-akisi": (s) => { const [b, , ka, he, p] = s.split(",");
    return { t: Number(b) * 1000, kaynak: "ag-akisi", konak: null, adres: ka, aktor: null,
      eylem: null, hedef: `${he}:${p}`, sonuc: null }; },
};
export const HAM = { "yonetim-duzlemi": yd.map((o) => JSON.stringify(o)), "uc-nokta": un,
                     "ag-akisi": aa };
const ETIKETLI = { "yonetim-duzlemi": etiketli.yd, "uc-nokta": etiketli.un,
                   "ag-akisi": etiketli.aa };
const hepsi = Object.entries(HAM).flatMap(([k, l]) =>
  l.map((s, i) => [normal[k](s), ETIKETLI[k][i]])).sort((a, b) => a[0].t - b[0].t);
export const OLAY = hepsi.map((x) => x[0]);
export const ETIKET = hepsi.map((x) => x[1]);   // ortak olay indeksi ya da -1; hat GORMEZ

if (import.meta.url === `file://${process.argv[1]}`) {
  const gen = (B) => (h) => h.map((v, j) => (j ? String(v).padStart(B[j])
    : String(v).padEnd(B[0]))).join("");
  const yz = gen([18, 15, 8, 7, 14, 12, 11, 13, 14]);
  console.log(`model (tohum ${TOHUM}): ${OLAY.length} kayit, ${SEMA.length} alanlik sema`);
  for (const k of ["yonetim-duzlemi", "uc-nokta", "ag-akisi"]) console.log(HAM[k][0]);
  console.log();
  console.log(yz(["kaynak", "bicim", "kayit", "alan", "eslenen alan", "artik alan",
    "bos sema", "zaman coz.", "aktarim gec."]));
  for (const [ad, bicim, alan, esl, gec, coz] of KAYNAK) {
    const ornek = normal[ad](HAM[ad][0]);
    const dolu = SEMA.filter((a) => a !== "kaynak" && ornek[a] !== null).length;
    console.log(yz([ad, bicim, HAM[ad].length, alan, esl, alan - esl,
      SEMA.length - 1 - dolu, coz, `${gec} dk`]));
  }
  const t = KAYNAK.reduce((a, k) => a + k[2], 0), e = KAYNAK.reduce((a, k) => a + k[3], 0);
  console.log(`\ntoplam ${t} kaynak alani: ${e} tanesi semaya esleniyor, ` +
    `${t - e} tanesi artik kaliyor; aktor alani ag akisinda hicbir kayitta yok`);
}
model (tohum 20260402): 787 kayit, 8 alanlik sema
{"ts":"2026-04-02T10:26:21.519Z","actor":{"id":"ab-4401","type":"kullanici"},"op":"yetki.degistir","target":"kova/olcum/888","result":"izin-verildi","srcIp":"10.40.1.22","requestId":"q96644"}
zaman=1775125160 konak=uc-113 olay=surec-olusturma kullanici=sh-201 pid=4052 ust=405 yol=/usr/bin/arsivle karma=3718b893
1775125395,7,10.40.1.22,10.90.2.18,5671,giden,120991,443

kaynak                      bicim   kayit   alan  eslenen alan  artik alan   bos sema   zaman coz.  aktarim gec.
yonetim-duzlemi              json     139      8             6           2          1         1 ms          8 dk
uc-nokta            anahtar=deger     244      8             5           3          2          1 s          1 dk
ag-akisi                      csv     404      8             4           4          4          1 s          5 dk

toplam 24 kaynak alani: 15 tanesi semaya esleniyor, 9 tanesi artik kaliyor; aktor alani ag akisinda hicbir kayitta yok

Üç örnek satır üç ayrı dünya gösteriyor. Yönetim düzlemi kaydı iç içe geçmiş bir nesne yazıyor ve aktörü actor.id yolunda saklıyor. Uç nokta kaydı düz anahtar=deger çiftleri yazıyor ve aktörü kullanici diye adlandırıyor. Ağ akış kaydı ise başlıksız bir virgüllü satırdır: alan adı kaydın içinde yoktur, yalnız sıradadır. İlk sütunun zaman olduğunu bilen tek şey ayrıştırıcıdır.

Yirmi dört kaynak alanının 15’i şemaya oturuyor, 9’u artık kalıyor. Artık alan tam bir kayıp değildir — ham kayıt saklanır — ama ortak şema üzerinden sorgulanamaz; süreç kimliği ya da bayt sayısı şemada yer bulmadığı için hiçbir bağıntı kuralı onu ölçüt olarak kullanamaz.

Asıl kayıp bos sema sütunundadır. Ağ akış kaydında dört şema alanı boştur: konak, aktör, eylem ve sonuç. Bunların içinde en ağırı aktördür, çünkü kursun bütün bağıntı işlemi aktör ekseninde yürüyecektir. 404 akış kaydının hiçbirinde kimin yaptığı yazmaz. Uç nokta kaydında sonuç alanı boştur: bir sürecin çalıştığı yazılır, izin verilip verilmediği yazılmaz.

Son iki sütun zamanın iki ayrı sorununu ayırıyor. Çözünürlük iki kaynağın olayları saniyeye yuvarlaması demektir; aynı saniyedeki iki kaydın sırası kaybolur. Yazma gecikmesi daha belirleyicidir: aynı olay uç noktada bir, ağ akışında beş, yönetim düzleminde sekiz dakika sonra kayda geçer. Hat üç kaydı yedi dakikaya yayılmış görür ve yayılmanın gerçek mi aktarımdan mı geldiğini ayırt edemez.

Eşlenemeyen Alanı Doldurmak

Aktör alanı boş bırakılamaz, çünkü boş kalırsa üç kaynak birbirine hiç bağlanmaz. Doldurmanın iki yolu vardır ve ikisi de günlüğün dışındaki bir tabloya dayanır: portal kimliğini hesaba çeviren statik bir eşleme ve adresi konağa, konağı da o andaki oturuma bağlayan zamana duyarlı bir arama.

// birlestir.mjs — eslenemeyen aktor alani ara tablolarla doldurulur, sonra kayitlar toplanir.
import { OLAY, ETIKET, ORTAK, KONAK, ADRES, HESAP } from "./kaynak.mjs";

// Ara tablolar model verisidir: gunlukte yoktur, varlik envanterinden gelir.
const adresKonak = new Map(ADRES.map((a, i) => [a, KONAK[i]]));
const portalHesap = new Map(HESAP.slice(0, 28).map((h, i) => [`ab-${4401 + i}`, h]));

const uc = OLAY.filter((o) => o.kaynak === "uc-nokta");
// Ag akisi kaydinda aktor yok: adres konaga, konak da +/- W dakikalik pencerede
// uc nokta kaydindaki hesaba baglanmaya calisilir.
function aktorAta(pencere) {
  const cozum = new Array(OLAY.length).fill(null);
  let atanan = 0, belirsiz = 0, bos = 0, portalCevrilen = 0;
  for (const [i, o] of OLAY.entries()) {
    if (o.kaynak === "uc-nokta") { cozum[i] = o.aktor; continue; }
    if (o.kaynak === "yonetim-duzlemi") {
      cozum[i] = portalHesap.get(o.aktor) || null;
      if (cozum[i]) portalCevrilen++;
      continue;
    }
    const k = adresKonak.get(o.adres);
    const aday = [...new Set(uc.filter((u) => u.konak === k &&
      Math.abs(u.t - o.t) <= pencere * 60e3).map((u) => u.aktor))];
    if (aday.length === 1) { cozum[i] = aday[0]; atanan++; }
    else if (aday.length > 1) belirsiz++;
    else bos++;
  }
  return { cozum, atanan, belirsiz, bos, portalCevrilen };
}

// Aktor alani dolu kayitlar hesap ekseninde, W dakikalik bosluk kuralina gore kumelenir.
function kumele(cozum, pencere) {
  const grup = new Map();
  for (const [i, a] of cozum.entries()) if (a) (grup.get(a) || grup.set(a, []).get(a)).push(i);
  const kume = [];
  for (const [, l] of grup) {
    let s = [l[0]];
    for (const i of l.slice(1)) {
      if (OLAY[i].t - OLAY[s[s.length - 1]].t <= pencere * 60e3) s.push(i);
      else { kume.push(s); s = [i]; }
    }
    kume.push(s);
  }
  const cok = kume.filter((s) => new Set(s.map((i) => OLAY[i].kaynak)).size >= 2);
  const toplanan = new Set(), karisik = cok.filter((s) => {
    const e = new Set(s.map((i) => ETIKET[i]).filter((x) => x >= 0));
    for (const x of e) if (s.filter((i) => ETIKET[i] === x).length >= 2) toplanan.add(x);
    return e.size >= 2;
  });
  const ucKaynak = [...toplanan].filter((x) =>
    cok.some((s) => new Set(s.filter((i) => ETIKET[i] === x)
      .map((i) => OLAY[i].kaynak)).size === 3)).length;
  return { kume: cok.length, toplanan: toplanan.size, ucKaynak, karisik: karisik.length };
}

const gen = (B) => (h) => h.map((v, j) => (j ? String(v).padStart(B[j])
  : String(v).padEnd(B[0]))).join("");
const yz = gen([12, 11, 11, 9, 9, 15, 13, 11]);
const ag = OLAY.filter((o) => o.kaynak === "ag-akisi").length;
console.log(`${OLAY.length} normallestirilmis kayit; ${ag} ag akisi kaydinin aktor alani bos, ` +
  `${OLAY.filter((o) => o.kaynak === "yonetim-duzlemi").length} yonetim duzlemi kaydinda ` +
  `aktor portal kimligi olarak yaziyor`);
const ikiUstu = ORTAK.filter((o) => [o.uc, o.ag, o.yd].filter(Boolean).length >= 2).length;
console.log(`modelin bildigi ortak olay ${ORTAK.length}, bunlarin ${ikiUstu} tanesi en az iki ` +
  `kaynakta iz birakiyor (hat bunu gormez)`);
console.log();
console.log(yz(["pencere", "aktor atn.", "belirsiz", "bos", "kume", "toplanan olay",
  "uc kaynakli", "karisik"]));
for (const p of [1, 5, 15, 60]) {
  const a = aktorAta(p), k = kumele(a.cozum, p);
  console.log(yz([`${p} dk`, a.atanan, a.belirsiz, a.bos, k.kume, `${k.toplanan}/${ikiUstu}`,
    k.ucKaynak, k.karisik]));
}
const a5 = aktorAta(5);
console.log(`\nportal kimligi hesaba cevrilen yonetim duzlemi kaydi: ${a5.portalCevrilen}; ` +
  `cevrilemeyen ${OLAY.filter((o) => o.kaynak === "yonetim-duzlemi").length - a5.portalCevrilen}`);
console.log(`aktor alani dolu kayit ${a5.cozum.filter(Boolean).length}/${OLAY.length}`);
787 normallestirilmis kayit; 404 ag akisi kaydinin aktor alani bos, 139 yonetim duzlemi kaydinda aktor portal kimligi olarak yaziyor
modelin bildigi ortak olay 30, bunlarin 26 tanesi en az iki kaynakta iz birakiyor (hat bunu gormez)

pencere      aktor atn.   belirsiz      bos     kume  toplanan olay  uc kaynakli    karisik
1 dk                  3          0      401        3           0/26            0          0
5 dk                190          2      212      184          21/26           13          1
15 dk               195          7      202      179          21/26           13          1
60 dk               208         39      157      145          20/26           12          1

portal kimligi hesaba cevrilen yonetim duzlemi kaydi: 115; cevrilemeyen 24
aktor alani dolu kayit 549/787

Statik eşleme kolay olanıdır ve o bile tam değildir: 139 yönetim düzlemi kaydının 115’i bir hesaba çevriliyor, 24’ü çevrilemiyor. Karşılığı olmayan altı portal kimliği servis kimliğidir ve envanterde bir kişiye bağlı değildir. Bu 24 kayıt şemada aktör alanı dolu görünür, ama içindeki değer öteki iki kaynakla hiçbir zaman eşleşmez — dolu bir alan boş bir alandan daha yanıltıcıdır.

Zamana duyarlı arama ise doğrudan pencereye bağlıdır ve tablo pencerenin iki yönlü etkisini gösteriyor. Bir dakikalık pencerede 404 akış kaydının yalnız 3’üne aktör atanabiliyor; kaynakların yazma gecikmeleri 1 ve 5 dakika olduğu için akış kaydı ile uç nokta kaydı arasında zaten dört dakika vardır. Beş dakikaya çıkıldığında atama 190’a fırlıyor. Altmış dakikada atama yalnız 18 kayıt daha kazanıyor, buna karşılık belirsiz kayıt 2’den 39’a çıkıyor: pencere genişledikçe aynı konakta birden çok hesabın oturumu görünür oluyor ve hangisinin akışı olduğu söylenemez hâle geliyor.

Son iki sütun ölçünün karşılığını veriyor. En az iki kaynakta iz bırakan 26 kurgu olayın beş dakikalık pencerede 21’i toplanıyor, 13’ü üç kaynağın hepsiyle birlikte. Bir dakikalık pencerede hiçbiri toplanmıyor — bu sıfır, verinin eksikliğinden değil, kaynakların farklı anlarda yazmasından geliyor. Toplanamayan beş olayın çoğunda ağ akışı kaydı yoktur; geriye kalan uç nokta ve yönetim düzlemi kayıtları arasında yedi dakika vardır ve beş dakikalık pencere onları köprüleyemez.

Karışık küme sayısı birde kalıyor: bu modelde pencereyi genişletmenin bedeli yanlış birleştirme değil, belirsizliktir. Yoğun bir ortamda o sütun büyür.

Özet

  • Üç kaynağın 24 alanının 15’i sekiz alanlık şemaya eşleniyor, 9’u artık kalıyor; artık alan saklanır ama ortak şema üzerinden sorgulanamaz, bu yüzden hiçbir kurala ölçüt olamaz.
  • Ağ akış kaydında dört şema alanı boştur ve en ağırı aktördür: 404 kaydın hiçbirinde kimin yaptığı yazmaz. Uç nokta kaydında sonuç alanı boştur.
  • Aynı olay uç noktada 1, ağ akışında 5, yönetim düzleminde 8 dakika sonra kayda geçiyor; hat üç kaydı yedi dakikaya yayılmış görür ve yayılmanın gerçek mi aktarımdan mı olduğunu ayıramaz.
  • Portal kimliğini hesaba çeviren statik eşleme 139 kaydın 115’ini çeviriyor, 24’ünü çeviremiyor; karşılığı olmayan servis kimliklerinde aktör alanı dolu görünür ama hiçbir şeyle eşleşmez.
  • Pencere iki yönlü çalışıyor: bir dakikada 3 atama ve toplanan olay sıfır, beş dakikada 190 atama ve 21/26, altmış dakikada 208 atama ama belirsiz kayıt 2’den 39’a çıkıyor.

Sonraki Adım

Bu derste kümeleme tek ölçütle yapıldı: aynı aktör ve bir zaman penceresi. Bu ölçüt 184 küme üretti ve bunların yalnız 21’i modelin bildiği bir olaya karşılık geliyor; geri kalanı aynı hesabın gün içindeki olağan işidir. Bir güvenlik bilgi ve olay yönetimi sistemi kümelemeyi böyle yapmaz; koşul dizisi yazar — hangi kaynaktan hangi alan, hangi sırayla, hangi sayıdan sonra. Sonraki ders bu derste normalleştirilmiş akışın üzerine bir bağıntı kuralı koşturur ve iki sayı çıkarır: kural kaç olayı tek uyarıda birleştiriyor ve birleştirdiklerinin dışında neyi hiç görmü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