Skip to main content

Rego als allgemeine Policy-Sprache verwenden

Artikel von
Headshot of Dickson Boateng

Dickson Boateng

feature iac drift blue

3. Juni 2022

0 Min. Lesezeit

Policies spielen in jeder Organisation eine wichtige Rolle, können je nach Kontext jedoch ganz Unterschiedliches bedeuten. In diesem Beitrag verstehen wir unter einer Policy die Grundsätze oder Ideen, nach denen eine Organisation Entscheidungen trifft.

In diesem Beitrag sprechen wir über den Open Policy Agent (OPA) und seine Regelsprache Rego. Dabei zeigen wir, wie sich damit eine einfache Policy für einen Payroll-Microservice schreiben lässt.

Was ist eine Policy?

In Softwaresystemen sind Policies Regeln, die steuern, wie ein System funktioniert. Computer und Menschen nutzen Policies häufig, um Fragen wie diese zu beantworten:

  • Darf Benutzer A die Konfiguration von Service X ändern?

  • In welcher Domäne sollten wir Anwendung X installieren?

  • Welche Vorgänge befinden sich in der falschen geografischen Region?

Wie wir eine Policy definieren und durchsetzen, hängt von mehreren Faktoren ab, etwa von der Technologie, für die sie gilt, und davon, wie klar sie formuliert ist. In manchen Fällen ist eine Policy nicht dokumentiertes Wissen. Wenn wir dann ein System ändern oder verstehen möchten, wie es funktionieren soll, müssen wir eine andere Person fragen. Mit der Zeit halten wir die Antworten schriftlich fest, doch diese Dokumente sind irgendwann veraltet.

Ein anderer Ansatz besteht darin, Policies fest in Softwaresysteme zu codieren. Leider ändern sich Policies im Laufe der Zeit. Neben nahezu ständigen Aktualisierungen und erneuten Schulungen erfordert die Änderung fest codierter Policies eine umfassende, gründliche Prüfung des Codes, um zu verstehen, was angepasst werden muss. Dadurch sind Policies schwerer zugänglich und Änderungen zeitaufwendiger.

Open Policy Agent im Überblick

Herkömmliche Ansätze für das Policy-Management bieten nur geringe Gewähr für die Durchsetzung und sind kostspielig in der Wartung. Eine moderne Lösung für dieses Problem ist der Open Policy Agent (OPA, ausgesprochen „OH-pa“).

OPA ist eine Open-Source-Policy-Engine für allgemeine Zwecke. Sie dient dazu, Policies in verschiedenen Systemen zu definieren, darunter Microservices, API-Gateways, CI/CD-Pipelines und Kubernetes. Mit OPA lassen sich Policies als Code schreiben und anschließend in den Entscheidungsprozess einbinden.

Mit OPA definieren wir Regeln, die das Verhalten eines Systems steuern. Diese Regeln beantworten Fragen wie:

  • Darf Benutzer A eine GET-Anfrage an diesen Service senden?

  • Welche Datensätze darf Benutzer B anzeigen?

  • Auf welchem Server sollten wir Anwendung X bereitstellen?

Wenn wir eine Policy-Entscheidung anfordern, analysiert OPA die von uns bereitgestellten Regeln und Daten und erstellt eine Antwort. Der Service, der die Entscheidung angefordert hat, setzt sie durch. Anders gesagt: OPA trifft die Policy-Entscheidung, während die in OPA integrierten Services für deren Umsetzung zuständig sind. Das folgende Diagramm zeigt den allgemeinen OPA-Workflow:

Diagramm, das zeigt, wie eine Benutzeranfrage einen Dienst erreicht, der eine JSON-Richtlinienabfrage an eine OPA Engine sendet und eine JSON-Richtlinienentscheidung erhält.

Um den gesamten OPA-Workflow zu verstehen, sehen wir uns an, wie OPA Anfragen in einem einfachen API-Autorisierungsfall verarbeitet. Dabei definieren wir Regeln, die den Zugriff auf bestimmte API-Services erlauben oder verweigern. Empfängt ein Service eine API-Anfrage, sendet er eine Abfrage an OPA. OPA gleicht die Abfrage mit vorhandenen Policies und Daten ab und gibt die Entscheidung „allow“ oder „deny“ zurück. Schließlich setzt der Service die Entscheidung von OPA um, indem er die API-Anfrage genehmigt oder ablehnt.

Die Policy-Sprache von OPA: Rego

OPA-Policies schreiben wir in einer deklarativen Hochsprache namens Rego (ausgesprochen „RAY-go“). Mit Rego lassen sich skalierbare Policy-Entscheidungen für unterschiedliche Arten von Services formulieren. Wir verwenden Rego, um die als Eingabe bereitgestellten Daten auszuwerten und darauf basierend Policy-Entscheidungen zu treffen. Wichtig ist: Rego ist keine Programmiersprache zum Erstellen von Software, sondern eine deklarative Sprache zum Formulieren von Regeln – ähnlich einer Abfragesprache wie SQL.

Rego ist eine Policy-Sprache für allgemeine Zwecke und funktioniert daher mit verschiedenen Systemen. Rego verarbeitet ausschließlich JSON-Daten. Solange die benötigten Daten im JSON-Format vorliegen, können wir eine Policy für jeden Service schreiben. So lassen sich mit Rego systemübergreifende Policies erstellen.

Ihre erste OPA-Policy schreiben

Schreiben wir nun eine einfache Policy mit Rego und testen sie im Rego Playground, einer interaktiven Online-Plattform. Die Policy legt fest, welche Benutzer auf Gehaltsinformationen in einem Payroll-Microservice zugreifen dürfen.

Löschen Sie zunächst den gesamten vorhandenen Code im Hauptfenster des Rego Playgrounds und ersetzen Sie ihn durch Folgendes:

package play 
default allow = false
# Users can only view their salary info
allow = true { 
    input.method = "GET" 
    input.path = ["getSalary", user_id] 
    input.user = user_id 
}

Sehen wir uns nun den obigen Codeausschnitt genauer an:

  • Die erste Zeile unserer Policy enthält den Paketnamen. Jede Rego-Policy hat einen Paketnamen, der ihren Geltungsbereich festlegt.

  • Die nächste Zeile legt fest, dass der Wert von allow standardmäßig false ist.

  • Das Rautezeichen (#) leitet einen Kommentar ein und enthält einfache Erläuterungen zum geschriebenen Code.

  • allow = true bedeutet, dass allow den Wert true erhält, wenn alle Ausdrücke in den Klammern true sind.

  • Die Ausdrücke in den Klammern bedeuten schließlich, dass Anfragen zugelassen werden, wenn die Eingabemethode GET lautet, der Pfad /getSalary/user_id ist und der Benutzer mit der user_id übereinstimmt. Beachten Sie, dass die Variable input JSON-Daten darstellt, die wir Rego bereitstellen.

Im Rego Playground können wir Code auswerten und prüfen, ob die Policy wie erwartet funktioniert. Im Eingabefeld können wir also eine Anfrage simulieren, indem wir folgenden Code hinzufügen:

{ 
    "method": "GET", 
    "path": ["getSalary","John"], 
    "user": "John" 
}

Klicken wir nun auf die Schaltfläche Evaluate, um zu sehen, wie OPA auf die obige Anfrage reagiert. Im Ausgabefeld sollte etwa Folgendes angezeigt werden:

{
    "allow": true 
}

Hier sehen Sie eine Momentaufnahme des Playgrounds nach Abschluss aller Schritte:

Die Rego-Playground-Oberfläche zeigt eine Richtlinie, die es Nutzern erlaubt, ihr eigenes Gehalt einzusehen. Eine GET-Anfrage für John gibt „allow“: true zurück.

Testen wir unsere Policy erneut, indem wir den Wert von user in der Anfrage in Jane ändern. Damit versucht ein Benutzer, die Gehaltsinformationen einer anderen Person einzusehen. Wenn wir auf Evaluate klicken, wird das folgende erwartete Ergebnis angezeigt:

{
    "allow": false
}

Als Nächstes aktualisieren wir die Policy, damit Mitarbeitende der Finanzabteilung die Gehaltsinformationen aller Benutzer einsehen können. Dazu ergänzen wir die zuvor definierte Policy um folgenden Code:

#finance department workers can view every user's salary info
allow = true { 
    input.method = "GET" 
    input.path = ["getSalary", user_id] 
    finance[input.user] 
} 
finance = {"Ruth","Josh","Vivian"}

In unserem neuen Policy-Code haben wir ein finance-Objekt definiert und die Namen aller Mitarbeitenden der Finanzabteilung hinzugefügt.

Testen Sie die Policy, indem Sie für user und user_id denselben Namen einsetzen (z. B. Joe). Die Policy sollte true zurückgeben. Ändern Sie nun user in John, einen Mitarbeiter der Finanzabteilung, und führen Sie die Policy aus. Auch jetzt sollte sie true zurückgeben. Ändern Sie user schließlich in einen Namen, der nicht im finance-Objekt aufgeführt ist (z. B. Jane). Diesmal sollte die Policy false zurückgeben.

Alles zusammenführen

Wenn wir alle Codeausschnitte zusammenführen, erhalten wir unsere neue Policy:

package play 
default allow = false
# Users should have access to view their salary 
allow = true { 
    input.method = "GET" 
    input.path = ["getSalary", user_id] 
    input.user = user_id 
}
allow = true { 
    input.method = "GET" 
    input.path = ["getSalary", user_id] 
    finance[input.user] 
} 
finance = {"John","Mary","Peter","Vivian"}

Die Zukunft der individuellen Policy-Gestaltung

Nachdem Sie nun wissen, wie Sie mit OPA und Rego neue Policies schreiben, müssen Sie diese warten und scannen, damit sie frei von Schwachstellen bleiben. Mit Snyk Infrastructure as Code (Snyk IaC), das OPA für Policy-Scans nutzt, können Sie Ihre neuen und bestehenden Policies mit wenigen einfachen Befehlen in Ihre Scans aufnehmen. Weitere Informationen finden Sie in der Snyk-IaC-Dokumentation und in unserem Artikel Individuelle IaC-Regeln mit Snyk entwickeln.

Legen Sie jetzt Ihr kostenloses Snyk-Konto an und finden und beheben Sie IaC-Fehlkonfigurationen direkt in Ihrem Workflow – mit integrierten Sicherheitsprüfungen, Policy-Leitplanken und entwicklerfreundlichen Empfehlungen zur Problembehebung.

Sichern Sie Ihre Infrastruktur an der Quelle

Snyk automatisiert die IaC-Sicherheit und Compliance in Workflows und erkennt abweichende sowie fehlende Ressourcen.