From 2588b66fd9544d6f009a6c086da9694b158ef408 Mon Sep 17 00:00:00 2001 From: CrazyMax <1951866+crazy-max@users.noreply.github.com> Date: Wed, 18 Jun 2025 13:36:26 +0200 Subject: [PATCH] build: fix buildx.build.provenance metadata Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com> --- build/provenance.go | 46 ++++++++++++++++--------------------- commands/history/inspect.go | 2 +- tests/bake.go | 2 +- tests/build.go | 2 +- 4 files changed, 23 insertions(+), 29 deletions(-) diff --git a/build/provenance.go b/build/provenance.go index 4a9b2d188..b15109051 100644 --- a/build/provenance.go +++ b/build/provenance.go @@ -13,6 +13,7 @@ import ( "github.com/containerd/containerd/v2/core/content/proxy" "github.com/docker/buildx/util/confutil" "github.com/docker/buildx/util/progress" + slsa1 "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v1" controlapi "github.com/moby/buildkit/api/services/control" "github.com/moby/buildkit/client" provenancetypes "github.com/moby/buildkit/solver/llbsolver/provenance/types" @@ -22,15 +23,6 @@ import ( "golang.org/x/sync/errgroup" ) -type provenancePredicate struct { - Builder *provenanceBuilder `json:"builder,omitempty"` - provenancetypes.ProvenancePredicateSLSA02 -} - -type provenanceBuilder struct { - ID string `json:"id,omitempty"` -} - func setRecordProvenance(ctx context.Context, c *client.Client, sr *client.SolveResponse, ref string, mode confutil.MetadataProvenanceMode, pw progress.Writer) error { if mode == confutil.MetadataProvenanceModeDisabled { return nil @@ -69,7 +61,7 @@ func fetchProvenance(ctx context.Context, c *client.Client, ref string, mode con continue } if ev.Record.Result != nil { - desc := lookupProvenance(ev.Record.Result) + desc, predicateType := lookupProvenance(ev.Record.Result) if desc == nil { continue } @@ -78,7 +70,7 @@ func fetchProvenance(ctx context.Context, c *client.Client, ref string, mode con if err != nil { return errors.Wrapf(err, "failed to load provenance blob from build record") } - prv, err := encodeProvenance(dt, mode) + prv, err := encodeProvenance(dt, predicateType, mode) if err != nil { return err } @@ -92,7 +84,7 @@ func fetchProvenance(ctx context.Context, c *client.Client, ref string, mode con }) } else if ev.Record.Results != nil { for platform, res := range ev.Record.Results { - desc := lookupProvenance(res) + desc, predicateType := lookupProvenance(res) if desc == nil { continue } @@ -101,7 +93,7 @@ func fetchProvenance(ctx context.Context, c *client.Client, ref string, mode con if err != nil { return errors.Wrapf(err, "failed to load provenance blob from build record") } - prv, err := encodeProvenance(dt, mode) + prv, err := encodeProvenance(dt, predicateType, mode) if err != nil { return err } @@ -119,7 +111,7 @@ func fetchProvenance(ctx context.Context, c *client.Client, ref string, mode con return out, eg.Wait() } -func lookupProvenance(res *controlapi.BuildResultInfo) *ocispecs.Descriptor { +func lookupProvenance(res *controlapi.BuildResultInfo) (*ocispecs.Descriptor, string) { for _, a := range res.Attestations { if a.MediaType == "application/vnd.in-toto+json" && strings.HasPrefix(a.Annotations["in-toto.io/predicate-type"], "https://slsa.dev/provenance/") { return &ocispecs.Descriptor{ @@ -127,27 +119,29 @@ func lookupProvenance(res *controlapi.BuildResultInfo) *ocispecs.Descriptor { Size: a.Size, MediaType: a.MediaType, Annotations: a.Annotations, - } + }, a.Annotations["in-toto.io/predicate-type"] } } - return nil + return nil, "" } -func encodeProvenance(dt []byte, mode confutil.MetadataProvenanceMode) (string, error) { - var prv provenancePredicate - if err := json.Unmarshal(dt, &prv); err != nil { +func encodeProvenance(dt []byte, predicateType string, mode confutil.MetadataProvenanceMode) (string, error) { + var pred *provenancetypes.ProvenancePredicateSLSA02 + if predicateType == slsa1.PredicateSLSAProvenance { + var pred1 *provenancetypes.ProvenancePredicateSLSA1 + if err := json.Unmarshal(dt, &pred1); err != nil { + return "", errors.Wrapf(err, "failed to unmarshal provenance") + } + pred = pred1.ConvertToSLSA02() + } else if err := json.Unmarshal(dt, &pred); err != nil { return "", errors.Wrapf(err, "failed to unmarshal provenance") } - if prv.Builder != nil && prv.Builder.ID == "" { - // reset builder if id is empty - prv.Builder = nil - } if mode == confutil.MetadataProvenanceModeMin { // reset fields for minimal provenance - prv.BuildConfig = nil - prv.Metadata = nil + pred.BuildConfig = nil + pred.Metadata = nil } - dtprv, err := json.Marshal(prv) + dtprv, err := json.Marshal(pred) if err != nil { return "", errors.Wrapf(err, "failed to marshal provenance") } diff --git a/commands/history/inspect.go b/commands/history/inspect.go index 920143fb9..545558d01 100644 --- a/commands/history/inspect.go +++ b/commands/history/inspect.go @@ -441,7 +441,7 @@ workers0: if err := json.Unmarshal(dt, &pred02); err != nil { return errors.Errorf("failed to unmarshal provenance %s: %v", prov.descr.Digest, err) } - pred = provenancetypes.ConvertSLSA02ToSLSA1(pred02) + pred = pred02.ConvertToSLSA1() } else if err := json.Unmarshal(dt, &pred); err != nil { return errors.Errorf("failed to unmarshal provenance %s: %v", prov.descr.Digest, err) } diff --git a/tests/bake.go b/tests/bake.go index 0ce6d216c..b6fd15858 100644 --- a/tests/bake.go +++ b/tests/bake.go @@ -1398,7 +1398,7 @@ target "default" { var prv provenancetypes.ProvenancePredicateSLSA02 require.NoError(t, json.Unmarshal(dtprv, &prv)) - require.Equal(t, provenancetypes.BuildKitBuildType, prv.BuildType) + require.Equal(t, provenancetypes.BuildKitBuildType02, prv.BuildType) } func testBakeMetadataWarnings(t *testing.T, sb integration.Sandbox) { diff --git a/tests/build.go b/tests/build.go index e179163cf..f494907a6 100644 --- a/tests/build.go +++ b/tests/build.go @@ -835,7 +835,7 @@ func buildMetadataProvenance(t *testing.T, sb integration.Sandbox, metadataMode var prv provenancetypes.ProvenancePredicateSLSA02 require.NoError(t, json.Unmarshal(dtprv, &prv)) - require.Equal(t, provenancetypes.BuildKitBuildType, prv.BuildType) + require.Equal(t, provenancetypes.BuildKitBuildType02, prv.BuildType) } func testBuildMetadataWarnings(t *testing.T, sb integration.Sandbox) {