RBAC with API Gateway and Open Policy Agent (OPA)

Bobur Umurzokov

Bobur Umurzokov

May 15, 2023

Technology

Mit verschiedenen Zugriffskontrollmodellen und Implementierungsmethoden, die zur Verfügung stehen, kann der Aufbau eines Autorisierungssystems für Backend-Service-APIs immer noch eine Herausforderung darstellen. Das ultimative Ziel ist jedoch sicherzustellen, dass die richtige Person den entsprechenden Zugriff auf die relevanten Ressourcen hat. In diesem Artikel werden wir diskutieren, wie Sie das rollenbasierte Zugriffskontrollmodell (RBAC) für Ihre API mit dem Open-Source-API-Gateway Apache APISIX und Open Policy Agent (OPA) aktivieren können.

Lernziele

Sie werden im Laufe des Artikels Folgendes lernen:

  • Was ist RBAC und wie funktioniert es?
  • Was ist OPA und wie funktioniert es?
  • Wie implementiert man RBAC mit OPA und Apache APISIX?
  • Wie definiert und registriert man die Richtlinie in OPA.
  • Wie erstellt man ein Upstream, eine Route und aktiviert das OPA-Plugin.
  • Wie die Rolle und Berechtigung des Benutzers aus dem JWT-Token-Payload oder den Consumer-Daten extrahiert wird.

Was ist RBAC?

Rollenbasierte Zugriffskontrolle (RBAC) und Attributbasierte Zugriffskontrolle (ABAC) sind zwei häufig verwendete Zugriffskontrollmodelle, die verwendet werden, um Berechtigungen zu verwalten und den Zugriff auf Ressourcen in Computersystemen zu steuern. RBAC weist Benutzern Berechtigungen basierend auf ihrer Rolle innerhalb einer Organisation zu. In RBAC werden Rollen basierend auf den Funktionen oder Verantwortlichkeiten der Benutzer definiert, und Berechtigungen werden diesen Rollen zugewiesen. Benutzer werden dann einer oder mehreren Rollen zugewiesen und erben die mit diesen Rollen verbundenen Berechtigungen. Im API-Kontext könnte beispielsweise eine Entwicklerrolle die Berechtigung haben, API-Ressourcen zu erstellen und zu aktualisieren, während eine Endbenutzerrolle möglicherweise nur die Berechtigung hat, API-Ressourcen zu lesen oder auszuführen.

Grundsätzlich weist RBAC Berechtigungen basierend auf Benutzerrollen zu, während ABAC Berechtigungen basierend auf Attributen zuweist, die mit Benutzern und Ressourcen verbunden sind.

In RBAC wird eine Richtlinie durch die Kombination der zugewiesenen Rolle eines Benutzers, der Aktionen, die er ausführen darf, und der Ressourcen, auf denen er diese Aktionen ausführen kann, definiert.

Was ist OPA?

OPA (Open Policy Agent) ist eine Policy-Engine und eine Reihe von Tools, die einen einheitlichen Ansatz zur Durchsetzung von Richtlinien in einem gesamten verteilten System bieten. Es ermöglicht Ihnen, Richtlinien zentral von einem einzigen Punkt aus zu definieren, zu verwalten und durchzusetzen. Durch die Definition von Richtlinien als Code ermöglicht OPA eine einfache Überprüfung, Bearbeitung und Rücknahme von Richtlinien, was ein effizientes Richtlinienmanagement erleichtert.

Open Policy Agent Beispielbild

OPA bietet eine deklarative Sprache namens Rego, mit der Sie Richtlinien in Ihrem gesamten Stack erstellen und durchsetzen können. Wenn Sie eine Richtlinienentscheidung von OPA anfordern, verwendet es die Regeln und Daten, die Sie in einer .rego-Datei bereitgestellt haben, um die Abfrage zu bewerten und eine Antwort zu erzeugen. Das Abfrageergebnis wird dann als Richtlinienentscheidung an Sie zurückgesendet. OPA speichert alle Richtlinien und die benötigten Daten in seinem In-Memory-Cache. Dadurch gibt OPA Ergebnisse schnell zurück. Hier ist ein Beispiel für eine einfache OPA-Rego-Datei:

package example

default allow = false

allow {
    input.method == "GET"
    input.path =="/api/resource"
    input.user.role == "admin"
}

In diesem Beispiel haben wir ein Paket namens "example", das eine Regel namens "allow" definiert. Die "allow"-Regel gibt an, dass die Anfrage erlaubt ist, wenn die Eingabemethode "GET" ist, der angeforderte Pfad /api/resource ist und die Rolle des Benutzers "admin" ist. Wenn diese Bedingungen erfüllt sind, wird die "allow"-Regel als "true" bewertet, wodurch die Anfrage fortgesetzt werden kann.

Warum OPA und API-Gateway für RBAC verwenden?

API-Gateways bieten einen zentralen Ort, um APIs und API-Consumer zu konfigurieren und zu verwalten. Es kann als zentrales Authentifizierungsgateway verwendet werden, indem verhindert wird, dass jeder einzelne Dienst die Authentifizierungslogik im Dienst selbst implementiert. Andererseits fügt OPA eine Autorisierungsschicht hinzu und entkoppelt die Richtlinie vom Code, wodurch ein deutlicher Vorteil für die Autorisierung entsteht. Mit dieser Kombination können Sie Berechtigungen für eine API-Ressource einer Rolle hinzufügen. Benutzer können einer oder mehreren Benutzerrollen zugeordnet sein. Jede Benutzerrolle definiert eine Reihe von Berechtigungen (GET, PUT, DELETE) für RBAC-Ressourcen (definiert durch URI-Pfade). Im nächsten Abschnitt lernen wir, wie man RBAC mit diesen beiden erreicht.

Open Policy Agent mit Apache APISIX API-Gateway

Wie implementiert man RBAC mit OPA und Apache APISIX

In Apache APISIX können Sie Routen und Plugins konfigurieren, um das Verhalten Ihrer API zu definieren. Sie können das APISIX opa-Plugin verwenden, um RBAC-Richtlinien durchzusetzen, indem Anfragen an OPA zur Entscheidungsfindung weitergeleitet werden. Dann trifft OPA eine Autorisierungsentscheidung basierend auf den Rollen und Berechtigungen der Benutzer in Echtzeit.

Angenommen, wir haben eine Conference API, über die Sie Veranstaltungssitzungen, Themen und Sprecherinformationen abrufen/bearbeiten können. Ein Sprecher kann nur seine eigenen Sitzungen und Themen lesen, während der Administrator weitere Sitzungen und Themen hinzufügen/bearbeiten kann. Oder Teilnehmer können ihr Feedback zur Sitzung des Sprechers über eine POST-Anfrage an /speaker/speakerId/session/feedback hinterlassen, und der Sprecher kann dies nur sehen, indem er die GET-Methode derselben URI anfordert. Das folgende Diagramm veranschaulicht das gesamte Szenario:

Open Policy Agent mit Apache APISIX

  1. Der API-Consumer fordert eine Route auf dem API-Gateway mit seinen Anmeldeinformationen wie einem JWT-Token im Autorisierungsheader an.
  2. Das API-Gateway sendet die Consumer-Daten mit einem JWT-Header an die OPA-Engine.
  3. OPA bewertet, ob der Consumer das Recht hat, auf die Ressource zuzugreifen, indem es die Richtlinien (Rollen und Berechtigungen) verwendet, die wir in der .rego-Datei angegeben haben.
  4. Wenn die OPA-Entscheidung erlaubt ist, wird die Anfrage an den Upstream-Conference-Dienst weitergeleitet.

Als Nächstes installieren und konfigurieren wir APISIX und definieren Richtlinien in OPA.

Voraussetzungen

  • Docker wird verwendet, um den containerisierten etcd und APISIX zu installieren.
  • curl wird verwendet, um Anfragen an die APISIX-Admin-API zu senden. Sie können auch Tools wie Postman verwenden, um mit der API zu interagieren.

Schritt 1: Apache APISIX installieren

APISIX kann einfach mit dem folgenden Quickstart-Skript installiert und gestartet werden:

curl -sL https://run.api7.ai/apisix/quickstart | sh

Schritt 2: Den Backend-Dienst (Upstream) konfigurieren

Um Anfragen an den Backend-Dienst für die Conference API weiterzuleiten, müssen Sie diesen konfigurieren, indem Sie einen Upstream-Server in Apache APISIX über die Admin-API hinzufügen.

curl http://127.0.0.1:9180/apisix/admin/upstreams/1 -X PUT -d '
{
   "name":"Conferences API upstream",
   "desc":"Register Conferences API as the upstream",
   "type":"roundrobin",
   "scheme":"https",
   "nodes":{
      "conferenceapi.azurewebsites.net:443":1
   }
}'

Schritt 3: Einen API-Consumer erstellen

Als Nächstes erstellen wir einen Consumer (einen neuen Sprecher) mit dem Benutzernamen jack in Apache APISIX. Es richtet das jwt-auth-Plugin für den Consumer mit dem angegebenen Schlüssel und Geheimnis ein. Dies ermöglicht es dem Consumer, sich mit einem JSON Web Token (JWT) zu authentifizieren.

curl http://127.0.0.1:9180/apisix/admin/consumers -X PUT -d '
{
    "username": "jack",
    "plugins": {
        "jwt-auth": {
            "key": "user-key",
            "secret": "my-secret-key"
        }
    }
}'

Schritt 4: Einen öffentlichen Endpunkt zum Generieren eines JWT-Tokens erstellen

Sie müssen auch eine neue Route einrichten, die das Token mit dem public-api-Plugin generiert und signiert. In diesem Szenario fungiert das API-Gateway als Identitätsanbieter-Server, um das Token mit dem Schlüssel unseres Consumers Jack zu erstellen und zu überprüfen. Der Identitätsanbieter kann auch ein anderer Drittanbieterdienst wie Google, Okta, Keycloak oder Ory Hydra sein.

curl http://127.0.0.1:9180/apisix/admin/routes/jas -X PUT -d '
{
    "uri": "/apisix/plugin/jwt/sign",
    "plugins": {
        "public-api": {}
    }
}'

Schritt 5: Ein neues JWT-Token für den API-Consumer beanspruchen

Jetzt können wir ein neues Token für unseren Sprecher Jack vom API-Gateway über den von uns erstellten öffentlichen Endpunkt erhalten. Der folgende curl-Befehl generiert ein neues Token mit den Anmeldeinformationen von Jack und weist die Rolle und Berechtigung im Payload zu.

curl -G --data-urlencode 'payload={"role":"speaker","permission":"read"}' http://127.0.0.1:9080/apisix/plugin/jwt/sign?key=user-key -i

Nachdem Sie den obigen Befehl ausgeführt haben, erhalten Sie ein Token als Antwort. Speichern Sie dieses Token an einem sicheren Ort, da wir es später verwenden werden, um auf unseren neuen API-Gateway-Endpunkt zuzugreifen.

Schritt 6: Eine neue Plugin-Konfiguration erstellen

Dieser Schritt beinhaltet die Konfiguration von 3 Plugins von APISIX: proxy-rewrite, jwt-auth und opa.

curl "http://127.0.0.1:9180/apisix/admin/plugin_configs/1" -X PUT -d '
{
   "plugins":{
      "jwt-auth":{
      },
      "proxy-rewrite":{
         "host":"conferenceapi.azurewebsites.net"
      }
   }
}'
  • Das proxy-rewrite-Plugin ist so konfiguriert, dass Anfragen an den Host conferenceapi.azurewebsites.net weitergeleitet werden.
  • Das OPA-Authentifizierungs-Plugin ist so konfiguriert, dass es die OPA-Policy-Engine verwendet, die unter http://localhost:8181/v1/data/rbacExample läuft. Außerdem sendet APISIX alle Consumer-bezogenen Informationen an OPA. Wir werden diese Richtlinien-.rego-Datei im OPA-Konfigurationsabschnitt hinzufügen.

Schritt 7: Eine Route für Conference-Sitzungen erstellen

Der letzte Schritt besteht darin, eine neue Route für die Conference-API-Sprechersitzungen zu erstellen:

curl "http://127.0.0.1:9180/apisix/admin/routes/1" -X PUT -d '
{
    "name":"Conferences API speaker sessions route",
    "desc":"Create a new route in APISIX for the Conferences API speaker sessions",
    "methods": ["GET", "POST"],
    "uris": ["/speaker/*/topics","/speaker/*/sessions"],
    "upstream_id":"1",
    "plugin_config_id":1
}'

Die Payload enthält Informationen über die Route, wie ihren Namen, Beschreibung, Methoden, URIs, Upstream-ID und Plugin-Konfigurations-ID. In diesem Fall ist die Route so konfiguriert, dass sie GET- und POST-Anfragen für zwei verschiedene URIs, /speaker/topics und /speaker/sessions, verarbeitet. Das Feld "upstream_id" gibt die ID des Upstream-Dienstes an, der eingehende Anfragen für diese Route verarbeitet, während das Feld "plugin_config_id" die ID der Plugin-Konfiguration angibt, die für diese Route verwendet werden soll.

Schritt 8: Das Setup ohne OPA testen

Bisher haben wir alle notwendigen Konfigurationen für APISIX eingerichtet, um eingehende Anfragen an die Conference-API-Endpoints weiterzuleiten, wobei nur autorisierte API-Consumer zugelassen sind. Jedes Mal, wenn ein API-Consumer auf einen Endpunkt zugreifen möchte, muss er ein JWT-Token bereitstellen, um Daten vom Conference-Backend-Dienst abzurufen. Sie können dies überprüfen, indem Sie den Endpunkt aufrufen, und die Domain-Adresse, die wir jetzt anfordern, ist unser benutzerdefiniertes API-Gateway, nicht der eigentliche Conference-Dienst:

curl -i http://127.0.0.1:9080/speaker/1/topics -H 'Authorization: {API_CONSUMER_TOKEN}'

Schritt 9: Den OPA-Dienst ausführen

Die anderen beiden Schritte bestehen darin, den OPA-Dienst mit Docker auszuführen und unsere Richtliniendefinition über seine API hochzuladen, die verwendet werden kann, um Autorisierungsrichtlinien für eingehende Anfragen zu bewerten.

docker run -d --network=apisix-quickstart-net --name opa -p 8181:8181 openpolicyagent/opa:latest run -s

Dieser Docker-Befehl führt einen Container des OPA-Images mit der neuesten Version aus. Es erstellt einen neuen Container im bestehenden APISIX-Netzwerk apisix-quickstart-net mit dem Namen opa und macht Port 8181 verfügbar. So kann APISIX Richtlinienprüfanfragen direkt an OPA unter der Adresse [http://opa:8181](http://opa:8181) senden. Beachten Sie, dass OPA und APISIX im selben Docker-Netzwerk laufen sollten.

Schritt 10: Die Richtlinie definieren und registrieren

Der zweite Schritt auf der OPA-Seite besteht darin, die Richtlinien zu definieren, die verwendet werden, um den Zugriff auf API-Ressourcen zu steuern. Diese Richtlinien sollten die für den Zugriff erforderlichen Attribute definieren (Welche Benutzer haben welche Rollen) und die Berechtigungen (Welche Rollen haben welche Berechtigungen), die basierend auf diesen Attributen erlaubt oder verweigert werden. In der folgenden Konfiguration sagen wir OPA beispielsweise, dass es die user_roles-Tabelle überprüfen soll, um die Rolle für jack zu ermitteln. Diese Informationen werden von APISIX innerhalb von input.consumer.username gesendet. Außerdem überprüfen wir die Berechtigung des Consumers, indem wir den JWT-Payload lesen und token.payload.permission daraus extrahieren. Die Kommentare beschreiben die Schritte klar.

curl -X PUT '127.0.0.1:8181/v1/policies/rbacExample' \
    -H 'Content-Type: text/plain' \
    -d 'package rbacExample

# Zuweisung von Benutzerrollen

user_roles := {
    "jack": ["speaker"],
    "bobur":["admin"]
}

# Rollenberechtigungszuweisungen
role_permissions := {
    "speaker": [{"permission": "read"}],
    "admin":   [{"permission": "read"}, {"permission": "write"}]
}

# Hilfsfunktionen für JWT
bearer_token := t {
 t := input.request.headers.authorization
}

# Dekodieren des Autorisierungstokens, um eine Rolle und Berechtigung zu erhalten
token = {"payload": payload} {
 [_, payload, _] := io.jwt.decode(bearer_token)
}

# Logik, die RBAC implementiert
default allow = false

allow {
    # Nachschlagen der Liste der Rollen für den Benutzer
    roles := user_roles[input.consumer.username]

    # Für jede Rolle in dieser Liste
    r := roles[_]

    # Nachschlagen der Berechtigungsliste für die Rolle r
    permissions := role_permissions[r]

    # Für jede Berechtigung
    p := permissions[_]

    # Überprüfen, ob die für r gewährte Berechtigung der Benutzeranfrage entspricht
    p == {"permission": token.payload.permission}
}'

Schritt 11: Die bestehende Plugin-Konfiguration mit dem OPA-Plugin aktualisieren

Sobald wir die Richtlinien auf dem OPA-Dienst definiert haben, müssen wir die bestehende Plugin-Konfiguration für die Route aktualisieren, um das OPA-Plugin zu verwenden. Wir geben dies im policy-Attribut des OPA-Plugins an.

curl "http://127.0.0.1:9180/apisix/admin/plugin_configs/1" -X PATCH -d '
{
   "plugins":{
      "opa":{
         "host":"http://opa:8181",
         "policy":"rbacExample",
         "with_consumer":true
      }
   }
}'

Schritt 12: Das Setup mit OPA testen

Jetzt können wir alle Setups, die wir mit OPA-Richtlinien durchgeführt haben, testen. Wenn Sie versuchen, denselben curl-Befehl auszuführen, um auf den API-Gateway-Endpunkt zuzugreifen, überprüft es zuerst das JWT-Token als Teil des Authentifizierungsprozesses und sendet die Consumer- und JWT-Token-Daten an OPA, um die Rolle und Berechtigung als Teil des Autorisierungsprozesses zu überprüfen. Jede Anfrage ohne ein JWT-Token oder ohne die erlaubten Rollen wird abgelehnt.

curl -i http://127.0.0.1:9080/speaker/1/topics -H 'Authorization: {API_CONSUMER_TOKEN}'

Fazit

In diesem Artikel haben wir gelernt, wie man RBAC mit OPA und Apache APISIX implementiert. Wir haben eine einfache benutzerdefinierte Richtlinienlogik definiert, um den Zugriff auf API-Ressourcen basierend auf der Rolle und den Berechtigungen unseres API-Consumers zu erlauben/zu verweigern. Außerdem hat dieses Tutorial gezeigt, wie wir API-Consumer-bezogene Informationen in der Richtliniendatei aus dem JWT-Token-Payload oder dem Consumer-Objekt, das von APISIX gesendet wird, extrahieren können.

Verwandte Ressourcen

Empfohlene Inhalte

Tags: