Kod yazarken hepimiz bir an önce o "deploy" butonuna basmak, emeğimizin karşılığını canlıda görmek istiyoruz. Hele ki startup hızında çalışıyorsan, "security" genelde işleri yavaşlatan o sinir bozucu engel gibi görünüyor. Ama işin aslı şu ki; o hızlıca geçtiğin güvenlik adımları, bir gece yarısı gelen "verilerimiz sızmış olabilir mi?" telefonuyla kabusa dönüşebiliyor.
Geçenlerde bir pentest çalışmasındayız. Ekip canla başla yeni bir mikroservis mimarisine geçmeye çalışıyor. Süreçleri o kadar hızlı ki, CI/CD pipeline'ları tıkır tıkır işliyor. Fakat bir şeyi gözden kaçırmışlar: GitHub Actions içerisinde kullandıkları bir "secret", aslında o kadar da gizli değilmiş. Sadece o pipeline'ın loglarına bakarak bütün AWS ortamının anahtarını alabildim. İşte tam burada DevSecOps'un neden sadece havalı bir kelimeden ibaret olmadığını anlıyorsun.
Güvenliği Sola Çekmek (Shift Left) Ama Nasıl?
"Shift Left" lafını her yerde duyuyorsundur. Güvenliği sürecin en başına, yani kodun yazıldığı ana çekmekten bahsediyorum. Ama bunu "herkese güvenlik eğitimi verelim" gibi sıkıcı ve genelde işe yaramayan yöntemlerle değil, süreci otomatikleştirerek yapmalısın.
Benim en çok gördüğüm hata, güvenlik testlerini sadece prod öncesi bir "gate" (kapı) olarak konumlandırmak. Eğer bir developer kodunu bitirip kahvesini içmeye gittiğinde güvenlik ekibi "Hop, burada açık var, her şeyi geri alıyoruz" diyorsa, orada kavga çıkar. İşin doğrusu, o developer daha kodu git push yaptığı an hatasını görmeli.
Mesela, basit bir pre-commit hook'u ile işe başlayabilirsin. Gidip de koda yanlışlıkla yazdığın o AWS key'in repoya girmesini engellemek bu kadar basit aslında.
# .pre-commit-config.yaml örneği
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: check-yaml
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/zricethezav/gitleaks
rev: v8.17.0
hooks:
- id: gitleaks
Bunu ekibe kurdurduğun an, aslında devasa bir yükten kurtuluyorsun. "Aman koda şifre yazmayın" diye bağırmana gerek kalmıyor, sistem zaten buna izin vermiyor.
SAST ve DAST: Hangisi Daha Çok Baş Ağrıtır?
Şimdi dürüst olalım; SAST (Static Analysis) araçları bazen o kadar çok "false positive" (yanlış alarm) veriyor ki, insan bir noktadan sonra hepsini görmezden gelmeye başlıyor. Bir bakıyorsun bin tane "kritik" uyarı var ama aslında yarısı kütüphanenin içindeki gereksiz bir yorum satırından kaynaklanıyor.
Sıkça karşılaştığım bir durum: Şirket pahalı bir SAST aracı alıyor, pipeline'a entegre ediyor. İlk çalıştırmada 5000 tane hata çıkıyor. Sonuç? Developer'lar o aracı devre dışı bırakmanın yollarını arıyor.
Bence burada strateji şu olmalı: Sadece gerçekten can yakan şeylere odaklan. İlk aşamada SQL Injection ve Hardcoded Secrets yakalasan yeter. Diğer "best practice" uyarılarını zamanla eklersin.
DAST (Dynamic Analysis) ise bambaşka bir dünya. Uygulama çalışırken dışarıdan bir saldırgan gibi test etmek harika, ama pipeline'ı acayip yavaşlatabiliyor. Eğer her commit'te full bir DAST scan koşturmaya kalkarsan, o pipeline bitene kadar herkes emekli olur. Bunun yerine, kritik endpoint'leri tarayan "smoke test" tarzı hızlı taramalar yapıp, derinlemesine taramayı haftalık periyotlara bırakabilirsin.
Bağımlılıklar: Senin Yazmadığın Kodlar Seni Yakar
SCA (Software Composition Analysis) dediğimiz olay aslında en sevdiğim ve en kolay halledilebilecek kısımlardan biri. Yazdığın kodun belki sadece %20'si sana ait, geri kalan %80 kütüphanelerden geliyor. Ve o kütüphanelerin birinde çıkan bir açık, senin bütün sistemini savunmasız bırakabiliyor.
Bir keresinde bir projede, sadece eski bir log4j sürümü yüzünden (evet, o meşhur Log4Shell) koca bir finans uygulamasının admin yetkilerini alabildik. Developer arkadaş "Ama ben o kütüphaneyi sadece basit bir loglama için kullanıyordum" dedi. Haklıydı ama saldırgan haklı haksız bakmıyor.
GitHub kullanıyorsan Dependabot bu işin can damarı. GitLab'de de benzer araçlar var. Bunları aktif et ve gelen güncelleme PR'larını (Pull Request) görmezden gelme.
Pipeline'ın Kendisi Bir Hedef
Bak burası çok kritik. Biz hep "uygulama güvenliği" diyoruz ama o uygulamayı dağıtan pipeline'ın güvenliği genelde unutuluyor. CI/CD sunucusuna sızan birisi, senin bütün production ortamına istediği kodu enjekte edebilir.
Dikkat etmen gereken birkaç şey:
- Runner Güvenliği: Kendi runner'larını kullanıyorsan, bunların her işten sonra temizlendiğinden emin ol. Bir önceki işten kalan bir temp dosyası, bir sonraki işin sırlarını ifşa edebilir.
- Secret Yönetimi: Pipeline içindeki şifreleri asla düz metin olarak değişkenlere yazma. HashiCorp Vault gibi araçlar kullan ya da en azından cloud sağlayıcının (AWS Secrets Manager vb.) sunduğu çözümlere yönel.
- Zayıf İzinler: Pipeline'a her şeye erişebilen bir
Administratoryetkisi verme. Sadece ihtiyacı olan yetkiyi (Least Privilege) tanımla.
Mesela bir GitLab CI örneği üzerinden gidelim. Sadece ihtiyacımız olan yetkiyi vermek ve Docker imajımızı taramak için şöyle bir şey yapabiliriz:
stages:
- test
- build
- scan
container_scanning:
stage: scan
image:
name: aquasec/trivy:latest
entrypoint: [""]
script:
- trivy image --exit-code 1 --severity CRITICAL my-app-image:latest
allow_failure: false
Burada trivy kullanarak imajdaki kritik açıkları tarıyoruz. Eğer kritik bir açık varsa, pipeline duruyor (exit-code 1). Bu kadar basit bir adım bile seni büyük bir beladan kurtarabilir.
İletişim: Araçlardan Daha Önemli
İşin aslı, DevSecOps teknik bir konudan çok, bir iletişim konusu. Güvenlikçilerle developer'lar arasındaki o meşhur duvarı yıkman lazım. Ben bir Red Team uzmanı olarak bir açık bulduğumda, gidip o kodu yazan arkadaşla kahve içip "Bak burada böyle bir durum var, gel beraber nasıl daha sağlam yaparız bakalım" dediğimde aldığım sonuç, sadece bir PDF raporu gönderdiğimdeki sonuçtan kat kat daha iyi oluyor.
Developer'ların üzerine "güvenlik polisliği" yaparak değil, onlara güvenliği kolaylaştıracak araçlar vererek başarılı olabilirsin. Güvenlik, kod yazma sürecinin bir parçası haline gelmeli, ona eklenen bir yük değil.
Son Söz Niyetine
Öğrenmeye açık olmak bu işin anahtarı. Teknoloji çok hızlı değişiyor; bugün güvenli dediğimiz konteyner yapısı yarın bambaşka bir zafiyetle karşımıza çıkabiliyor. Önemli olan, hata yaptığında o hatanın nerede olduğunu hızlıca görebilecek bir sisteme sahip olmak.
Kendi projelerinde ufak bir lint kontrolüyle başla, sonra SCA araçlarını ekle, en son pipeline güvenliğine odaklan. Adım adım gitmezsen her şey birbirine karışır.
Eğer bu konularda takıldığın bir yer olursa, "ya şu pipeline'da nasıl bir takla atabiliriz?" diye düşünürsen, her zaman buralardayım. Güvenlikte her şeyi bilmek imkansız, ama beraber kafa yormak her zaman yeni bir kapı açar.
Kodu temiz, pipeline'ı sağlam tut. Görüşürüz!
