Architettura di Vault
Questa pagina è un riferimento tecnico per operatori e contributori attenti alla sicurezza che desiderano comprendere in modo approfondito come funziona l’integrazione del vault di Switchbord. Per le istruzioni di configurazione, vedi Configurazione di Vault.Modello di Memorizzazione
Switchbord utilizza due livelli di oggetti del database per memorizzare i segreti del workspace:vault.secrets (integrato in Supabase)
I valori dei segreti effettivamente crittografati risiedono qui. Ogni riga contiene una colonna secret crittografata con pgsodium (AES-256-GCM), una colonna name per l’identificazione leggibile e un key_id che fa riferimento alla chiave pgsodium utilizzata per la crittografia. Le righe sono identificate da un UUID.
app_private.workspace_secret_bindings (personalizzata di Switchbord)
Questa tabella mappa un workspace ai suoi segreti:
vault.secrets.
Perché lo Schema app_private
Lo schema app_private è utilizzato per tabelle e funzioni che non devono essere esposte tramite PostgREST (l’API REST auto-generata di Supabase). Per impostazione predefinita, PostgREST espone solo gli oggetti nello schema public (e gli schemi esplicitamente elencati in db_schema). Il posizionamento di workspace_secret_bindings in app_private garantisce che:
- Nessun client anonimo o autenticato possa eseguire direttamente una
SELECTsulla tabella dei binding tramite la libreria client di Supabase - Non venga generato alcun endpoint REST per
/app_private/workspace_secret_bindings - L’accesso sia possibile solo tramite funzioni esplicitamente definite eseguite come
SECURITY DEFINER
workspace_secret_bindings come misura di defense-in-depth, ma il posizionamento nello schema app_private è il livello di isolamento primario.
Il pattern dello schema
app_private è una convenzione standard di Supabase per gli oggetti di schema sensibili. È documentato nelle guide di Supabase su “Row Level Security” e “Functions” come il modo consigliato per proteggere dati che non dovrebbero mai essere accessibili direttamente.Architettura del Percorso di Lettura
Il percorso di lettura è progettato per evitare di richiedere una connessione diretta al database dal servizio worker. Tutte le letture sensibili passano attraverso funzioni RPC di Supabase definite conSECURITY DEFINER.
Funzioni SECURITY DEFINER
Per garantire che gli elementi del vault non vengano mai esposti tramite lo schema public standard o gli endpoint REST auto-generati, Switchbord utilizza il pattern dello schema app_private.
app_private.read_workspace_secret
Unisce app_private.workspace_secret_bindings con vault.decrypted_secrets per restituire il valore in chiaro. Viene eseguita come SECURITY DEFINER, consentendole di accedere allo schema vault, normalmente limitato.
app_private.resolve_workspace_by_verify_token
Utilizzata durante la verifica del webhook Meta per instradare le richieste al workspace corretto senza esporre i token al client.
Wrapper RPC Pubblici
Poiché PostgREST espone solo lo schemapublic, forniamo wrapper leggeri che applicano l’autorizzazione:
public.sb_read_workspace_secret: validaauth.role() == 'service_role'prima di delegare alla funzione privata.public.sb_resolve_workspace_by_verify_token: segue lo stesso pattern di sicurezza per la risoluzione del token.
Percorso di Scrittura
Il percorso di scrittura passa attraverso l’applicazione web di Switchbord e non coinvolge il worker:SUPABASE_DB_URL) quando invoca vault.create_secret() dall’esterno del server applicativo, ma la route API Next.js gestisce questo utilizzando il client con ruolo di servizio di Supabase. Chi effettua il self-hosting non necessita di SUPABASE_DB_URL nel worker — solo nell’applicazione web se sono necessarie scritture al vault dal codice lato server.
Crittografia a Riposo
Supabase Vault utilizza pgsodium, un’estensione PostgreSQL che avvolge libsodium.- Algoritmo: XChaCha20-Poly1305 (un cifrario a flusso con autenticazione)
- Gestione delle chiavi: pgsodium utilizza una chiave radice derivata da un segreto memorizzato fuori dal database (nell’infrastruttura di gestione delle chiavi di Supabase per Cloud, o configurata separatamente per il self-hosting)
- Ambito della crittografia: ogni segreto in
vault.secretsviene crittografato con una chiave derivata dalla chiave radice. Il testo cifrato e l’ID della chiave vengono memorizzati insieme; il testo in chiaro non viene mai persistito. - Decrittografia: la vista
vault.decrypted_secretsesegue la decrittografia in modo trasparente utilizzandopgsodium.crypto_aead_det_decrypt(). Solo i ruoli del database con permesso SELECT su questa vista possono leggere i valori in chiaro.
Per i deployment su Supabase Cloud, la chiave radice pgsodium è gestita da Supabase e non viene mai esposta ai proprietari del progetto. Per Supabase self-hosted, l’utente è responsabile della protezione della chiave radice — vedi la guida al self-hosting di Supabase per la configurazione delle chiavi.
Riepilogo del Controllo degli Accessi
Il worker autentica tutte le chiamate RPC utilizzando il JWT del ruolo di servizio (
SUPABASE_SECRET_KEY). Questa chiave deve essere mantenuta segreta e non deve mai essere esposta ai client browser o registrata nei log.
Riferimento per la Migrazione
L’integrazione del vault è composta da due livelli: Integrato in Supabase (nessuna azione richiesta)- Schema
vaulte tabellavault.secrets - Vista
vault.decrypted_secrets - Funzione
vault.create_secret() - Estensione pgsodium
CREATE EXTENSION supabase_vault.
Personalizzato di Switchbord (applicato tramite migrazioni)
- Creazione dello schema
app_private - Tabella
app_private.workspace_secret_bindings - Funzione
app_private.read_workspace_secret() - Funzione
app_private.resolve_workspace_by_verify_token() - Wrapper
public.sb_read_workspace_secret() - Wrapper
public.sb_resolve_workspace_by_verify_token()
supabase/migrations/. L’esecuzione di supabase db push applica tutte le migrazioni in sospeso e garantisce l’esistenza di questi oggetti.
Se è necessario ispezionare direttamente le definizioni delle funzioni:
Considerazioni sulla Sicurezza per chi Effettua il Self-Hosting
Esposizione della chiave del ruolo di servizio LaSUPABASE_SECRET_KEY può invocare qualsiasi funzione RPC e ignora la RLS. Trattarla con la stessa cura di una password root del database. Ruotarla immediatamente in caso di sospetta esposizione.
Chiave pgsodium di Supabase self-hosted
Se si esegue Supabase localmente o sulla propria infrastruttura, la chiave radice pgsodium deve essere impostata prima che venga memorizzato qualsiasi segreto. Se la chiave cambia o viene persa, tutti i segreti vault memorizzati diventano irrecuperabili — non esiste alcun key escrow.
Integrità delle migrazioni
Le funzioni SECURITY DEFINER in app_private sono sicure solo quanto lo è il ruolo proprietario del database. Assicurarsi che solo le parti fidate abbiano la possibilità di ridefinire o sostituire queste funzioni tramite migrazioni.
Guide Correlate
- Configurazione di Vault — configurazione per il self-hosting, variabili d’ambiente e risoluzione dei problemi
- Segreti e Crittografia — politica di sicurezza, hashing delle API key e header di sicurezza HTTP
- Multi-Tenancy — modello di isolamento dei workspace
- Autenticazione — gestione del JWT e modello di sessione