Files
attest-provider/pkg/handler/validate.go
2024-06-24 09:55:52 +01:00

101 lines
2.6 KiB
Go

package handler
import (
"encoding/json"
"fmt"
"io"
"net/http"
"path/filepath"
"runtime/debug"
"github.com/docker/attest/pkg/attest"
"github.com/docker/attest/pkg/oci"
"github.com/docker/attest/pkg/policy"
intoto "github.com/in-toto/in-toto-golang/in_toto"
"github.com/open-policy-agent/frameworks/constraint/pkg/externaldata"
"github.com/open-policy-agent/gatekeeper-external-data-provider/pkg/utils"
"k8s.io/klog/v2"
)
type ValidationResult struct {
Outcome attest.Outcome `json:"outcome"`
Input *policy.PolicyInput `json:"input"`
VSA *intoto.Statement `json:"vsa"`
Violations []policy.Violation `json:"violations"`
}
func Validate() http.Handler {
return http.HandlerFunc(validate)
}
func validate(w http.ResponseWriter, req *http.Request) {
defer func() {
if r := recover(); r != nil {
klog.Error(string(debug.Stack()))
klog.ErrorS(fmt.Errorf("%v", r), "panic occurred")
}
}()
// read request body
requestBody, err := io.ReadAll(req.Body)
if err != nil {
utils.SendResponse(nil, fmt.Sprintf("unable to read request body: %v", err), w)
return
}
klog.InfoS("received request", "body", requestBody)
// parse request body
var providerRequest externaldata.ProviderRequest
err = json.Unmarshal(requestBody, &providerRequest)
if err != nil {
utils.SendResponse(nil, fmt.Sprintf("unable to unmarshal request body: %v", err), w)
return
}
results := make([]externaldata.Item, 0)
// create a tuf client
tufOutputPath := filepath.Join("/tuf_temp", ".docker", "tuf")
tufClient, err := createTufClient(tufOutputPath)
if err != nil {
utils.SendResponse(nil, err.Error(), w)
return
}
for _, key := range providerRequest.Request.Keys {
platform := "linux/amd64"
src, err := oci.ParseImageSpec(key, oci.WithPlatform(platform))
if err != nil {
utils.SendResponse(nil, err.Error(), w)
return
}
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
}
ctx := req.Context()
debug := true
ctx = policy.WithPolicyEvaluator(ctx, policy.NewRegoEvaluator(debug))
result, err := attest.Verify(ctx, src, opts)
if err != nil {
utils.SendResponse(nil, err.Error(), w)
return
}
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)
}