Skip to content

Casbin

Repository ufficiale: casbin/casbin: An authorization library that supports access control models like ACL, RBAC, ABAC in Golang (github.com)

Documentazione ufficiale: Panoramica | Casbin

TIP

Questo articolo può essere considerato come un articolo introduttivo su Casbin. Se desideri approfondire ulteriormente, visita il sito ufficiale.

Introduzione

In un sistema, i programmatori backend devono essere responsabili della gestione delle autorizzazioni per le API, il che richiede molto lavoro. Se ogni progetto deve scrivere manualmente un proprio sistema, sarà uno spreco enorme di tempo. Le grandi aziende con più risorse umane e materiali tendono a sviluppare autonomamente un framework di autorizzazione, ma la maggior parte delle piccole e medie imprese non può sostenere questi costi di sviluppo. Pertanto, i framework di autorizzazione open source sul mercato diventano la loro scelta preferita. Casbin è proprio una libreria di controllo accessi open source ed efficiente, sviluppata in Go, ma supporta anche altri linguaggi principali.

Va notato che Casbin è solo un framework di controllo accessi, responsabile solo del controllo degli accessi. La logica di autenticazione degli accessi non è di competenza di Casbin, che memorizza solo le relazioni di mappatura tra utenti e ruoli. Supporta i seguenti modelli di controllo accessi:

  1. ACL (Access Control List, Lista di Controllo Accessi)
  2. ACL con superutente
  3. ACL senza utenti: particolarmente utile per sistemi senza autenticazione o login utente.
  4. ACL senza risorse: alcuni scenari possono riguardare solo i tipi di risorse, non le singole risorse, come i permessi write-article, read-log. Non controlla l'accesso a articoli o log specifici.
  5. RBAC (Controllo Accessi Basato sui Ruoli)
  6. RBAC con ruoli risorsa: gli utenti e le risorse possono avere contemporaneamente ruoli (o gruppi).
  7. RBAC con domini/tenant: gli utenti possono impostare diversi insiemi di ruoli per diversi domini/tenant.
  8. ABAC (Controllo Accessi Basato sugli Attributi): supporta l'uso di sintassi come resource.Owner per ottenere attributi di elementi.
  9. RESTful: supporta percorsi come /res/*, /res/: id e metodi HTTP come GET, POST, PUT, DELETE.
  10. Priorità al rifiuto: supporta autorizzazioni consentite e rifiutate, il rifiuto ha priorità sul consenso.
  11. Priorità: le regole delle policy sono prioritarie in base al loro ordine, simile alle regole del firewall.

Come Funziona

In Casbin, i modelli di controllo accessi sono astratti in file di configurazione basati su PERM, dove PERM sta per Policy (politica), Effect (effetto), Request (richiesta), Matcher (corrispondenza). Quando si modifica il meccanismo di autorizzazione nel progetto, è sufficiente modificare semplicemente il file di configurazione. Il contenuto di un file Model normale è il seguente:

bash
[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act

Questo è il modello di controllo accessi ACL più semplice.

Policy

Nel file di configurazione, la parte di definizione della policy è

[policy_definition]
p = sub, obj, act

p indica policy e non può essere sostituito da altri caratteri. sub indica subject (soggetto), obj indica object (oggetto), act indica action (azione).

p = sub, obj, act

Può esserci anche un quarto campo eft, che se omesso è impostato su allow per impostazione predefinita.

p=sub, obj, act, eft

Questa riga descrive solo come scrivere la policy, non è la definizione concreta della policy. Di seguito è riportato un esempio concreto di policy:

p, jojo, cake, eat

p rappresenta che questa è una definizione di regola di policy, jojo è il soggetto della policy, cake è l'oggetto della policy, eat è l'azione. Il significato completo è che il soggetto jojo può eseguire l'azione eat sull'oggetto cake. Le regole concrete della policy non appariranno nel file del modello; ci saranno file di policy dedicati o database per memorizzare le policy.

Richiesta

Nel file di configurazione, la parte di definizione della richiesta è

[request_definition]
r = sub, obj, act

r indica request e non può essere sostituito da altri caratteri. sub indica il soggetto della richiesta, obj indica l'oggetto della richiesta, act indica l'azione della richiesta. Generalmente la definizione della richiesta e la definizione della policy hanno gli stessi nomi di campo. La parte della richiesta non è gestita da Casbin; spetta allo sviluppatore decidere cosa è il soggetto della richiesta e cosa è l'oggetto della richiesta. Casbin deve solo eseguire il controllo degli accessi in base ai campi passati.

Corrispondenza

Nel file di configurazione, la parte di definizione della corrispondenza è

[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act

m indica matcher e non può essere sostituito da altri caratteri. Dopo di esso ci sono le regole di corrispondenza corrispondenti. Quanto sopra è una semplice espressione booleana che significa che tutti i campi della richiesta passati corrispondono a tutti i campi della regola della policy. Naturalmente, può anche essere un wildcard o un'espressione regolare più potente.

Oltre a ciò, il matcher supporta anche la sintassi in, ad esempio

[matchers]
m = r.sub in ("root","admin")

Può anche essere

[matchers]
m = r.sub.Name in (r.obj.Admins)
go
e.Enforce(Sub{Name: "alice"}, Obj{Name: "a book", Admins: []interface{}{"alice", "bob"}})

Durante la corrispondenza, Casbin non esegue il controllo dei tipi, ma lo tratta come interface ed esegue un controllo == per verificare l'uguaglianza.

Effetto

La definizione dell'effetto effettua nuovamente una valutazione logica combinata sui risultati della corrispondenza. Nel file di configurazione, la parte di definizione dell'effetto è

[policy_effect]
e = some(where (p.eft == allow))

e indica effect e non può essere sostituito da altri caratteri. Il quantificatore some verifica se esiste una regola di policy che soddisfa il matcher. Il quantificatore any verifica se tutte le regole della policy soddisfano il matcher.

some(where (p.eft == allow))

Questa regola significa che se nei risultati della corrispondenza c'è un risultato allow, il risultato finale è allow.

e = !some(where (p.eft == deny))

Questa regola significa che se nei risultati della corrispondenza non ci sono risultati deny, il risultato finale è allow.

e = some(where (p.eft == allow)) && !some(where (p.eft == deny))

Questa regola significa che nei risultati della corrispondenza, se c'è un risultato allow e non ci sono risultati deny, il risultato finale è allow.

Sebbene Casbin abbia progettato la grammatica per questi effetti delle policy, l'esecuzione attuale utilizza solo effetti di policy hardcoded. Ritengono che questa flessibilità non sia particolarmente necessaria. Finora devi utilizzare gli effetti delle policy incorporati e non puoi personalizzarli. Gli effetti delle policy incorporati supportati sono i seguenti.

Definizione Policy effectSignificatoEsempio
some(where (p.eft == allow))allow-overrideACL, RBAC, ecc.
!some(where (p.eft == deny))deny-overrideRifiuto sovrascrittura
some(where (p.eft == allow)) && !some(where (p.eft == deny))allow-and-denyConsenso e rifiuto
priority(p.eft) || denypriorityPriorità
subjectPriority(p.eft)Priorità basata sui ruoliPriorità soggetto

TIP

  1. Le quattro definizioni sopra possono essere definite più volte, la sintassi è type+number, ad esempio r2,p2,e2,m2.

  2. I file del modello possono avere commenti, commentati con il simbolo #.

Esempio

Di seguito è riportato un esempio che dimostra il processo di lavoro del file del modello. Innanzitutto definisci un semplice file di modello ACL come segue

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act

Il file Policy è il seguente

p, alice, data1, read
p, bob, data2, write

Il processo di astrazione di soggetto, oggetto e azione è determinato dalla logica di business, che non è importante qui quindi viene omesso. Di seguito viene mostrato il modo più semplice per trasmettere la richiesta:

alice, data1, read
bob, data1, read
alice, data2, write
bob, data2, write

Nel file policy è definito che alice ha il permesso di eseguire operazioni di lettura su data1, bob ha il permesso di eseguire operazioni di scrittura su data2. Quindi nelle richieste trasmesse

alice, data1, read

indica che alice vuole eseguire un'operazione di lettura su data1,

bob, data1, read

indica che bob vuole eseguire un'operazione di lettura su data1, e così via. Il risultato finale è

true
false
false
true

Questo è un esempio ACL più semplice. Sul sito ufficiale di Casbin è possibile modificare e testare gli esempi online. Vai a Casbin editor per testare.

RBAC

RBAC (Role-Based-Access-Controll), Controllo Accessi Basato sui Ruoli, rispetto al modello ACL avrà un [role definition] in più. Di seguito è riportato un semplice modello RBAC:

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[role_definition]
g = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act

La definizione dei ruoli è la seguente

[role_definition]
g = _, _

g indica group e non può essere sostituito da altri caratteri. Supporta la creazione di più definizioni con il metodo type+number. _ è un segnaposto che indica quanti parametri di input ci sono. Generalmente, nella Policy, g è solitamente nel seguente formato:

g, alice, data2_admin
g, mike, data1_admin
g, data1_admin data2_admin

alice indica il soggetto, data2_admin indica il ruolo. Strettamente parlando, Casbin li tratta come stringhe; come interpretarne il significato e l'uso dipende dallo sviluppatore.

g, alice, data2_admin

indica che alice ha il ruolo data2_admin

g, mike, data1_admin

indica che mike ha il ruolo data1_admin

g, data1_admin data2_admin

indica che il ruolo data1_admin ha il ruolo data2_admin, questa è la relazione di ereditarietà tra i ruoli.

Modello Ruoli Risorsa

Il modello ruoli risorsa aggiunge un g2 come definizione del ruolo della risorsa. La definizione del modello è la seguente

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[role_definition]
g = _, _
g2 = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = g(r.sub, p.sub) && g2(r.obj, p.obj) && r.act == p.act

La definizione di esempio della Policy è la seguente

p, alice, data1, read
p, bob, data2, write
p, data_group_admin, data_group, write

g, alice, data_group_admin
g2, data1, data_group
g2, data2, data_group

g2 definisce il gruppo di ruoli risorsa, assegna le risorse a diversi ruoli e definisce le relazioni utente tra i ruoli utente e i ruoli risorsa.

p, data_group_admin, data_group, write

Questa regola di policy definisce che un utente con il ruolo data_group_admin può eseguire operazioni di scrittura sulle risorse con il ruolo data_group.

Modello Multi-Tenant/Dominio

[request_definition]
r = sub, dom, obj, act

[policy_definition]
p = sub, dom, obj, act

[role_definition]
g = _, _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = g(r.sub, p.sub, r.dom) && r.dom == p.dom && r.obj == p.obj && r.act == p.act

Il modello multi-tenant/dominio ha il campo dom in più rispetto al modello RBAC tradizionale, utilizzato per indicare il dominio a cui appartiene il soggetto. La Policy di esempio è la seguente

p, admin, domain1, data1, read
p, admin, domain1, data1, write
p, admin, domain2, data2, read
p, admin, domain2, data2, write

g, alice, admin, domain1
g, bob, admin, domain2

Ad esempio

p, admin, domain1, data1, read

definisce che il soggetto admin appartenente al dominio domain1 ha il permesso di eseguire operazioni di lettura su data1

g, alice, admin, domain1

definisce che alice appartiene a domain1 e ha il ruolo admin

ABAC

Golang by www.golangdev.cn edit