Dieses Dokument wurde mithilfe automatisierter maschineller Übersetzungstechnologie übersetzt. Wir bemühen uns um korrekte Übersetzungen, übernehmen jedoch keine Gewähr für die Vollständigkeit, Richtigkeit oder Zuverlässigkeit der übersetzten Inhalte. Im Falle von Abweichungen ist die englische Originalversion maßgebend und stellt den verbindlichen Text dar.

Dies ist eine unveröffentlichte Dokumentation für Admission Controller 1.34-dev.

Roh-Richtlinien schreiben

Roh-Richtlinien sind Richtlinien, die beliebige JSON-Dokumente auswerten können. Für weitere Informationen zu Roh-Richtlinien verweisen Sie bitte auf die Roh-Richtlinien Seite.

Beispiele

Die folgenden Beispiele sollten Ihnen vertraut sein, wenn Sie den Abschnitt Validierung dieses Tutorials abgeschlossen haben.

Denken Sie daran, die Richtlinie als raw zu kennzeichnen, indem Sie das policyType Feld in der metadata.yml Konfiguration verwenden. Bitte beziehen Sie sich auf die Metadaten Spezifikation für weitere Informationen.

metadata.yml mit policyType: raw
rules:
- apiGroups: [""]
  apiVersions: ["v1"]
  resources: ["pods"]
  operations: ["CREATE"]
mutating: false
contextAware: false
executionMode: kubewarden-wapc
policyType: raw
# Consider the policy for the background audit scans. Default is true. Note the
# intrinsic limitations of the background audit feature on docs.kubewarden.io;
# If your policy hits any limitations, set to false for the audit feature to
# skip this policy and not generate false positives.
backgroundAudit: true
annotations:
  # kubewarden specific:
  io.kubewarden.policy.title: policy-name
  io.kubewarden.policy.version: 0.1.0  # should match the OCI tag
  io.kubewarden.policy.description: Short description
  io.kubewarden.policy.author: "Author name <author-email@example.com>"
  io.kubewarden.policy.url: https://github.com/yourorg/policy-name
  io.kubewarden.policy.source: https://github.com/yourorg/policy-name
  io.kubewarden.policy.license: Apache-2.0
  # The next two annotations are used in the policy report generated by the
  # Audit scanner. Severity indicates policy check result criticality and
  # Category indicates policy category. See more here at docs.kubewarden.io
  io.kubewarden.policy.severity: medium # one of info, low, medium, high, critical. See docs.
  io.kubewarden.policy.category: Resource validation
  # artifacthub specific: (optional, to release in Artifact Hub)
  io.kubewarden.policy.ociUrl: ghcr.io/yourorg/policies/policy-name # must match release workflow oci-target
  io.artifacthub.displayName: Policy Name
  io.artifacthub.resources: Pod
  io.artifacthub.keywords: pod, cool policy, kubewarden

Validation

Sie möchten eine Richtlinie schreiben, die eine Anfrage im folgenden Format akzeptiert:

{
  "request": {
    "user": "alice",
    "action": "delete",
    "resource": "products"
  }
}

und validiert, dass:

  • user ist in der Liste der gültigen Benutzer

  • action ist in der Liste der gültigen Aktionen

  • resource ist in der Liste der gültigen Ressourcen

Beginnen Sie damit, die Richtlinie mit der Go-Richtlinienvorlage zu erstellen. Stellen Sie sicher, dass alles mit einem make, make test und make e2e-tests an seinem Platz ist.

Zuerst definieren Sie die Typen, die die Nutzlast der Anfrage darstellen.

Sie müssen einen benutzerdefinierten RawValidationRequest Typ deklarieren (erstellen Sie eine Datei request.go), die die RawValidationRequest und die Settings Strukturen enthält, anstatt den vom SDK bereitgestellten ValidationRequest Typ zu verwenden:

// RawValidationRequest represents the request that is sent to the validate function by the Policy Server.
type RawValidationRequest struct {
    Request Request `+json:"request"+`
    // Raw policies can have settings.
    Settings Settings `+json:"settings"+`
}

// Request represents the payload of the request.
type Request struct {
    User     string `+json:"user"+`
    Action   string `+json:"action"+`
    Resource string `+json:"resource"+`
}

Dann müssen Sie den Settings Typ sowie die Valid und validateSettings Funktionen in settings.go definieren:

Die Settings Struktur sowie die Valid und validateSettings Funktionen in settings.go.
// Settings represents the settings of the policy.
type Settings struct {
    ValidUsers     []string `+json:"validUsers"+`
    ValidActions   []string `+json:"validActions"+`
    ValidResources []string `+json:"validResources"+`
}

// Valid returns true if the settings are valid.
func (s *Settings) Valid() (bool, error) {
    if len(s.ValidUsers) == 0 {
        return false, fmt.Errorf("validUsers cannot be empty")
    }

    if len(s.ValidActions) == 0 {
        return false, fmt.Errorf("validActions cannot be empty")
    }

    if len(s.ValidResources) == 0 {
        return false, fmt.Errorf("validResources cannot be empty")
    }

    return true, nil
}

// validateSettings validates the settings.
func validateSettings(payload []byte) ([]byte, error) {
    logger.Info("validating settings")

    settings := Settings{}
    err := json.Unmarshal(payload, &settings)
    if err != nil {
        return kubewarden.RejectSettings(kubewarden.Message(fmt.Sprintf("Provided settings are not valid: %v", err)))
    }

    valid, err := settings.Valid()
    if err != nil {
        return kubewarden.RejectSettings(kubewarden.Message(fmt.Sprintf("Provided settings are not valid: %v", err)))
    }
    if valid {
        return kubewarden.AcceptSettings()
    }

    logger.Warn("rejecting settings")
    return kubewarden.RejectSettings(kubewarden.Message("Provided settings are not valid"))
}

Schließlich ersetzen Sie die validate Funktion (in validate.go):

Die validate Funktion in validate.go.
func validate(payload []byte) ([]byte, error) {
    // Unmarshal the payload into a RawValidationRequest instance
    validationRequest := RawValidationRequest{}
    err := json.Unmarshal(payload, &validationRequest)
    if err != nil {
        // If the payload is not valid, reject the request
        return kubewarden.RejectRequest(
            kubewarden.Message(err.Error()),
            kubewarden.Code(400))
    }

    request := validationRequest.Request
    settings := validationRequest.Settings

    // Validate the payload
    if slices.Contains(settings.ValidUsers, request.User) &&
        slices.Contains(settings.ValidActions, request.Action) &&
        slices.Contains(settings.ValidResources, request.Resource) {
        return kubewarden.AcceptRequest()
    }

    return kubewarden.RejectRequest(
        kubewarden.Message("The request cannot be accepted."),
        kubewarden.Code(400))
}

Sie können einen Test in e2e.bats einrichten:

e2e.bats
#!/usr/bin/env bats

@test "accept" {
  run kwctl run annotated-policy.wasm -r test_data/request.json -s test_data/settings.json

  # this prints the output when one the checks below fails
  echo "output = ${output}"

  # request allowed
  [ "$status" -eq 0 ]
  [ $(expr "$output" : '.*allowed.*true') -ne 0 ]
}

Dann sind die Ausgaben von make, make test und make e2e:

Ausgaben
make && make test && make e2e-tests
docker run \
    --rm \
    -e GOFLAGS="-buildvcs=false" \
    -v /home/jhk/projects/suse/tmp/fab-goraw:/src \
    -w /src tinygo/tinygo:0.30.0 \
    tinygo build -o policy.wasm -target=wasi -no-debug .
go test -v
=== RUN   TestAcceptValidSettings
--- PASS: TestAcceptValidSettings (0.00s)
=== RUN   TestRejectSettingsWithEmptyValidUsers
--- PASS: TestRejectSettingsWithEmptyValidUsers (0.00s)
=== RUN   TestRejectSettingsWithEmptyValidActions
--- PASS: TestRejectSettingsWithEmptyValidActions (0.00s)
=== RUN   TestRejectSettingsWithEmptyValidResources
--- PASS: TestRejectSettingsWithEmptyValidResources (0.00s)
=== RUN   TestValidateRequestAccept
--- PASS: TestValidateRequestAccept (0.00s)
=== RUN   TestValidateRequestReject
--- PASS: TestValidateRequestReject (0.00s)
PASS
ok      github.com/kubewarden/go-policy-template    0.002s
kwctl annotate -m metadata.yml -u README.md -o annotated-policy.wasm policy.wasm
bats e2e.bats
e2e.bats
 ✓ accept

1 test, 0 failures

Mutation

Sie müssen das frühere Beispiel ändern, um die Anfrage zu mutieren, anstatt sie abzulehnen. Die Einstellungen sollten die defaultUser, defaultAction und defaultRequest enthalten, um die Anfrage zu mutieren, falls der Benutzer, die Aktion oder die Ressource ungültig ist.

Sie müssen den Settings Typ mit den neuen Feldern aktualisieren:

// Settings defines the settings of the policy.
type Settings struct {
    ValidUsers      []string `+json:"validUsers"+`
    ValidActions    []string `+json:"validActions"+`
    ValidResources  []string `+json:"validResources"+`
    DefaultUser     string   `+json:"defaultUser"+`
    DefaultAction   string   `+json:"defaultAction"+`
    DefaultResource string   `+json:"defaultResource"+`
}

// Valid returns true if the settings are valid.
func (s *Settings) Valid() (bool, error) {
    if len(s.ValidUsers) == 0 {
        return false, fmt.Errorf("validUsers cannot be empty")
    }

    if len(s.ValidActions) == 0 {
        return false, fmt.Errorf("validActions cannot be empty")
    }

    if len(s.ValidResources) == 0 {
        return false, fmt.Errorf("validResources cannot be empty")
    }

    if s.DefaultUser == "" {
        return false, fmt.Errorf("defaultUser cannot be empty")
    }

    if s.DefaultAction == "" {
        return false, fmt.Errorf("defaultUser cannot be empty")
    }

    if s.DefaultResource == "" {
        return false, fmt.Errorf("defaultResource cannot be empty")
    }

    return true, nil
}

Außerdem die validate Funktion zur Einführung der Mutation:

func validate(payload []byte) ([]byte, error) {
    // Unmarshal the payload into a RawValidationRequest instance
    validationRequest := RawValidationRequest{}
    err := json.Unmarshal(payload, &validationRequest)
    if err != nil {
        // If the payload is not valid, reject the request
        return kubewarden.RejectRequest(
            kubewarden.Message(err.Error()),
            kubewarden.Code(400))
    }

    request := validationRequest.Request
    settings := validationRequest.Settings

    logger.Info("validating request")

    // Accept the request without mutating it if it is valid
    if slices.Contains(settings.ValidUsers, request.User) &&
        slices.Contains(settings.ValidActions, request.Action) &&
        slices.Contains(settings.ValidResources, request.Resource) {
        return kubewarden.AcceptRequest()
    }

    logger.Info("mutating request")

    // Mutate the request if it is not valid
    if !slices.Contains(settings.ValidUsers, request.User) {
        request.User = settings.DefaultUser
    }

    if !slices.Contains(settings.ValidActions, request.Action) {
        request.Action = settings.DefaultAction
    }

    if !slices.Contains(settings.ValidResources, request.Resource) {
        request.Resource = settings.DefaultResource
    }

    return kubewarden.MutateRequest(request)
}