Files
attest-provider/pkg/handler/mutate.go
Jonny Stoten 74bd930006 Rename module to docker/attest-provider
We were still using the name from the template
2024-06-26 12:16:04 +01:00

88 lines
2.1 KiB
Go

package handler
import (
"encoding/json"
"fmt"
"io"
"net/http"
"runtime/debug"
"github.com/docker/attest-provider/pkg/utils"
"github.com/docker/attest/pkg/oci"
"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/open-policy-agent/frameworks/constraint/pkg/externaldata"
"k8s.io/klog/v2"
)
type mutateHandler struct{}
func NewMutateHandler() (http.Handler, error) {
return &mutateHandler{}, nil
}
func (h *mutateHandler) ServeHTTP(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)
ctx := req.Context()
opts := oci.WithOptions(ctx, nil)
for _, key := range providerRequest.Request.Keys {
output, err := getReferenceWithDigest(key, opts)
if err != nil {
utils.SendResponse(nil, err.Error(), w)
return
}
results = append(results, externaldata.Item{
Key: key,
Value: output,
})
}
utils.SendResponse(&results, "", w)
}
func getReferenceWithDigest(imageRef string, opts []remote.Option) (string, error) {
ref, err := name.ParseReference(imageRef)
if err != nil {
return "", fmt.Errorf("unable to parse reference %s: %v", imageRef, err)
}
// if it already contains a digest, just return it as is
if _, ok := ref.(name.Digest); ok {
return ref.String(), nil
}
// we need to make a request to the registry to get the digest
desc, err := remote.Head(ref, opts...)
if err != nil {
return "", fmt.Errorf("unable to get digest for reference %s: %v", imageRef, err)
}
return ref.Name() + "@" + desc.Digest.String(), nil
}