Skip to content

Commit f0391e0

Browse files
committed
Don't store old signature manifest
Signed-off-by: Ayato Tokubi <[email protected]>
1 parent 307f02c commit f0391e0

File tree

2 files changed

+42
-3
lines changed

2 files changed

+42
-3
lines changed

image/oci/layout/oci_dest.go

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,33 @@ func (d *ociImageDestination) addManifest(desc *imgspecv1.Descriptor) {
313313
d.index.Manifests = append(slices.Clone(d.index.Manifests), *desc)
314314
}
315315

316+
// addSignatureManifest is similar to addManifest, but replace the entry based on imgspecv1.AnnotationRefName
317+
// and returns the old digest to delete it later.
318+
func (d *ociImageDestination) addSignatureManifest(desc *imgspecv1.Descriptor) (*imgspecv1.Descriptor, error) {
319+
if desc.Annotations == nil || desc.Annotations[imgspecv1.AnnotationRefName] == "" {
320+
return nil, errors.New("cannot add signature manifest without ref.name")
321+
}
322+
for i, m := range d.index.Manifests {
323+
if m.Annotations[imgspecv1.AnnotationRefName] == desc.Annotations[imgspecv1.AnnotationRefName] {
324+
// Replace it completely.
325+
oldDesc := d.index.Manifests[i]
326+
d.index.Manifests[i] = *desc
327+
return &oldDesc, nil
328+
}
329+
}
330+
// It shouldn't happen, but if there's no entry with the same ref name, but the same digest, just replace it.
331+
for i, m := range d.index.Manifests {
332+
if m.Digest == desc.Digest && m.Annotations[imgspecv1.AnnotationRefName] == "" {
333+
// Replace it completely.
334+
d.index.Manifests[i] = *desc
335+
return nil, nil
336+
}
337+
}
338+
// It's a new entry to be added to the index. Use slices.Clone() to avoid a remote dependency on how d.index was created.
339+
d.index.Manifests = append(slices.Clone(d.index.Manifests), *desc)
340+
return nil, nil
341+
}
342+
316343
// CommitWithOptions marks the process of storing the image as successful and asks for the image to be persisted.
317344
// WARNING: This does not have any transactional semantics:
318345
// - Uploaded data MAY be visible to others before CommitWithOptions() is called
@@ -324,7 +351,7 @@ func (d *ociImageDestination) CommitWithOptions(ctx context.Context, options pri
324351
if err != nil {
325352
return err
326353
}
327-
// Delete unreferenced blobs (e.g. old signature manifest config)
354+
// Delete unreferenced blobs (e.g. old signature manifest and its config)
328355
if !d.blobsToDelete.Empty() {
329356
count := make(map[digest.Digest]int)
330357
err = d.ref.countBlobsReferencedByIndex(count, &d.index, d.sharedBlobDir)
@@ -471,15 +498,26 @@ func (d *ociImageDestination) putSignaturesToSigstoreAttachment(ctx context.Cont
471498
if err != nil {
472499
return err
473500
}
474-
d.addManifest(&imgspecv1.Descriptor{
501+
oldDesc, err := d.addSignatureManifest(&imgspecv1.Descriptor{
475502
MediaType: signManifest.MediaType,
476503
Digest: signDigest,
477504
Size: int64(len(signManifestBlob)),
478505
Annotations: map[string]string{
479506
imgspecv1.AnnotationRefName: signTag,
480507
},
481508
})
482-
509+
if err != nil {
510+
return err
511+
}
512+
// If it overwrote an existing signature manifest, delete blobs referenced by the old manifest.
513+
if oldDesc != nil {
514+
referencedBlobs := make(map[digest.Digest]int)
515+
err = d.ref.countBlobsForDescriptor(referencedBlobs, oldDesc, d.sharedBlobDir)
516+
if err != nil {
517+
return fmt.Errorf("error counting blobs for digest %s: %w", oldDesc.Digest.String(), err)
518+
}
519+
d.blobsToDelete.AddSeq(maps.Keys(referencedBlobs))
520+
}
483521
return nil
484522
}
485523

image/oci/layout/oci_dest_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ func TestPutSignaturesWithFormatTwice(t *testing.T) {
301301
require.NoError(t, err)
302302
require.Len(t, sign, 2)
303303
require.Equal(t, sigstoreSign, sign[0])
304+
require.Equal(t, sigstoreSign2, sign[1])
304305
}
305306

306307
// TestPutSignaturesWithFormatNilDigest tests error handling when instanceDigest is nil

0 commit comments

Comments
 (0)