diff --git a/exporter/containerimage/export.go b/exporter/containerimage/export.go index 9c5262377d3f..55eaf3ff5803 100644 --- a/exporter/containerimage/export.go +++ b/exporter/containerimage/export.go @@ -78,7 +78,8 @@ func (e *imageExporter) Resolve(ctx context.Context, opt map[string]string) (exp RefCfg: cacheconfig.RefConfig{ Compression: compression.New(compression.Default), }, - BuildInfo: true, + BuildInfo: true, + ForceInlineAttestations: true, }, store: true, } diff --git a/exporter/containerimage/opts.go b/exporter/containerimage/opts.go index 057bd299e4f2..c12d86127e0f 100644 --- a/exporter/containerimage/opts.go +++ b/exporter/containerimage/opts.go @@ -12,13 +12,14 @@ import ( ) const ( - keyImageName = "name" - keyLayerCompression = "compression" - keyCompressionLevel = "compression-level" - keyForceCompression = "force-compression" - keyOCITypes = "oci-mediatypes" - keyBuildInfo = "buildinfo" - keyBuildInfoAttrs = "buildinfo-attrs" + keyImageName = "name" + keyLayerCompression = "compression" + keyCompressionLevel = "compression-level" + keyForceCompression = "force-compression" + keyOCITypes = "oci-mediatypes" + keyBuildInfo = "buildinfo" + keyBuildInfoAttrs = "buildinfo-attrs" + keyForceInlineAttestations = "attestation-inline" // preferNondistLayersKey is an exporter option which can be used to mark a layer as non-distributable if the layer reference was // already found to use a non-distributable media type. @@ -34,6 +35,8 @@ type ImageCommitOpts struct { BuildInfoAttrs bool Annotations AnnotationsGroup Epoch *time.Time + + ForceInlineAttestations bool // force inline attestations to be attached } func (c *ImageCommitOpts) Load(opt map[string]string) (map[string]string, error) { @@ -73,6 +76,8 @@ func (c *ImageCommitOpts) Load(opt map[string]string) (map[string]string, error) err = parseBoolWithDefault(&c.BuildInfo, k, v, true) case keyBuildInfoAttrs: err = parseBoolWithDefault(&c.BuildInfoAttrs, k, v, false) + case keyForceInlineAttestations: + err = parseBool(&c.ForceInlineAttestations, k, v) case keyPreferNondistLayers: err = parseBool(&c.RefCfg.PreferNonDistributable, k, v) default: diff --git a/exporter/containerimage/writer.go b/exporter/containerimage/writer.go index c9b5d48b804e..068d86958f8f 100644 --- a/exporter/containerimage/writer.go +++ b/exporter/containerimage/writer.go @@ -69,22 +69,24 @@ func (ic *ImageWriter) Commit(ctx context.Context, inp *exporter.Source, session return nil, err } - requiredAttestations := false - for _, p := range ps.Platforms { - if atts, ok := inp.Attestations[p.ID]; ok { - atts = attestation.Filter(atts, nil, map[string][]byte{ - result.AttestationInlineOnlyKey: []byte(strconv.FormatBool(true)), - }) - if len(atts) > 0 { - requiredAttestations = true - break + if !isMap { + // enable index if we need to include attestations + for _, p := range ps.Platforms { + if atts, ok := inp.Attestations[p.ID]; ok { + if !opts.ForceInlineAttestations { + // if we don't need force inline attestations (for oci + // exporter), filter them out + atts = attestation.Filter(atts, nil, map[string][]byte{ + result.AttestationInlineOnlyKey: []byte(strconv.FormatBool(true)), + }) + } + if len(atts) > 0 { + isMap = true + break + } } } } - if requiredAttestations { - isMap = true - } - if opts.Epoch == nil { if tm, ok, err := epoch.ParseSource(inp); err != nil { return nil, err @@ -108,9 +110,6 @@ func (ic *ImageWriter) Commit(ctx context.Context, inp *exporter.Source, session if len(ps.Platforms) > 1 { return nil, errors.Errorf("cannot export multiple platforms without multi-platform enabled") } - if requiredAttestations { - return nil, errors.Errorf("cannot export attestations without multi-platform enabled") - } var ref cache.ImmutableRef var p exptypes.Platform