Vai al contenuto principale

Autorizzazione in APISIX utilizzando Casbin

· 6 minuti di lettura
Rushikesh Tote

Introduzione

APISIX è un gateway API cloud nativo ad alte prestazioni e scalabile basato su Nginx e etcd. È un progetto open source della Apache Software Foundation. Oltre a ciò, ciò che rende APISIX così buono è il supporto di molti ottimi plugin integrati che possono essere utilizzati per implementare funzionalità come autenticazione, monitoraggio, routing, ecc. E il fatto che i plugin in APISIX siano ricaricati in modalità "hot" (senza riavvii) lo rende molto dinamico.

Tuttavia, durante l'uso di APISIX, potrebbero verificarsi scenari in cui potresti voler aggiungere logica di autorizzazione complessa nella tua applicazione. Questo è dove authz-casbin potrebbe aiutarti, authz-casbin è un plugin di APISIX basato su Lua Casbin che abilita un'autorizzazione potente basata su vari modelli di controllo degli accessi. Casbin è una libreria di autorizzazione che supporta modelli di controllo degli accessi come ACL, RBAC, ABAC. Inizialmente scritto in Go, è stato portato in molte lingue e Lua Casbin è l'implementazione Lua di Casbin. Lo sviluppo di authz-casbin è iniziato quando abbiamo proposto un nuovo plugin per l'autorizzazione nel repository di APISIX (#4674) a cui i membri core hanno dato il loro consenso. E dopo le utili revisioni che hanno portato a alcune modifiche e miglioramenti principali, la PR (#4710) è stata finalmente unita.

In questo blog, useremo il plugin authz-casbin per mostrare come puoi implementare un modello di autorizzazione basato sul Controllo degli Accessi Basato sui Ruoli (RBAC) in APISIX.

NOTA: Dovrai utilizzare qualche altro plugin o flusso di lavoro personalizzato per autenticare l'utente poiché Casbin farà solo autorizzazione e non autenticazione.

Creazione di un modello

Il plugin utilizza tre parametri per autorizzare qualsiasi richiesta - soggetto, oggetto e azione. Qui, il soggetto è il valore dell'intestazione del nome utente, che potrebbe essere qualcosa come [username: alice]. Quindi, l'oggetto è il percorso URL che viene acceduto e l'azione è il metodo di richiesta utilizzato.

Diciamo che vogliamo creare un modello con tre risorse nei percorsi - /`\`, /res1\ e `/res2`. E vogliamo avere un modello come questo:

immagine

Ciò significherebbe che tutti gli utenti (*`\`) come ad esempio jack\ possono accedere alla homepage (/`\`). E gli utenti con autorizzazioni di admin\ come alice`\` e bob\ possono accedere a tutte le pagine e le risorse (come res1`\` e res2\). Inoltre, limitiamo gli utenti senza alcuna autorizzazione di amministratore all'uso solo del metodo di richiesta `GET`. Per questo scenario, potremmo definire il modello come:

[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) || keyMatch(r.sub, p.sub)) && keyMatch(r.obj, p.obj) && keyMatch(r.act, p.act)

Creazione di una politica

Dallo scenario sopra descritto, la politica sarebbe:

p, *, /, GET
p, admin, *, *
g, alice, admin
g, bob, admin

Il matcher dal modello significa:

  1. (g(r.sub, p.sub) || keyMatch(r.sub, p.sub))`\`: O il soggetto della richiesta ha un ruolo come il soggetto della politica o il soggetto della richiesta corrisponde al soggetto della politica in keyMatch\. `keyMatch` è una funzione incorporata in Lua Casbin, puoi dare un'occhiata alla descrizione della funzione e ad altre funzioni simili che potrebbero essere utili qui.
  2. `keyMatch(r.obj, p.obj)`: L'oggetto della richiesta corrisponde all'oggetto della politica (percorso URL qui).
  3. `keyMatch(r.act, p.act)`: L'azione della richiesta corrisponde all'azione della politica (metodo di richiesta HTTP qui).

Abilitazione del plugin sulla route

Una volta creato il modello e la politica, puoi abilitarlo su una route utilizzando l'API di amministrazione di APISIX. Per abilitarlo utilizzando i percorsi dei file del modello e del policy:

curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"plugins": {
"authz-casbin": {
"model_path": "/path/to/model.conf",
"policy_path": "/path/to/policy.csv",
"username": "username"
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/*"
}'

Qui, il campo username è il nome dell'intestazione che utilizzerai per passare il soggetto. Ad esempio, se passerà l'intestazione username come user: alice, dovresti usare "username": "user".

Per utilizzare il testo del modello/policy invece dei file, puoi utilizzare i campi model e policy al posto di:

curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"plugins": {
"authz-casbin": {
"model": "[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) || keyMatch(r.sub, p.sub)) && keyMatch(r.obj, p.obj) && keyMatch(r.act, p.act)",

"policy": "p, *, /, GET
p, admin, *, *
g, alice, admin
g, bob, admin",

"username": "username"
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/*"
}'

Abilitazione del plugin utilizzando un modello/policy globale

Potrebbero esserci situazioni in cui potresti voler utilizzare una singola configurazione di modello e policy su più route. Puoi farlo prima inviando una richiesta PUT per aggiungere la configurazione del modello e della policy ai metadati del plugin:

curl http://127.0.0.1:9080/apisix/admin/plugin_metadata/authz-casbin -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -i -X PUT -d '
{
"model": "[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) || keyMatch(r.sub, p.sub)) && keyMatch(r.obj, p.obj) && keyMatch(r.act, p.act)",

"policy": "p, *, /, GET
p, admin, *, *
g, alice, admin
g, bob, admin"
}'

E poi per abilitare la stessa configurazione su una rotta, invia una richiesta utilizzando l'API di Admin:

curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"plugins": {
"authz-casbin": {
"username": "username"
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/route1/*"
}'

Questo aggiungerà la configurazione dei metadati del plugin alla rotta. Puoi anche facilmente aggiornare la configurazione dei metadati del plugin rispedendo la richiesta ai metadati del plugin con la configurazione del modello e della politica aggiornati, il plugin aggiornerà automaticamente tutte le rotte che utilizzano i metadati del plugin.

Casi d'uso

  • Il caso d'uso principale di questo plugin sarebbe nell'implementazione dell'autorizzazione nelle tue API. Puoi facilmente aggiungere questo plugin su qualsiasi rotta API che stai utilizzando con il tuo modello di autorizzazione e configurazione della politica.
  • Se desideri avere un singolo modello di autorizzazione per tutte le tue API, puoi utilizzare il metodo del modello/politica globale. Questo rende facile l'aggiornamento della politica per tutte le rotte, poiché devi solo aggiornare i metadati in etcd.
  • Mentre se desideri utilizzare un modello diverso per ogni rotta diversa, puoi utilizzare il metodo della rotta. Questo è utile quando diverse route API hanno diversi set di permessi utente. Puoi anche utilizzare questo quando hai a che fare con politiche più grandi, poiché renderà l'autorizzazione più veloce quando filtrata in più route.