PRODEgemen Avrupa BaaS platformuKontrol Panelini Aç →

Mühendislik · 10 dk. okuma

RLS ve proje başına özel bir veritabanı karşılaştırması

Affane Daylami · Fondateur · 27 Temmuz 2026

Bloga geri dön

"RLS multi-tenant postgres" diye arama yaptığınızda neredeyse her yerde aynı şemayla karşılaşırsınız: paylaşılan bir veritabanı, tenant_idcolumn, satırları filtreleyen bir politika. Aurabase'in projelerini birbirinden izole etmek için kullandığı model bu değil. Her proje kendi Postgres 16 veritabanını alır ve hiçbir zaman başka bir müşteriyle paylaşılmaz; RLS orada kalır, ancak başka bir katta: veritabanınızda, kendi kullanıcılarınız için.

Bu İngilizce metin, Fransızca orijinalinden otomatik olarak oluşturulmuştur ve henüz incelenmemiştir.
Bu sayfa otomatik olarak çevrildi. İngilizce versiyonu yetkilidir.

"RLS" ve "çok kiracılı", konuyla ilgili halihazırda yayınlanmış içeriğin neredeyse tamamında yan yana bulunuyor; birçok SaaS mimarisi için meşru bir seçim, ancak bu, Aurabase'in kendi müşterilerini birbirinden ayırma tercihi değil. Bu gönderide, basitleştirilmiş bir pazarlama açıklaması değil, gerçek provizyon motoru ile gerçekte uygulanan RLS politikaları arasındaki fark açıklanmaktadır. Aurabase'in Yönetilen Postgres motorunun izolasyonun ötesinde neler kapsadığına ilişkin genel bir bakış için veritabanıbelgelerine bakın.

Temeller

  • Aurabase, projeler arasında özel Postgres tabanıyla izolasyon yapar, asla tek başına RLS tarafından değil; her projenin kendi fiziksel tabanı vardır, özel bir CNPG kümesinde (şirket düzeyinde) veya kendi kuruluşunun CNPG kümesinde (ücretsiz/profesyonel/ekip) asla başka bir kuruluşla paylaşılmaz.
  • RLS (auth.uid(), auth.role(), auth.jwt()) aktif kalır ve kendi kullanıcılarınızı izole etmek için tabanınızda önerilir; Supabase ile aynı kural.
  • service_role ve proje tabanlı yönetim rolleri, tasarım gereği RLS'yi atlar (BYPASSRLS): sunucu işlemleri için varsayılan bir mimari tercihtir, bir kusur değildir.
  • Bu depoda zaten düzeltilmiş olan bir gerileme - eski paylaşılan şemalarda yanlışlıkla verilen PUBLIC hakları - temel düzeydeki bir sınırın neden salt uygulama sınırından daha iyi direnç gösterdiğini somut olarak göstermektedir.
#
Varsayılan model

Çok kiracılı RLS kılavuzlarının çoğunun kullandığı kısayol

Çok kiracılı Postgres için en çok belgelenen model üç satırdan oluşur: tek bir taban, her tabloda bir tenant_id sütunu, bu sütunu JWT'den çıkarılan bir değerle karşılaştıran bir RLS politikası. Ekonomiktir (bir bağlantı havuzu, bir diyagram, çalıştırılacak tek bir örnek) ve kiracılar çok sayıda, küçük ve bireysel riskin düşük olduğu durumlarda iyi çalışır.

Uzlaşma gerçektir: iki istemci arasındaki sınır, tablo tablo değerlendirilen bir SQL ifadesi haline gelir. Yeni bir tabloda unutulan bir politika, süper kullanıcı rolüyle çalışan bir bağlantı, canlı olarak başlatılan bir hata ayıklama komut dosyası; bu olayların her biri, operasyonda ne kadar önemsiz olursa olsun, tüm kiracıların hatlarını aynı anda sessizce açığa çıkarabilir. O halde güvenlik sınırı ve teknik sınır (temel) tamamen aynı şeydir.

Bilgi

Bu kendi başına kötü bir seçim değil; birçok ürün için doğru bir uzlaşmadır. Bu yazının amacı başka bir yerde: Bu, Aurabase'in kendi müşterilerini (potansiyel olarak farklı uyumluluk gereksinimlerine sahip tüm projeler) birbirinden ayırmak için yaptığı bir uzlaşma değildir.

#
Kodda

İki mimari, asla projeler arasında paylaşılmayan bir temel

Provizyonun yakın zamanda birleştirilmesinden bu yana (kodda "Görev 12" olarak işaretlenmiştir), Aurabase'deki aktif bir Postgres projesi tam olarak iki mimarinin kapsamına girmektedir - aslında birkaç proje arasında paylaşılan bir tabanı olan eski modeller, provizyon yolundan kaldırılmıştır.

provisioning/instances.rsrust
pub enum ProjectInstanceKind {
    /// YALNIZCA BU projeye ayrılmış CNPG kümesi (şirket düzeyinde).
    FullyDedicated,

    /// ORGANİZASYON projesinin CNPG kümesine ilişkin veritabanı —
    /// AYNI kuruluşun DİĞER projeleriyle paylaşıldı,
    /// asla üçüncü taraf bir kuruluşla.
    SharedClusterDedicated,
}

İkisinden hangisinin geçerli olduğuna proje düzeyi karar verir ve bunu kontrol panelinde işaretlenen kutu değil, kod belirler:

provisioning/rules.rsrust
fn should_provision_dedicated(engine: &str, db_url_encrypted: &Option<String>, plan: &str) -> bool {
    matches!(engine, "postgres" | "postgresql")
        && plan == "enterprise"
        && !non_empty(db_url_encrypted)
}

// Should_route_to_fleet(): şirket dışı herhangi bir katman (ücretsiz/profesyonel/ekip)
// KENDİ organizasyonunuzun CNPG kümesine giden rota, asla o değil
// diğerinden — bkz. geçiş 073, 2 mimariye birleştirme.
BoyutlarTamamen Özel (şirket)SharedClusterDedicated (ücretsiz/profesyonel/ekip)
CNPG kümesiBu tek projeye adanmışPaylaşılır ancak asla iki kuruluş arasında paylaşılmaz
Postgres veritabanıuygulama, yalnızca proje üzerindeproject_<uuid>, kümedeki proje başına bir tane
PostgreSQL GirişiKümede tek bir proje: çapraz üyelik riski yokProje başına oturum açma (F-013), tek rollerinin üyesi kiracı_<uuid>

Her iki mimaride de taban veya küme hiçbir zaman iki farklı kuruluşa ev sahipliği yapmaz; dolayısıyla soru "verileriniz izole edilmiş mi" değil, "projeniz CloudNativePG hesaplamasına sahip mi, yoksa bunu aynı kuruluştaki diğer projelerle paylaşıyor mu?"

İki mimarinin bu şekilde birleştirilmesi yakın zamanda gerçekleşti: kod daha önce iki ek yol taşıyordu; birkaç projenin aynı veritabanında bir arada bulunduğu, yalnızca diyagramla izole edilmiş bir "paylaşılan ana" ve bir postgrest_dedicated_shared_dbçeşidi. Özel bir geçiş, bunları kaldırdı ve projects tablosunun kısıtlamasını yalnızca kalan iki değerle sıkılaştırdı; çünkü tam olarak paylaşılan şema modeli, aşağıda açıklanan hatanın kaynağıydı.

#
Güvenlik sınırı

Özel bir taban neden müşteriler arasında paylaşılan bir EPIRB'den daha üstün?

Ayrı bir Postgres veritabanı, satır düzeyinde bir sınır değil, bağlantı düzeyinde bir sınırdır. A projesinin veritabanına bağlı bir uygulama rolü, B projesinin tablolarını sorgulayamaz; kendisine açık bir oturumu yoktur. Bu özellik, bir RLS politikası kötü yazılmış olsa, bir tabloda eksik olsa veya yüksek bir rol tarafından atlansa bile geçerlidir: en kötü durum, tek bir veritabanında sınırlı kalır.

Bu mevduat aynı zamanda tam tersi riski gösteren gerçek bir hatanın izini de taşıyor. Eski paylaşılan şema modelinde (geri çekildikten sonra), provision_postgres_schema yanlışlıkla her proje şemasına GRANT ALL ... TO PUBLIC hakları verdi - üyelik koşulları olmadan veritabanındaki tüm rollere uygulanan PUBLIC, proje başına yalıtılmış bir oturum açma işlemi, diğerinin şemasını okuyabilir ve yazabilir. Düzeltici bir geçiş (066), bu hakları mevcut haklardan kaldırdı.

Öğrenilen ders

Yama, sızıntıyı gidermek için bir RLS politikası daha eklemedi; iki projenin bir veritabanını paylaşma olasılığını ortadan kaldırdı. Mevcut iki mimariye ilişkin provisioning.rs'den gelen bir yorum bunu siyah beyaz olarak belgeliyor: "her projenin zaten kendi fiziksel Postgres veritabanı var". Temel düzeyde bir sınır, her politikanın her zaman doğru yazılmasına güvenmek yerine, bu tür hataların bulunduğu sınıfın tamamını erişilemez hale getirir.

23 Ağustos 2026 tarihli bir yama da aynı yönde ilerliyor: Provizyon sağlayıcı tarafından koşulsuz olarak yerleştirilen bir REVOKE ALL ON SCHEMA public topolojiye bağlı hale getirildi, çünkü yalnızca eski paylaşılan veritabanı modelinde gerçek izolasyon sağladı; mevcut iki mimaride, açıkça public.<table>referansına sahip SQL dökümlerinin içe aktarılmasını hiçbir fayda sağlamadan engelledi.

#
Uygulamada RLS

EPIRB, kullanıcılarınız için veritabanınızda orada kalır

Yukarıdakilerin hiçbiri EPIRB'i işe yaramaz hale getirmez; yalnızca katları değiştirir. proje veritabanınıza girdikten sonra Aurabase, Supabasetarafından alınan PostgREST kuralını tam olarak ortaya çıkarır: request.jwt.claimsiçindeki ağ geçidi tarafından ayarlanan JWT taleplerini okuyan üç SQL işlevi.

libs/aura-migrations/golden/auth_global.sqlsql
create function auth.uid() returns uuid
    language sql stable security definer
    set search_path to 'pg_catalog', 'pg_temp'
    as $$
    select nullif(nullif(current_setting('request.jwt.claims', true), '')::json->>'sub', '')::uuid
$$;

Bu yardımcılar, yalnızca sizin için belgelenmiş değil, Aurabase'in gerçek politikalarında da kullanılır. storage_objectsdeposuna yerleştirildiği şekliyle (okunması için birkaç satırda yeniden biçimlendirilmiş) koruyan politika aşağıdadır:

libs/aura-migrations/golden/storage.sqlsql
alter table storage_objects enable row level security;

create policy storage_objects_select on storage_objects
  for select using (
    (owner_id = auth.uid())
    or (
      exists (
        select 1 from storage_buckets b
        where (b.name = storage_objects.bucket_name and b.public)
      )
    )
  );

Uygulama tablolarınızı taşıyan kendi project_<uuid>şemanızda, Aurabase kasıtlı olarak sizin adınıza herhangi bir politika yerleştirmez; kod bunu bir "Supabase modeli" olarak belgelemektedir: tablolarınızın RLS'si, aynı işlevler ve aynı sözdizimiyle sizin sorumluluğunuzda kalır.

#
BYPASSRLS varsayıldı

service_role RLS'yi atlıyor — tasarım gereği, tesadüf değil

Postgres yerel olarak tüm politikaları göz ardı eden , BYPASSRLSrol özelliğini sunar. Aurabase bunu gönüllü olarak iki rol ailesinde kullanır: aura_service_role (tarayıcı tarafında hiçbir zaman gösterilmeyen sunucu rolü) ve ALTER SCHEMA ... OWNER TOgibi DDL işlemleri sırasında kullanılan, her projeye özel yönetim rolü.

provisioning/roles.sqlsql
create role aura_service_role nologin bypassrls;
-- Sunucu rolü: tarayıcı tarafında asla gösterilmez, asla üye olmaz
-- başka bir projeden roller.

anon/authenticated — tenant_<uuid> — isteklerinize hizmet eden rolde herhangi bir BYPASSRLSyoktur: RLS, istisnasız olarak buna normal şekilde uygulanır. Bonus olarak, her projeye özel sistem diyagramları (_auth, _storage, _platform) politika olmadan etkinleştirilmiş bir RLS alır; dolayısıyla bypass olmayan herhangi bir rol için varsayılan olarak tamamen reddedilme, bir uygulama yolunun bir gün yanlışlıkla ona erişmesi durumunda derinlemesine bir savunma.

Bilgi

RLS'yi yükseltilmiş bir sunucu rolüyle atlamak Aurabase'e özgü değildir; Supabase tarafındaki service_role ile aynı yapıdır. Önemli olan BYPASSRLS'dan kaçınmak değil, onu hiçbir zaman istemciden erişilebilen bir role vermemek ve onu tek bir projeyle sınırlamaktır.

Bu sunucu rolü, Güvenlik ve RBACsayfasında ayrıntıları verilen önceden tanımlanmış roller, özel RBAC, denetim günlükleri gibi daha geniş bir duruşun parçasıdır.

#
Derinlemesine savunma

Paylaşılan bir kümede veritabanı tüm işi tek başına yapmaz

SharedClusterDedicateddüzeyinde, aynı kuruluştan çeşitli projeler tek bir CNPG kümesinde bir arada bulunur. Fiziksel veritabanı zaten projeleri birbirinden ayırıyor ancak PostgreSQL rolleri (onlar) veritabanına değil kümeye yönelik küresel nesnelerdir. Bu nedenle Aurabase bir katman ekler: proje başına ayrı bir PostgreSQL girişi.

libs/aura-core/src/lib.rsrust
pub fn project_authenticator_role(project_id: &str) -> String {
    format!("project_{}_authenticator", project_id.replace('-', '_'))
}

// Varsayılan olarak etkin (F013_PER_PROJECT_AUTHENTICATOR), devre dışı bırakılabilir
// açıkça acil kaçış olarak.

Her proje kendi oturum açma bilgileriyle bağlanır, yalnızca kendi tenant_<uuid> / tenant_<uuid>_admin rollerinin üyesidir; asla aynı kümedeki başka bir projenin üyeleri değildir. Veritabanı zaten verileri izole ediyor; Proje başına bu oturum açma işlemi aynı zamanda kendisine bağlanan kimliği de yalıtır, böylece bir projedeki bir olay, oturum açma bilgilerinin bir başkasına devralınacak herhangi bir üyeliğini vermez.

#
Mimariniz için

Tek başına RLS veya özel taban: kendi SaaS'ınıza nasıl karar verilir?

Aurabase'in seçimi evrensel bir kural değildir; belirli bir duruma yönelik bir uzlaşmadır: potansiyel olarak farklı uyumluluk gereksinimlerine sahip müşterileri, kontrol etmedikleri bir platformda birbirlerinden izole etmek. Kendi SaaS'ınızı oluşturuyorsanız, aynı soru farklı bir ölçekte sizin için de ortaya çıkıyor.

  • Paylaşılan bir tabanda tenant_id ile RLS — kiracılarınız çok sayıda olduğunda, bireysel olarak düşük hisseye sahip olduğunda ve kiracı başına bir tabanın maliyeti orantısız olduğunda geçerlidir. İstisnasız her tablodaki her politikayı pg_proveile test edin.
  • Özel taban veya diyagram — kiracının kendi uyumluluk sorunu (sağlık, İK, kamu sektörü) olduğunda, performans izolasyonunu haklı çıkaran bir hacimde veya iki belirli müşteri arasındaki bir sızıntının maliyetinin ek altyapı maliyetiyle orantısız olacağı durumlarda geçerlidir.

Aurabase fiyatlandırma düzeyi aynı kararı kendi müşterilerine de uygular: varsayılan olarak kuruluşa göre paylaşılan taban, projenin zorluğu gerektirdiğinde özel küme. Kendi veritabanınızdaki RLS kalıpları için (sahiplik, kuruluşa göre çok kiracılı, rol hiyerarşisi) üretimdeki RLS kılavuzu, pgTAPtestleriyle üç durumu ayrıntılarıyla anlatır. Diyagramınızda otomatik olarak oluşturulan API, REST'in ötesinde ilginizi çekiyorsa, pg_graphql ile Hasura ve PostGraphile arasındaki karşılaştırma, Aurabase tarafından açığa çıkarılan Postgres yüzeyinin diğer yarısını kapsar.

#
Sıkça Sorulan Sorular

SSS

Tek bir Postgres veritabanındaki kiracıları izole etmek için RLS tek başına yeterli midir?+
Teknik olarak evet, eğer her tablo doğru bir politika taşıyorsa ve hiçbir bağlantı baypas dışı rolden kaçamıyorsa. Bu tam olarak Aurabase'in farklı projeler arasında almamayı seçtiği operasyonel risktir; her politika hatası tek bir tabanla sınırlı kalacaktır. Tek bir projede kendi kiracılarınız için RLS + tenant_id meşru ve yaygın olarak kullanılan bir seçim olmaya devam ediyor.
Ücretsiz projelerin neden kurumsal katmandaki gibi özel bir Postgres kümesi yok?+
Ücretsiz projeler de dahil olmak üzere proje başına özel bir CloudNativePG kümesi, ayrılmış bilgi işlem miktarını, çoğunluğunun fiili kullanımıyla hiçbir ilgisi olmadan çoğaltacaktır. Aurabase bunun yerine, her kurumsal olmayan projeye, birbirini tanımayan birkaç müşteri arasında ortak bir veri tabanındaki bir şema yerine, kendi kuruluşunun CNPG kümesinde kendi fiziksel Postgres veritabanını verir (hiçbir zaman başka bir kuruluşla paylaşılmaz).
auth.uid() teknik olarak kim olduğumu nasıl biliyor?+
Aurabase ağ geçidi, JWT'nizi doğrular ve ardından işlem süresince taleplerini Postgres oturum parametresi request.jwt.claims'e yerleştirir. auth.uid(), bu JSON'dan alt alanı çıkarmak ve onu uuid'e yayınlamaktan başka bir şey yapmaz; herhangi bir talepte bulunulmadan (anonim istek veya bir ağ geçidi dışında doğrudan bağlantı), current_setting() NULL değerini döndürür ve auth.uid() bu nedenle NULL değerini döndürür; bu da (owner_id = auth.uid()) kullanarak bir politikaya erişimi kapatır.

DAĞITILMAYA HAZIR MISINIZ?

Beş dakika içinde arka ucunuz.

Kredi kartı gerekmez · 500 MB ücretsiz · 50.000 MAU