Policy as Code (PaC) mit OPA und Rego ermöglichen
19. Januar 2022
0 Min. LesezeitDas Cambridge Dictionary definiert eine Policy als „eine Gruppe von Ideen oder einen Plan für das Vorgehen in bestimmten Situationen, auf den sich eine Gruppe von Menschen, ein Unternehmen, eine Regierung oder eine politische Partei offiziell geeinigt hat“. Im Kontext der Softwareentwicklung hat Ihre Organisation möglicherweise Regeln dazu, wie eine Policy erstellt, konfiguriert, bereitgestellt und verwendet wird. Beispiele für Software-Policies sind:
Anwendungs-Policies
Auf bestimmte Kontexte eines Webservices können nur interne Nutzer zugreifen.
Regionale Funktionen werden nur bei Anfragen von Nutzern mit IP-Adressen am jeweiligen geografischen Standort angezeigt.
Transaktionen über bestimmten Beträgen sind nur für Nutzer mit Führungspositionen zulässig.
Build- und Deployment-Policies
Alle Open-Source-Bibliotheken in Anwendungen müssen eine der genehmigten Lizenzen verwenden.
Alle Container-Images müssen aus bestimmten Registries bezogen werden.
Kein Kubernetes-Pod darf jemals im privilegierten Modus ausgeführt werden.
Das Standard-Token eines ServiceAccounts darf nicht automatisch in einen Container eingebunden werden.
Policy as Code (PaC) bezeichnet das Verfahren, Policies mithilfe einer deklarativen High-Level-Sprache als Code zu definieren. Dadurch können Sie die Durchsetzung Ihrer Policies automatisieren und sie zentral verwalten. Das reduziert den Bedarf an duplizierter Logik in Ihren zunehmend verteilten Anwendungsservices, die möglicherweise verschiedene Programmiersprachen und Plattformen verwenden.
In diesem Blogbeitrag sehen wir uns den Open Policy Agent (OPA) und seine Regelsprache Rego an. Damit können Sie Ihre PaC-Vorhaben sowohl für Ihre eigenen Anwendungen als auch für die Durchsetzung von Policies für containerisierte Workloads auf Kubernetes effizienter umsetzen.
Einheitliche Policy-Definition für unterschiedliche Services
Die Durchsetzung von Anwendungs-Policies wird häufig direkt im Code implementiert. In den heutigen verteilten Systemen kann dieselbe Logik mehrfach vorhanden sein. Das Problem verschärft sich, wenn die verschiedenen Services von unterschiedlichen Teams und/oder mit unterschiedlichen Technologien entwickelt werden.
Standardisierte Policy-Definitionen und Tools zur Durchsetzung, die von allen Teams Ihrer Organisation verwendet werden können – unabhängig von den Programmiersprachen und Frameworks – sind unerlässlich. Einheitliche Policy-Definitionen ermöglichen eine einfache, flexible Implementierung und erleichtern allen Beteiligten die Compliance-Governance.
Proaktive statt reaktive Policy-Durchsetzung bei Build und Deployment
Build- und Deployment-Policies werden häufig durch eine Kombination aus manuellen Code-Reviews, statischer Analyse (hoffentlich automatisiert in Ihrer CI/CD-Pipeline) oder schlicht durch die Androhung disziplinarischer Maßnahmen bei Verstößen durchgesetzt. Diese Praktiken sind reaktiv: Sie machen uns auf Policy-Verstöße aufmerksam, wenn eine Art Audit durchgeführt wird. Das kann zwar funktionieren, führt aber oft zu einem Konflikt zwischen den Verantwortlichen für Policies und den Entwicklern, denen die Policy-Regeln möglicherweise gar nicht bekannt sind.
Wenn Sie Policies in den Entwickler-Workflow integrieren und dort durchsetzen – entweder als Teil des Build-Prozesses oder als Deployment-Schranke –, können Sie Verstöße bereits bei ihrer Entstehung verhindern, statt sich auf Audits in späteren Phasen oder manuelle Reviews verlassen zu müssen.
Einheitliche Anwendung von Policies in unterschiedlichen Umgebungen
Sobald Sie Ihre Policy-Regeln auf einer gemeinsamen Plattform vereinheitlicht haben, können Sie sie in allen Umgebungen einheitlich anwenden. Wenn Ihr Kubernetes-Cluster für die Entwicklungs-Sandbox beispielsweise alles und jedes zulässt, Ihr Produktions-Cluster jedoch zahlreiche Einschränkungen hat, bemerken Entwickler möglicherweise erst später im SDLC, dass sie einen Verstoß eingebaut haben. Verwenden alle Cluster hingegen denselben Regelsatz, ist es deutlich unwahrscheinlicher, dass solche Verstöße in die Versionsverwaltung gelangen, da sie bereits bei den ersten Unit-Tests aufgefallen wären.
Open Policy Agent (OPA)
Der Open Policy Agent – üblicherweise mit den Initialen OPA abgekürzt und „oh-pah“ ausgesprochen – ist ein Open-Source-Projekt mit CNCF-Abschlussstatus, das eine universell einsetzbare Policy-Engine bereitstellt. Er wird häufig sowohl für Anwendungs-Policies – insbesondere in verteilten Microservices-Architekturen – als auch als Kubernetes-API-Zulassungskontroller verwendet, oft in Verbindung mit dem Projekt OPA Gatekeeper.
Anwendungen können die Policy-Validierung an OPA delegieren und so vermeiden, diese Logik eng an ihre Codebasis zu koppeln. In der Praxis wird häufig ein OPA-Prozess neben dem Anwendungsservice gestartet, der eine REST-API für die Kommunikation mit der Anwendung bereitstellt. Bei einem Kubernetes-Deployment geschieht das üblicherweise über einen Sidecar-Container im selben Pod wie der Service-Container. So entsteht eine extrem latenzarme Verbindung über „localhost“. OPA kann jedoch auch als externer Service ausgeführt werden. Es gibt weitere Möglichkeiten, OPA in Ihre Anwendung einzubinden. Zum Zeitpunkt der Veröffentlichung gehören dazu eine Go-API, WebAssembly und ein SDK, mit dem OPA in eine Go-Anwendung eingebettet werden kann.
Policies in OPA werden als Sammlung von Regeln in einer Sprache namens Rego geschrieben.
Rego: die Policy-Regelsprache von OPA
Rego ist eine deklarative High-Level-Sprache, die für die Definition von Regeln für strukturierte Dokumente wie JSON entwickelt wurde. Eine ausführliche Anleitung zum Schreiben von Rego-Regeln würde den Rahmen dieses Artikels sprengen. Ich empfehle Ihnen jedoch dringend, sich die offizielle Dokumentation und den hervorragenden Lernkurs von Styra, den Entwicklern von OPA und Rego, anzusehen.
Rego-Grundlagen
Rego kann auf verschiedene Weise mit strukturierten Datendokumenten arbeiten. Am häufigsten übergibt der aufrufende Prozess ein Dokument, oft im JSON- oder YAML-Format, als input. Anschließend werden die Regeln angewendet, indem Elemente dieses Eingabedokuments mit Ausdrücken verglichen werden.
Angenommen, wir haben eine Kubernetes-Pod-Validierungs-Policy, die „true“ zurückgibt, solange der Eingabewert image nicht mit „:latest“ endet. Eine einfache Rego-Implementierung dieser Policy könnte etwa so aussehen:
Wird das folgende JSON mit dieser Policy geprüft, erhalten wir die Antwort { “allow”: false }, da „:latest“ nicht am Ende des Image-Werts steht.
Rego-Beispiel im Detail
Sehen wir uns den Rego-Code aus dem obigen Beispiel genauer an:
Hier deklarieren wir, zu welchem package die Regel gehört. Das ähnelt der Paketstruktur in anderen Programmiersprachen und dient dazu, ähnliche Regeln in demselben Namespace zusammenzufassen.
Das Schlüsselwort import weist den Rego-Parser an, die Regel in aus dem Package future.keyworks in den Gültigkeitsbereich dieser Policy aufzunehmen, sodass sie einfach als in referenziert werden kann.
„Damit wird der default-Wert von allow auf „false“ gesetzt, wenn kein anderer Zuweisungsausdruck in der Policy einen anderen Wert festlegt.
Hier sehen wir den Großteil der Regellogik. Bei der Ausführung erhält allow den Auswertungswert des Inhalts in den geschweiften Klammern { }. Alle Ausdrücke innerhalb dieser Klammern werden mit einem impliziten „AND“ verknüpft. Das bedeutet, dass jeder Ausdruck „true“ ergeben muss, damit allow auf „true“ gesetzt wird.
Die drei Zeilen lassen sich so verstehen: „Solange der Wert von input.kind „Pod“ ist und mindestens einige Container in input.spec vorhanden sind, wird „true“ zurückgegeben – es sei denn, eines der Felder image der Container endet mit „:latest“.“
Rego Playground
Das OPA-Projekt bietet eine Online-Umgebung zum Bearbeiten von Rego namens The Rego Playground. Dort können Sie nach Belieben mit Regeln experimentieren und sie anhand von Eingabedokumenten ausführen. So können Sie Ihre Regelideen interaktiv ausprobieren und Ihre Experimente mit anderen teilen.

Der obige Rego-Code und das Eingabedokument sind in diesem Rego-Playground-Beispiel verfügbar. Öffnen Sie es in einem anderen Tab, führen Sie es aus und probieren Sie es aus.
Benutzerdefinierte Policies mit Snyk IaC und Rego schreiben
Snyk Infrastructure as Code (Snyk IaC) nutzt OPA für Policy-Scans. Mit wenigen einfachen Befehlen können Sie Ihren Scans eigene Policies hinzufügen. Lesen Sie die Snyk-IaC-Dokumentation sowie unseren Artikel Eigene IaC-Regeln mit Snyk entwickeln, um loszulegen.
Mit einem kostenlosen Snyk-Konto können Sie IaC-Fehlkonfigurationen erkennen und beheben, indem Sie Sicherheitsprüfungen, Policy-Leitplanken und entwicklerfreundliche Anleitungen zur Fehlerbehebung nahtlos in Ihre Workflows integrieren.
Sichern Sie Ihre Infrastruktur an der Quelle
Snyk automatisiert die IaC-Sicherheit und Compliance in Workflows und erkennt abweichende sowie fehlende Ressourcen.
Weitere Informationsquellen
Nachdem Sie nun einen grundlegenden Überblick über OPA und Rego sowie einige Anwendungsbereiche erhalten haben, empfehle ich Ihnen, die vielfältigen Möglichkeiten zu erkunden, wie Sie die Tools für Ihre Software einsetzen können:
Lernen Sie Rego mit dem hervorragenden Tutorial-Kurs von Styra.
Experimentieren Sie mit Ihren Regeln und erstellen Sie neue im The Rego Playground.
Installieren Sie OPA Gatekeeper, um Ihre Kubernetes-Cluster besser zu schützen.
Passen Sie Ihre Snyk-IaC-Scan-Policies an, um Sicherheit in Ihren SDLC-Pipelines frühzeitig zu integrieren und Verstöße zu erkennen, bevor sie die Produktion erreichen.
Vielen Dank fürs Lesen – und viel Spaß beim Automatisieren der Policy-Durchsetzung!
