Ders 01 / 11
DevSecOps ve DevOps Farkı
Aynı 23 kalemlik küme iki akışta koşturulur: dağıtım öncesinde duran tek güvenlik kapısı 10 kalem yakalar, 5 kalemi hiç görmez ve 60. günde 120 değişikliği kuyrukta bekletir; denetim altı aşamaya dağıtıldığında 23 kalemin tamamı yakalanır ve ortalama gecikme 1,94 aşamadan 0,13 aşamaya iner. Dağıtmanın bedeli 200 uyarının 177'sinin yanlış pozitif olmasıdır.
İçindekiler
Önceki müfredat on kurs boyunca savunmanın kapattığı yolu saydı ve kapanışında kıt bir bütçenin hangi kaleme gideceğini sordu. Bütün o ölçümlerin ortak ve sessiz bir varsayımı vardı: yazılım zaten yazılmıştı. Yol kümesi çalışan bir sistemden çıkarılıyor, denetim çalışan bir sisteme konuyordu. Bu kurs o varsayımı kaldırır ve aynı ölçüm ağının yazılımını üretilirken ele alır.
Ölçü birimi değişir. Yol yerine aşama sayılır: bir açık ya da yanlış karar hangi aşamada doğuyor, hangi aşamada yakalanabiliyor ve aradaki fark kaç aşama. Bu ilk ders farkın en kaba biçimini ölçer — güvenliğin akışa dahil olmasıyla akışın sonunda ayrı bir kapı olarak durması arasındaki fark. İki düzenek aynı kalem kümesi üzerinde koşturulur; üç sütun çıkar: kaç kalem yakalanıyor, kaç aşama geç yakalanıyor, karşılığında ne ödeniyor.
- DY1. Ağ ve yazılımı kurgusaldır: bölgesel ölçüm ağının abone portalı, sayaç toplama servisi,
faturalama ve saha uygulaması beş ekipçe geliştiriliyor. Değişiklik akışı ve kalem kümesi
nodeile modellenir; ölçülen şey bu modeldir. - DY2. Aşama kümesi altı ögedir: gereksinim, tasarım, kod, yapı, dağıtım, çalışma zamanı. Bir kalem tek bir aşamada doğar ve doğduğu aşamadan önce yakalanamaz.
- DY3. Görünürlük vektörü model kararıdır: o aşamaya konan bir denetimin kalemi görüp göremeyeceğini söyler. Gerçekte bu eşleme denenerek çıkarılır; dersin noktası eşleme değil, üzerinde yapılan sayımdır.
- DY4. Bir denetim kalemi ya görür ya görmez. Kısmi görme ve gözden kaçırma olasılığı modellenmiyor; ikisi de yakalanan kalem sayısını düşürür, yönünü değiştirmez.
- DY5. Kapı incelemesi paket düzeyinde yapılır. Bir pakette kapının gördüğü bir kalem varsa paketin tamamı geri döner; paketteki öbür değişiklikler de bekler.
- DY6. Uyarı sayıları ve dakika değerleri verilmiş model değerleridir. Yanlış pozitif sayısı verilmez, uyarı sayısından gerçekten yakalanan kalem çıkarılarak bulunur.
Kalem Kümesi ve Değişiklik Akışı
Model iki şeyi ayrı tutar: akıştan geçen değişiklikler ve o değişikliklerin bir bölümünün taşıdığı kalemler. Kalem, doğduğu aşamayla ve altı basamaklı bir görünürlük vektörüyle tanımlanır.
// akis.mjs — kurgusal olcum agi yaziliminin degisiklik akisi ve kalem kumesi (model) export const ASAMA = ['gereksinim', 'tasarim', 'kod', 'yapi', 'dagitim', 'calisma-zamani']; export const EKIP = [['abone-portali', 10], ['sayac-toplama', 8], ['faturalama', 6], ['saha-uygulamasi', 5], ['ortak-kitaplik', 6]]; export const GUN = 60; // 12 haftalik olcum penceresi, is gunu // kalem: ad | dogdugu asama | gorunurluk vektoru (asama basina 1/0: oraya konan bir // denetim bu kalemi gorebilir mi). Vektorler model kararidir, olcum degil. export const KALEM = ` veri-siniflandirmasi-yok 0 100000 saklama-suresi-tanimsiz 0 100001 kisisel-veri-kapsami-belirsiz 0 100010 kimlik-dogrulamasiz-ic-cagri 1 011110 zayif-oturum-modeli 1 010011 guven-sinirsiz-veri-akisi 1 010000 yetki-modelinde-eksik-rol 1 011001 eksik-yetki-denetimi 2 001101 gomulu-gizli-anahtar 2 001110 dogrulanmamis-girdi 2 001001 gunluge-yazilan-kisisel-veri 2 001001 yarim-kalan-hata-yolu 2 001000 zayif-rastgelelik 2 001000 sinirsiz-sorgu-boyu 2 000001 guncel-olmayan-bagimlilik 3 000110 imzasiz-yapi-ciktisi 3 000110 gereksiz-yapi-araci 3 000100 varsayilan-parola 4 000011 asiri-genis-ag-kurali 4 000011 sifresiz-yedek 4 000010 acik-yonetim-ucu 4 000011 olcek-altinda-yaris 5 000001 ucuncu-tarafta-aciklanan-acik 5 000001` .trim().split('\n').map((r) => { const [ad, d, g] = r.trim().split(/\s+/); return { ad, dogus: +d, g }; }); export const GUNLUK = EKIP.reduce((s, [, n]) => s + n, 0) / 5; export const TOPLAM_DEGISIKLIK = GUNLUK * GUN; // Kalem tasiyan degisiklik, akista esit araliklarla yerlestirilir (model). export const TASIYAN = new Map(KALEM.map((k, i) => [Math.floor((i * TOPLAM_DEGISIKLIK) / KALEM.length), k])); // Ilk gorulebilen asama: dogustan sonra gorunurluk vektorunun 1 oldugu ilk asama. export const ilkGorulen = (k, asamalar) => asamalar.find((i) => i >= k.dogus && k.g[i] === '1') ?? null;
Vektörler dersin asıl bilgisini taşır. veri-siniflandirmasi-yok yalnız gereksinim aşamasında
görülebilir; sonraki hiçbir denetim onu bulamaz, çünkü ortada yanlış bir satır yoktur, eksik bir
karar vardır. sinirsiz-sorgu-boyu kod aşamasında doğar ama yalnız çalışma zamanında görünür:
kodda hatalı bir şey yoktur, veri büyüdüğünde ortaya çıkan bir sınır yokluğu vardır.
Ayrı Kapının Kuyruğu
İlk düzenek güvenliği tek noktaya koyar: dağıtımdan önce duran bir inceleme kapısı. Kapının günlük kapasitesi sınırlıdır, geliş hızı ise ekiplerin toplamıdır.
// kosum1.mjs — ayri kapi: degisiklikler dagitim oncesi tek noktada kuyruga girer import { GUN, GUNLUK, TOPLAM_DEGISIKLIK, TASIYAN, KALEM } from './akis.mjs'; const KAPASITE = 5; // kapinin gunde bitirebildigi inceleme sayisi (model) function kos(b) { const paket = []; for (let i = 0; i < TOPLAM_DEGISIKLIK; i += b) { const son = Math.min(i + b, TOPLAM_DEGISIKLIK) - 1, ic = []; for (let c = i; c <= son; c++) if (TASIYAN.has(c)) ic.push(TASIYAN.get(c)); paket.push({ ilk: i, n: son - i + 1, hazir: Math.floor(son / GUNLUK), ic, biten: null }); } for (let g = 0; g < GUN * 20; g++) { let yer = KAPASITE; for (const p of paket) if (p.biten === null && p.hazir <= g && yer-- > 0) p.biten = g; } // Bir degisikligin beklemesi: kendi geldigi gunden paketinin bittigi gune kadar. let bekleme = 0; for (const p of paket) for (let c = p.ilk; c < p.ilk + p.n; c++) bekleme += p.biten - Math.floor(c / GUNLUK); const acik = paket.filter((p) => p.hazir < GUN && p.biten >= GUN); return { gunluk: paket.length / GUN, bekleyen: acik.reduce((s, p) => s + p.n, 0), ort: bekleme / TOPLAM_DEGISIKLIK, donen: paket.filter((p) => p.ic.some((k) => k.g[4] === '1')).reduce((s, p) => s + p.n, 0) }; } const gorulen = KALEM.filter((k) => k.g[4] === '1').length; console.log(`${GUNLUK} degisiklik/gun, ${GUN} gun, ${TOPLAM_DEGISIKLIK} degisiklik; ` + `kapi ${KAPASITE} inceleme/gun; kapinin gorebildigi kalem ${gorulen}/${KALEM.length}`); console.log('\npaket inceleme/gun 60. gunde bekleyen degisiklik ortalama bekleme gun geri donen degisiklik'); for (const b of [1, 2, 3, 5, 7]) { const r = kos(b); console.log(String(b).padEnd(7) + r.gunluk.toFixed(1).padEnd(14) + String(r.bekleyen).padEnd(30) + r.ort.toFixed(1).padEnd(22) + r.donen); }
7 degisiklik/gun, 60 gun, 420 degisiklik; kapi 5 inceleme/gun; kapinin gorebildigi kalem 10/23 paket inceleme/gun 60. gunde bekleyen degisiklik ortalama bekleme gun geri donen degisiklik 1 7.0 120 12.0 10 2 3.5 0 0.1 20 3 2.3 0 0.1 30 5 1.4 0 0.3 50 7 1.0 0 0.0 70
İlk satır kapının kapasite sorununu veriyor: günde yedi değişiklik geliyor, kapı beşini bitirebiliyor. Aradaki iki değişiklik biriktiği için altmışıncı günde 120 değişiklik hâlâ kuyrukta, ortalama bekleme 12 gündür. Bu bir yavaşlama değil, doymuş bir kuyruktur: fark kapanmadıkça bekleme süresi süre geçtikçe büyümeye devam eder.
Ekiplerin bu duruma verdiği karşılık paketlemedir — değişiklikleri biriktirip tek incelemeye sokmak. Tablo paketlemenin çalıştığını gösteriyor: paket boyu ikiye çıktığında kuyruk kapanıyor ve ortalama bekleme onda bir güne iniyor. Son sütun bedeli yazıyor. Kapının gerçekten gördüğü kalem sayısı her satırda onda sabit kalırken, o on kalem yüzünden geri dönen değişiklik sayısı 10’dan 70’e çıkıyor. Paket boyu yedide, tek bir kalem için altı meşru değişiklik daha bekletiliyor.
Kapının ikinci sınırı en baştaki satırda duruyor: yirmi üç kalemin yalnız onu kapının bakabildiği biçimdedir. Kalan on üç kalem kapıdan sorunsuz geçer, çünkü kapı bir gereksinim kararına ya da bir tasarım boşluğuna bakmaz — elindeki tek şey dağıtılmak üzere olan yapının kendisidir.
Aynı Kalem Kümesi, Dağıtılmış Denetim
İkinci düzenek aynı kalem kümesini alır ve denetimi altı aşamaya dağıtır. Karşılaştırma bu yüzden adildir: değişen tek şey denetimin nerede durduğudur.
İki düzeneğin adlandırılması burada anlam kazanır. Geliştirme ve işletimin tek akışta birleşmesi (DevOps) bir araç seçimi değil, bir geri bildirim kuralıdır: her karar, sonucunu gördüğü döngü ne kadar kısaysa o kadar ucuza düzeltilir. Kapı düzeneği bu kuralı teslim hızı için uygular ama güvenlik kalemini kuralın dışında bırakır; güvenliğin geri bildirim döngüsü, ne kadar hızlı çalışırsa çalışsın, akışın en sonundaki tek noktadan geçer. Güvenliğin akışa dahil edilmesi (DevSecOps) aynı kuralı güvenlik kalemine de uygulamaktan ibarettir. Ayırt edici olan yeni bir denetim türü eklemek değildir — tablodaki altı denetimin beşi kapı düzeneğinde de kurulabilir. Ayırt edici olan, denetimin kalemin doğduğu döngüye yerleştirilmesidir.
// kosum2.mjs — ayni kalem kumesi iki akista: denetim tek kapida ve asamalara dagitilmis import { ASAMA, KALEM, ilkGorulen } from './akis.mjs'; // Akisa dahil denetimin asama basina uretimi (model): calisan birim, uretilen uyari, // uyari basina gelistirici dakikasi. const DENETIM = [['gereksinim incelemesi', 18, 5, 25], ['tasarim oturumu', 12, 9, 30], ['statik kod cozumlemesi', 420, 96, 6], ['bagimlilik taramasi', 420, 54, 8], ['yapilandirma denetimi', 60, 22, 12], ['calisma zamani gozlemi', 60, 14, 20]]; const akislar = [['ayri kapi', [4, 5]], ['akisa dahil', [0, 1, 2, 3, 4, 5]]]; console.log('akis yakalanan hic gorulmeyen toplam gecikme asama ortalama gecikme'); const sonuc = new Map(); for (const [ad, asamalar] of akislar) { const y = KALEM.map((k) => [k, ilkGorulen(k, asamalar)]); const bulunan = y.filter(([, i]) => i !== null); const gec = bulunan.reduce((s, [k, i]) => s + i - k.dogus, 0); sonuc.set(ad, y); console.log(ad.padEnd(13) + String(bulunan.length).padEnd(11) + String(KALEM.length - bulunan.length).padEnd(16) + String(gec).padEnd(22) + (gec / bulunan.length).toFixed(2)); } console.log('\nasama dogan kapi akisinda yakalanan dagitilmis akista yakalanan'); for (const [i, a] of ASAMA.entries()) console.log(a.padEnd(16) + String(KALEM.filter((k) => k.dogus === i).length).padEnd(7) + String(sonuc.get('ayri kapi').filter(([, j]) => j === i).length).padEnd(24) + sonuc.get('akisa dahil').filter(([, j]) => j === i).length); console.log('\ndenetim birim uyari gercek yanlis pozitif gelistirici dakikasi'); let uy = 0, dk = 0; for (const [i, [ad, birim, uyari, dak]] of DENETIM.entries()) { const gercek = sonuc.get('akisa dahil').filter(([, j]) => j === i).length; uy += uyari; dk += uyari * dak; console.log(ad.padEnd(24) + String(birim).padEnd(7) + String(uyari).padEnd(7) + String(gercek).padEnd(8) + String(uyari - gercek).padEnd(16) + uyari * dak); } console.log(`\ntoplam ${uy} uyari, ${dk} dakika (${(dk / 60).toFixed(1)} saat), ` + `kalem basina ${(dk / 60 / 23).toFixed(1)} saat`); const kapiSaat = 300 * 3; console.log(`kapi: 300 inceleme x 3 saat = ${kapiSaat} saat, 10 kalem, ` + `kalem basina ${(kapiSaat / 10).toFixed(0)} saat`);
akis yakalanan hic gorulmeyen toplam gecikme asama ortalama gecikme ayri kapi 18 5 35 1.94 akisa dahil 23 0 3 0.13 asama dogan kapi akisinda yakalanan dagitilmis akista yakalanan gereksinim 3 0 3 tasarim 4 0 4 kod 7 0 6 yapi 3 0 3 dagitim 4 10 4 calisma-zamani 2 8 3 denetim birim uyari gercek yanlis pozitif gelistirici dakikasi gereksinim incelemesi 18 5 3 2 125 tasarim oturumu 12 9 4 5 270 statik kod cozumlemesi 420 96 6 90 576 bagimlilik taramasi 420 54 3 51 432 yapilandirma denetimi 60 22 4 18 264 calisma zamani gozlemi 60 14 3 11 280 toplam 200 uyari, 1947 dakika (32.5 saat), kalem basina 1.4 saat kapi: 300 inceleme x 3 saat = 900 saat, 10 kalem, kalem basina 90 saat
Birinci tablo iki ayrı sayı veriyor ve ikisini karıştırmamak gerekir. Kapı akışında 18 kalem yakalanıyor, ama bunların yalnız onu kapıda yakalanıyor; kalan sekizi çalışma zamanında bir olayla ortaya çıkıyor. Ortaya çıkma yakalama değildir, ama kalem hiç değilse bilinir hâle gelir. 5 kalem ise hiçbir düzeneğin görmediği kalemdir: gereksinimdeki sınıflandırma boşluğu, tasarımdaki sınırsız veri akışı, koddaki yarım hata yolu ve zayıf rastgelelik, yapıdaki gereksiz araç. Bunlar kayıtta yoktur, sıralamaya girmez, bütçede yer tutmaz.
Gecikme sütunu farkı tek sayıya indiriyor. Kapı akışında yakalanan kalemler toplam 35 aşama
geç bulunuyor, kalem başına 1,94 aşama. Dağıtılmış akışta toplam gecikme 3 aşamadır ve tamamı
tek bir kalemden gelir: kod aşamasında doğan sinirsiz-sorgu-boyu, ancak çalışma zamanında görünür.
İkinci tablo bu tek kalemi doğrudan gösteriyor. Kod aşamasında yedi kalem doğuyor, dağıtılmış akış altısını kod aşamasında yakalıyor. Yedincisi hiçbir erken denetimin bakamayacağı sınıftandır ve denetimi ne kadar sola alırsanız alın orada kalır. Bu kursun ikinci dersi tam olarak o sınıfı sayar.
Dağıtmanın Bedeli
Üçüncü tablo dağıtılmış akışın faturasıdır. Altı denetim toplam 200 uyarı üretiyor; bunların 23’ü gerçek kalem, 177’si yanlış pozitiftir. Oran denetimden denetime değişir: gereksinim incelemesi beş uyarının üçünü doğru yazar, statik kod çözümlemesi doksan altı uyarının altısını. Sıklık arttıkça isabet düşer, çünkü kod çözümlemesi 420 değişikliğin her birinde koşarken gereksinim incelemesi on sekiz kez toplanır.
Toplam yük 1.947 geliştirici dakikası, yani 32,5 saattir. Kapı akışının aynı pencerede harcadığı süre 300 inceleme çarpı üç saat, yani 900 saattir. Kalem başına ödenen bedel dağıtılmış akışta 1,4 saat, kapı akışında 90 saattir — altmış dört katlık bir fark. İki sayının aynı işi ölçmediği not edilmelidir: kapı her değişikliğe bakar, dağıtılmış denetim yalnız uyarı üretenlere bakar. Farkın kaynağı da budur.
Bedelin ikinci kalemi tabloda görünmez. 177 yanlış pozitif, 177 kez bir geliştiricinin işini bölmesi demektir; bunların doksanı tek bir denetimden gelir. Bir denetimin gerçek maliyeti çalıştığı süre değil, ürettiği uyarının kaçının bir insan tarafından okunmak zorunda olduğudur. Yanlış pozitif oranı yükseldiğinde uyarılar okunmaz hâle gelir ve o denetimin yakaladığı gerçek kalemler de görünmez olur — bu, denetimi hiç koymamakla aynı sonucu verir, ancak maliyeti sürer.
Özet
- Kurgusal ölçüm ağı yazılımında 60 iş gününde 420 değişiklik akıyor ve 23 kalem taşıyor; kalemler altı aşamanın hepsinde doğuyor, en çok kod aşamasında (7 kalem).
- Dağıtım öncesinde duran tek kapı 23 kalemin yalnız 10’unu görebilir. Günde 7 değişiklik gelir, 5 inceleme biter; 60. günde 120 değişiklik kuyrukta bekler ve ortalama bekleme 12 gündür.
- Paketleme kuyruğu kapatır ama bedeli geri dönen meşru değişikliktir: paket boyu 1’de 10, paket boyu 7’de 70 değişiklik aynı 10 kalem yüzünden bekletilir.
- Denetim altı aşamaya dağıtıldığında 23 kalemin tamamı yakalanır; hiç görülmeyen kalem 5’ten 0’a, toplam gecikme 35 aşamadan 3 aşamaya, kalem başına gecikme 1,94’ten 0,13 aşamaya iner.
- Dağıtmanın bedeli 200 uyarının 177’sinin yanlış pozitif olmasıdır; 1.947 geliştirici dakikasının 576’sı tek bir denetimin ürettiği 96 uyarıya gider.
- Kod aşamasında doğan 7 kalemin 6’sı kod aşamasında yakalanır, biri yalnız çalışma zamanında görünür; erken denetim bu kalemin gecikmesini düşürmez.
Sonraki Adım
Bu ders denetimin yerini değiştirdi ve yakalanan kalem sayısının arttığını, gecikmenin düştüğünü saydı. Ölçülmeyen tek şey bu gecikmenin ne kadara mal olduğudur. Otuz beş aşamalık gecikme bir sayıdır, ama bir kalemi tasarım aşamasında düzeltmekle çalışma zamanında düzeltmek arasındaki fark aşama sayısı değil, harcanan iştir: bir tasarım kararını değiştirmek bir toplantıdır, aynı kararı dağıtılmış bir sistemden geri almak veri göçü, sürüm planı ve kesinti penceresidir. Sonraki ders aşama başına düzeltme maliyetini modelin içine koyar, aynı kalem kümesini geç ve erken denetimli iki akışta koşturur ve toplam katı hesaplar. Aynı ders ikinci bir soruyu da sorar: bu katın hangi kalemler için geçerli olmadığını, yani erken yakalamanın hiçbir şey kazandırmadığı kalem sınıfının ne kadar büyük olduğunu.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.