Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pkg/api/constants/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const (
Uploads = "uploads"
DistAPIVersion = "Docker-Distribution-API-Version"
DistContentDigestKey = "Docker-Content-Digest"
SubjectDigestKey = "OCI-Subject"
BlobUploadUUID = "Blob-Upload-UUID"
DefaultMediaType = "application/json"
BinaryMediaType = "application/octet-stream"
Expand Down
6 changes: 5 additions & 1 deletion pkg/api/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,7 @@ func (rh *RouteHandler) UpdateManifest(response http.ResponseWriter, request *ht
return
}

digest, err := imgStore.PutImageManifest(name, reference, mediaType, body)
digest, subjectDigest, err := imgStore.PutImageManifest(name, reference, mediaType, body)
if err != nil {
if errors.Is(err, zerr.ErrRepoNotFound) { //nolint:gocritic // errorslint conflicts with gocritic:IfElseChain
WriteJSON(response, http.StatusNotFound,
Expand Down Expand Up @@ -656,6 +656,10 @@ func (rh *RouteHandler) UpdateManifest(response http.ResponseWriter, request *ht
}
}

if subjectDigest.String() != "" {
response.Header().Set(constants.SubjectDigestKey, subjectDigest.String())
Comment thread
rchincha marked this conversation as resolved.
}

response.Header().Set("Location", fmt.Sprintf("/v2/%s/manifests/%s", name, digest))
response.Header().Set(constants.DistContentDigestKey, digest.String())
response.WriteHeader(http.StatusCreated)
Expand Down
30 changes: 20 additions & 10 deletions pkg/api/routes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,10 @@ func TestRoutes(t *testing.T) {
"reference": "reference",
},
&mocks.MockedImageStore{
PutImageManifestFn: func(repo, reference, mediaType string, body []byte) (godigest.Digest, error) {
return "", zerr.ErrRepoNotFound
PutImageManifestFn: func(repo, reference, mediaType string, body []byte) (godigest.Digest,
godigest.Digest, error,
) {
return "", "", zerr.ErrRepoNotFound
},
})
So(statusCode, ShouldEqual, http.StatusNotFound)
Expand All @@ -161,8 +163,10 @@ func TestRoutes(t *testing.T) {
},

&mocks.MockedImageStore{
PutImageManifestFn: func(repo, reference, mediaType string, body []byte) (godigest.Digest, error) {
return "", zerr.ErrManifestNotFound
PutImageManifestFn: func(repo, reference, mediaType string, body []byte) (godigest.Digest,
godigest.Digest, error,
) {
return "", "", zerr.ErrManifestNotFound
},
})
So(statusCode, ShouldEqual, http.StatusNotFound)
Expand All @@ -173,8 +177,10 @@ func TestRoutes(t *testing.T) {
"reference": "reference",
},
&mocks.MockedImageStore{
PutImageManifestFn: func(repo, reference, mediaType string, body []byte) (godigest.Digest, error) {
return "", zerr.ErrBadManifest
PutImageManifestFn: func(repo, reference, mediaType string, body []byte) (godigest.Digest,
godigest.Digest, error,
) {
return "", "", zerr.ErrBadManifest
},
})
So(statusCode, ShouldEqual, http.StatusBadRequest)
Expand All @@ -185,8 +191,10 @@ func TestRoutes(t *testing.T) {
"reference": "reference",
},
&mocks.MockedImageStore{
PutImageManifestFn: func(repo, reference, mediaType string, body []byte) (godigest.Digest, error) {
return "", zerr.ErrBlobNotFound
PutImageManifestFn: func(repo, reference, mediaType string, body []byte) (godigest.Digest,
godigest.Digest, error,
) {
return "", "", zerr.ErrBlobNotFound
},
})
So(statusCode, ShouldEqual, http.StatusBadRequest)
Expand All @@ -198,8 +206,10 @@ func TestRoutes(t *testing.T) {
"reference": "reference",
},
&mocks.MockedImageStore{
PutImageManifestFn: func(repo, reference, mediaType string, body []byte) (godigest.Digest, error) {
return "", zerr.ErrRepoBadVersion
PutImageManifestFn: func(repo, reference, mediaType string, body []byte) (godigest.Digest,
godigest.Digest, error,
) {
return "", "", zerr.ErrRepoBadVersion
},
})
So(statusCode, ShouldEqual, http.StatusInternalServerError)
Expand Down
2 changes: 1 addition & 1 deletion pkg/extensions/search/cve/trivy/scanner_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func generateTestImage(storeController storage.StoreController, image string) {

manifestBlob, err := json.Marshal(manifest)
So(err, ShouldBeNil)
_, err = store.PutImageManifest(repoName, tag, ispec.MediaTypeImageManifest, manifestBlob)
_, _, err = store.PutImageManifest(repoName, tag, ispec.MediaTypeImageManifest, manifestBlob)
So(err, ShouldBeNil)
}

Expand Down
24 changes: 16 additions & 8 deletions pkg/extensions/search/search_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4515,8 +4515,10 @@ func TestRepoDBWhenSigningImages(t *testing.T) {
Convey("imageIsSignature fails", func() {
// make image store ignore the wrong format of the input
ctlr.StoreController.DefaultStore = mocks.MockedImageStore{
PutImageManifestFn: func(repo, reference, mediaType string, body []byte) (godigest.Digest, error) {
return "", nil
PutImageManifestFn: func(repo, reference, mediaType string, body []byte) (godigest.Digest,
godigest.Digest, error,
) {
return "", "", nil
},
DeleteImageManifestFn: func(repo, reference string, dc bool) error {
return ErrTestError
Expand Down Expand Up @@ -5783,8 +5785,10 @@ func TestRepoDBWhenDeletingImages(t *testing.T) {

Convey("imageIsSignature fails", func() {
ctlr.StoreController.DefaultStore = mocks.MockedImageStore{
PutImageManifestFn: func(repo, reference, mediaType string, body []byte) (godigest.Digest, error) {
return "", nil
PutImageManifestFn: func(repo, reference, mediaType string, body []byte) (godigest.Digest,
godigest.Digest, error,
) {
return "", "", nil
},
DeleteImageManifestFn: func(repo, reference string, dc bool) error {
return nil
Expand All @@ -5807,8 +5811,10 @@ func TestRepoDBWhenDeletingImages(t *testing.T) {

return configBlob, nil
},
PutImageManifestFn: func(repo, reference, mediaType string, body []byte) (godigest.Digest, error) {
return "", nil
PutImageManifestFn: func(repo, reference, mediaType string, body []byte) (godigest.Digest,
godigest.Digest, error,
) {
return "", "", nil
},
DeleteImageManifestFn: func(repo, reference string, dc bool) error {
return nil
Expand All @@ -5835,8 +5841,10 @@ func TestRepoDBWhenDeletingImages(t *testing.T) {

return configBlob, nil
},
PutImageManifestFn: func(repo, reference, mediaType string, body []byte) (godigest.Digest, error) {
return "", ErrTestError
PutImageManifestFn: func(repo, reference, mediaType string, body []byte) (godigest.Digest,
godigest.Digest, error,
) {
return "", "", ErrTestError
},
DeleteImageManifestFn: func(repo, reference string, dc bool) error {
return nil
Expand Down
6 changes: 3 additions & 3 deletions pkg/extensions/sync/signatures.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ func (sig *signaturesCopier) syncCosignSignature(localRepo, remoteRepo, digestSt
}

// push manifest
_, err = imageStore.PutImageManifest(localRepo, cosignTag,
_, _, err = imageStore.PutImageManifest(localRepo, cosignTag,
ispec.MediaTypeImageManifest, cosignManifestBuf)
if err != nil {
sig.log.Error().Str("errorType", common.TypeOf(err)).
Expand Down Expand Up @@ -258,7 +258,7 @@ func (sig *signaturesCopier) syncORASRefs(localRepo, remoteRepo, digestStr strin
}
}

_, err = imageStore.PutImageManifest(localRepo, ref.Digest.String(),
_, _, err = imageStore.PutImageManifest(localRepo, ref.Digest.String(),
oras.MediaTypeArtifactManifest, body)
if err != nil {
sig.log.Error().Str("errorType", common.TypeOf(err)).
Expand Down Expand Up @@ -359,7 +359,7 @@ func (sig *signaturesCopier) syncOCIRefs(localRepo, remoteRepo, digestStr string
continue
}

digest, err := imageStore.PutImageManifest(localRepo, ref.Digest.String(),
digest, _, err := imageStore.PutImageManifest(localRepo, ref.Digest.String(),
ref.MediaType, OCIRefBody)
if err != nil {
sig.log.Error().Str("errorType", common.TypeOf(err)).
Expand Down
4 changes: 2 additions & 2 deletions pkg/extensions/sync/sync_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,7 @@ func TestSyncInternal(t *testing.T) {

manifestDigest := godigest.FromBytes(manifestContent)

_, err = testImageStore.PutImageManifest(repo, manifestDigest.String(),
_, _, err = testImageStore.PutImageManifest(repo, manifestDigest.String(),
ispec.MediaTypeImageManifest, manifestContent)
So(err, ShouldBeNil)

Expand All @@ -715,7 +715,7 @@ func TestSyncInternal(t *testing.T) {
So(digest, ShouldNotBeNil)

// upload index image
_, err = testImageStore.PutImageManifest(repo, "latest", ispec.MediaTypeImageIndex, content)
_, _, err = testImageStore.PutImageManifest(repo, "latest", ispec.MediaTypeImageIndex, content)
So(err, ShouldBeNil)

err = pushSyncedLocalImage(repo, "latest", testRootDir, nil, imageStore, log)
Expand Down
4 changes: 2 additions & 2 deletions pkg/extensions/sync/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ func pushSyncedLocalImage(localRepo, reference, localCachePath string,
}
}

_, err = imageStore.PutImageManifest(localRepo, reference, mediaType, manifestBlob)
_, _, err = imageStore.PutImageManifest(localRepo, reference, mediaType, manifestBlob)
if err != nil {
log.Error().Str("errorType", common.TypeOf(err)).
Err(err).Msg("couldn't upload manifest")
Expand Down Expand Up @@ -393,7 +393,7 @@ func copyManifest(localRepo string, manifestContent []byte, reference string, re
return err
}

digest, err := imageStore.PutImageManifest(localRepo, reference,
digest, _, err := imageStore.PutImageManifest(localRepo, reference,
ispec.MediaTypeImageManifest, manifestContent)
if err != nil {
log.Error().Str("errorType", common.TypeOf(err)).
Expand Down
2 changes: 1 addition & 1 deletion pkg/meta/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ func OnDeleteManifest(repo, reference, mediaType string, digest godigest.Digest,
log.Info().Msg("repodb: restoring image store")

// restore image store
_, err := imgStore.PutImageManifest(repo, reference, mediaType, manifestBlob)
_, _, err := imgStore.PutImageManifest(repo, reference, mediaType, manifestBlob)
if err != nil {
log.Error().Err(err).Msg("repodb: error while restoring image store, database is not consistent")
}
Expand Down
6 changes: 3 additions & 3 deletions pkg/storage/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func TestValidateManifest(t *testing.T) {
body, err := json.Marshal(manifest)
So(err, ShouldBeNil)

_, err = imgStore.PutImageManifest("test", "1.0", ispec.MediaTypeImageManifest, body)
_, _, err = imgStore.PutImageManifest("test", "1.0", ispec.MediaTypeImageManifest, body)
So(err, ShouldNotBeNil)
})

Expand Down Expand Up @@ -101,7 +101,7 @@ func TestValidateManifest(t *testing.T) {
body, err := json.Marshal(manifest)
So(err, ShouldBeNil)

_, err = imgStore.PutImageManifest("test", "1.0", ispec.MediaTypeImageManifest, body)
_, _, err = imgStore.PutImageManifest("test", "1.0", ispec.MediaTypeImageManifest, body)
So(err, ShouldNotBeNil)
})

Expand Down Expand Up @@ -130,7 +130,7 @@ func TestValidateManifest(t *testing.T) {
body, err := json.Marshal(manifest)
So(err, ShouldBeNil)

_, err = imgStore.PutImageManifest("test", "1.0", ispec.MediaTypeImageManifest, body)
_, _, err = imgStore.PutImageManifest("test", "1.0", ispec.MediaTypeImageManifest, body)
So(err, ShouldBeNil)
})
})
Expand Down
59 changes: 35 additions & 24 deletions pkg/storage/local/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -455,11 +455,11 @@ func (is *ImageStoreLocal) GetImageManifest(repo, reference string) ([]byte, god
// PutImageManifest adds an image manifest to the repository.
func (is *ImageStoreLocal) PutImageManifest(repo, reference, mediaType string, //nolint: gocyclo
body []byte,
) (godigest.Digest, error) {
) (godigest.Digest, godigest.Digest, error) {
if err := is.InitRepo(repo); err != nil {
is.log.Debug().Err(err).Msg("init repo")

return "", err
return "", "", err
}

var lockLatency time.Time
Expand All @@ -469,23 +469,23 @@ func (is *ImageStoreLocal) PutImageManifest(repo, reference, mediaType string, /

digest, err := storage.ValidateManifest(is, repo, reference, mediaType, body, is.log)
if err != nil {
return digest, err
return digest, "", err
}

refIsDigest := true

mDigest, err := storage.GetAndValidateRequestDigest(body, reference, is.log)
if err != nil {
if errors.Is(err, zerr.ErrBadManifest) {
return mDigest, err
return mDigest, "", err
}

refIsDigest = false
}

index, err := storage.GetIndex(is, repo, is.log)
if err != nil {
return "", err
return "", "", err
}

// create a new descriptor
Expand All @@ -497,13 +497,32 @@ func (is *ImageStoreLocal) PutImageManifest(repo, reference, mediaType string, /
desc.Annotations = map[string]string{ispec.AnnotationRefName: reference}
}

var subjectDigest godigest.Digest

artifactType := ""

if mediaType == ispec.MediaTypeImageManifest {
var manifest ispec.Manifest

err := json.Unmarshal(body, &manifest)
if err != nil {
return "", "", err
}

if manifest.Subject != nil {
subjectDigest = manifest.Subject.Digest
}

artifactType = zcommon.GetManifestArtifactType(manifest)
}

updateIndex, oldDgst, err := storage.CheckIfIndexNeedsUpdate(&index, &desc, is.log)
if err != nil {
return "", err
return "", "", err
}

if !updateIndex {
return desc.Digest, nil
return desc.Digest, subjectDigest, nil
}

// write manifest to "blobs"
Expand All @@ -515,12 +534,12 @@ func (is *ImageStoreLocal) PutImageManifest(repo, reference, mediaType string, /
if err := is.writeFile(file, body); err != nil {
is.log.Error().Err(err).Str("file", file).Msg("unable to write")

return "", err
return "", "", err
}

err = storage.UpdateIndexWithPrunedImageManifests(is, &index, repo, desc, oldDgst, is.log)
if err != nil {
return "", err
return "", "", err
}

// now update "index.json"
Expand All @@ -532,45 +551,37 @@ func (is *ImageStoreLocal) PutImageManifest(repo, reference, mediaType string, /
if err := test.Error(err); err != nil {
is.log.Error().Err(err).Str("file", file).Msg("unable to marshal JSON")

return "", err
return "", "", err
}

if mediaType == ispec.MediaTypeImageManifest {
var manifest ispec.Manifest

err := json.Unmarshal(body, &manifest)
if err != nil {
return "", err
}

desc.ArtifactType = zcommon.GetManifestArtifactType(manifest)
}
// update the descriptors artifact type in order to check for signatures when applying the linter
desc.ArtifactType = artifactType

// apply linter only on images, not signatures or indexes
pass, err := storage.ApplyLinter(is, is.linter, repo, desc)
if !pass {
is.log.Error().Err(err).Str("repository", repo).Str("reference", reference).Msg("linter didn't pass")

return "", err
return "", "", err
}

err = is.writeFile(file, buf)
if err := test.Error(err); err != nil {
is.log.Error().Err(err).Str("file", file).Msg("unable to write")

return "", err
return "", "", err
}

if is.gc {
if err := is.garbageCollect(dir, repo); err != nil {
return "", err
return "", "", err
}
}

monitoring.SetStorageUsage(is.metrics, is.rootDir, repo)
monitoring.IncUploadCounter(is.metrics, repo)

return desc.Digest, nil
return desc.Digest, subjectDigest, nil
}

// DeleteImageManifest deletes the image manifest from the repository.
Expand Down
Loading