Fine-Grained Authorization (Modello Zanzibar)
Il Role-Based Access Control (RBAC) è sufficiente per molte applicazioni: gli utenti hanno ruoli, i ruoli hanno permessi, si verifica se un utente ha il permesso corretto. Ma RBAC non basta quando si ha bisogno di un controllo degli accessi a livello di risorsa — “Alice può modificare il documento 42, ma non il 43”, oppure “Bob può vedere tutti i documenti del suo team.”
Auris implementa un motore FGA compatibile con Zanzibar (Fine-Grained Authorization) per gestire questi scenari.
Cos’è Zanzibar?
Zanzibar è il sistema di autorizzazione globale di Google, pubblicato in un paper di ricerca nel 2019. Gestisce il controllo degli accessi per Gmail, Drive, Docs, Maps e decine di altri prodotti Google — elaborando trilioni di verifiche di autorizzazione al secondo con latenza millisecondale.
L’intuizione centrale di Zanzibar è modellare l’autorizzazione come relazioni tra oggetti e soggetti, memorizzate come tuple. Le domande di autorizzazione diventano problemi di attraversamento di grafi: “Esiste un percorso dal soggetto user:alice all’oggetto document:readme tramite la relazione viewer?”
Auris implementa un motore FGA compatibile con Zanzibar con:
- Un DSL compatibile con OpenFGA per definire i modelli di autorizzazione
- Un tuple store su PostgreSQL (via Prisma)
- Un algoritmo di verifica ricorsivo con rilevamento dei cicli
- Operazioni di query Expand e list-objects
- Un debugger visuale nella Console Auris
Concetti Core
Oggetto
Un oggetto è qualsiasi risorsa che si vuole proteggere. Gli oggetti hanno un tipo e un ID:
document:readme
folder:engineering
organization:acme-corp
report:q4-2024Il tipo è definito nel modello di autorizzazione. L’ID è una qualsiasi stringa che identifica l’istanza specifica.
Relazione
Una relazione è un arco nominato nel grafo di autorizzazione — un tipo di rapporto che un oggetto può avere con i soggetti. Le relazioni sono definite per tipo di oggetto nel modello:
documentpuò avere relazioni:owner,editor,viewerfolderpuò avere relazioni:owner,viewerorganizationpuò avere relazioni:admin,member
Soggetto
Un soggetto è chi (o cosa) ha una relazione con un oggetto. I soggetti possono essere:
- Un utente:
user:alice - Un userset (la relazione di un altro oggetto):
group:engineering#member(tutti i membri del gruppo engineering)
Tupla
Una tupla è un fatto memorizzato: “questo soggetto ha questa relazione con questo oggetto.”
Formato: object#relation@subject
Esempi:
document:readme#viewer@user:alice
document:readme#editor@user:bob
document:readme#viewer@group:engineering#member
folder:engineering#owner@user:charlieL’esempio penultimo significa: “tutti i membri del gruppo engineering sono viewer del documento readme.” Questo si chiama userset — un gruppo di soggetti definito da un’altra relazione.
Il DSL Auris
Auris usa un domain-specific language compatibile con OpenFGA per definire i modelli di autorizzazione. Il DSL specifica i tipi di oggetti e le loro relazioni, incluso come le relazioni sono derivate da altre relazioni.
Struttura di Base
type user
type group
relations
define member: [user]
type folder
relations
define owner: [user]
define viewer: [user, group#member] or owner
type document
relations
define parent: [folder]
define owner: [user] or owner from parent
define editor: [user, group#member] or owner
define viewer: [user, group#member] or editorOgni blocco type definisce un tipo di oggetto. relations elenca le relazioni nominate per quel tipo, con le regole su come vengono derivate.
Leggere le Definizioni di Relazione
define viewer: [user, group#member] or editorQuesto significa: “Un soggetto è viewer di un documento se:
- Il soggetto è un tipo
userE esiste una tupla direttadocument:X#viewer@user:Y, OPPURE - Il soggetto è un
group#member(un membro di qualche gruppo) E esiste una tupla direttadocument:X#viewer@group:Z, OPPURE - Il soggetto è un
editordel documento (calcolato ricorsivamente).”
I Sei Tipi di Riscrittura
Il motore di autorizzazione supporta sei tipi di regole di riscrittura. Possono essere composte per modellare quasi qualsiasi schema di accesso.
1. this — Assegnazione Diretta
La regola più semplice: la relazione vale se una tupla esiste direttamente nello store.
define owner: [user]2. computedUserset — Eredita da un’altra Relazione
La relazione vale se il soggetto ha una relazione diversa con lo stesso oggetto.
define editor: [user] or owner3. tupleToUserset — Segui una Relazione verso un altro Oggetto
Questa è la regola più potente. Segue una relazione dall’oggetto corrente a un altro oggetto, poi verifica una relazione su quell’altro oggetto.
define owner: [user] or owner from parent“L’utente Alice è owner di document:X se esiste una tupla owner diretta per lei, OPPURE se esiste una tupla document:X#parent@folder:Y E Alice è owner di folder:Y.”
Questo è il funzionamento dell’ereditarietà in Google Drive: i documenti ereditano i permessi dalla cartella padre.
4. union — Combinazione OR
Un’unione di due o più riscritture. La relazione vale se una qualsiasi delle sub-regole corrisponde.
5. intersection — Combinazione AND
Tutte le sub-regole devono valere. Utile per richiedere più condizioni contemporaneamente.
define restricted_viewer: [user] and approved6. exclusion — Differenza di Insiemi (A MA NON B)
La relazione vale per i soggetti nel primo insieme ma non nel secondo. Utile per le deny list.
define viewer: [user] but not blockedL’Algoritmo di Verifica
Quando si chiama POST /api/fga/check, il motore valuta se objectType:objectId#relation@subjectType:subjectId vale.
L’algoritmo usa un set visited per prevenire loop infiniti in modelli con riferimenti di relazione circolari. La profondità massima di ricorsione è limitata a 25.
Modalità Explain
Quando si passa explain: true a POST /api/fga/check, il motore restituisce un albero di risoluzione che mostra esattamente quale regola ha corrisposto (o fallito), fino alla tupla specifica trovata (o non trovata). Questo è prezioso per il debugging dei problemi di controllo degli accessi.
Pattern di Modellazione
Modello Google Drive
Utenti e gruppi hanno accesso ai documenti direttamente o ereditandolo dalla cartella padre:
type user
type group
relations
define member: [user]
type folder
relations
define owner: [user]
define editor: [user, group#member] or owner
define viewer: [user, group#member] or editor
type document
relations
define parent: [folder]
define owner: [user] or owner from parent
define editor: [user, group#member] or owner or editor from parent
define viewer: [user, group#member] or editor or viewer from parentModello SaaS Multi-Tenant
type user
type organization
relations
define admin: [user]
define member: [user] or admin
type project
relations
define parent_org: [organization]
define owner: [user] or admin from parent_org
define contributor: [user, organization#member] or owner
define viewer: [user, organization#member] or contributorMigrazione da RBAC a FGA
Non è necessario scegliere uno o l’altro. Auris supporta l’uso di RBAC e FGA insieme:
- RBAC gestisce: Accesso coarse-grained alle funzionalità (
view:invoices,manage:users) - FGA gestisce: Accesso fine-grained a livello di risorsa (
document:X#editor@user:Y)
Debug con la Console
La Console Auris fornisce un debugger FGA visuale in Amministrazione → Fine-Grained Authorization → Debugger. Supporta tre operazioni:
- Check: Inserisci un oggetto, relazione e soggetto — vedi se la verifica passa o fallisce, con l’albero di risoluzione completo
- Expand: Inserisci un oggetto e relazione — vedi tutti i soggetti che hanno quella relazione
- List Objects: Inserisci un soggetto e relazione — vedi tutti gli oggetti di un determinato tipo accessibili al soggetto
L’albero di risoluzione visuale usa la codifica a colori:
- Nodi verdi: regola valutata come vera
- Nodi rossi: regola valutata come falsa
- Nodi blu: usersets computati intermedi
Concetti Correlati
- Guida Fine-Grained Authorization — Guida pratica all’implementazione FGA
- Ruoli & Permessi — Come RBAC e FGA lavorano insieme
- FGA Debugger — Testa le verifiche di autorizzazione nella Console
- API Fine-Grained Authorization — Modelli, tuple, check, expand e list-objects
- JavaScript SDK —
client.fga.check()e gestione delle tuple