Einschränkungsvorlage schreiben

In diesem Thema wird gezeigt, wie Sie eine benutzerdefinierte Einschränkungsvorlage schreiben und damit Policy Controller erweitern.

Überblick

Einschränkungsvorlagen können zum Erweitern von Policy Controller verwendet werden. Falls Sie keine vorab geschriebene Vorlage finden, die Ihren Anforderungen entspricht, können Sie Ihre eigene Vorlage schreiben.

Policy Controller-Richtlinien werden mit dem OPA Constraint Framework beschrieben und in Rego geschrieben. Eine Richtlinie kann jedes Feld eines Kubernetes-Objekts auswerten.

Das Schreiben von Richtlinien mit Rego ist eine spezialisierte Fähigkeit. Aus diesem Grund wird standardmäßig eine -Bibliothek mit allgemeinen Einschränkungsvorlagen installiert. Die meisten Nutzer können diese Einschränkungsvorlagen beim Erstellen von Einschränkungen aufrufen. Wenn Sie spezielle Anforderungen haben, können Sie Ihre eigenen Einschränkungsvorlagen erstellen.

Mithilfe von Einschränkungsvorlagen können Sie die Logik einer Richtlinie für die Wiederverwendung und Delegierung von ihren spezifischen Anforderungen trennen. Sie können Einschränkungen mithilfe von Einschränkungsvorlagen erstellen, die von Drittanbietern entwickelt wurden, z. B. Open-Source-Projekten, Softwareanbietern oder Aufsichtsexperten.

Hinweis

Beispiel für eine Einschränkungsvorlage

Unten finden Sie eine beispielhafte Einschränkungsvorlage, die alle Ressourcen ablehnt, deren Name mit einem vom Ersteller der Einschränkung angegebenen Wert übereinstimmt. Auf dem Rest dieser Seite wird der Inhalt der Vorlage erläutert und wichtige Konzepte hervorgehoben.

Einschränkungsvorlage

apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8sdenyname
spec:
  crd:
    spec:
      names:
        kind: K8sDenyName
      validation:
        # Schema for the `parameters` field
        openAPIV3Schema:
          properties:
            invalidName:
              type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sdenynames
        violation[{"msg": msg}] {
          input.review.object.metadata.name == input.parameters.invalidName
          msg := sprintf("The name %v is not allowed", [input.parameters.invalidName])
        }

Einschränkung

Hier ist eine beispielhafte Einschränkung, die ein Nutzer implementieren kann, um alle Ressourcen mit dem Namen "Richtlinienverletzung" abzulehnen:

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sDenyName
metadata:
  name: no-policy-violation
spec:
  parameters:
    invalidName: "policy-violation"

Teile einer Einschränkungsvorlage

Einschränkungsvorlagen bestehen aus zwei wichtigen Elementen:

  • Das Schema der Einschränkung, die Nutzer erstellen sollen. Das Schema einer Einschränkungsvorlage wird im Feld crd gespeichert.

  • Der Rego-Quellcode, der ausgeführt wird, wenn die Einschränkung ausgewertet wird. Der Rego-Quellcode für eine Vorlage wird im Feld targets gespeichert.

Das CRD-Feld

Das CRD-Feld ist eine Blaupause zum Erstellen der Kubernetes Custom Resource Definition, die die Einschränkungsressource für den Kubernetes API-Server definiert. Sie müssen nur die folgenden Felder ausfüllen:

  • spec.crd.spec.names.kind ist die Art der Einschränkung. Im Kleinbuchstaben muss der Wert dieses Feldes gleich metadata.name sein.
  • spec.crd.spec.validation.openAPIV3Schema ist das Schema für das Feld spec.parameters der Einschränkungsressource (der Rest des Einschränkungsschemas wird automatisch von Anthos Config Management definiert). Es folgt den gleichen Konventionen wie bei einer regulären CRD-Ressource. Die Definition dafür ist hier dokumentiert.

Das Präfixieren der Einschränkungsvorlage mit dem Namen "K8s" ist eine Konvention, mit der Kollisionen mit anderen Arten von Einschränkungsvorlagen vermieden werden können, z. B. Forseti-Vorlagen, die auf GCP-Ressourcen abzielen.

Der Rego-Quellcode

Ort

Der Rego-Quellcode wird im Feld spec.targets gespeichert, wobei targets ein Array von Objekten des Formats {"target": "admission.k8s.gatekeeper.sh", "rego": <REGO SOURCE CODE>, "libs": <LIST OF REGO LIBRARIES>} ist. Derzeit ist nur ein Eintrag in targets zulässig.

  • target teilt Anthos Config Management mit, um welches System es sich handelt (in diesem Fall Kubernetes).
  • rego ist der Quellcode für die Einschränkung
  • libs ist eine optionale Liste von Rego-Code-Bibliotheken, die der Einschränkungsvorlage zur Verfügung gestellt werden. Es soll die Verwendung gemeinsam genutzter Bibliotheken vereinfachen und ist für dieses Lernprogramm nicht verfügbar.

Quellcode

Werfen wir einen Blick auf die Rego für die oben genannte Einschränkung:

package k8sdenynames

violation[{"msg": msg}] {
   input.review.object.metadata.name == input.parameters.invalidName
   msg := sprintf("The name %v is not allowed", [input.parameters.invalidName])
}

Hier sind einige Punkte zu beachten:

  • package k8sdenynames wird von OPA (Regos Laufzeit) benötigt. Der Wert wird ignoriert.
  • Die Rego-Regel, die Policy Controller aufruft, um festzustellen, ob Verstöße vorliegen, heißt violation. Wenn diese Regel übereinstimmt, ist ein Verstoß gegen die Einschränkung aufgetreten.
  • Die Regel violation hat die Signatur violation[{"msg": "violation message for the user"}], wobei der Wert von "msg" die Verstoßmeldung ist, die an den Nutzer zurückgegeben wird.
  • Die für die Einschränkung bereitgestellten Parameter werden unter dem Schlüsselwort input.parameters verfügbar gemacht.
  • Die zu testende Anfrage wird unter dem Schlüsselwort input.review gespeichert

input.review hat die folgenden Felder:

  • uid ist die eindeutige ID für diese bestimmte Anforderung, die während der Prüfung nicht verfügbar ist
  • kind ist die Art der Information für das zu testende Objekt. Das Format sieht folgendermaßen aus:
    • kind die Art der Ressource
    • group die Ressourcengruppe
    • version die Ressourcenversion
  • name ist der Name der Ressource. Es kann leer sein, wenn sich der Nutzer auf den API-Server verlässt, um den Namen für eine CREATE-Anforderung zu generieren.
  • namespace ist der Ressourcennamensraum (nicht für Ressourcen mit Clusterbereich vorgesehen).
  • operation ist die angeforderte Operation (z. B. CREATE oder UPDATE), die während der Prüfung nicht verfügbar ist.
  • userInfo ist die anfordernde Nutzerinformation, die während der Prüfung nicht verfügbar ist.
    • username ist der Nutzer, der die Anfrage stellt
    • uid ist die UID des Benutzers
    • groups ist eine Liste von Gruppen, in denen der Nutzer Mitglied ist
    • extra sind zusätzliche Benutzerinformationen, die von Kubernetes bereitgestellt werden
  • object ist das Objekt, das der Nutzer zu ändern/erstellen versucht
  • oldObject ist der ursprüngliche Status des Objekts, der nur bei UPDATE-Operationen verfügbar ist
  • dryRun gibt an, ob diese Anforderung mit kubectl --dry-run aufgerufen wurde und während der Prüfung nicht verfügbar ist

Schreiben von Vorlagen für referenzielle Einschränkungen

Vorlagen für referenzielle Einschränkungen sind Vorlagen, mit denen der Nutzer ein Objekt in Bezug auf andere Objekte einschränken kann. Ein Beispiel hierfür könnte sein: "Erlaube nicht, dass ein Pod erstellt wird, bevor bekannt ist, dass ein übereinstimmender Eingang vorhanden ist." Ein anderes Beispiel könnte sein: "Lassen Sie nicht zu, dass zwei Dienste denselben Hostnamen haben".

Mit Policy Controller können Sie referenzielle Einschränkungen schreiben, indem Sie den API-Server auf einen vom Nutzer bereitgestellten Satz von Ressourcen beobachten. Wenn eine Ressource geändert wird, speichert Policy Controller sie lokal zwischen, damit sie vom Rego-Quellcode problemlos referenziert werden kann. Policy Controller stellt diesen Cache unter dem Schlüsselwort data.inventory zur Verfügung.

Ressourcen mit Cluster-Gültigkeitsbereich werden an folgendem Speicherort zwischengespeichert:

data.inventory.cluster[<groupVersion>][<kind>][<name>]

Ein Knoten mit dem Namen my-favorite-node könnte z. B. gefunden werden unter

data.inventory.cluster["v1"]["Node"]["my-favorite-node"]

Ressourcen mit Namespace-Bereich werden hier zwischengespeichert:

data.inventory.namespace[<namespace>][<groupVersion>][<kind>][<name>]

Beispielsweise könnte eine ConfigMap mit dem Namen production-variables im Namespace shipping-prod unter gefunden werden

data.inventory.namespace["shipping-prod"]["v1"]["ConfigMap"]["production-variables"]

Der vollständige Inhalt des Objekts wird an diesem Cache-Speicherort gespeichert und kann in Ihrem Rego nach Belieben referenziert werden.

Weitere Informationen zu Rego

Die obigen Informationen bieten die einzigartigen Funktionen von Policy Controller, die das Schreiben von Einschränkungen für Kubernetes-Ressourcen in Rego vereinfachen. Ein vollständiges Tutorial zum Schreiben in Rego ist in diesem Handbuch nicht enthalten. Auf der Open Policy Agent-Website finden Sie jedoch Dokumentation zur Syntax und zu den Funktionen der Rego-Sprache.

Ihre Einschränkungsvorlage installieren

Nachdem Sie Ihre Einschränkungsvorlage erstellt haben, kümmern Sie sich einfach um kubectl apply, und Policy Controller kümmert sich um die Aufnahme. Prüfen Sie unbedingt das Feld status Ihrer Einschränkungsvorlage, um sicherzustellen, dass keine Fehler beim Instanziieren aufgetreten sind. Bei erfolgreicher Aufnahme sollte das Feld status created: true anzeigen und das im Feld status angegebene observedGeneration sollte dem Feld metadata.generation entsprechen.

Nachdem die Vorlage aufgenommen wurde, können Sie Einschränkungen anwenden, wie unter Erstellen von Einschränkungen beschrieben.

Eine Einschränkungsvorlage entfernen

Stellen Sie zuerst sicher, dass keine Einschränkungen, die Sie beibehalten möchten, die Einschränkungsvorlage verwenden:

kubectl get [TEMPLATE-NAME]

Im Falle eines Namenskonflikts zwischen dem Namen der Einschränkungsvorlage und einem anderen Objekt im Cluster können Sie stattdessen den folgenden Befehl verwenden:

kubectl get [TEMPLATE-NAME].constraints.gatekeeper.sh

Entfernen Sie die Einschränkungsvorlage:

kubectl delete constrainttemplate [CONSTRAINT-TEMPLATE-NAME]

Wenn Sie eine Einschränkungsvorlage entfernen, können Sie keine Einschränkungen mehr erstellen, die darauf verweisen.

Nächste Schritte