Ders 03 / 10
Güvenlik Mimarisi
Güven sınırlarının grafik olarak sayılması: kaç sınır olduğu, hangi verinin hangi sınırı geçtiği, sınır başına denetim ve denetimsiz geçiş, bir sınırın kaldırılmasının açtığı yol sayısı, ve kuralın bilinen güvenlik olaylarında yakaladığı, kaçırdığı, boşa öttüğü durumlar.
İçindekiler
Önceki derste güvenlik tek bir skordu — üç yaprağın eşiğe göre payının ortalaması — ve yükseldiğinde neyin değiştiğini söylemiyordu. Güvenlik kararı bir sayıya değil bir yere konur: verinin bir bölgeden ötekine geçtiği noktaya.
Kimlik doğrulama ve yetkilendirmenin nasıl gerçekleştirildiği Kimlik Doğrulama ve Yetkilendirme kursunda, gizli değer yönetimi Sunucu Güvenliği ve Üretime Alma kursunda ölçüldü; burada tekrarlanmaz. Buradaki soru mimari düzeydedir: kaç güven sınırı var, hangi veri hangi sınırı geçiyor, her sınırda kaç denetim duruyor, hangi geçişler hiçbir denetimden geçmiyor. Kursun sorusu da sürer — bu grafik koşturulabilir bir kurala çevrilebiliyor mu.
Güven Sınırı Grafiği
Aşağıdaki blok, kurgusal bölgesel kütüphane ağının güven bölgelerini, sınırları, sınırların taşıdığı denetimleri, veri türlerinin gerektirdiği denetimleri ve bir çeyrekte gözlenen geçişleri modelliyor. Denetimsiz geçiş, gerekli denetimlerden en az biri geçtiği sınırda bulunmayan geçiştir.
// sinir.mjs — guven sinirlari grafigini modeller ve sinir basina denetimi sayar import { mkdirSync, writeFileSync } from "node:fs"; // KN10: kurgusal bolgesel kutuphane aginin yedi guven bolgesi ve aralarindaki sekiz sinir. // Her sinir, o gecerken uygulanan denetimleri tasir. Model. const SINIR = [ ["S1", "uye cihazi", "merkez servis", ["kimlik", "sifreleme"]], ["S2", "sube uc birim", "sube agi", ["kimlik"]], ["S3", "sube agi", "merkez servis", ["sifreleme", "kayit"]], ["S4", "merkez servis", "veri katmani", ["yetki", "sifreleme"]], ["S5", "merkez servis", "belediye kimlik", ["kimlik", "sifreleme", "kayit"]], ["S6", "merkez servis", "dis katalog", ["sifreleme"]], ["S7", "sube agi", "veri katmani", []], ["S8", "uye cihazi", "dis katalog", []], ]; // KN11: yedi veri turu ve her turun bir siniri gecerken gerektirdigi denetimler. Katalog // kaydi acik veridir, denetim gerektirmez. Model. const GEREKLI = { "uye kimligi": ["kimlik", "sifreleme"], "odunc gecmisi": ["kimlik", "yetki", "maskeleme"], "katalog kaydi": [], "ucret kaydi": ["kimlik", "yetki", "kayit"], "personel yetkisi": ["kimlik", "yetki", "kayit"], "denetim kaydi": ["yetki", "kayit"], "sir degeri": ["sifreleme", "kayit"], }; // KN12: bir ceyrekte gozlenen on sekiz veri gecisi [veri, kaynak bolge, hedef bolge]. Model. const AKIS = [ ["uye kimligi", "uye cihazi", "merkez servis"], ["uye kimligi", "merkez servis", "belediye kimlik"], ["uye kimligi", "sube uc birim", "sube agi"], ["odunc gecmisi", "veri katmani", "merkez servis"], ["odunc gecmisi", "merkez servis", "uye cihazi"], ["odunc gecmisi", "veri katmani", "sube agi"], ["odunc gecmisi", "sube agi", "sube uc birim"], ["katalog kaydi", "dis katalog", "merkez servis"], ["katalog kaydi", "dis katalog", "uye cihazi"], ["katalog kaydi", "merkez servis", "veri katmani"], ["katalog kaydi", "sube agi", "merkez servis"], ["ucret kaydi", "merkez servis", "veri katmani"], ["ucret kaydi", "sube uc birim", "sube agi"], ["personel yetkisi", "belediye kimlik", "merkez servis"], ["personel yetkisi", "merkez servis", "sube agi"], ["denetim kaydi", "merkez servis", "veri katmani"], ["sir degeri", "merkez servis", "dis katalog"], ["sir degeri", "merkez servis", "veri katmani"], ]; const BOLGE = [...new Set(SINIR.flatMap(([, a, b]) => [a, b]))]; const sinirBul = (a, b) => SINIR.find(([, x, y]) => (x === a && y === b) || (x === b && y === a)); const eksik = (veri, s) => GEREKLI[veri].filter((d) => !s[3].includes(d)); mkdirSync("graf", { recursive: true }); writeFileSync("graf/graf.mjs", `export const SINIR = ${JSON.stringify(SINIR)};\n` + `export const GEREKLI = ${JSON.stringify(GEREKLI)};\n` + `export const AKIS = ${JSON.stringify(AKIS)};\n`); console.log(`${BOLGE.length} guven bolgesi, ${SINIR.length} sinir, ${AKIS.length} veri gecisi, ` + `${Object.keys(GEREKLI).length} veri turu`); console.log(`\n${"sinir".padEnd(6)}${"bolge cifti".padEnd(34)}${"denetim".padStart(8)}` + `${"gecis".padStart(7)}${"eksigi olan gecis".padStart(19)}`); for (const s of SINIR) { const gecis = AKIS.filter(([, a, b]) => sinirBul(a, b) === s); console.log(`${s[0].padEnd(6)}${`${s[1]} - ${s[2]}`.padEnd(34)}${String(s[3].length).padStart(8)}` + `${String(gecis.length).padStart(7)}` + `${String(gecis.filter(([v]) => eksik(v, s).length > 0).length).padStart(19)}`); } const kusurlu = AKIS.map((a) => [a, sinirBul(a[1], a[2])]) .map(([a, s]) => [a, s, eksik(a[0], s)]).filter(([, , e]) => e.length > 0); console.log(`\ndenetimsiz gecis: ${kusurlu.length}/${AKIS.length} gecis en az bir gerekli denetimden gecmiyor`); console.log(`${"sinir".padEnd(6)}${"veri".padEnd(18)}${"yon".padEnd(34)}eksik denetim`); for (const [a, s, e] of kusurlu) console.log(`${s[0].padEnd(6)}${a[0].padEnd(18)}${`${a[1]} -> ${a[2]}`.padEnd(34)}${e.join(", ")}`); const hicbiri = kusurlu.filter(([, s]) => s[3].length === 0); console.log(`\nhicbir denetimi olmayan sinir: ${SINIR.filter((s) => s[3].length === 0).map((s) => s[0]).join(", ")}; ` + `bu sinirlardan gecip denetim gerektiren veri sayisi ${hicbiri.length}`); const turBasina = Object.keys(GEREKLI).map((v) => [v, kusurlu.filter(([a]) => a[0] === v).length]).filter(([, n]) => n > 0); console.log(`veri turu basina eksigi olan gecis: ` + turBasina.map(([v, n]) => `${v} ${n}`).join(", "));
7 guven bolgesi, 8 sinir, 18 veri gecisi, 7 veri turu sinir bolge cifti denetim gecis eksigi olan gecis S1 uye cihazi - merkez servis 2 2 1 S2 sube uc birim - sube agi 1 3 3 S3 sube agi - merkez servis 2 2 1 S4 merkez servis - veri katmani 2 5 4 S5 merkez servis - belediye kimlik 3 2 1 S6 merkez servis - dis katalog 1 2 1 S7 sube agi - veri katmani 0 1 1 S8 uye cihazi - dis katalog 0 1 0 denetimsiz gecis: 12/18 gecis en az bir gerekli denetimden gecmiyor sinir veri yon eksik denetim S2 uye kimligi sube uc birim -> sube agi sifreleme S4 odunc gecmisi veri katmani -> merkez servis kimlik, maskeleme S1 odunc gecmisi merkez servis -> uye cihazi yetki, maskeleme S7 odunc gecmisi veri katmani -> sube agi kimlik, yetki, maskeleme S2 odunc gecmisi sube agi -> sube uc birim yetki, maskeleme S4 ucret kaydi merkez servis -> veri katmani kimlik, kayit S2 ucret kaydi sube uc birim -> sube agi yetki, kayit S5 personel yetkisi belediye kimlik -> merkez servis yetki S3 personel yetkisi merkez servis -> sube agi kimlik, yetki S4 denetim kaydi merkez servis -> veri katmani kayit S6 sir degeri merkez servis -> dis katalog kayit S4 sir degeri merkez servis -> veri katmani kayit hicbir denetimi olmayan sinir: S7, S8; bu sinirlardan gecip denetim gerektiren veri sayisi 1 veri turu basina eksigi olan gecis: uye kimligi 1, odunc gecmisi 4, ucret kaydi 2, personel yetkisi 2, denetim kaydi 1, sir degeri 2
On sekiz geçişin on ikisi en az bir gerekli denetimden geçmiyor. Sınır başına dağılım eşit değil: belediye kimlik servisine bakan sınırda üç denetim var, şube ağı ile veri katmanı arasındakinde hiç yok. Ama denetimsiz iki sınır aynı şey değil: üye cihazı ile dış katalog arasında da denetim yok, oradan yalnız açık veri olan katalog kaydı geçiyor. Denetimsiz sınır tek başına kusur değildir; kusur, denetimsiz sınırdan denetim gerektiren verinin geçmesidir.
En yüklü sınır, en çok eksiği olan sınır: merkez servis ile veri katmanı arasından beş geçiş var, dördünde eksik denetim. Rastlantı değil — bir sınırdan geçen veri türü arttıkça gereken denetim kümesi genişler, ama sınırdaki denetim kümesi tektir.
Veri türü başına ödünç geçmişi dört eksik geçişle başta: dört ayrı sınırdan geçiyor ve gerektirdiği üç denetimden biri, maskeleme, sekiz sınırın hiçbirinde tanımlı değil. Gerekli denetimlerden biri sistemde hiç yok ve bu, ancak gerekli küme ile var olan küme yan yana konduğunda görünüyor.
Sınır Kaldırmak ve Kuralın Sınırı
Grafiğin ikinci sorusu: bir sınır kaldırılırsa ne olur. Kaldırmak, iki bölgenin tek güven bölgesi olması, birindeki verinin koşulsuz ötekine geçmesi demektir. Aşağıdaki blok bunu her sınır için hesaplıyor, sonra kuralı bilinen olaylarda koşturuyor.
// kaldirma.mjs — sinir kaldirmanin actigi yolu sayar ve kurali bilinen ihlal kumesinde kosar import { SINIR, GEREKLI, AKIS } from "./graf/graf.mjs"; // KN13: her veri turunun dogdugu bolge; yayilim, kaynaktan baslayip akis oklarini izleyen // gecisli kapanistir. Model. const KAYNAK = { "uye kimligi": "uye cihazi", "odunc gecmisi": "veri katmani", "katalog kaydi": "dis katalog", "ucret kaydi": "sube uc birim", "personel yetkisi": "belediye kimlik", "denetim kaydi": "merkez servis", "sir degeri": "merkez servis", }; const VERI = Object.keys(GEREKLI); // Bir sinir kaldirildiginda iki bolge tek guven bolgesi olur: iki uc arasinda her veri turu // icin kosulsuz gecis dogar. const yayilim = (veri, kaldirilan) => { const ulasilan = new Set([KAYNAK[veri]]); const es = kaldirilan ? [kaldirilan[1], kaldirilan[2]] : []; for (let n = 0; n < SINIR.length + 1; n += 1) for (const [v, a, b] of AKIS) { if (v === veri && ulasilan.has(a)) ulasilan.add(b); if (es.length && ulasilan.has(es[0])) ulasilan.add(es[1]); if (es.length && ulasilan.has(es[1])) ulasilan.add(es[0]); } return ulasilan; }; const temel = Object.fromEntries(VERI.map((v) => [v, yayilim(v, null)])); const temelToplam = VERI.reduce((s, v) => s + temel[v].size, 0); console.log(`temel yayilim: ${temelToplam} (veri turu, bolge) cifti, ` + `${VERI.length} veri turu x ${new Set(SINIR.flatMap((s) => [s[1], s[2]])).size} bolge icinde`); console.log(`\n${"sinir".padEnd(6)}${"kaldirilirsa birlesen bolgeler".padEnd(34)}` + `${"acilan yol".padStart(11)} en cok acilan veri`); const acilan = SINIR.map((s) => { const yeni = VERI.map((v) => [v, yayilim(v, s).size - temel[v].size]); return [s, yeni.reduce((t, [, n]) => t + n, 0), yeni.sort((a, b) => b[1] - a[1])[0]]; }).sort((a, b) => b[1] - a[1]); for (const [s, toplam, [v, n]] of acilan) console.log(`${s[0].padEnd(6)}${`${s[1]} + ${s[2]}`.padEnd(34)}${String(toplam).padStart(11)}` + ` ${n > 0 ? `${v} (${n})` : "-"}`); // Kural: her gecis, gectigi sinirda veri turunun gerektirdigi denetimlerden gecmeli. const sinirBul = (a, b) => SINIR.find(([, x, y]) => (x === a && y === b) || (x === b && y === a)); const eksik = (veri, s) => (s ? GEREKLI[veri].filter((d) => !s[3].includes(d)) : null); const uyari = AKIS.map((a) => [a, sinirBul(a[1], a[2])]) .filter(([a, s]) => eksik(a[0], s).length > 0); // KN14: bilinen ihlal kumesi — gecen iki ceyrekte kayda gecmis on guvenlik olayi // [veri, kaynak, hedef, not]. Model. const IHLAL = [ ["odunc gecmisi", "veri katmani", "sube agi", ""], ["ucret kaydi", "sube uc birim", "sube agi", ""], ["sir degeri", "merkez servis", "dis katalog", ""], ["odunc gecmisi", "sube agi", "sube uc birim", ""], ["personel yetkisi", "merkez servis", "sube agi", ""], ["ucret kaydi", "merkez servis", "veri katmani", ""], ["odunc gecmisi", "veri katmani", "veri katmani", "bolge ici yedek kopyasi"], ["sir degeri", "merkez servis", "merkez servis", "kayit dosyasina dusen sir"], ["uye kimligi", "veri katmani", "dis katalog", "grafikte tanimsiz yol"], ["uye kimligi", "uye cihazi", "merkez servis", "denetimleri tam olan sinir"], ]; // KN15: uyarilan gecislerden ucunde eksik denetim sinirda degil baska yerde karsilaniyor. const KARSILANAN = [["denetim kaydi", "merkez servis", "veri katmani", "veri katmani islem gunlugu"], ["sir degeri", "merkez servis", "veri katmani", "veri katmani islem gunlugu"], ["personel yetkisi", "belediye kimlik", "merkez servis", "yetki kaynakta imzalaniyor"]]; const es = (a, b) => a[0] === b[0] && a[1] === b[1] && a[2] === b[2]; const yakalanan = IHLAL.filter((i) => uyari.some(([a]) => es(a, i))); const kacan = IHLAL.filter((i) => !yakalanan.includes(i)); const yanlis = uyari.filter(([a]) => KARSILANAN.some((k) => es(a, k))); const acikBosluk = uyari.length - yakalanan.length - yanlis.length; console.log(`\n${uyari.length} uyari, ${IHLAL.length} bilinen olay: yakalanan ${yakalanan.length}, ` + `kacan ${kacan.length}, yanlis alarm ${yanlis.length}, ` + `henuz olay uretmemis acik bosluk ${acikBosluk}`); for (const i of kacan) { const s = sinirBul(i[1], i[2]); console.log(` kacan: ${i[0].padEnd(16)} ${`${i[1]} -> ${i[2]}`.padEnd(32)} ` + `${i[3] || (s ? "sinirda eksik denetim yok" : "sinir yok")}`); } for (const [a] of yanlis) { const k = KARSILANAN.find((n) => es(a, n)); console.log(` yanlis alarm: ${a[0].padEnd(16)} eksik denetim baska yerde: ${k[3]}`); } // KN16: cevrilemeyen kisim. Grafik bildirilen sinirlardaki gecisi denetler; sinirin yerini ve // bildirilmemis yolu denetleyemez. Yerine ceyrekte bir, sinir basina 3 kisi-saatlik gozden // gecirme konur. const SAAT = 3; const grafDisi = kacan.filter((i) => !sinirBul(i[1], i[2])).length; console.log(`\ncevrilemeyen: sinirin dogru yerde olmasi ve bildirilmemis yol; kacan ` + `${kacan.length} olayin ${grafDisi} tanesi grafikte yolu olmayan gecis`); console.log(`yerine konan: ${SINIR.length} sinir icin gozden gecirme, ` + `${SINIR.length * SAAT} kisi-saat/ceyrek; siralamayi kaldirma analizi veriyor ` + `(en ustteki ${acilan[0][0][0]}, ${acilan[0][1]} yol)`); const kayit = SINIR.length + AKIS.length + VERI.length; console.log(`denetim maliyeti: elle tutulan ${kayit} grafik kaydi (sinir, akis, veri turu); ` + `kosum ${AKIS.reduce((s, a) => s + GEREKLI[a[0]].length, 0)} denetim karsilastirmasi + ` + `${SINIR.length} kaldirma hesabi; grafik guncellenmezse kacan artar`);
temel yayilim: 22 (veri turu, bolge) cifti, 7 veri turu x 7 bolge icinde sinir kaldirilirsa birlesen bolgeler acilan yol en cok acilan veri S3 sube agi + merkez servis 6 ucret kaydi (2) S7 sube agi + veri katmani 5 katalog kaydi (1) S5 merkez servis + belediye kimlik 4 odunc gecmisi (1) S6 merkez servis + dis katalog 4 uye kimligi (1) S1 uye cihazi + merkez servis 3 personel yetkisi (1) S8 uye cihazi + dis katalog 3 uye kimligi (1) S4 merkez servis + veri katmani 2 uye kimligi (1) S2 sube uc birim + sube agi 1 personel yetkisi (1) 12 uyari, 10 bilinen olay: yakalanan 6, kacan 4, yanlis alarm 3, henuz olay uretmemis acik bosluk 3 kacan: odunc gecmisi veri katmani -> veri katmani bolge ici yedek kopyasi kacan: sir degeri merkez servis -> merkez servis kayit dosyasina dusen sir kacan: uye kimligi veri katmani -> dis katalog grafikte tanimsiz yol kacan: uye kimligi uye cihazi -> merkez servis denetimleri tam olan sinir yanlis alarm: personel yetkisi eksik denetim baska yerde: yetki kaynakta imzalaniyor yanlis alarm: denetim kaydi eksik denetim baska yerde: veri katmani islem gunlugu yanlis alarm: sir degeri eksik denetim baska yerde: veri katmani islem gunlugu cevrilemeyen: sinirin dogru yerde olmasi ve bildirilmemis yol; kacan 4 olayin 3 tanesi grafikte yolu olmayan gecis yerine konan: 8 sinir icin gozden gecirme, 24 kisi-saat/ceyrek; siralamayi kaldirma analizi veriyor (en ustteki S3, 6 yol) denetim maliyeti: elle tutulan 33 grafik kaydi (sinir, akis, veri turu); kosum 36 denetim karsilastirmasi + 8 kaldirma hesabi; grafik guncellenmezse kacan artar
Sınırlar eşit değerde değil. Şube ağı ile merkez servis arasındaki sınır kaldırılırsa altı yeni yol açılıyor, şube uç birimi ile şube ağı arasındaki kaldırılırsa bir. Sıralama sınırdaki denetim sayısıyla örtüşmüyor: iki denetim taşıyan sınır, hiç denetim taşımayandan daha çok yol açıyor. Bir sınırın değeri taşıdığı denetimle değil, ayırdığı bölgelerin grafiğe bağlanma biçimiyle ölçülüyor.
Kural on iki uyarı üretiyor, kayıtta on olay var: altısı yakalanıyor, dördü kaçıyor, üçü yanlış alarm. Kalan üç uyarı ikisinden de değil — eksik denetim gerçekten eksik, henüz olay üretmemiş. Olay üretmemiş uyarı yanlış alarm değildir; yanlış alarm, denetimin gerçekte karşılandığı halde eksik göründüğü uyarıdır. Ayrım yapılmazsa uyarıların yarısı boşa sayılır ve kural gevşetilir.
Kaçan dört olayın nedenleri ayrı okunmalı. İkisi bölge içinde kaldı — yedek kopyası ve kayıt dosyası hiçbir sınırı geçmedi. Biri grafikte tanımsız bir yoldan geçti. Dördüncüsü en öğreticisi: denetimleri tam olan bir sınırda gerçekleşti. Grafik denetimin var olup olmadığını görür, doğru işleyip işlemediğini görmez. Çevrilemeyen kısım buradan çıkıyor: sınırın doğru yerde olması ve bildirilmemiş yolun bulunmaması denetlenemiyor, kaçanların üçü bu kapsamda. Yerine sekiz sınır için çeyrekte bir gözden geçirme konuyor, 24 kişi-saat; sırasını kaldırma analizi veriyor.
Maliyetin ağırlığı koşumda değil: kural otuz altı karşılaştırma ile sekiz kaldırma hesabı, elle tutulan otuz üç grafik kaydı her mimari değişiklikte güncellenmek zorunda. Grafik güncellenmezse kural sessizce yanlışlanır: grafikte olmayan bir akıştaki her olay kaçan olur.
Özet
- Güven sınırı grafiği yedi bölge, sekiz sınır, on sekiz geçiş; on ikisi en az bir gerekli denetimden geçmiyor.
- Denetimsiz sınır tek başına kusur değildir: iki denetimsiz sınırdan yalnız birinden denetim gerektiren veri geçiyor; en yüklü sınır en çok eksiği olan sınır.
- Gerekli denetimlerden biri (maskeleme) sekiz sınırın hiçbirinde tanımlı değil; ancak gerekli küme ile var olan küme yan yana konduğunda görünüyor.
- Bir sınırın kaldırılması 1 ile 6 arasında yeni yol açıyor; sıralamayı denetim sayısı değil, bölgelerin grafiğe bağlanma biçimi belirliyor.
- On iki uyarı, on olay: 6 yakalanan, 4 kaçan, 3 yanlış alarm, 3 açık boşluk; kaçanların üçü grafikte yolu olmayan geçiş, biri denetimi tam sınırda.
Sonraki Adım
Sınır grafiği hangi bölgenin hangisinden ayrıldığını söyledi, kaç kopyası olduğunu söylemedi. Sistem büyüdüğünde asıl soru şudur: neyin kopyalanacağı. Sonraki ders üç ölçek birimi adayını yan yana koyar — tüm sistemin kopyalanması, tek tek servislerin kopyalanması, kiracı başına kopyalama — ve her aday için kopyalanan bileşeni, paylaşılan kalan kaynağı ve hiçbir biçimde kopyalanamayan tekil noktayı sayar.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.