“RLS” e “multi-tenant” si trovano fianco a fianco in quasi tutti i contenuti già pubblicati sull’argomento – una scelta legittima per molte architetture SaaS, ma che non è la scelta di Aurabase di separare i propri clienti gli uni dagli altri. Questo post spiega la differenza con il motore di provisioning reale e le policy RLS effettivamente applicate, non una descrizione di marketing semplificata. Per una panoramica di ciò che il motore Managed Postgres di Aurabase copre oltre l'isolamento, consultare la documentazione database.
L'essenziale
- Tra un progetto e l'altro, Aurabase si isola tramite base Postgres dedicata, mai solo tramite RLS: ogni progetto ha la propria base fisica, su un cluster CNPG dedicato (a livello aziendale) o sul cluster CNPG della propria organizzazione (gratuito/pro/team), mai condiviso con un'altra organizzazione.
- L'RLS (
auth.uid(),auth.role(),auth.jwt()) rimane attivo e consigliato all'interno di la tua base, per isolare i tuoi utenti - stessa convenzione di Supabase. service_rolee i ruoli di amministrazione basati su progetto ignorano la RLS in base alla progettazione (BYPASSRLS): una scelta architetturale presunta per le operazioni del server, non un difetto.- Una regressione già corretta in questo repository - diritti
PUBLICconcessi per errore su vecchi schemi condivisi - illustra concretamente perché un confine a livello base resiste meglio di un confine puramente applicativo.
La scorciatoia adottata dalla maggior parte delle guide RLS multi-tenant
Il modello più documentato per Postgres multi-tenant è costituito da tre righe: una singola base, una colonna tenant_id su ciascuna tabella, una policy RLS che confronta questa colonna con un valore estratto dal JWT. È economico (un pool di connessioni, un diagramma, una singola istanza da eseguire) e funziona bene quando gli inquilini sono numerosi, piccoli e con una bassa partecipazione individuale.
Il compromesso è reale: il confine tra due client diventa un'espressione SQL , valutata tabella per tabella. Una policy dimenticata su una nuova tabella, una connessione in esecuzione con un ruolo di superutente, uno script di debug lanciato in tempo reale: ognuno di questi incidenti, per quanto banale nel funzionamento, può esporre silenziosamente le linee di tutti gli inquilini allo stesso tempo. Il confine di sicurezza e il confine tecnico (la base) sono quindi esattamente la stessa cosa.
Questa non è una cattiva scelta in sé: è il giusto compromesso per molti prodotti. Il punto di questo post è altrove: non si tratta del compromesso che Aurabase ha fatto per separare i propri clienti (interi progetti, potenzialmente con requisiti di conformità diversi) gli uni dagli altri.
Due architetture, mai una base condivisa tra progetti
Da un recente consolidamento del provisioner (contrassegnato nel codice come "Task 12"), un progetto Postgres attivo presso Aurabase rientra esattamente in due architetture: i vecchi modelli con una base effettivamente condivisa tra diversi progetti sono stati rimossi dal percorso di provisioning.
Il livello di progetto decide quale dei due si applica ed è il codice che decide, non una casella selezionata in una dashboard:
| Dimensioni | Completamente dedicato (azienda) | SharedClusterDedicated (gratuito/pro/team) |
|---|---|---|
| Cluster CNPG | Dedicato a questo progetto | Condiviso, ma mai tra due organizzazioni |
| Banca dati Postgres | app, proietta solo su di essa | project_<uuid>, uno per progetto nel cluster |
| Accesso PostgreSQL | Un unico progetto sul cluster: nessun rischio di cross membership | Accesso per progetto (F-013), membro dei suoi unici ruoli tenant_<uuid> |
Su entrambe le architetture, la base o il cluster non ospita mai due organizzazioni diverse, quindi la domanda non è "i tuoi dati sono isolati" ma "il tuo progetto ha il calcolo CloudNativePG tutto per sé o lo condivide con altri progetti nella stessa organizzazione".
Questo consolidamento di due architetture è recente: il codice in precedenza prevedeva due percorsi aggiuntivi: un “master condiviso” in cui più progetti coesistevano nello stesso database, isolati solo dal diagramma, e una variante postgrest_dedicated_shared_db. Una migrazione dedicata li ha rimossi e ha stretto il vincolo della tabella projects ai soli due valori rimanenti, proprio perché il modello a schema condiviso era all'origine del bug descritto di seguito.
Perché una base dedicata batte un EPIRB condiviso tra i clienti
Un database Postgres separato è un limite a livello di connessione, non a livello di riga. Un ruolo dell'applicazione connesso al database del progetto A semplicemente non può interrogare le tabelle del progetto B: non ha una sessione aperta. Questa proprietà vale anche se una policy RLS è scritta male, manca da una tabella o bypassata da un ruolo elevato: il caso peggiore rimane confinato all'interno di un singolo database.
Questo deposito porta anche la traccia di un vero e proprio bug che illustra il rischio opposto. Nel vecchio modello di schema condiviso (da allora ritirato), provision_postgres_schema concedeva erroneamente a GRANT ALL ... TO PUBLIC i diritti su ogni schema di progetto: PUBLIC applicando a tutti i ruoli nel database senza condizioni di appartenenza, un accesso isolato per progetto poteva leggere e scrivere nello schema di un altro. Una migrazione correttiva (066) ha rimosso questi diritti da quello esistente.
La patch non ha aggiunto un'altra policy RLS per tamponare la falla: ha eliminato la possibilità stessa che due progetti condividessero un database. Sulle due architetture attuali, un commento di provisioning.rs lo documenta nero su bianco: “ogni progetto ha già il proprio database fisico Postgres”. Un limite di livello base rende un'intera classe di tali bug semplicemente irraggiungibile, invece di fare affidamento sul fatto che ogni politica sia sempre scritta correttamente.
Una patch del 23 agosto 2026 va nella stessa direzione: un REVOKE ALL ON SCHEMA public inserito incondizionatamente dal provisioner è stato condizionato alla topologia, perché forniva solo un reale isolamento sul vecchio modello di database condiviso; sulle due architetture attuali, bloccava senza alcun beneficio l'importazione di dump SQL che fanno riferimento esplicitamente a public.<table>.
L'EPIRB rimane lì: nel tuo database, per i tuoi utenti
Niente di quanto sopra rende l’EPIRB inutile: cambia solo piano. Una volta in il database del tuo progetto, Aurabase espone esattamente la convenzione PostgREST ripresa da Supabase: tre funzioni SQL che leggono le attestazioni JWT impostate dal gateway in request.jwt.claims.
Questi aiutanti vengono utilizzati nelle politiche effettive di Aurabase stessa, non solo documentati per le tue. Ecco la policy che protegge storage_objects, così come è inserita nel repository (riformattata su più righe per la lettura):
Nel tuo schema project_<uuid>, quello che contiene le tue tabelle applicative, Aurabase non inserisce deliberatamente alcuna policy per tuo conto: il codice lo documenta come un “modello Supabase”: la RLS delle tue tabelle rimane di tua responsabilità, con le stesse funzioni, la stessa sintassi.
service_role bypassa RLS: in base alla progettazione, non per caso
Postgres offre nativamente un attributo di ruolo , BYPASSRLS, che ignora tutte le policy. Aurabase lo utilizza volontariamente su due famiglie di ruoli: aura_service_role (il ruolo server, mai esposto lato browser) e il ruolo di amministrazione specifico per ciascun progetto, utilizzato durante le operazioni DDL come ALTER SCHEMA ... OWNER TO.
Il ruolo che serve le tue richieste anon/authenticated — tenant_<uuid> — non ha alcun BYPASSRLS: la RLS si applica normalmente, senza eccezioni. Come bonus, i diagrammi di sistema specifici di ciascun progetto (_auth, _storage, _platform) ricevono un RLS attivato senza policy — quindi un rifiuto totale per impostazione predefinita per qualsiasi ruolo di non bypass, una difesa approfondita nel caso in cui un percorso applicativo vi acceda un giorno per errore.
Bypassare la RLS con un ruolo server elevato non è un'esclusiva di Aurabase: è lo stesso costrutto di service_role sul lato Supabase. Il punto non è evitare BYPASSRLS, ma non concederlo mai a un ruolo accessibile da un client e confinarlo in un singolo progetto.
Questo ruolo del server fa parte di un approccio più ampio: ruoli predefiniti, RBAC personalizzato, log di controllo, dettagliato nella pagina Sicurezza e RBAC.
In un cluster condiviso, il database non esegue tutto il lavoro da solo
Al livello SharedClusterDedicated, diversi progetti della stessa organizzazione coesistono su un unico cluster CNPG. Il database fisico separa già i progetti gli uni dagli altri, ma i ruoli PostgreSQL – loro – sono oggetti globali per il cluster, non per il database. Aurabase aggiunge quindi un livello: un login PostgreSQL separato per progetto.
Ogni progetto si connette con il proprio login, membro solo dei propri ruoli tenant_<uuid> / tenant_<uuid>_admin, mai quelli di un altro progetto nello stesso cluster. Il database già isola i dati; Questo login per progetto isola anche l'identità che si connette ad esso, in modo che un incidente su un progetto non conferisca al suo login alcuna appartenenza da ereditare a un altro.
RLS sola o base dedicata: come decidere per il proprio SaaS
La scelta di Aurabase non è una regola universale: è un compromesso per un caso specifico: isolare i clienti gli uni dagli altri, potenzialmente con requisiti di conformità diversi, su una piattaforma che non controllano. Se stai costruendo il tuo SaaS, ti si pone la stessa domanda, su scala diversa.
- RLS con
tenant_idin una base condivisa — rilevante quando i tuoi inquilini sono numerosi, individualmente con una posta bassa e il costo di una base per inquilino sarebbe sproporzionato. Testa ogni policy conpg_prove, su ogni tabella, senza eccezioni. - Base o diagramma dedicato — rilevante ogni volta che un inquilino ha un proprio problema di conformità (salute, risorse umane, settore pubblico), un volume che giustifica l'isolamento delle prestazioni o il costo di una perdita tra due clienti specifici sarebbe sproporzionato rispetto al costo dell'infrastruttura aggiuntiva.
Il livello di prezzo di Aurabase applica lo stesso arbitrato ai propri clienti: base condivisa dall'organizzazione per impostazione predefinita, cluster dedicato quando la sfida del progetto lo giustifica. Per i modelli RLS all'interno del tuo database (proprietà, multi-tenant per organizzazione, gerarchia dei ruoli) la guida RLS in produzione descrive in dettaglio i tre casi con test pgTAP. E se l'API generata automaticamente sul tuo diagramma ti interessa oltre REST, il confronto su pg_graphql rispetto a Hasura e PostGraphile copre l'altra metà della superficie Postgres esposta da Aurabase.