diff --git a/modules/packages/container/metadata.go b/modules/packages/container/metadata.go index 2fce7d976ad4f..3ef0684d13f33 100644 --- a/modules/packages/container/metadata.go +++ b/modules/packages/container/metadata.go @@ -4,7 +4,6 @@ package container import ( - "errors" "fmt" "io" "strings" @@ -72,20 +71,39 @@ type Manifest struct { Size int64 `json:"size"` } +func IsMediaTypeValid(mt string) bool { + return strings.HasPrefix(mt, "application/vnd.docker.") || strings.HasPrefix(mt, "application/vnd.oci.") +} + +func IsMediaTypeImageManifest(mt string) bool { + return strings.EqualFold(mt, oci.MediaTypeImageManifest) || strings.EqualFold(mt, "application/vnd.docker.distribution.manifest.v2+json") +} + +func IsMediaTypeImageIndex(mt string) bool { + return strings.EqualFold(mt, oci.MediaTypeImageIndex) || strings.EqualFold(mt, "application/vnd.docker.distribution.manifest.list.v2+json") +} + // ParseImageConfig parses the metadata of an image config -func ParseImageConfig(mt string, r io.Reader) (*Metadata, error) { - if strings.EqualFold(mt, helm.ConfigMediaType) { +func ParseImageConfig(mediaType string, r io.Reader) (*Metadata, error) { + if strings.EqualFold(mediaType, helm.ConfigMediaType) { return parseHelmConfig(r) } // fallback to OCI Image Config - return parseOCIImageConfig(r) + // FIXME: this fallback is not right, we should strictly check the media type in the future + metadata, err := parseOCIImageConfig(r) + if err != nil { + if !IsMediaTypeImageManifest(mediaType) { + return &Metadata{Platform: "unknown/unknown"}, nil + } + return nil, err + } + return metadata, nil } func parseOCIImageConfig(r io.Reader) (*Metadata, error) { var image oci.Image - // EOF means empty input, still use the default data - if err := json.NewDecoder(r).Decode(&image); err != nil && !errors.Is(err, io.EOF) { + if err := json.NewDecoder(r).Decode(&image); err != nil { return nil, err } diff --git a/modules/packages/container/metadata_test.go b/modules/packages/container/metadata_test.go index 74b0a379c6fe2..0f2d702925c28 100644 --- a/modules/packages/container/metadata_test.go +++ b/modules/packages/container/metadata_test.go @@ -59,10 +59,8 @@ func TestParseImageConfig(t *testing.T) { assert.ElementsMatch(t, []string{author}, metadata.Authors) assert.Equal(t, projectURL, metadata.ProjectURL) assert.Equal(t, repositoryURL, metadata.RepositoryURL) -} -func TestParseOCIImageConfig(t *testing.T) { - metadata, err := parseOCIImageConfig(strings.NewReader("")) + metadata, err = ParseImageConfig("anything-unknown", strings.NewReader("")) require.NoError(t, err) - assert.Equal(t, &Metadata{Type: TypeOCI, Platform: DefaultPlatform, ImageLayers: []string{}}, metadata) + assert.Equal(t, &Metadata{Platform: "unknown/unknown"}, metadata) } diff --git a/routers/api/packages/api.go b/routers/api/packages/api.go index 41e89ae5672b2..df5897e45e3de 100644 --- a/routers/api/packages/api.go +++ b/routers/api/packages/api.go @@ -693,6 +693,8 @@ func ContainerRoutes() *web.Router { &container.Auth{}, }) + // TODO: Content Discovery / References (not implemented yet) + r.Get("", container.ReqContainerAccess, container.DetermineSupport) r.Group("/token", func() { r.Get("", container.Authenticate) diff --git a/routers/api/packages/container/manifest.go b/routers/api/packages/container/manifest.go index a640bcda255f8..b69b7af3f7cda 100644 --- a/routers/api/packages/container/manifest.go +++ b/routers/api/packages/container/manifest.go @@ -29,18 +29,6 @@ import ( oci "github.com/opencontainers/image-spec/specs-go/v1" ) -func isMediaTypeValid(mt string) bool { - return strings.HasPrefix(mt, "application/vnd.docker.") || strings.HasPrefix(mt, "application/vnd.oci.") -} - -func isMediaTypeImageManifest(mt string) bool { - return strings.EqualFold(mt, oci.MediaTypeImageManifest) || strings.EqualFold(mt, "application/vnd.docker.distribution.manifest.v2+json") -} - -func isMediaTypeImageIndex(mt string) bool { - return strings.EqualFold(mt, oci.MediaTypeImageIndex) || strings.EqualFold(mt, "application/vnd.docker.distribution.manifest.list.v2+json") -} - // manifestCreationInfo describes a manifest to create type manifestCreationInfo struct { MediaType string @@ -66,16 +54,16 @@ func processManifest(ctx context.Context, mci *manifestCreationInfo, buf *packag return "", err } - if !isMediaTypeValid(mci.MediaType) { + if !container_module.IsMediaTypeValid(mci.MediaType) { mci.MediaType = index.MediaType - if !isMediaTypeValid(mci.MediaType) { + if !container_module.IsMediaTypeValid(mci.MediaType) { return "", errManifestInvalid.WithMessage("MediaType not recognized") } } - if isMediaTypeImageManifest(mci.MediaType) { + if container_module.IsMediaTypeImageManifest(mci.MediaType) { return processOciImageManifest(ctx, mci, buf) - } else if isMediaTypeImageIndex(mci.MediaType) { + } else if container_module.IsMediaTypeImageIndex(mci.MediaType) { return processOciImageIndex(ctx, mci, buf) } return "", errManifestInvalid @@ -201,7 +189,7 @@ func processOciImageIndex(ctx context.Context, mci *manifestCreationInfo, buf *p } for _, manifest := range index.Manifests { - if !isMediaTypeImageManifest(manifest.MediaType) { + if !container_module.IsMediaTypeImageManifest(manifest.MediaType) { return errManifestInvalid } @@ -336,7 +324,7 @@ func createPackageAndVersion(ctx context.Context, mci *manifestCreationInfo, met return nil, err } - if isMediaTypeImageIndex(mci.MediaType) { + if container_module.IsMediaTypeImageIndex(mci.MediaType) { if pv.CreatedUnix.AsTime().Before(time.Now().Add(-24 * time.Hour)) { if err = packages_service.DeletePackageVersionAndReferences(ctx, pv); err != nil { return nil, err