Açık konuşayım: Azure DevOps’ta CodeQL taramasını kurmak, bir dönem benim en sevmediğim işlerden biriydi. Her repo için ayrı pipeline, YAML’a elle dokunma, task ekleme, agent pool ayarı… Yüzlerce reposu olan kurumsal bir müşteride bunu yaptığınızı düşünün. Bir keresinde bankacılık tarafında, tam 47 repo için bu akışı kurmuştuk; üç hafta gitti. Evet, baya yordu.
Şimdi Microsoft burada işi biraz toparlamış. Hatta beklediğimden fazla toparlamış diyebilirim. Advanced Security tarafına gelen iki yenilik var: CodeQL default setup ve Security Overview’da birleşik uyarı deneyimi. İlk bakışta küçük duruyorlar, ama pratikte epey fark ediyorlar.
Önce kısa bir özet vereyim, sonra detaya gireriz. Yeni yapıda kod taramasını tek tıkla açabiliyorsunuz, organizasyon seviyesinde uyarıları da tek ekran üstünden yönetiyorsunuz (hani eskiden ayrı ayrı repo gezip uğraşıyorduk ya, işte o kısmı ciddi biçimde azaltıyor) (inanın bana). Ben AZ-500 hazırlığı sırasında Defender for DevOps tarafında benzer akışları çok denedim; orada bile bu kadar sade bir deneyim yoktu açıkçası. Peki neden önemli? Çünkü zaman kazandırıyor.
Eski dünya neden bu kadar ağırdı?
İşin garibi, Bakın şimdi. Azure DevOps Advanced Security’yi ilk duyurduklarında (GitHub Advanced Security for Azure DevOps — kısaca GHAzDO) verdikleri ana söz basitti: GitHub’daki güvenlik özelliklerini Azure DevOps’a da taşıyacağız. Secret scanning var, dependency scanning var, code scanning de var. Güzel duruyor. Ama işin CodeQL tarafı, yani code scanning kısmı, baştan beri biraz kenarda kalmış gibiydi.
Durun, bir saniye.
Neden böyle oldu? Çünkü GitHub tarafında “Default setup” butonu vardı, Azure DevOps’ta yoktu (bizzat test ettim). Siz de her repo için tek tek uğraşıyordunuz:
- Bir Azure Pipeline oluşturacaksınız
AdvancedSecurity-Codeql-Init@1,AdvancedSecurity-Codeql-Analyze@1gibi task’leri YAML’a ekleyeceksiniz- Dil algılama, build step’leri, timeout ayarları… hepsini elle kuracaksınız
- Sonra da bu pipeline’ı zamanla güncel tutacaksınız (versiyon değişiyor, küçük detay kaçıyor, sonra yine dönüp bakıyorsunuz)
Tuhaf ama, Hani 10 repo’nuz varsa, tamam, çok da büyütmezsiniz. Ama 300 repo’su olan bir telekom müşterisinde? Orada tablo değişiyor. Geçen sene böyle bir müşteride — isim vermeyeyim ama İstanbul merkezli büyük bir operatör — sadece pipeline hazırlama işine iki haftalık bir FTE ayırmıştık. İki hafta. Sırf boilerplate YAML yazmak için.
Evet.
“Güvenlik, sürtünme yarattığı an uygulanmaz.” — Bu lafı bir CISO’dan duymuştum, aklımdan çıkmıyor. Default setup tam da bu sürtünmeyi yok etmeye çalışıyor.
CodeQL Default Setup: gerçekten tek tık mı?
Evet, tek tık gibi duruyor. Ama durun bir saniye, bu “tek tık” meselesine fazla kapılmayın; arka tarafta ne döndüğünü anlamadan geçerseniz, sonra sürpriz yaşayabilirsiniz. Public preview’da olduğu için de ben açık konuşayım, production-critical işlerde hemen koşup kullanmazdım.
Ne oluyor perde arkasında?
Siz butona bastığınız anda Advanced Security, sizin yerinize Azure Pipelines üzerinde CodeQL taramasını çalıştırıyor. YAML yazmıyorsunuz, task kurmuyorsunuz, build step eklemiyorsunuz; yani işin en sıkıcı kısmı ortadan kalkıyor. Sadece şunları yapıyorsunuz:
- Repository / Project / Organization ayarlarına gidiyorsunuz
- Code Security planını açıyorsunuz (bu kritik)
- Enable CodeQL default setup” diyorsunuz
- Bitti.
Taramalar belirli bir schedule ile koşuyor (organizasyon seviyesinde bunu değiştirebiliyorsunuz), ama asıl can alıcı nokta agent pool seçimi (buna dikkat edin). Büyük repo’larda Microsoft-hosted agent’lar bazen yetmeyebiliyor, hatta hiç beklemediğiniz yerde darboğaz çıkarabiliyor; ben olsam kurumsal bir self-hosted pool tanımlar, işi oraya yönlendirirdim. Şey, küçük ekipte idare eder ama büyüyünce tablo değişiyor.
Üç seviyeli kapsama
Aslında en hoş tarafı burada çıkıyor. Enablement üç ayrı seviyede çalışıyor ve bu da işi biraz daha esnek hale getiriyor; bazen tek repo yeter, bazen proje geneline yaymak mantıklı olur, bazen de org’un tamamını bir anda kapsamak istersiniz. Kısacası seçenek var:
| Seviye | Kapsam | Kime uygun? |
|---|---|---|
| Repository | Tek repo | Pilot yapacaksanız, küçük ekipler |
| Project | Proje içindeki tüm repo’lar | Orta ölçek, tek ürün ekibi |
| Organization | Tüm org — yeni eklenen repo’lar dahil | Enterprise, policy-driven ekipler |
Şunu fark ettim: Organization seviyesinde açtığınızda yeni oluşturulan her repo otomatik olarak taramaya giriyor. Güzel tarafı şu: developer repo’yu açıyor ve kod yazmaya başlıyor ama güvenlik taraması zaten hazır bekliyor (yani sonradan “aa bunu da mı ekleyeceğiz” telaşı olmuyor). Bu yaklaşım tam da shift-left security dediğimiz şeye oturuyor. Evet.
Türkiye’deki kurumsal yapılar için ne anlama geliyor?
Şimdi bu kısmı atlamadan geçmek istemiyorum. Çünkü Türkiye’de görüyorum, güvenlik aracı almak başka şey, o aracı gerçekten çalıştırmak bambaşka şey; KVKK. BDDK tarafındaki baskı yüzünden bankacılık ile sigorta müşterilerinde GHAzDO lisansı alınıyor, ama kullanım oranına bakınca insan biraz duraksıyor, çoğu yerde yüzde 30’u bile zor görüyor.
Ve işler burada ilginçleşiyor.
Tuhaf ama, Neden böyle? Basit aslında. Pipeline kurma işi DevOps ekibine kalıyor, ekip zaten işten başını kaldıramıyor, güvenlik tarafı “yapın” diyor ama aracın teknik ayrıntısına çok hakim değil, sonra herkes birbirine bakıp duruyor. Default setup tam burada devreye giriyor; güvenlik müdürü ayarlar ekranına girip butona basıyor, tamamdır. Açık konuşayım, lisans yatırımının geri dönmesini sağlayan en kritik parçalardan biri bu gibi duruyor.
Bakın, Maliyet tarafını da es geçmeyeyim (bizzat test ettim). GHAzDO aktif committer başına aylık ücretleniyor (şu an kişi başı yaklaşık $49 gibi bir rakam var — kur değişiyor tabi, güncel rakama yine Azure pricing sayfasından bakmak lazım),. 100 developer varsa ay sonunda kabaca 5000 dolar çıkıyor. Bu parayı verip özelliği kullanmamak… nasıl desem, biraz iç yakıyor. Default setup gelince bahane de azalıyor.
Security Overview: nihayet tek ekran
Gelelim ikinci büyük yeniliğe. Combined alerts view. Duyunca ilk tepkim şu oldu: “Ya, bunu neden 2 sene önce yapmadınız?” Açık konuşayım, insanın aklına ilk bu geliyor.
İşte tam da bu noktada devreye giriyor.
Eski düzende bir güvenlik yöneticisi organizasyondaki tabloyu görmek için repo repo geziyordu. 50 repo varsa 50 sekme açıyordunuz, sonra da gözünüz döner gibi oluyordu; bir keresinde Logosoft’ta bir müşteri için özel bir PowerShell script yazmıştık — Azure DevOps REST API’lerinden alert’leri çekip CSV’ye basıyordu, biraz yamuk yumuk bir çözümdü ama başka yol da yoktu (ki bu çoğu kişinin gözünden kaçıyor)
Ne sunuyor bu yeni deneyim?
Security Overview altında yeni bir “Alerts” tab’i var. Orada organizasyondaki tüm repo’ların default branch’lerindeki tüm alert’leri tek ekranda görebiliyorsunuz. Search var, filtre var, sıralama var; yani el yordamıyla dolaşma işi baya azalıyor (ben de ilk duyduğumda şaşırmıştım). En sevdiğim tarafı şu: severity’ye göre filtreleyip sadece Critical. High olanları bırakabiliyorsunuz, sonra da doğrudan aksiyona geçiyorsunuz. Kubernetes v1.36 ile Gelen Değişiklikler ve Notlarım yazımızda bu konuya da değinmiştik.
Dürüst olmak gerekirse, Mesela geçen hafta bir e-ticaret müşterisinde Log4Shell benzeri bir CVE çıkıntısı vardı — aslında daha küçük bir dependency vulnerability’di ama ekipte kısa süreli panik yaratmıştı. Eski dünyada 23 repo’yu tek tek açıp bakacaktık, biraz eziyet olurdu; yeni ekranda CVE ID’sini filtreye yazdım, 4 repo’da gözüktü, 30 dakikada remediation planı çıkardık. Bitti gitti. Bu gerçek bir verimlilik kazancı, hani laf olsun diye söylemiyorum.
Security Campaigns: koordinasyonun dijitalleşmesi
Campaigns tarafı da ayrı bir konu. Filtrelenmiş bir alert view oluşturup ekibinizle paylaşıyorsunuz. Mesela “Tüm Python repo’larındaki High severity SQL injection alert’leri” diye bir campaign kurabiliyorsunuz. Filtre canlı kalıyor — yeni alert çıktığında otomatik campaign’e düşüyor; şey, klasik “Excel’e döküp Jira’ya ticket açma” döngüsünü ciddi şekilde kısaltıyor. .NET MAUI 11’de Harita Pin Kümeleme: Pratik Rehber yazımızda bu konuya da değinmiştik.
Ha şu da var — campaigns henüz çok olgun değil bence. Assignment, SLA takibi, reporting tarafı biraz zayıf kalıyor; ServiceNow veya Jira entegrasyonu olsa fena olmazdı. Yani kağıt üstünde iyi duruyor ama pratikte biraz daha pişmesi lazım, burada durup süper demek de pek doğru olmaz.
Pratik rehber: nereden başlamalı?
Tuhaf ama, Eğer bu özelliği yeni açacaksanız, ben olsam şöyle giderim. Mantıklı değil mi? Önce küçük başlarım, sonra büyütürüm; çünkü ilk anda her yere yayılınca işler biraz dağılıyor, özellikle de repo sayısı artmışsa ve ekip de “bir bakalım nasıl gidiyor” modundaysa.
- Pilot seç: Tek bir repo alın, orta büyüklükte olsun. Production-critical olmasın. Repository seviyesinde default setup’ı açın; böylece neyin nasıl davrandığını daha net görürsünüz.
- İlk taramayı izle: Azure Pipelines üzerinde koşan ilk scan’in ne kadar sürdüğüne bakın. 30 dakikayı aşıyorsa, durup agent pool tarafına tekrar bakmak lazım; bazen sorun kodda değil, sırada bekleyen iş yükünde oluyor.
- Sonuçları gözden geçir: False positive oranı yüksekse, CodeQL query pack’leri tarafında konuşacak bir şeyler vardır (evet, o konu ayrı bir yazı ister). (bence en önemlisi)
- Project seviyesine çık: Pilot iyi gittiyse projeye yayabilirsiniz. Acele etmeyin ama fazla da oyalanmayın. — ciddi fark yaratıyor
- Organization seviyesine çık: En son buraya gelin. Ve önce self-hosted agent pool’unu kapasite olarak büyütün; yoksa Pipelines kuyruk yapar, sonra herkes birbirine bakar.
- Campaign kur: İlk campaign’iniz şu olsun: “Critical + High severity, last 30 days”. Bu sizin savaş panonuz olur; hani sabah açıp “bugün neye saldırıyoruz?” diye baktığınız ekran var ya, işte o.
Bir de şunu ekleyeyim. Default setup’ı açınca otomatik scheduling varsayılan olarak haftalık geliyor. Açık konuşayım, finans sektöründeki müşterilerimde bu çoğu zaman yetmiyor; günlük tarama istiyoruz. Organization ayarlarından schedule’ı değiştirebiliyorsunuz — bunu atlamayın (evet, doğru duydunuz)
Bir dakika — bununla bitmedi.
Tamam mı? İyi gibi görünse de küçük bir detay kaçarsa sonra uğraştırıyor.
Startup vs Enterprise: farklı stratejiler
Küçük ekipseniz (5-15 developer, 10 altı repo), repository seviyesinde tek tek açın. Custom YAML pipeline’lar kurup zaman kaybetmeyin; bazen sade yol daha az baş ağrıtır, hatta bütçe dardı ise CodeQL yerine Semgrep OSS gibi daha hafif alternatiflere bakmak da mantıklı olabilir.
Bakın, Büyük kurumsalsanız (100+ repo, regülasyona tabi sektör), hikaye değişiyor biraz. Organization seviyesinde açın, self-hosted pool kurun, security campaign’leri tanımlayın ve haftalık triage toplantısı düzenleyin; bunları kullanmıyorsanız GHAzDO lisans parasına yazık ediyorsunuz demektir (açık söyleyeyim). Bu konuyla ilgili Ingress’ten Gateway API’ye Geçiş: 1.0 Rehberi yazımıza da göz atmanızı tavsiye ederim.
Neyse uzatmayalım. Küçük ekipte hız önemli, büyük yapıda ise disiplin (ciddiyim). Merkezi kontrol daha çok iş görüyor; ikisini aynı kefeye koyunca sonuç biraz yamuk çıkabiliyor (bizzat test ettim)
Peki siz hangisine yakınsınız? VS Live! Las Vegas 2026: İzlemeye Değer 20 Oturum yazımızda bu konuya da değinmiştik.
Dikkat edilecek noktalar ve eksikler
İtiraf edeyim, Her şey toz pembe değil. Public preview olunca iş biraz kırpılıyor, yani bazı sınırlar var (buna dikkat edin). Bunu baştan bilmek iyi oluyor; yoksa insan bir anda “neden çalışmadı bu?” diye kalıyor, ben de ilk bakışta öyle düşündüm açıkçası.
- Custom CodeQL query pack’leri: Default setup ile kendi custom query’lerinizi şu an koşturamıyorsunuz. Bunun için hâlâ advanced setup (YAML) gerekiyor, biraz uğraştırıyor ama durum bu.
- Monorepo desteği: Birden fazla dilin iç içe geçtiği büyük monorepo’larda dil algılama bazen şaşıyor. Bir
.NET + Python + JSkarışık repo’da bende sadece C# taradı, Python ve JS’i atladı; garip geldi ama oldu işte, ticket açtım, bakıyorlar. - Build gerektiren diller: C++, C#, Java gibi compile edilmesi gereken dillerde bazen build step otomatik çözülemiyor. O noktada manuel YAML’a geri dönmek zorunda kalıyorsunuz, pek hoş değil ama pratikte böyle.
- Combined alerts view’da henüz assignment yok: “Bu alert’i şu developer’a ata” diyemiyorsunuz. Şimdilik sadece filtreleyebiliyorsunuz; küçük bir eksik gibi duruyor ama ekip büyüyünce can sıkabiliyor. (bu kritik)
Size bir şey söyleyeyim, Neyse, çok dağıtmayayım. İlgili konularda daha önce yazdığım şu yazılara da göz atabilirsiniz: GitHub Status Sayfası Yenilendi: Şeffaflık Dönemi Başladı ve Azure MCP Visual Studio 2022’de: Eklenti Devri Bitti. İkisi de DevOps ekosistemindeki değişim rüzgarını anlatıyor; biri görünürlük tarafına dokunuyor, diğeri de araçların nasıl el değiştirdiğine. Azure Smart Tier GA: Blob Depolamada Otomatik Tasarruf yazımızda bu konuya da değinmiştik.
Bir örnek akış: 24 saat içinde org-wide tarama
Yeni başlayanlara pratik olsun diye, tipik bir deployment plan’ı paylaşayım. Aşağıdaki REST API örneği, otomasyon yapmak isteyenler için baya iş görüyor,. Şey, ilk bakışta biraz dağınık durabiliyor:
# Organization seviyesinde CodeQL default setup durumunu kontrol et
curl -X GET \
"https://advsec.dev.azure.com/{org}/_apis/AdvancedSecurity/CodeQLDefaultSetup?api-version=7.2-preview.1" \
-H "Authorization: Bearer $PAT"
# Belirli bir repo'da enable et
curl -X PATCH \
"https://advsec.dev.azure.com/{org}/{project}/_apis/AdvancedSecurity/repositories/{repoId}/CodeQLDefaultSetup?api-version=7.2-preview.1" \
-H "Authorization: Bearer $PAT" \
-H "Content-Type: application/json" \
-d '{ "state": "configured", "schedule": "weekly" }'
Burada önce org seviyesindeki durumu çekiyorsunuz, sonra da tek tek repo bazında açıyorsunuz; yani işin mantığı aslında sade, ama dikkat edin, her ortamda aynı davranmıyor olabilir (özellikle yetki modeli ve pipeline düzeni farklıysa), o yüzden ben bunu önce küçük bir pilotta denemeyi daha güvenli buluyorum.
Bu API’leri kullanarak kendi dashboard’unuzu da kurabilirsiniz. Policy-as-code yaklaşımıyla her yeni repo’da otomatik enable edebilirsiniz. Ben bir müşteride Terraform modülüne gömdüm bunu, repo provisioning sırasında otomatik açılıyor.
Evet.
Vallahi, İşin güzel tarafı burada çıkıyor. Bir yerde elle tıklayıp unutma derdi azalıyor, diğer tarafta da standart bozulmuyor; ama dur bir saniye — eğer organizasyonda exception listesi çok kabarıksa, otomasyonun faydası biraz törpüleniyor, onu da dürüstçe söyleyeyim.
İtiraf edeyim, Peki neden? Çünkü aynı akışı tekrar tekrar uygulamak yerine, setup’ı kodla yönetince hem iz bırakıyorsunuz hem de geri almak daha kolay oluyor; ben açık konuşayım, bu tarz küçük görünen işler sonradan büyük kafa ağrısını kesiyor.
Sıkça Sorulan Sorular
CodeQL default setup ücretsiz mi?
Araya gireyim: Özelliğin kendisi için ekstra bir ücret yok aslında, ama Advanced Security (GHAzDO) lisansınız olması şart. Bu lisans aktif committer başına aylık olarak ücretlendiriliyor. Bir de taramalar Azure Pipelines üzerinde koştuğu için agent dakikalarınızı yiyor — self-hosted pool kullanırsanız bu sorun ortadan kalkıyor zaten.
Mevcut YAML pipeline’ımı silmem gerekiyor mu?
Tuhaf ama, Hayır, gerekmiyor. Ama şunu söyleyeyim: aynı repo’da hem default setup hem de eski manuel CodeQL pipeline’ınız çalışırsa aynı alert’leri iki kere görürsünüz, hani gereksiz gürültü oluyor. Bence en temiz yol şu — önce default setup’a geçin, sonra eski pipeline’daki CodeQL step’lerini kaldırın, sadece build veya test step’lerinizi bırakın.
Hangi diller destekleniyor?
Bakın, Şu an C/C++, C#, Go, Java/Kotlin, JavaScript/TypeScript, Python, Ruby ve Swift var. Liste aslında GitHub tarafındaki CodeQL desteğiyle paralel gidiyor,. GitHub’da yeni bir dile destek geldikçe Azure DevOps’a da yansıyor.
Combined alerts view’da private repo alert’leri güvende mi?
Evet, güvende. Security Overview sayfası sadece Project Collection Administrator veya Advanced Security Administrator rolündeki kişilere görünüyor. Alert detayları da repo permission’larına göre filtreleniyor — açıkçası yetkisi olmayan biri hiçbir şey göremez, oldukça düzgün bir izolasyon var bence.
Self-hosted agent kullanmak zorunda mıyım?
Zorunlu değil, Microsoft-hosted agent’lar varsayılan olarak çalışıyor. Ama tecrübeme göre büyük C++ veya Java projelerinde tarama süresi 60 dakikayı rahatça geçebiliyor. O noktada Microsoft-hosted timeout’a takılıyorsunuz. Yani 500+ MB’lık repo’larınız varsa self-hosted pool kurmayı düşünün, açıkçası uzun vadede çok daha az baş ağrısı yaşarsınız.
Hmm, bunu nasıl anlatsamdı…
Kaynaklar ve İleri Okuma
Microsoft DevBlogs: One-click security scanning and org-wide alert triage — Orijinal duyuru yazısı.
Azure DevOps Docs: CodeQL Default Setup — Resmi dokümantasyon, adım adım kurulum.
GitHub Advanced Security for Azure DevOps Genel Bakış — Lisans modeli, fiyatlandırma. Özellik karşılaştırması için başlangıç noktası.
CodeQL Resmi Dokümantasyonu — Custom query yazmak isteyenler için.
Bu içerik işinize yaradı mı?
Benzer içerikleri kaçırmamak için beni sosyal medyada takip edin.



