Skip to content

Commit 3ca6a43

Browse files
authored
Merge pull request #3433 from tonistiigi/imagetools-create-referrers
imagetools: support for creating attestations/signatures
2 parents 5f5beef + 79b6474 commit 3ca6a43

File tree

392 files changed

+31457
-9213
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

392 files changed

+31457
-9213
lines changed

build/build.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -723,7 +723,7 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opts map[
723723
return err
724724
}
725725

726-
dt, desc, _, err := itpull.Combine(ctx, srcs, indexAnnotations, false)
726+
dt, desc, _, err := itpull.Combine(ctx, srcs, indexAnnotations, false, nil)
727727
if err != nil {
728728
return err
729729
}

commands/imagetools/create.go

Lines changed: 7 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
"os"
88
"strings"
99

10-
"github.com/containerd/containerd/v2/core/images"
10+
"github.com/containerd/containerd/v2/core/remotes"
1111
"github.com/containerd/platforms"
1212
"github.com/distribution/reference"
1313
"github.com/docker/buildx/builder"
@@ -16,7 +16,6 @@ import (
1616
"github.com/docker/buildx/util/imagetools"
1717
"github.com/docker/buildx/util/progress"
1818
"github.com/docker/cli/cli/command"
19-
"github.com/moby/buildkit/util/attestation"
2019
"github.com/moby/buildkit/util/progress/progressui"
2120
"github.com/opencontainers/go-digest"
2221
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
@@ -169,12 +168,12 @@ func runCreate(ctx context.Context, dockerCli command.Cli, in createOptions, arg
169168
return errors.Wrapf(err, "failed to parse annotations")
170169
}
171170

172-
dt, desc, srcMap, err := r.Combine(ctx, srcs, annotations, in.preferIndex)
173-
if err != nil {
174-
return err
175-
}
171+
ctx = remotes.WithMediaTypeKeyPrefix(ctx, "application/vnd.oci.empty.v1+json", "empty")
172+
ctx = remotes.WithMediaTypeKeyPrefix(ctx, "application/vnd.dev.cosign.artifact.sig.v1+json", "cosign")
173+
ctx = remotes.WithMediaTypeKeyPrefix(ctx, "application/vnd.dev.cosign.simplesigning.v1+json", "simplesigning")
174+
ctx = remotes.WithMediaTypeKeyPrefix(ctx, "application/vnd.dev.sigstore.bundle.v0.3+json", "sigstore-bundle")
176175

177-
dt, desc, manifests, err := filterPlatforms(dt, desc, srcMap, platforms)
176+
dt, desc, manifests, err := r.Combine(ctx, srcs, annotations, in.preferIndex, platforms)
178177
if err != nil {
179178
return err
180179
}
@@ -186,7 +185,7 @@ func runCreate(ctx context.Context, dockerCli command.Cli, in createOptions, arg
186185

187186
// manifests can be nil only if pushing one single-platform desc directly
188187
if manifests == nil {
189-
manifests = []descWithSource{{Descriptor: desc, Source: srcs[0]}}
188+
manifests = []imagetools.DescWithSource{{Descriptor: desc, Source: srcs[0]}}
190189
}
191190

192191
// new resolver cause need new auth
@@ -234,124 +233,6 @@ func runCreate(ctx context.Context, dockerCli command.Cli, in createOptions, arg
234233
return err
235234
}
236235

237-
type descWithSource struct {
238-
ocispecs.Descriptor
239-
Source *imagetools.Source
240-
}
241-
242-
func filterPlatforms(dt []byte, desc ocispecs.Descriptor, srcMap map[digest.Digest]*imagetools.Source, plats []ocispecs.Platform) ([]byte, ocispecs.Descriptor, []descWithSource, error) {
243-
matcher := platforms.Any(plats...)
244-
245-
if !images.IsIndexType(desc.MediaType) {
246-
if len(plats) == 0 {
247-
return dt, desc, nil, nil
248-
}
249-
var mfst ocispecs.Manifest
250-
if err := json.Unmarshal(dt, &mfst); err != nil {
251-
return nil, ocispecs.Descriptor{}, nil, errors.Wrapf(err, "failed to parse manifest")
252-
}
253-
if desc.Platform == nil {
254-
return nil, ocispecs.Descriptor{}, nil, errors.Errorf("cannot filter platforms from a manifest without platform information")
255-
}
256-
if !matcher.Match(*desc.Platform) {
257-
return nil, ocispecs.Descriptor{}, nil, errors.Errorf("input platform %s does not match any of the provided platforms", platforms.Format(*desc.Platform))
258-
}
259-
return dt, desc, nil, nil
260-
}
261-
262-
var idx ocispecs.Index
263-
if err := json.Unmarshal(dt, &idx); err != nil {
264-
return nil, ocispecs.Descriptor{}, nil, errors.Wrapf(err, "failed to parse index")
265-
}
266-
if len(plats) == 0 {
267-
mfsts := make([]descWithSource, len(idx.Manifests))
268-
for i, m := range idx.Manifests {
269-
src, ok := srcMap[m.Digest]
270-
if !ok {
271-
defaultSource, ok := srcMap[desc.Digest]
272-
if !ok {
273-
return nil, ocispecs.Descriptor{}, nil, errors.Errorf("internal error: no source found for %s", m.Digest)
274-
}
275-
src = defaultSource
276-
}
277-
mfsts[i] = descWithSource{
278-
Descriptor: m,
279-
Source: src,
280-
}
281-
}
282-
return dt, desc, mfsts, nil
283-
}
284-
285-
manifestMap := map[digest.Digest]ocispecs.Descriptor{}
286-
for _, m := range idx.Manifests {
287-
manifestMap[m.Digest] = m
288-
}
289-
references := map[digest.Digest]struct{}{}
290-
for _, m := range idx.Manifests {
291-
if refType, ok := m.Annotations[attestation.DockerAnnotationReferenceType]; ok && refType == attestation.DockerAnnotationReferenceTypeDefault {
292-
dgstStr, ok := m.Annotations[attestation.DockerAnnotationReferenceDigest]
293-
if !ok {
294-
continue
295-
}
296-
dgst, err := digest.Parse(dgstStr)
297-
if err != nil {
298-
continue
299-
}
300-
subject, ok := manifestMap[dgst]
301-
if !ok {
302-
continue
303-
}
304-
if subject.Platform == nil || matcher.Match(*subject.Platform) {
305-
references[m.Digest] = struct{}{}
306-
}
307-
}
308-
}
309-
310-
var mfsts []ocispecs.Descriptor
311-
var mfstsWithSource []descWithSource
312-
313-
for _, m := range idx.Manifests {
314-
if _, isRef := references[m.Digest]; isRef || m.Platform == nil || matcher.Match(*m.Platform) {
315-
src, ok := srcMap[m.Digest]
316-
if !ok {
317-
defaultSource, ok := srcMap[desc.Digest]
318-
if !ok {
319-
return nil, ocispecs.Descriptor{}, nil, errors.Errorf("internal error: no source found for %s", m.Digest)
320-
}
321-
src = defaultSource
322-
}
323-
mfsts = append(mfsts, m)
324-
mfstsWithSource = append(mfstsWithSource, descWithSource{
325-
Descriptor: m,
326-
Source: src,
327-
})
328-
}
329-
}
330-
if len(mfsts) == len(idx.Manifests) {
331-
// all platforms matched, no need to rewrite index
332-
return dt, desc, mfstsWithSource, nil
333-
}
334-
335-
if len(mfsts) == 0 {
336-
return nil, ocispecs.Descriptor{}, nil, errors.Errorf("none of the manifests match the provided platforms")
337-
}
338-
339-
idx.Manifests = mfsts
340-
idxBytes, err := json.MarshalIndent(&idx, "", " ")
341-
if err != nil {
342-
return nil, ocispecs.Descriptor{}, nil, errors.Wrap(err, "failed to marshal index")
343-
}
344-
345-
desc = ocispecs.Descriptor{
346-
MediaType: desc.MediaType,
347-
Size: int64(len(idxBytes)),
348-
Digest: digest.FromBytes(idxBytes),
349-
Annotations: desc.Annotations,
350-
}
351-
352-
return idxBytes, desc, mfstsWithSource, nil
353-
}
354-
355236
func parseSources(in []string) ([]*imagetools.Source, error) {
356237
out := make([]*imagetools.Source, len(in))
357238
for i, in := range in {

go.mod

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ go 1.24.3
55
require (
66
github.com/Masterminds/semver/v3 v3.4.0
77
github.com/Microsoft/go-winio v0.6.2
8-
github.com/aws/aws-sdk-go-v2/config v1.27.27
8+
github.com/aws/aws-sdk-go-v2/config v1.31.3
99
github.com/compose-spec/compose-go/v2 v2.9.1
1010
github.com/containerd/console v1.0.5
1111
github.com/containerd/containerd/v2 v2.2.0-rc.1
@@ -20,7 +20,7 @@ require (
2020
github.com/docker/cli-docs-tool v0.10.0
2121
github.com/docker/docker v28.5.1+incompatible
2222
github.com/docker/go-units v0.5.0
23-
github.com/gofrs/flock v0.12.1
23+
github.com/gofrs/flock v0.13.0
2424
github.com/google/go-dap v0.12.0
2525
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
2626
github.com/google/uuid v1.6.0
@@ -29,7 +29,7 @@ require (
2929
github.com/hashicorp/hcl/v2 v2.24.0
3030
github.com/in-toto/in-toto-golang v0.9.0
3131
github.com/mitchellh/hashstructure/v2 v2.0.2
32-
github.com/moby/buildkit v0.25.0-rc1.0.20251011181741-9b6f60ac8bf9
32+
github.com/moby/buildkit v0.25.0-rc1.0.20251105204500-e18be4182830
3333
github.com/moby/go-archive v0.1.0
3434
github.com/moby/sys/atomicwriter v0.1.0
3535
github.com/moby/sys/mountinfo v0.7.2
@@ -49,19 +49,19 @@ require (
4949
github.com/tonistiigi/go-csvvalue v0.0.0-20240814133006-030d3b2625d0
5050
github.com/tonistiigi/jaeger-ui-rest v0.0.0-20250408171107-3dd17559e117
5151
github.com/zclconf/go-cty v1.17.0
52-
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0
53-
go.opentelemetry.io/otel v1.37.0
52+
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0
53+
go.opentelemetry.io/otel v1.38.0
5454
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.31.0
55-
go.opentelemetry.io/otel/metric v1.37.0
56-
go.opentelemetry.io/otel/sdk v1.37.0
57-
go.opentelemetry.io/otel/trace v1.37.0
55+
go.opentelemetry.io/otel/metric v1.38.0
56+
go.opentelemetry.io/otel/sdk v1.38.0
57+
go.opentelemetry.io/otel/trace v1.38.0
5858
go.yaml.in/yaml/v3 v3.0.4
5959
golang.org/x/mod v0.29.0
6060
golang.org/x/sync v0.17.0
6161
golang.org/x/sys v0.37.0
6262
golang.org/x/term v0.35.0
6363
golang.org/x/text v0.29.0
64-
google.golang.org/genproto/googleapis/rpc v0.0.0-20250804133106-a7a43d27e69b
64+
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5
6565
google.golang.org/grpc v1.76.0
6666
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1
6767
google.golang.org/protobuf v1.36.10
@@ -75,19 +75,19 @@ require (
7575
github.com/agext/levenshtein v1.2.3 // indirect
7676
github.com/apparentlymart/go-cidr v1.0.1 // indirect
7777
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
78-
github.com/aws/aws-sdk-go-v2 v1.30.3 // indirect
79-
github.com/aws/aws-sdk-go-v2/credentials v1.17.27 // indirect
80-
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 // indirect
81-
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 // indirect
82-
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15 // indirect
83-
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
84-
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 // indirect
85-
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 // indirect
86-
github.com/aws/aws-sdk-go-v2/service/sso v1.22.4 // indirect
87-
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 // indirect
88-
github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 // indirect
89-
github.com/aws/smithy-go v1.20.3 // indirect
90-
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
78+
github.com/aws/aws-sdk-go-v2 v1.38.1 // indirect
79+
github.com/aws/aws-sdk-go-v2/credentials v1.18.7 // indirect
80+
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.4 // indirect
81+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.4 // indirect
82+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.4 // indirect
83+
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect
84+
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 // indirect
85+
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.4 // indirect
86+
github.com/aws/aws-sdk-go-v2/service/sso v1.28.2 // indirect
87+
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.34.0 // indirect
88+
github.com/aws/aws-sdk-go-v2/service/sts v1.38.0 // indirect
89+
github.com/aws/smithy-go v1.22.5 // indirect
90+
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
9191
github.com/containerd/containerd/api v1.10.0-rc.0 // indirect
9292
github.com/containerd/errdefs/pkg v0.3.0 // indirect
9393
github.com/containerd/ttrpc v1.2.7 // indirect
@@ -111,7 +111,7 @@ require (
111111
github.com/google/gnostic-models v0.7.0 // indirect
112112
github.com/google/go-cmp v0.7.0 // indirect
113113
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect
114-
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 // indirect
114+
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
115115
github.com/hashicorp/errwrap v1.1.0 // indirect
116116
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
117117
github.com/inconshreveable/mousetrap v1.1.0 // indirect
@@ -139,7 +139,7 @@ require (
139139
github.com/rivo/uniseg v0.2.0 // indirect
140140
github.com/russross/blackfriday/v2 v2.1.0 // indirect
141141
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 // indirect
142-
github.com/secure-systems-lab/go-securesystemslib v0.6.0 // indirect
142+
github.com/secure-systems-lab/go-securesystemslib v0.9.1 // indirect
143143
github.com/shibumi/go-pathspec v1.3.0 // indirect
144144
github.com/theupdateframework/notary v0.7.0 // indirect
145145
github.com/tonistiigi/dchapes-mode v0.0.0-20250318174251-73d941a28323 // indirect
@@ -148,22 +148,22 @@ require (
148148
github.com/x448/float16 v0.8.4 // indirect
149149
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
150150
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
151-
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect
152-
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.60.0 // indirect
153-
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 // indirect
154-
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.35.0 // indirect
155-
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect
156-
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 // indirect
157-
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 // indirect
158-
go.opentelemetry.io/otel/sdk/metric v1.37.0 // indirect
159-
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
151+
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect
152+
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.61.0 // indirect
153+
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.38.0 // indirect
154+
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.38.0 // indirect
155+
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 // indirect
156+
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 // indirect
157+
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 // indirect
158+
go.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect
159+
go.opentelemetry.io/proto/otlp v1.7.1 // indirect
160160
go.yaml.in/yaml/v2 v2.4.2 // indirect
161161
golang.org/x/crypto v0.42.0 // indirect
162162
golang.org/x/net v0.44.0 // indirect
163163
golang.org/x/oauth2 v0.30.0 // indirect
164164
golang.org/x/time v0.14.0 // indirect
165165
golang.org/x/tools v0.37.0 // indirect
166-
google.golang.org/genproto/googleapis/api v0.0.0-20250804133106-a7a43d27e69b // indirect
166+
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect
167167
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
168168
gopkg.in/inf.v0 v0.9.1 // indirect
169169
gopkg.in/yaml.v3 v3.0.1 // indirect

0 commit comments

Comments
 (0)