c8d/resolveImage: Fix Digested and Named reference

When resolving a reference that is both a Named and Digested, it could
be resolved to an image that has the same digest, but completely
different repository name.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
(cherry picked from commit 48fc306764fc5c39d4284021520a0337ef7e0cb0)
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
This commit is contained in:
Paweł Gronowski 2023-07-18 14:21:00 +02:00
parent 8ab6d025f6
commit 3c5c192baf
No known key found for this signature in database
GPG key ID: B85EFCFE26DEF92A
2 changed files with 53 additions and 0 deletions

View file

@ -274,6 +274,24 @@ func (i *ImageService) resolveImage(ctx context.Context, refOrID string) (contai
return containerdimages.Image{}, images.ErrImageDoesNotExist{Ref: parsed}
}
// If reference is both Named and Digested, make sure we don't match
// images with a different repository even if digest matches.
// For example, busybox@sha256:abcdef..., shouldn't match asdf@sha256:abcdef...
if parsedNamed, ok := parsed.(reference.Named); ok {
for _, img := range imgs {
imgNamed, err := reference.ParseNormalizedNamed(img.Name)
if err != nil {
logrus.WithError(err).WithField("image", img.Name).Warn("image with invalid name encountered")
continue
}
if parsedNamed.Name() == imgNamed.Name() {
return img, nil
}
}
return containerdimages.Image{}, images.ErrImageDoesNotExist{Ref: parsed}
}
return imgs[0], nil
}

View file

@ -6,9 +6,11 @@ import (
"testing"
"github.com/docker/docker/api/types"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/integration/internal/container"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
"gotest.tools/v3/skip"
)
func TestRemoveImageOrphaning(t *testing.T) {
@ -57,3 +59,36 @@ func TestRemoveImageOrphaning(t *testing.T) {
_, _, err = client.ImageInspectWithRaw(ctx, commitResp2.ID)
assert.Check(t, is.ErrorContains(err, "No such image:"))
}
func TestRemoveByDigest(t *testing.T) {
skip.If(t, !testEnv.UsingSnapshotter(), "RepoDigests doesn't include tags when using graphdrivers")
defer setupTest(t)()
ctx := context.Background()
client := testEnv.APIClient()
err := client.ImageTag(ctx, "busybox", "test-remove-by-digest:latest")
assert.NilError(t, err)
inspect, _, err := client.ImageInspectWithRaw(ctx, "test-remove-by-digest")
assert.NilError(t, err)
id := ""
for _, ref := range inspect.RepoDigests {
if strings.Contains(ref, "test-remove-by-digest") {
id = ref
break
}
}
assert.Assert(t, id != "")
t.Logf("removing %s", id)
_, err = client.ImageRemove(ctx, id, types.ImageRemoveOptions{})
assert.NilError(t, err)
inspect, _, err = client.ImageInspectWithRaw(ctx, "busybox")
assert.Check(t, err, "busybox image got deleted")
inspect, _, err = client.ImageInspectWithRaw(ctx, "test-remove-by-digest")
assert.Check(t, is.ErrorType(err, errdefs.IsNotFound))
}