Bir Cosmos DB hesabı açtınız. Portal size iki tane key ve bir connection string verdi. Uygulama da çalıştı. Sonra ne oldu? Büyük ihtimalle o connection string’i bir appsettings.Development.json dosyasına yapıştırdınız, “production’da düzeltirim” dediniz, iş bitti.
Tanıdık geldi mi? Bana da geldi. Hatta bir keresinde, finans tarafında orta ölçekli bir fintech müşterimde tam bu senaryoyu yaşadık; üç yıl önce yazılmış bir mikroservis hâlâ primary key ile Cosmos’a bağlanıyordu, key rotation işe hiç yapılmamıştı,. Hangi servisin o key’i kullandığını kimse net bilmiyordu.
İşte bu yazı bunun için. Yeni bir Cosmos DB projesine başlıyorsanız, ilk gün almanız gereken güvenlik kararlarını konuşalım. Enterprise karmaşasına dalmadan ama “sonra düzeltirim” tuzağına da düşmeden.
Önce dürüst bir tehdit modeli yapalım
Açık konuşayım: gerçek hayatta Cosmos DB hesaplarına yapılan saldırılar film sahnesi gibi olmuyor. Hani sıfırıncı gün açıkları, devlet destekli APT grupları falan… öyle şeyler nadir. Olan şu:
- Bir geliştirici
.envdosyasını yanlışlıkla public repo’ya pushluyor. Connection string orada duruyor. Bot 12 dakika içinde buluyor. - Uygulamaya gereğinden fazla yetki veriliyor. Read-only olması gereken analytics servisi, yanlışlıkla DELETE de yapabiliyor.
- Cosmos DB endpoint’i tüm internete açık bırakılıyor. Bir credential sızarsa, saldırgan ile veriniz arasında pek bir şey kalmıyor.
- Client’tan gelen JSON körü körüne kabul ediliyor. 5 MB’lık dokümanlar, sınırsız query’ler… sonra performans niye düştü diye bakılıyor.
- Diagnostic log kapalı oluyor. Olay yaşanınca “kim, ne zaman, neyi okudu?” sorusuna cevap yok. Tahmin yürütüyorsunuz.
Yani işin aslı şu: pahalı bir güvenlik aracı almadan da çok şey yapılır. Basit hataları yapmamak çoğu zaman yeterli oluyor — ama bunun için ilk günden doğru karar vermek gerekiyor.
“Production’da düzeltirim” diye başlayan her config, çoğu zaman production’a aynen gidiyor. Bunu kariyerimde defalarca gördüm — maalesef ben de yaptım.
Anahtarlar mı, Entra ID mi? İşte can alıcı nokta burada
Cosmos DB hesabı oluşturduğunuzda size dört key veriyor: primary, secondary, read-only primary ve read-only secondary. Bunlar hemen çalışıyor, her tutorial’da var, o yüzden insanlar doğal olarak bunlara sarılıyor. Sorun da tam burada başlıyor.
Key’lerin asıl sıkıntısı: Kim kullandı?
Key’ler aslında birer bearer token. Kim eline geçirirse yetki onun oluyor. Diagnostic logging açıksa IP adresi ya da user agent gibi şeyleri görebilirsiniz ama “Ahmet mi yaptı, Mehmet mi?” sorusunun cevabı çıkmıyor; çünkü key paylaşılıyor ve beş servis aynı key’i kullanıyorsa hangisinin yaptığı belli olmuyor.
Bir de key sızınca ne oluyor? Tek çare regenerate etmek. Sonra o key’i kullanan her sistemi tek tek güncelleyeceksiniz. Geçen sene bir telekom projesinde bunu yaşadık; toplam 23 servis bağımlıydı ve 4 tanesini unutmuşuz, prod’da yarım gün kesinti yedik (evet, doğru duydunuz). Hiç hoş değildi.
Peki Entra ID neden daha mantıklı?
Entra ID (eski adıyla Azure AD) ile uygulamanız bir kimlik kazanıyor — managed identity veya service principal gibi düşünün. O kimliğe sadece gereken yetkileri veriyorsunuz. Sızıntı olursa? Kimliği devre dışı bırakıyorsunuz; başka hiçbir sistemi update etmeniz gerekmiyor ve audit log’da kim ne yaptı net görünüyor.
Tavsiyem: Daha development ortamında bile Entra ID ile başlayın. Setup sandığınız kadar zor değil; üstüne bir sürü dertten kurtarıyor sızı.
//.NET ile Entra ID kullanımı — bu kadar basit
using Azure.Identity;
using Microsoft.Azure.Cosmos;
var credential = new DefaultAzureCredential();
var cosmosClient = new CosmosClient(
accountEndpoint: "https://your-account.documents.azure.com:443/",
tokenCredential: credential
);
// Connection string yok. Key yok. Sızıntı riski azalıyor.
Local development’ta DefaultAzureCredential, Azure CLI ya da Visual Studio login’ınızı kullanıyor; production’da işe managed identity devreye giriyor. Tek satır kod gibi duruyor ama arkada işi bayağı toparlıyor.
Yetkilendirme: Uygulamanız tam olarak ne yapabilmeli?
Cosmos DB’de iki farklı erişim katmanı var ve bunları karıştırmak çok yaygın bir hata:
| Katman | Neyi kontrol ediyor? | Nasıl yönetiliyor? |
|---|---|---|
| Control plane | Hesap/database/container oluşturma, silme ve ayar değiştirme | Azure RBAC (IAM üzerinden) |
| Data plane | Doküman okuma, yazma ve query çalıştırma | Cosmos DB veri rolleri |
Sizin uygulamanızın data plane’e ihtiyacı var. Control plane’e değil. Ama insanlar genelde “Cosmos DB Contributor” rolü verip geçiyor — bu ciddi risk yaratabiliyor çünkü o rol container silebilir, throughput’u sıfırlayabilir, başka şeyler de yapabilir. Uygulama niye bunları yapsın ki?
Builtin data rolü var; çoğu zaman biri yeterli oluyor
- Cosmos DB Built-in Data Reader: Sadece okuma yapar. Analytics ve reporting servisleri için uygun.
- Cosmos DB Built-in Data Contributor: Okuma + yazma yapar. Asıl uygulama servisi için kullanılır.
Biri e-ticaret projesinde şöyle ayırmıştık: sipariş alma servisi Data Contributor kullanıyordu, raporlama dashboard’u Data Reader ile çalışıyordu, admin paneli işe Control Plane Contributor almıştı ama sadece spesifik admin kullanıcıları için. Üç ayrı identity, üç ayrı yetki… Saldırgan reporting servisine sızsa bile veriyi değiştiremiyordu; işte blast radius dediğimiz şey biraz bu.
Ve işler burada ilginçleşiyor.
Ağ erişimi: Internet’e açık bırakmayın, lütfen
Kosmos DB endpoint’ınız varsayılan olarak tüm internete açık geliyor mu? Evet geliyor gibi düşünebilirsiniz; endpoint URL’sını bilen herkes deneme yapabiliyor (inanın bana). Key ya da token olmadan zaten çok ileri gidemez ama credential leak olursa tek savunma hattınız o key kalıyor — bu da pek rahatlatıcı değil.
Peki hangi seçenek size uyuyor?
1. IP firewall: En basit yöntem bu. Belirli IP aralıklarından erişim açarsınız; küçük ekipseniz veya Azure dışında host edilen bir backend’ınız varsa mantıklı başlangıç ölür. Bu konuyla ilgili AKS Fleet Manager Cross-Cluster Networking: Saha Notları yazımıza da göz atmanızı tavsiye ederim.
Açıkçası, 2. VNet service endpoint: Azure içinde VNet’ınız varsa Cosmos DB’ye sadece o VNet’ten erişim açarsınız. Trafik Microsoft backbone üzerinden akar; internet tarafına çıkmazsınız (ben de ilk duyduğumda şaşırmıştım) Bu konuyla ilgili Kubernetes CVE Kayıtları Düzeltiliyor: Sahadan Notlar yazımıza da göz atmanızı tavsiye ederim.
3. Private endpoint: En sıkı çözüm bu diyebilirim. Cosmos DB hesabınız VNet’inizin içinde özel IP alır ve public endpoint’i tamamen kapatabilirsiniz; enterprise projelerde biz bunu standart sayıyoruz artık.
Peki loglama? Olay olmadan açmazsanız geç kalırsınız
Açıkçası, Burası kritik ama çoğu ekip atlıyor işte burayı. Diagnostic logging açık değilse güvenlik olayı yaşandığında elinizde kanıt kalmıyor; “sanırım şu olmuş”, “muhtemelen bu olmuş” diye konuşuyorsunuz adeta adlı analiz yerine tahmin oyunu oynanıyor. Entra External ID Native Auth: Apple Watch RT Transferi GA yazımızda bu konuya da değinmiştik.
Açmanız gereken Cosmos DB log kategorileri şunlar: Bu konuyla ilgili Visual Studio Mayıs Güncellemesi: Plan, İncele, İyileştir yazımıza da göz atmanızı tavsiye ederim. GitHub Copilot’u.NET’te Verimli Kullanma Rehberi yazımızda bu konuya da değinmiştik.
- User request logs / DataPlaneRequests: Her okuma-yazma operasyonu burada görünür; hangi IP’den gelmiş, hangi identity kullanılmış, ne zaman olmuş hepsi çıkar.
- QueryRuntimeStatistics:: Çalıştırılan query’leri gösterir; performans tarafında da işe yarar hani.
- :ControlPlaneRequests:: Ayar değişikliklerini yakalar; biri throughput’u 100K RU’ya çektiyse burada görünür.
Oops!
Sıkça Sorulan Sorular
Cosmos DB key authentication’ı tamamen kapatabiliyor muyum?
Doğrusu, Evet, “disableLocalAuth” özelliğiyle key authentication’ı tamamen devre dışı bırakabiliyorsun. Bu durumda yalnızca Entra ID üzerinden bağlantı kabul ediliyor. Açıkçası production hesapları için neredeyse kesinlikle öneriyorum. Ama önce mevcut bağlantılarının Entra ID’ye geçtiğinden emin ol — yoksa servislerinin çökeceğini söylemek zorundayım (evet, doğru duydunuz)
Managed identity ile bağlantı local development’ta da çalışıyor mu?
Çalışıyor. DefaultAzureCredential, hani Azure CLI’dan (az login), Visual Studio ya da VS Code’dan login bilgilerini otomatik alıyor (buna dikkat edin). Yani local’de kendi kullanıcınla, prod’da managed identity ile bağlanıyorsun — kod aynı kalıyor, bu kısmı gerçekten şık. Tek koşul şu: kendi kullanıcına da geliştirme ortamı için ilgili Cosmos rolünü vermen gerekiyor.
Private endpoint kullanırsam maliyet ne kadar artıyor?
Aslında, Private endpoint’in kendisi saatlik ücretlendiriliyor. Ay sonunda aşağı yukarı 7-8 USD civarında bir ek fatura görüyorsun, endpoint başına. Bir de veri transfer ücreti var, ama VNet içi trafik ücretsiz. Bence küçük ölçekli bir uygulamada görmezden gelinebilecek bir maliyet — karşılığında aldığın güvenlik kazancı düşünülünce aslında oldukça makul.
Birden fazla servisim aynı Cosmos hesabına erişiyor, hepsine ayrı identity mi vereyim?
Şöyle ki, Evet, kesinlikle ayrı ver. Her servis kendi managed identity’sine sahip olmalı. Tecrübeme göre bunun üç somut faydası var: bir servis ele geçirildiğinde diğerleri etkilenmiyor, log’larda hangi servisin ne yaptığı net görünüyor. Yetkileri servis bazında ince ayar yapabiliyorsun. Tek bir “shared identity” kullanmak, yani mesela herkese aynı kimliği vermek, klasik bir anti-pattern.
Diagnostic log’ları ne kadar süre saklamalıyım?
Sektörüne ve regülasyonlarına bağlı değişiyor. KVKK kapsamında kişisel veri işleyen sistemler için en az 2 yıl tavsiye ediliyor. Finans tarafında, yani BDDK için, bu süre 10 yıla kadar çıkabiliyor. Log Analytics’te 30 günlük retention ücretsiz, sonrası ek ücretli. Eski log’ları daha ucuz storage’a, mesela Archive tier’a, taşıyabilirsin — açıkçası bu yolu kullanmalarını öneririm.
Evet, doğru duydunuz.
Kaynaklar ve İleri Okuma
Araya gireyim: Azure Cosmos DB için RBAC Kurulumu — Microsoft Learn
Cosmos DB Private Endpoint Konfigürasyonu
Ne yalan söyleyeyim, Orijinal Yazı: Cosmos DB Security for New Apps — DevBlogs
Cosmos DB Güvenlik Genel Bakış
Bu içerik işinize yaradı mı?
Benzer içerikleri kaçırmamak için beni sosyal medyada takip edin.



