Casbin
Offizielles Repository: casbin/casbin: An authorization library that supports access control models like ACL, RBAC, ABAC in Golang (github.com)
Offizielle Dokumentation: Überblick | Casbin
TIP
Dieser Artikel ist lediglich eine Einführung in Casbin. Für ein detaillierteres Verständnis besuchen Sie bitte die offizielle Website.
Einführung
In einem System sind Backend-Entwickler für die Verwaltung der API-Berechtigungen verantwortlich, was viel Arbeit erfordert. Wenn jedes Projekt eine eigene Berechtigungslogik implementieren müsste, würde dies viel Zeit verschwenden. Größere Unternehmen mit mehr Ressourcen entwickeln lieber ihre eigenen Berechtigungsframeworks, aber die meisten kleinen und mittleren Unternehmen können sich diese Entwicklungskosten nicht leisten, daher sind Open-Source-Berechtigungsframeworks ihre erste Wahl. Casbin ist eine solche Open-Source-Zugangskontrollbibliothek, die in Go entwickelt wurde und auch andere wichtige Programmiersprachen unterstützt.
Es ist wichtig zu beachten, dass Casbin nur ein Zugangskontrollframework ist und nur für die Zugangskontrolle verantwortlich ist. Die Authentifizierungslogik wird nicht von Casbin verwaltet; es speichert nur die Zuordnungsbeziehungen zwischen Benutzern und Rollen. Es unterstützt folgende Zugangskontrollmodelle:
- ACL (Access Control List, Zugangskontrollliste)
- ACL mit Superuser
- ACL ohne Benutzer: Besonders nützlich für Systeme ohne Authentifizierung oder Benutzeranmeldung.
- ACL ohne Ressourcen: In bestimmten Szenarien kann es nur um Ressourcentypen gehen, nicht um einzelne Ressourcen, wie Berechtigungen für
write-article,read-logusw. Es kontrolliert nicht den Zugriff auf bestimmte Artikel oder Protokolle. - RBAC (Rollenbasierte Zugangskontrolle)
- RBAC mit Ressourcenrollen: Benutzer und Ressourcen können gleichzeitig Rollen (oder Gruppen) haben.
- RBAC mit Domains/Tenants: Benutzer können für verschiedene Domains/Tenants unterschiedliche Rollensätze haben.
- ABAC (Attributbasierte Zugangskontrolle): Unterstützt die Nutzung syntaktischen Zuckers wie
resource.Owner, um auf Attribute von Elementen zuzugreifen. - RESTful: Unterstützt Pfade wie
/res/*,/res/:idund HTTP-Methoden wieGET,POST,PUT,DELETE. - Ablehnung vorrangig: Unterstützt Erlaubnis und Ablehnung bei der Autorisierung, wobei Ablehnung vor Erlaubnis geht.
- Priorität: Strategieeregeln werden nach ihrer Reihenfolge priorisiert, ähnlich wie Firewall-Regeln.
Funktionsweise
In Casbin wird das Zugangskontrollmodell als PERM-basierte Konfigurationsdatei abstrahiert. PERM steht für Policy (Strategie), Effect (Effekt), Request (Anfrage), Matcher (Vergleicher). Bei Änderungen der Autorisierungsmechanismen in einem Projekt muss nur die Konfigurationsdatei geändert werden. Eine normale Model-Konfigurationsdatei sieht wie folgt aus:
[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.actDies ist ein einfaches ACL-Zugangskontrollmodell.
Strategie (Policy)
In der Konfigurationsdatei lautet der Strategie-Definitionsteil:
[policy_definition]
p = sub, obj, actp steht für policy und kann nicht durch andere Zeichen ersetzt werden. sub steht für subject (Strategiesubjekt), obj für object (Strategieobjekt), act für action (Aktion).
p = sub, obj, actEs kann auch ein viertes Feld eft geben; wenn weggelassen, ist eft standardmäßig allow.
p=sub, obj, act, eftDiese Zeile beschreibt nur, wie eine Strategie geschrieben werden soll, nicht die konkrete Strategiedefinition. Hier ist ein konkretes Beispiel für eine Strategie:
p, jojo, cake, eatp zeigt an, dass dies eine Strategie-Regeldefinition ist, jojo ist das Strategie-Subjekt, cake ist das Strategie-Objekt, eat ist die Aktion. Die vollständige Bedeutung ist: Das Subjekt jojo kann die Aktion eat auf dem Objekt cake ausführen. Die konkreten Strategieregeln erscheinen nicht in der Model-Datei, sondern werden in separaten Policy-Dateien oder Datenbanken gespeichert.
Anfrage (Request)
In der Konfigurationsdatei lautet der Anfrage-Definitionsteil:
[request_definition]
r = sub, obj, actr steht für request und kann nicht durch andere Zeichen ersetzt werden. sub steht für subject (Anfragesubjekt), obj für object (Anfrageobjekt), act für action (Anfrageaktion). Normalerweise sind die Feldnamen der Anfragedefinition mit denen der Strategiedefinition identisch. Der Anfrage-Teil wird nicht von Casbin verwaltet; der Entwickler entscheidet selbst, was das Anfragesubjekt und das Anfrageobjekt ist. Casbin ist nur für die Zugangskontrolle basierend auf den übergebenen Feldern verantwortlich.
Matcher (Vergleicher)
In der Konfigurationsdatei lautet der Matcher-Definitionsteil:
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.actm steht für matcher und kann nicht durch andere Zeichen ersetzt werden. Danach folgen die entsprechenden Vergleichsregeln. Das Obige ist ein einfacher boolescher Ausdruck, der bedeutet: Alle Felder der eingehenden Anfrage stimmen mit den Feldern der Strategieregel überein. Es können auch Wildcards oder ausdrucksstärkere reguläre Ausdrücke verwendet werden.
Darüber hinaus unterstützt der Matcher auch die in-Syntax, zum Beispiel:
[matchers]
m = r.sub in ("root","admin")Es kann auch sein:
[matchers]
m = r.sub.Name in (r.obj.Admins)e.Enforce(Sub{Name: "alice"}, Obj{Name: "a book", Admins: []interface{}{"alice", "bob"}})Beim Vergleich führt Casbin keine Typprüfung durch, sondern prüft als interface mit == auf Gleichheit.
Effekt (Effect)
Der Effekt-Definitionsteil trifft weitere logische Kombinationsentscheidungen für das Vergleichsergebnis. In der Konfigurationsdatei lautet der Effekt-Definitionsteil:
[policy_effect]
e = some(where (p.eft == allow))e steht für effect und kann nicht durch andere Zeichen ersetzt werden. Der Quantor some prüft, ob es eine Strategieregel gibt, die dem Matcher entspricht. Der Quantor any prüft, ob alle Strategieregeln dem Matcher entsprechen.
some(where (p.eft == allow))Diese Regel bedeutet: Wenn es in den Vergleichsergebnissen ein allow gibt, ist das Endergebnis allow.
e = !some(where (p.eft == deny))Diese Regel bedeutet: Wenn es in den Vergleichsergebnissen kein deny gibt, ist das Endergebnis allow.
e = some(where (p.eft == allow)) && !some(where (p.eft == deny))Diese Regel bedeutet: Wenn es in den Vergleichsergebnissen ein allow gibt und kein deny, ist das Endergebnis allow.
Obwohl Casbin die oben genannte Syntax für Richtlinieneffekte entworfen hat, verwendet die aktuelle Ausführung nur hartcodierte Richtlinieneffekte. Es wird angenommen, dass diese Flexibilität nicht sehr notwendig ist. Bis jetzt müssen Sie die integrierten Policy-Effects verwenden und können diese nicht anpassen. Die unterstützten integrierten Policy-Effects sind:
| Policy-Effect-Definition | Bedeutung | Beispiel |
|---|---|---|
| some(where (p.eft == allow)) | allow-override | ACL, RBAC, etc. |
| !some(where (p.eft == deny)) | deny-override | Ablehnung überschreiben |
| some(where (p.eft == allow)) && !some(where (p.eft == deny)) | allow-and-deny | Erlauben und Ablehnen |
| priority(p.eft) || deny | priority | Priorität |
| subjectPriority(p.eft) | rollenbasierte Priorität | Subjekt-Priorität |
TIP
Alle vier Definitionen können mehrfach definiert werden, die Syntax ist
type+number, zum Beispielr2,p2,e2,m2.Model-Dateien können Kommentare enthalten, die mit
#eingeleitet werden.
Beispiel
Hier ist ein Beispiel, das den Arbeitsprozess der Model-Datei demonstriert. Zuerst definieren wir eine einfache ACL-Model-Datei:
[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.actDie Policy-Datei sieht wie folgt aus:
p, alice, data1, read
p, bob, data2, writeWie Subjekt, Objekt und Aktion abstrahiert werden, wird durch die Geschäftslogik bestimmt und ist hier nicht wichtig, daher wird es weggelassen. Im Folgenden werden die eingehenden Anfragen auf einfachste Weise dargestellt:
alice, data1, read
bob, data1, read
alice, data2, write
bob, data2, writeDie Policy-Datei definiert, dass alice die Berechtigung hat, data1 zu lesen, und bob die Berechtigung hat, data2 zu schreiben. Bei den eingehenden Anfragen:
alice, data1, readbedeutet, dass alice eine read-Operation auf data1 durchführen möchte.
bob, data1, readbedeutet, dass bob eine read-Operation auf data1 durchführen möchte. Der Rest ist analog. Das Endergebnis lautet:
true
false
false
trueDies ist ein einfaches ACL-Beispiel. Auf der Casbin-Website können Sie Beispiele online bearbeiten und testen. Besuchen Sie Casbin editor zum Testen.
RBAC
RBAC (Role-Based-Access-Control), rollenbasierte Zugangskontrolle, hat im Vergleich zum ACL-Modell eine zusätzliche [role_definition]. Hier ist ein einfaches RBAC-Modell:
[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.actDie Rollendefinition lautet:
[role_definition]
g = _, _g steht für group und kann nicht durch andere Zeichen ersetzt werden. Es unterstützt die type+number-Methode zur Erstellung mehrerer Definitionen. _ ist ein Platzhalter, der angibt, wie viele Eingabeparameter es gibt. Normalerweise hat g in der Policy folgendes Format:
g, alice, data2_admin
g, mike, data1_admin
g, data1_admin data2_adminalice bezieht sich auf das Subjekt, data2_admin auf die Rolle. Streng genommen betrachtet Casbin alles als Zeichenketten; wie sie verstanden und verwendet werden, hängt vom Entwickler ab.
g, alice, data2_adminbedeutet, dass alice die Rolle data2_admin hat.
g, mike, data1_adminbedeutet, dass mike die Rolle data1_admin hat.
g, data1_admin data2_adminbedeutet, dass die Rolle data1_admin die Rolle data2_admin hat. Dies ist eine Vererbungsbeziehung zwischen Rollen.
Ressourcenrollen-Modell
Das Ressourcenrollen-Modell fügt ein g2 als Ressourcenrollendefinition hinzu. Die Modelldefinition lautet:
[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.actEin Beispiel für die Policy-Definition:
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_groupg2 definiert Ressourcenrollengruppen und weist Ressourcen verschiedenen Rollen zu. Gleichzeitig werden die Benutzerbeziehungen zwischen Benutzerrollen und Ressourcenrollen definiert.
p, data_group_admin, data_group, writeDiese Strategie definiert, dass Benutzer mit der Rolle data_group_admin Schreiboperationen auf Ressourcen mit der Rolle data_group durchführen können.
Multi-Tenant-Domain-Modell
[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.actDas Multi-Tenant-Domain-Modell hat im Vergleich zum traditionellen RBAC-Modell ein zusätzliches dom-Feld, das die Domain angibt, zu der das Subjekt gehört. Ein Beispiel für die Policy:
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, domain2Zum Beispiel:
p, admin, domain1, data1, readdefiniert, dass das Subjekt admin in der Domain domain1 die Berechtigung hat, data1 zu lesen.
g, alice, admin, domain1definiert, dass alice zur Domain domain1 gehört und die Rolle admin hat.
