Mert Tosun
← Yazılar
PostgreSQL Row Level Security ile Çoklu Kiracılı SaaS Güvenliği

PostgreSQL Row Level Security ile Çoklu Kiracılı SaaS Güvenliği

Blog YazarıVeritabanı

SaaS ürünleri büyüdükçe çoklu kiracılı (multi-tenant) mimaride veri izolasyonu en kritik risk alanlarından biri haline gelir. Uygulama katmanındaki yetkilendirme kontrolleri tek başına yeterli değildir. Bir endpoint'te unutulan tek bir tenant_id filtresi, başka bir müşterinin verisinin sızmasına yol açabilir. PostgreSQL Row Level Security (RLS), bu riski azaltmak için veritabanı seviyesinde güçlü bir güvenlik katmanı sunar.

RLS yaklaşımında tabloya bağlı politikalar tanımlanır ve PostgreSQL her sorguya bu kuralları otomatik uygular. Böylece geliştiricinin her yerde WHERE tenant_id = ... yazmasına güvenmek yerine izolasyonu veritabanının varsayılan davranışı haline getirirsiniz. Özellikle hızlı gelişen ürünlerde bu yaklaşım hem güvenlik hem de denetlenebilirlik açısından ciddi avantaj sağlar.

RLS neden üretimde kritik?

Gerçek üretim sistemlerinde kod tabanı sürekli değişir. Yeni endpoint'ler eklenir, arka plan işleri yazılır, veri raporları hızla devreye alınır. Bu tempoda manuel tenant filtreleri zamanla tutarsızlaşır. Güvenli sistem tasarımında amaç "hata olursa kapalı kal" prensibidir ve RLS tam olarak bunu sağlar.

RLS olmayan yapılarda sık görülen riskler:

  • İç yönetim endpoint'lerinde tenant filtresinin atlanması.
  • Batch job kodunda geniş sorguların yanlış kapsamda çalışması.
  • Analitik join'lerinde tenant sınırının yanlış kurulması.
  • Refactor sonrası yeni repository metodlarında yetki kontrolünün unutulması.

RLS etkin ve zorunlu (force) olduğunda bu hatalar sorgu anında engellenir.

Uygulama modeli

Pratikte yaygın model, PostgreSQL oturumunda app.current_tenant_id gibi bir context değeri tutmaktır. Uygulama her istek başlangıcında bu değeri set eder, RLS politikası da satırdaki tenant_id ile bu context'i karşılaştırır. Bu sayede SQL ergonomisi korunur, izolasyon kuralları merkezi hale gelir.

Temel adımlar:

  • Tenant kapsamındaki tüm tablolarda tenant_id alanı bulundurmak.
  • Erişim desenine uygun bileşik index tasarlamak.
  • ALTER TABLE ... ENABLE ROW LEVEL SECURITY ile RLS'i açmak.
  • ALTER TABLE ... FORCE ROW LEVEL SECURITY ile owner bypass'ını kapatmak.
  • Okuma ve yazma için ayrı USING ve WITH CHECK politikaları tanımlamak.

WITH CHECK kuralı ihmal edilmemelidir; aksi halde kullanıcı başka tenant'a veri yazabilir.

Rol tasarımı ve bypass disiplini

Uygulama trafiği asla superuser veya bypass yetkili rol ile çalışmamalıdır. Standart trafik için minimum yetkili bir rol, operasyonel acil durumlar için ise ayrı ve denetlenebilir yetkili roller kullanılmalıdır.

Örnek model:

  • app_user: Sıkı RLS, bypass yok.
  • support_readonly: Maskeleme uygulanmış, sadece okuma.
  • ops_admin: Kırılma anı (break-glass) prosedürlerinde, audit zorunlu.

Bu ayrım hem güvenliği güçlendirir hem de operasyon ekibine kontrollü esneklik sağlar.

Performans etkisi ve optimizasyon

RLS'in performansı düşüreceği sıkça düşünülür; doğru şema ve index tasarımıyla etkisi çoğu sistemde kabul edilebilir seviyededir. Tenant erişim desenine uygun index'ler (tenant_id, created_at gibi) sorgu planlarının verimli kalmasını sağlar.

Burada önemli olan gerçekçi veri dağılımıyla test yapmaktır. Büyük tenant'lar cache davranışını ve plan seçimini etkileyebilir. EXPLAIN (ANALYZE, BUFFERS) çıktılarıyla RLS açık/kapalı karşılaştırması yapıp darboğazları ölçerek ilerlemek gerekir.

Mevcut sisteme geçiş stratejisi

Canlı sisteme RLS eklerken kademeli ilerleme en güvenli yoldur:

  1. Tenant kapsamındaki tabloların envanterini çıkar.
  2. Eksik tenant_id alanlarını ekle ve güvenli backfill yap.
  3. Constraint ve index düzenlemelerini tamamla.
  4. Politikaları önce pre-prod ortamında doğrula.
  5. RLS'i tablo tablo aktif et ve force uygula.
  6. İzolasyon testleri ve negatif sızıntı testleri çalıştır.

Negatif testler kritik önemdedir: farklı tenant verisi sorgulandığında sıfır satır dönmeli, cross-tenant insert/update denemeleri reddedilmelidir.

Operasyonel görünürlük

Güvenlik kontrolleri izlenmediğinde zamanla etkisini kaybeder. Bu nedenle rol kullanımını, tenant context set edilemeyen istekleri ve politika ihlali hatalarını ölçmek gerekir. Servis ve route bazlı "denied query" metrikleri, hem kötüye kullanım girişimlerini hem de uygulama hatalarını erken yakalamada çok etkilidir.

Ayrıca net bir runbook şarttır: yetkili erişim ne zaman açılır, kim onaylar, hangi log tutulur, nasıl geri alınır. Kriz anında belirsizlik, güvenlikten daha hızlı zarar üretir.

RLS tek başına tüm güvenlik problemlerini çözmez; ancak paylaşımlı veritabanı kullanan SaaS mimarilerinde en güçlü koruma katmanlarından biridir. Tenant izolasyonunu geliştirici dikkatinden bağımsız hale getirerek hem müşteri güvenini hem de ürün ölçeklenebilirliğini korursunuz.