Skip to main content

Rego 101: Einführung in Rego

Artikel von
feature cloud security

2. November 2023

0 Min. Lesezeit

Diese Blogbeitragsreihe bietet eine leicht verständliche Einführung in Rego, die Policy-Sprache der Entwickler der Open Policy Agent (OPA)-Engine. Wenn Sie Anfänger sind und mit dem Schreiben von Rego-Policy-as-Code beginnen möchten, sind Sie hier genau richtig.

In dieser dreiteiligen Reihe behandeln wir Folgendes:

  • Teil 1 (dieser Teil!): Rego-Grundlagen und die ersten Schritte mit OPA

  • Teil 2: Rego-Syntax für Fortgeschrittene

  • Teil 3: Wertetypen und Regeln

Was sind Rego und OPA?

Rego ist eine deklarative Abfragesprache von den Entwicklern des Open Policy Agent (OPA)-Frameworks. Die Cloud Native Computing Foundation (CNCF) nahm OPA im April 2019 als gehostetes Projekt im Inkubationsstatus auf. 2021 schloss OPA die Inkubationsphase ab.

Rego dient zum Schreiben von Policy-as-Code. Dabei werden Programmierpraktiken wie Versionskontrolle und modularer Entwurf auf die Bewertung von Cloud- und Infrastructure-as-Code-Ressourcen (IaC) angewendet.

OPA ist die Engine, die in Rego geschriebene Policy-as-Code-Regeln auswertet. Sie „entkoppelt die Policy-Entscheidung von der Durchsetzung der Policy“. Das bedeutet: Sie liefert eine Entscheidung darüber, ob eine Ressource den Richtlinien entspricht. So müssen Sie diese Prüfungen nicht fest in Ihren Anwendungscode integrieren.

Wenn Sie die Richtlinien von Ihrer Software trennen und die Policy-Prüfungen an OPA auslagern, gewinnen Sie an Geschwindigkeit und Flexibilität im Entwicklungslebenszyklus. Sie können Richtlinien jederzeit aktualisieren, ohne Ihre Anwendung neu kompilieren oder Ihren Service erneut bereitstellen zu müssen. So können Sie skalierbar entwickeln, den Überblick über Ihren Compliance-Status verbessern und Richtlinien programmgesteuert durchsetzen. Policy-as-Code bietet außerdem den Vorteil, die Cloud- und IaC-Entwicklung nach „links“ zu verschieben – also früher im Lebenszyklus anzusetzen.

Bei Snyk werden vorkonfigurierte und benutzerdefinierte Regeln für Snyk IaC+ in Rego geschrieben. Im Hintergrund verwendet Snyk die OPA-Engine, um Rego-Richtlinien auszuwerten und Entscheidungen zurückzugeben. Tatsächlich hat Snyk mit OPA bereits mehr als eine Milliarde Sicherheitsregelauswertungen durchgeführt!

Wie funktioniert Rego?

In einer deklarativen Abfragesprache wie Rego beschreiben Sie die Daten, die Sie abrufen möchten. Das Programm durchsucht dann eine Datenquelle – die sogenannte Eingabe – nach einer Übereinstimmung. Anders funktioniert es bei herkömmlichen imperativen Sprachen, in denen Sie die Schritte beschreiben, die zu einem Ergebnis führen sollen. Vielleicht kennen Sie bereits einige deklarative Abfragesprachen – SQL ist wahrscheinlich die am weitesten verbreitete.

Mit Rego beschreiben Sie die Bedingungen, unter denen eine Richtlinie erfüllt oder nicht erfüllt ist. OPA durchsucht dann ein JSON- (oder YAML-)Eingabedokument nach Daten, die diesen Erfüllt-/Nicht-erfüllt-Bedingungen entsprechen.

Das klingt in der Theorie gut – aber wie sieht eine Regel aus? Angenommen, wir müssen eine Unternehmensrichtlinie durchsetzen, nach der nur Alice, eine Netzwerkadministratorin, virtuelle Netzwerke in der Produktionsumgebung erstellen und löschen darf. Hier ist eine Beispielregel, die wir schreiben könnten:

allow := true {
  input.user == "alice"
}

Wir kommen gleich auf diese Regel zurück und erklären, was sie bewirkt und wie sie funktioniert. Bewundern Sie zunächst einfach ihre elegante Einfachheit!

Eingabe

OPA kann jedes JSON- oder YAML-Dokument als Eingabe verarbeiten. Ist Ihnen in der Beispielregel oben die Verwendung von input.user aufgefallen? input wird als spezielles JSON-Dokument behandelt, auf das global zugegriffen werden kann. Das heißt, Sie können in der gesamten Rego-Policy-Datei darauf verweisen.

Hier sehen Sie ein Beispiel für ein Eingabedokument zu unserer Beispielregel aus dem vorherigen Abschnitt:

{
  "user": "alice"
}

Wir gehen davon aus, dass dieses Dokument den aktuell angemeldeten Benutzer darstellt. In der Praxis könnte es sich bei diesem Eingabedokument um ein Kubernetes-Manifest oder die Ausgabe eines Terraform-Plans handeln. Ein Beispiel zeigen wir Ihnen in einem der nächsten Blogbeiträge.

Regeln

Nachdem Sie nun gesehen haben, wie eine Eingabe aussieht, sehen wir uns das Konzept der Regeln genauer an. In der Rego-Sprache ist eine Regel eine bedingte Zuweisung. Jede Regel besteht aus zwei Teilen:

a head {
  and a body
}
  • Der Kopf besteht aus einer Variablen und einem Wert, der ihr zugewiesen werden kann.

  • Der Rumpf besteht aus einer oder mehreren Abfragen, die OPA mitteilen, welche Bedingung(en) erfüllt sein müssen, damit der Wert der Variablen zugewiesen wird.

Sie können eine Regel folgendermaßen lesen:

THIS VARIABLE    :=	HAS THIS VALUE {
    IF THESE CONDITIONS ARE MET
}

Zusammengefasst fragt eine Regel die Eingabe ab, um eine Übereinstimmung mit einer Bedingung zu finden. Wird eine Übereinstimmung gefunden, wird einer Variablen ein Wert zugewiesen.

Hier ist die Beispielregel von vorhin:

allow := true {
  input.user == "alice"
}

Im obigen Beispiel ist der Kopf (Variable und Wert) allow := true und der Rumpf (Abfrage) input.user == "alice". Zusammen bilden Kopf und Rumpf eine vollständige Regel, die sich so lesen lässt:

Die Variable allow hat den Wert true, WENN user gleich "alice" ist.

Beachten Sie, dass := in Rego der Zuweisungsoperator ist, der manchmal auch Walross-Operator genannt wird. Er weist einer Variablen einfach einen Wert zu – ähnlich wie das Gleichheitszeichen in anderen Sprachen.

Abfragen

Sehen wir uns das Konzept der Abfragen genauer an. Wie bereits erwähnt, steht eine Abfrage für eine zu prüfende Bedingung – im Grunde ist sie die erste Hälfte einer WENN-Anweisung.

Zum Beispiel ist dies die Abfrage aus der Beispielregel im vorherigen Abschnitt:

input.user == "alice"

Diese Zeile weist OPA an, das Dokument input abzufragen, um herauszufinden, OB user gleich "alice" ist.

Dabei gibt es eine Feinheit: Rego ist deklarativ. Technisch gesehen stellt eine Abfrage also lediglich die Aussage „So ist es“ auf, und OPA findet alle Werte in der Eingabe, durch die diese Aussage wahr wird. In diesem Beispiel lautet die Abfrage also: „Die Eigenschaft user hat den Wert alice.“ OPA prüft die Eigenschaft user und sucht alle Benutzer in der Eingabe, durch die diese Aussage wahr wird – sofern es welche gibt. In diesem Fall wird nach dem Benutzer alice gesucht.

Auf Eingaben in einer Abfrage verweisen

Wenn Sie eine Rego-Abfrage erstellen, verwenden Sie die Punktnotation, um zur gewünschten Eigenschaft zu gelangen. Dabei wird jede verschachtelte Ebene des Eingabedokuments durch einen Punkt getrennt. Beginnen Sie zunächst mit input, fügen Sie dann einen Punkt und den Namen der Eigenschaft auf der obersten Ebene hinzu (in diesem Fall input.user).

Um auf eine verschachtelte Eigenschaft zu verweisen, müssen Sie alle Ebenen angeben, die Sie durchlaufen. Beginnen Sie mit input, einem Punkt und der Eigenschaft auf oberster Ebene (input.your-property-here). Fügen Sie dann weitere Punkte und Eigenschaftsnamen hinzu, bis Sie die gewünschte verschachtelte Eigenschaft erreichen. Wenn es sich bei der abzufragenden Eigenschaft um ein Array handelt, keine Sorge – darauf kommen wir gleich zurück.

Nehmen wir an, das Eingabedokument sieht stattdessen so aus:

{
  "admins": {
    "user": "alice"
  }
}

Da user in admins und dieses wiederum in input verschachtelt ist, würden Sie folgendermaßen darauf verweisen:

input.admins.user

Wenn es sich bei der Eingabeeigenschaft, auf die Sie verweisen, hingegen um ein Array (eine Liste) handelt, verwenden Sie den Platzhalter-Operator – einen Unterstrich –, um die Eigenschaft anzugeben. Nehmen wir zum Beispiel an, die Eingabe enthält ein user-Array:

{
  "users": [ "alice", "bob", "carlotta" ]
}

Wenn Sie in diesem Fall herausfinden möchten, ob alice im users-Array enthalten ist, verwenden Sie folgende Syntax:

allow := true {
  input.users[_] == "alice"
}

Der Platzhalter-Operator weist OPA an, das Array zu durchlaufen und zu prüfen, ob eines der Elemente gleich alice ist. Auf Iterationen gehen wir in einem zukünftigen Blogbeitrag genauer ein.

Nehmen wir ebenso an, Sie möchten prüfen, ob der Wert der Eigenschaft admin in einem der Elemente des folgenden users-Arrays true ist (auch wenn hier nur ein Element aufgeführt ist):

{
  "users": [
    {
      "name": "alice",
      "admin": true
    }
  ]
}

Dazu würden Sie eine Syntax wie diese verwenden:

allow := true {
  input.users[_].admin == true
}

Natürlich sind WENN-Bedingungen nicht besonders nützlich, wenn es keine bedingte Aktion dazu gibt. Deshalb ist es sinnvoll zu verstehen, wie Zuweisungen in Rego funktionieren – die zweite Hälfte der WENN-Anweisung.

Regelauswertung

Die bedingte Aktion in einer Regel besteht darin, einer Variablen einen Wert zuzuweisen. In unserem Beispiel prüfen wir die Eingabe, um festzustellen, ob der Variablen allow der Wert true zugewiesen werden soll. Sie können es folgendermaßen lesen:

allow := true {
  IF THIS CONDITION IS MET
}

Was sind Variablen?

Eine Variable ist ein Verweis auf einen bestimmten Wert. Hier wird der Variablen x der Wert 1 zugewiesen:

x := 1

Anschließend können Sie die Variable anstelle des Werts verwenden – für Rego macht das keinen Unterschied:

x := 1
y := 2
z := x + y

Kehren wir zu unserem Beispiel zurück: Die Variable ist allow, und der ihr zuzuweisende Wert lautet true:

allow := true

Zusammen mit der zuvor besprochenen Bedingung (Abfrage) ergibt sich die vollständige Regel:

allow := true {
  input.user == "alice"
}

Zur Erinnerung: Sie würden diese Regel so lesen:

Die Regel allow hat den Wert true, WENN input.user gleich "alice" ist.

In der Praxis sind solche Regeln sehr verbreitet. Deshalb können Sie sie in Rego auch verkürzt wie folgt schreiben:

allow {
  input.user == "alice"
}

Die Regel mit OPA auswerten

Wir haben eine Regel und ein Eingabedokument. Als Nächstes verwenden wir OPA, um die Eingabe anhand der Regel auszuwerten. Finden wir heraus, ob unsere Eingabe tatsächlich unserer Richtlinie entspricht – und ob der angemeldete Benutzer berechtigt ist, virtuelle Netzwerke in der Produktionsumgebung zu erstellen und zu löschen.

Wir konzentrieren uns auf zwei Möglichkeiten, mit OPA zu arbeiten:

  • Den Rego Playground verwenden

  • Das OPA-Befehlszeilentool verwenden

Den Rego Playground verwenden

Am einfachsten können Sie mit dem Schreiben von Regeln beginnen, indem Sie das Rego Playground von OPA verwenden. Mit diesem interaktiven Tool können Sie Regeln und Eingaben schreiben, testen und teilen.

Hier die Grundlagen:

  • Bearbeiten Sie eine Regel über das Regeltextfeld auf der linken Seite der Seite.

  • Bearbeiten Sie die Eingabe über das Feld „Input“ oben rechts auf der Seite. (Beachten Sie, dass sie gültiges JSON enthalten muss.)

  • Um eine Regel auszuwerten, wählen Sie oberhalb der Eingabe die Schaltfläche „Evaluate“ aus.

  • Die Auswertungsergebnisse finden Sie im Feld „Output“ unten rechts.

  • Um eine Regel mit anderen zu teilen, wählen Sie oben rechts die Schaltfläche „Publish“ aus. OPA erstellt eine URL, die Sie beliebigen Personen zur Verfügung stellen können, damit diese Ihre Regel und Eingabe testen oder ändern können.

Probieren Sie alles nach Herzenslust aus und scheuen Sie sich nicht, dabei auch Fehler zu machen! Sie können nichts kaputt machen – der Compiler weist Sie darauf hin, wenn das Rego ungültig ist. Laden Sie die Seite neu, wenn Sie das Playground auf den ursprünglichen Zustand zurücksetzen möchten (oder auf den veröffentlichten Zustand, wenn Sie ein veröffentlichtes Playground ansehen).

Wir haben ein Playground mit der Beispielregel allow und dem Eingabedokument geteilt. Sie können es unter dieser URL aufrufen: https://play.openpolicyagent.org/p/SH5ApmfodX 

Oder öffnen Sie einfach ein neues Playground und fügen Sie die Regel in das Textfeld links ein:

allow := true {
  input.user == "alice"
}

Fügen Sie die Eingabe in das Textfeld oben rechts ein:

{
  "user": "alice"
}

Zur Erinnerung: Laut unserer Unternehmensrichtlinie darf nur Alice, eine Netzwerkadministratorin, virtuelle Netzwerke in der Produktionsumgebung erstellen und löschen. Das Eingabedokument stellt den aktuell angemeldeten Benutzer dar. Unsere Regel prüft, ob der Benutzer im Eingabedokument gleich alice ist. Wenn ja, wird allow zu true ausgewertet.

Klicken Sie auf die Schaltfläche Evaluate. Daraufhin wird folgende Ausgabe angezeigt:

{
  "allow": true
}

Das bedeutet, dass allow tatsächlich zu true ausgewertet wird. OPA hat festgestellt, dass das Eingabedokument unserer Unternehmensrichtlinie entspricht. Der Benutzer ist Alice und somit berechtigt, virtuelle Netzwerke in der Produktionsumgebung zu erstellen und zu löschen.

Das OPA-Befehlszeilentool verwenden

Eine weitere Möglichkeit, Regeln mit OPA auszuwerten, ist das Befehlszeilentool opa. Eine Anleitung zur Installation von opa finden Sie in der OPA-Dokumentation. Nach der Installation benötigen Sie zwei Dateien:

  • Eine .rego-Policy-Datei mit Ihrer Regel und einer Paketanweisung wie package rules.check_user ganz oben. Unsere Policy-Datei heißt check_user.rego.

  • Eine .json-Datei mit der Eingabe. Unsere Eingabedatei heißt input.json.

Sobald Sie diese beiden Dinge haben, können Sie mit dem Befehl opa eval Ihre Policy als Code auswerten:

opa eval -i input.json -d check_user.rego "data.rules.check_user" --format pretty

Sie können Ihre Dateien natürlich beliebig benennen – achten Sie nur darauf, dass der Befehl dieser Struktur folgt:

opa eval -i <input file> -d <rule file> "data.<package name>" --format pretty

Wenn allow wie in unserem Beispiel zu true ausgewertet wird, sehen Sie dieselbe Ausgabe wie im Rego Playground:

{
  "allow": true
}

Auch hier zeigt OPA an, dass die Eingabe mit unserer Unternehmensrichtlinie übereinstimmt – also konform ist. Das bedeutet, dass der aktuell angemeldete Benutzer im Produktivkonto virtuelle Netzwerke erstellen und löschen darf.

Nicht konforme Eingaben testen

Wie sieht es aus, wenn ein Eingabedokument nicht konform ist? Ändern Sie im Playground oder in Ihrer lokalen .rego-Datei die Eingabe wie folgt:

{
  "user": "bob"
}

Wenn Sie die Regel jetzt auswerten (indem Sie im Rego Playground auf „Evaluate“ klicken oder den bereits erwähnten Befehl opa eval ausführen), sehen Sie folgende Ausgabe:

{}

Was bedeutet das? OPA gibt in diesem Beispiel das Ergebnis „undefined“ (also eine leere Menge) zurück, da es im Eingabewert keinen Wert findet, der der Bedingung input.user == "alice" entspricht. Die Menge ist leer, weil es keine Ergebnisse gibt. Daher wird allow nicht zu true ausgewertet, und das Eingabedokument ist nicht mit der Unternehmensrichtlinie konform. Tut uns leid, Bob!

Wie geht es weiter?

Lesen Sie auch die weiteren Beiträge unserer Blog-Serie „Rego für Einsteiger“. Darin befassen wir uns mit der Syntax für Regeln in Rego für Fortgeschrittene, darunter AND- und OR-Strukturen, benutzerdefinierte Meldungen, besondere Schlüsselwörter und vieles mehr.

In der Zwischenzeit finden Sie hier einige hilfreiche Ressourcen:

Wenn Sie Rego verwenden möchten, um benutzerdefinierte Regeln für Snyk IaC zu schreiben, finden Sie hier unsere Dokumentation. Zusätzlich zu den integrierten Sicherheits- und Compliance-Regelsätzen von Snyk können Sie mit benutzerdefinierten IaC+-Regeln maßgeschneiderte Sicherheitskontrollen für Ihren gesamten SDLC festlegen.

IaC+ bietet Ihnen eine zentrale Ansicht und Kontrollmöglichkeiten für Ihre Konfigurationsprobleme – vom Code bis zur Cloud. Dazu gehören eine Benutzeroberfläche für Probleme, ein Regelsatz und eine Policy-Engine, die IDE, SCM, CLI, CI/CD, Terraform Cloud sowie bereitgestellte Cloud-Umgebungen wie AWS, Azure und Google Cloud abdecken. 

IaC-Sicherheit für Entwickler

Snyk schützt Ihre Infrastructure as Code vom SDLC bis zur Laufzeit in der Cloud mit einer einheitlichen Policy-as-Code-Engine, damit jedes Team sicher entwickeln, bereitstellen und betreiben kann.

Weiterlesen

feature customer snowflake
Article

Sicherheit von Anfang an: Die Snyk Studio-Integration für Snowflake Cortex Code

Snyk Studio ist in Snowflake Cortex Code integriert und scannt KI-generierten Code, Abhängigkeiten und Container während der Entwicklung auf Schwachstellen.

blog feature pypi spoof
Article

Die gesamte Snyk AI Security Platform – kostenlos für Open-Source-Maintainer

Open-Source-Maintainer werden von echten Schwachstellenmeldungen überflutet und brauchen Unterstützung dabei, diese zu priorisieren, zu beheben und schneller Korrekturen bereitzustellen. Das Secure Developer Program von Snyk bietet qualifizierten Projekten kostenlosen Zugang zur Snyk AI Security Platform.

blog feature snyk code green
Blog

Sicherheit auf Typebene: Die Zukunft der sicheren KI-Codegenerierung?

Sicherheitsorientierte Typen können häufige Fehler zu Compile-Time-Fehlern machen. In diesem Beitrag erfahren Sie, wie Typsicherheit dazu beitragen könnte, ganze Klassen KI-generierter Schwachstellen zu verhindern.