1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
|
package proc
import (
"context"
"encoding/json"
"strconv"
slsa02 "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v0.2"
"github.com/moby/buildkit/executor/resources"
"github.com/moby/buildkit/exporter/containerimage/exptypes"
gatewaypb "github.com/moby/buildkit/frontend/gateway/pb"
"github.com/moby/buildkit/solver"
"github.com/moby/buildkit/solver/llbsolver"
"github.com/moby/buildkit/solver/result"
"github.com/moby/buildkit/util/tracing"
"github.com/pkg/errors"
)
func ProvenanceProcessor(attrs map[string]string) llbsolver.Processor {
return func(ctx context.Context, res *llbsolver.Result, s *llbsolver.Solver, j *solver.Job, usage *resources.SysSampler) (*llbsolver.Result, error) {
span, ctx := tracing.StartSpan(ctx, "create provenance attestation")
defer span.End()
ps, err := exptypes.ParsePlatforms(res.Metadata)
if err != nil {
return nil, err
}
var inlineOnly bool
if v, err := strconv.ParseBool(attrs["inline-only"]); v && err == nil {
inlineOnly = true
}
for _, p := range ps.Platforms {
cp, ok := res.Provenance.FindRef(p.ID)
if !ok {
return nil, errors.Errorf("no build info found for provenance %s", p.ID)
}
if cp == nil {
continue
}
ref, ok := res.FindRef(p.ID)
if !ok {
return nil, errors.Errorf("could not find ref %s", p.ID)
}
pc, err := llbsolver.NewProvenanceCreator(ctx, cp, ref, attrs, j, usage)
if err != nil {
return nil, err
}
filename := "provenance.json"
if v, ok := attrs["filename"]; ok {
filename = v
}
res.AddAttestation(p.ID, llbsolver.Attestation{
Kind: gatewaypb.AttestationKindInToto,
Metadata: map[string][]byte{
result.AttestationReasonKey: []byte(result.AttestationReasonProvenance),
result.AttestationInlineOnlyKey: []byte(strconv.FormatBool(inlineOnly)),
},
InToto: result.InTotoAttestation{
PredicateType: slsa02.PredicateSLSAProvenance,
},
Path: filename,
ContentFunc: func() ([]byte, error) {
pr, err := pc.Predicate()
if err != nil {
return nil, err
}
return json.MarshalIndent(pr, "", " ")
},
})
}
return res, nil
}
}
|