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 83 84 85 86 87 88 89 90
|
package proc
import (
"context"
"github.com/moby/buildkit/client/llb"
"github.com/moby/buildkit/client/llb/sourceresolver"
"github.com/moby/buildkit/executor/resources"
"github.com/moby/buildkit/exporter/containerimage/exptypes"
"github.com/moby/buildkit/frontend"
"github.com/moby/buildkit/frontend/attestations/sbom"
"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 SBOMProcessor(scannerRef string, useCache bool, resolveMode string) llbsolver.Processor {
return func(ctx context.Context, res *llbsolver.Result, s *llbsolver.Solver, j *solver.Job, usage *resources.SysSampler) (*llbsolver.Result, error) {
// skip sbom generation if we already have an sbom
if sbom.HasSBOM(res.Result) {
return res, nil
}
span, ctx := tracing.StartSpan(ctx, "create sbom attestation")
defer span.End()
ps, err := exptypes.ParsePlatforms(res.Metadata)
if err != nil {
return nil, err
}
scanner, err := sbom.CreateSBOMScanner(ctx, s.Bridge(j), scannerRef, sourceresolver.Opt{
ImageOpt: &sourceresolver.ResolveImageOpt{
ResolveMode: resolveMode,
},
})
if err != nil {
return nil, err
}
if scanner == nil {
return res, nil
}
for _, p := range ps.Platforms {
ref, ok := res.FindRef(p.ID)
if !ok {
return nil, errors.Errorf("could not find ref %s", p.ID)
}
if ref == nil {
continue
}
defop, err := llb.NewDefinitionOp(ref.Definition())
if err != nil {
return nil, err
}
st := llb.NewState(defop)
var opts []llb.ConstraintsOpt
if !useCache {
opts = append(opts, llb.IgnoreCache)
}
att, err := scanner(ctx, p.ID, st, nil, opts...)
if err != nil {
return nil, err
}
attSolve, err := result.ConvertAttestation(&att, func(st *llb.State) (solver.ResultProxy, error) {
def, err := st.Marshal(ctx)
if err != nil {
return nil, err
}
r, err := s.Bridge(j).Solve(ctx, frontend.SolveRequest{
Definition: def.ToPB(),
}, j.SessionID)
if err != nil {
return nil, err
}
return r.Ref, nil
})
if err != nil {
return nil, err
}
res.AddAttestation(p.ID, *attSolve)
}
return res, nil
}
}
|