diff --git a/solver/llbsolver/provenance.go b/solver/llbsolver/provenance.go index 923703021..4ddd4a4db 100644 --- a/solver/llbsolver/provenance.go +++ b/solver/llbsolver/provenance.go @@ -2,7 +2,6 @@ package llbsolver import ( "context" - "encoding/json" "sync" "github.com/containerd/containerd/platforms" @@ -59,7 +58,10 @@ func (b *provenanceBridge) allImages() []provenance.ImageSource { } func (b *provenanceBridge) requests(r *frontend.Result) (*resultRequests, error) { - reqs := &resultRequests{refs: make(map[string]*resultWithBridge)} + reqs := &resultRequests{ + refs: make(map[string]*resultWithBridge), + atts: make(map[string][]*resultWithBridge), + } if r.Ref != nil { ref, ok := b.findByResult(r.Ref) @@ -77,16 +79,25 @@ func (b *provenanceBridge) requests(r *frontend.Result) (*resultRequests, error) reqs.refs[k] = r } - if platformsBytes, ok := r.Metadata[exptypes.ExporterPlatformsKey]; ok { - var ps exptypes.Platforms - if len(platformsBytes) > 0 { - if err := json.Unmarshal(platformsBytes, &ps); err != nil { - return nil, errors.Wrapf(err, "failed to parse platforms passed to provenance processor") + for k, atts := range r.Attestations { + for _, att := range atts { + if att.Ref == nil { + continue } - reqs.platforms = ps.Platforms + r, ok := b.findByResult(att.Ref) + if !ok { + return nil, errors.Errorf("could not find request for ref %s", att.Ref.ID()) + } + reqs.atts[k] = append(reqs.atts[k], r) } } + ps, err := exptypes.ParsePlatforms(r.Metadata) + if err != nil { + return nil, err + } + reqs.platforms = ps.Platforms + return reqs, nil } @@ -97,15 +108,15 @@ func (b *provenanceBridge) findByResult(rp solver.ResultProxy) (*resultWithBridg } } for _, bld := range b.builds { - if bld.res.Ref != nil { - if bld.res.Ref.ID() == rp.ID() { - return &bld, true - } - } - for _, ref := range bld.res.Refs { - if ref.ID() == rp.ID() { - return &bld, true + found := false + bld.res.EachRef(func(r solver.ResultProxy) error { + if r.ID() == rp.ID() { + found = true } + return nil + }) + if found { + return &bld, true } } return nil, false @@ -165,6 +176,7 @@ func (b *provenanceBridge) Solve(ctx context.Context, req frontend.SolveRequest, type resultRequests struct { ref *resultWithBridge refs map[string]*resultWithBridge + atts map[string][]*resultWithBridge platforms []exptypes.Platform } @@ -228,6 +240,11 @@ func (reqs *resultRequests) allRes() map[string]struct{} { for _, r := range reqs.refs { res[r.res.Ref.ID()] = struct{}{} } + for _, rs := range reqs.atts { + for _, r := range rs { + res[r.res.Ref.ID()] = struct{}{} + } + } return res } diff --git a/solver/llbsolver/solver.go b/solver/llbsolver/solver.go index 950e5233f..3a4e7e482 100644 --- a/solver/llbsolver/solver.go +++ b/solver/llbsolver/solver.go @@ -412,6 +412,7 @@ func addProvenanceToResult(res *frontend.Result, br *provenanceBridge) (*Result, Result: res, Provenance: &provenance.Result{}, } + if res.Ref != nil { cp, err := getProvenance(res.Ref, reqs.ref.bridge, "", reqs) if err != nil { @@ -425,11 +426,10 @@ func addProvenanceToResult(res *frontend.Result, br *provenanceBridge) (*Result, return nil, err } } - if len(res.Refs) == 0 { - return out, nil - } - out.Provenance.Refs = make(map[string]*provenance.Capture, len(res.Refs)) + if len(res.Refs) != 0 { + out.Provenance.Refs = make(map[string]*provenance.Capture, len(res.Refs)) + } for k, ref := range res.Refs { cp, err := getProvenance(ref, reqs.refs[k].bridge, k, reqs) if err != nil { @@ -443,6 +443,22 @@ func addProvenanceToResult(res *frontend.Result, br *provenanceBridge) (*Result, return nil, err } } + + if len(res.Attestations) != 0 { + out.Provenance.Attestations = make(map[string][]result.Attestation[*provenance.Capture], len(res.Attestations)) + } + for k, as := range res.Attestations { + for i, a := range as { + a2, err := result.ConvertAttestation(&a, func(r solver.ResultProxy) (*provenance.Capture, error) { + return getProvenance(r, reqs.atts[k][i].bridge, k, reqs) + }) + if err != nil { + return nil, err + } + out.Provenance.Attestations[k] = append(out.Provenance.Attestations[k], *a2) + } + } + return out, nil }