From 26a7bf656722e99baa1a6cad62a465149ba9dcb2 Mon Sep 17 00:00:00 2001 From: Jonny Stoten Date: Thu, 20 Jun 2024 15:33:36 +0100 Subject: [PATCH] Return full verification result to rego --- pkg/handler/validate.go | 33 +++++++--------------- validation/attest-constraint-template.yaml | 32 +++++++++++++++------ 2 files changed, 33 insertions(+), 32 deletions(-) diff --git a/pkg/handler/validate.go b/pkg/handler/validate.go index 553a477..051bccc 100644 --- a/pkg/handler/validate.go +++ b/pkg/handler/validate.go @@ -64,7 +64,6 @@ func validate(w http.ResponseWriter, req *http.Request) { } for _, key := range providerRequest.Request.Keys { - // create a resolver for remote attestations platform := "linux/amd64" resolver, err := oci.NewRegistryAttestationResolver(key, platform) if err != nil { @@ -72,14 +71,12 @@ func validate(w http.ResponseWriter, req *http.Request) { return } - // configure policy options opts := &policy.PolicyOptions{ TufClient: tufClient, LocalTargetsDir: filepath.Join("/tuf_temp", ".docker", "policy"), // location to store policy files downloaded from TUF LocalPolicyDir: "", // overrides TUF policy for local policy files if set } - // verify attestations ctx := req.Context() debug := true ctx = policy.WithPolicyEvaluator(ctx, policy.NewRegoEvaluator(debug)) @@ -88,26 +85,16 @@ func validate(w http.ResponseWriter, req *http.Request) { utils.SendResponse(nil, err.Error(), w) return } - switch result.Outcome { - case attest.OutcomeSuccess: - klog.Info("policy passed") - results = append(results, externaldata.Item{ - Key: key, - Value: "admit: true, message: policy passed", - }) - case attest.OutcomeFailure: - klog.Info("policy failed") - results = append(results, externaldata.Item{ - Key: key, - Error: "admit: false, error: policy failed", - }) - case attest.OutcomeNoPolicy: - klog.Infof("no policy for image") - results = append(results, externaldata.Item{ - Key: key, - Value: "admit: true, message: no policy", - }) - } + + results = append(results, externaldata.Item{ + Key: key, + Value: ValidationResult{ + Outcome: result.Outcome, + Input: result.Input, + VSA: result.VSA, + Violations: result.Violations, + }, + }) } utils.SendResponse(&results, "", w) } diff --git a/validation/attest-constraint-template.yaml b/validation/attest-constraint-template.yaml index dda1823..92e045d 100644 --- a/validation/attest-constraint-template.yaml +++ b/validation/attest-constraint-template.yaml @@ -12,24 +12,38 @@ spec: rego: | package k8sexternaldata - violation[{"msg": msg}] { + external_data_response := response { # build a list of keys containing images images := [img | img = input.review.object.spec.containers[_].image] # send external data request response := external_data({"provider": "attest-provider-validate", "keys": images}) - - response_with_error(response) - - msg := sprintf("invalid response: %v", [response]) } - response_with_error(response) { + violation[{"msg": msg}] { + errs := response_with_error(external_data_response) + + msg := sprintf("invalid response: %v", [errs]) + } + + violation[{"msg": msg}] { + response := external_data_response.responses[_] + # a response is a list: [key, result, error] + image := response[0] + result := response[1] + + # here we could also check for no_policy if we wanted to fail closed if there is no policy for this image + result.outcome == "failure" + + msg := sprintf("policy failure for image %v:\n%v", [image, yaml.marshal({"violations": result.violations})]) + } + + response_with_error(response) := errs { count(response.errors) > 0 - errs := response.errors[_] - contains(errs[i], "admit: false") + errs := response.errors } - response_with_error(response) { + response_with_error(response) := errs { count(response.system_error) > 0 + errs := response.system_error }