mirror of
https://github.com/project-zot/zot.git
synced 2026-06-17 04:48:26 +08:00
fix: don't allow blobs to be deleted if in use (#1559)
dist-spec APIs independently allow deletion of blobs and manifests. Doing the former when in use by an image manifest or index is simply error-prone. So disallow it. Fixes issue #1509 Signed-off-by: Petu Eusebiu <peusebiu@cisco.com> Signed-off-by: Ramkumar Chinchani <rchincha@cisco.com> Co-authored-by: Ramkumar Chinchani <rchincha@cisco.com>
This commit is contained in:
@@ -457,6 +457,81 @@ func PruneImageManifestsFromIndex(imgStore storageTypes.ImageStore, repo string,
|
||||
return prunedManifests, nil
|
||||
}
|
||||
|
||||
func isBlobReferencedInManifest(imgStore storageTypes.ImageStore, repo string,
|
||||
bdigest, mdigest godigest.Digest, log zerolog.Logger,
|
||||
) (bool, error) {
|
||||
if bdigest == mdigest {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
manifestContent, err := GetImageManifest(imgStore, repo, mdigest, log)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Str("repo", repo).Str("digest", mdigest.String()).
|
||||
Msg("gc: failed to read manifest image")
|
||||
|
||||
return false, err
|
||||
}
|
||||
|
||||
if bdigest == manifestContent.Config.Digest {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
for _, layer := range manifestContent.Layers {
|
||||
if bdigest == layer.Digest {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func isBlobReferencedInImageIndex(imgStore storageTypes.ImageStore, repo string,
|
||||
digest godigest.Digest, index ispec.Index, log zerolog.Logger,
|
||||
) (bool, error) {
|
||||
for _, desc := range index.Manifests {
|
||||
var found bool
|
||||
|
||||
switch desc.MediaType {
|
||||
case ispec.MediaTypeImageIndex:
|
||||
/* this branch is not needed, because every manifests in index is already checked
|
||||
when this one is hit, all manifests are referenced in index.json */
|
||||
indexImage, err := GetImageIndex(imgStore, repo, desc.Digest, log)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Str("repository", repo).Str("digest", desc.Digest.String()).
|
||||
Msg("failed to read multiarch(index) image")
|
||||
|
||||
return false, err
|
||||
}
|
||||
|
||||
found, _ = isBlobReferencedInImageIndex(imgStore, repo, digest, indexImage, log)
|
||||
case ispec.MediaTypeImageManifest:
|
||||
found, _ = isBlobReferencedInManifest(imgStore, repo, digest, desc.Digest, log)
|
||||
}
|
||||
|
||||
if found {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func IsBlobReferenced(imgStore storageTypes.ImageStore, repo string,
|
||||
digest godigest.Digest, log zerolog.Logger,
|
||||
) (bool, error) {
|
||||
dir := path.Join(imgStore.RootDir(), repo)
|
||||
if !imgStore.DirExists(dir) {
|
||||
return false, zerr.ErrRepoNotFound
|
||||
}
|
||||
|
||||
index, err := GetIndex(imgStore, repo, log)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return isBlobReferencedInImageIndex(imgStore, repo, digest, index, log)
|
||||
}
|
||||
|
||||
func ApplyLinter(imgStore storageTypes.ImageStore, linter Lint, repo string, descriptor ispec.Descriptor,
|
||||
) (bool, error) {
|
||||
pass := true
|
||||
|
||||
Reference in New Issue
Block a user