forked from forgejo/forgejo
Use import of OCI structs (#22765)
Fixes #22758 Otherwise we would need to rewrite the structs in `oci.go`.
This commit is contained in:
parent
361d807274
commit
f8c1e14a13
13 changed files with 93 additions and 324 deletions
|
@ -22,19 +22,23 @@ import (
|
|||
"code.gitea.io/gitea/modules/log"
|
||||
packages_module "code.gitea.io/gitea/modules/packages"
|
||||
container_module "code.gitea.io/gitea/modules/packages/container"
|
||||
"code.gitea.io/gitea/modules/packages/container/oci"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/routers/api/packages/helper"
|
||||
packages_service "code.gitea.io/gitea/services/packages"
|
||||
container_service "code.gitea.io/gitea/services/packages/container"
|
||||
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
)
|
||||
|
||||
// maximum size of a container manifest
|
||||
// https://github.com/opencontainers/distribution-spec/blob/main/spec.md#pushing-manifests
|
||||
const maxManifestSize = 10 * 1024 * 1024
|
||||
|
||||
var imageNamePattern = regexp.MustCompile(`\A[a-z0-9]+([._-][a-z0-9]+)*(/[a-z0-9]+([._-][a-z0-9]+)*)*\z`)
|
||||
var (
|
||||
imageNamePattern = regexp.MustCompile(`\A[a-z0-9]+([._-][a-z0-9]+)*(/[a-z0-9]+([._-][a-z0-9]+)*)*\z`)
|
||||
referencePattern = regexp.MustCompile(`\A[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}\z`)
|
||||
)
|
||||
|
||||
type containerHeaders struct {
|
||||
Status int
|
||||
|
@ -434,16 +438,16 @@ func CancelUploadBlob(ctx *context.Context) {
|
|||
}
|
||||
|
||||
func getBlobFromContext(ctx *context.Context) (*packages_model.PackageFileDescriptor, error) {
|
||||
digest := ctx.Params("digest")
|
||||
d := ctx.Params("digest")
|
||||
|
||||
if !oci.Digest(digest).Validate() {
|
||||
if digest.Digest(d).Validate() != nil {
|
||||
return nil, container_model.ErrContainerBlobNotExist
|
||||
}
|
||||
|
||||
return workaroundGetContainerBlob(ctx, &container_model.BlobSearchOptions{
|
||||
OwnerID: ctx.Package.Owner.ID,
|
||||
Image: ctx.Params("image"),
|
||||
Digest: digest,
|
||||
Digest: d,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -498,14 +502,14 @@ func GetBlob(ctx *context.Context) {
|
|||
|
||||
// https://github.com/opencontainers/distribution-spec/blob/main/spec.md#deleting-blobs
|
||||
func DeleteBlob(ctx *context.Context) {
|
||||
digest := ctx.Params("digest")
|
||||
d := ctx.Params("digest")
|
||||
|
||||
if !oci.Digest(digest).Validate() {
|
||||
if digest.Digest(d).Validate() != nil {
|
||||
apiErrorDefined(ctx, errBlobUnknown)
|
||||
return
|
||||
}
|
||||
|
||||
if err := deleteBlob(ctx.Package.Owner.ID, ctx.Params("image"), digest); err != nil {
|
||||
if err := deleteBlob(ctx.Package.Owner.ID, ctx.Params("image"), d); err != nil {
|
||||
apiError(ctx, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
@ -520,15 +524,15 @@ func UploadManifest(ctx *context.Context) {
|
|||
reference := ctx.Params("reference")
|
||||
|
||||
mci := &manifestCreationInfo{
|
||||
MediaType: oci.MediaType(ctx.Req.Header.Get("Content-Type")),
|
||||
MediaType: ctx.Req.Header.Get("Content-Type"),
|
||||
Owner: ctx.Package.Owner,
|
||||
Creator: ctx.Doer,
|
||||
Image: ctx.Params("image"),
|
||||
Reference: reference,
|
||||
IsTagged: !oci.Digest(reference).Validate(),
|
||||
IsTagged: digest.Digest(reference).Validate() != nil,
|
||||
}
|
||||
|
||||
if mci.IsTagged && !oci.Reference(reference).Validate() {
|
||||
if mci.IsTagged && !referencePattern.MatchString(reference) {
|
||||
apiErrorDefined(ctx, errManifestInvalid.WithMessage("Tag is invalid"))
|
||||
return
|
||||
}
|
||||
|
@ -571,7 +575,7 @@ func UploadManifest(ctx *context.Context) {
|
|||
})
|
||||
}
|
||||
|
||||
func getManifestFromContext(ctx *context.Context) (*packages_model.PackageFileDescriptor, error) {
|
||||
func getBlobSearchOptionsFromContext(ctx *context.Context) (*container_model.BlobSearchOptions, error) {
|
||||
reference := ctx.Params("reference")
|
||||
|
||||
opts := &container_model.BlobSearchOptions{
|
||||
|
@ -579,14 +583,24 @@ func getManifestFromContext(ctx *context.Context) (*packages_model.PackageFileDe
|
|||
Image: ctx.Params("image"),
|
||||
IsManifest: true,
|
||||
}
|
||||
if oci.Digest(reference).Validate() {
|
||||
|
||||
if digest.Digest(reference).Validate() == nil {
|
||||
opts.Digest = reference
|
||||
} else if oci.Reference(reference).Validate() {
|
||||
} else if referencePattern.MatchString(reference) {
|
||||
opts.Tag = reference
|
||||
} else {
|
||||
return nil, container_model.ErrContainerBlobNotExist
|
||||
}
|
||||
|
||||
return opts, nil
|
||||
}
|
||||
|
||||
func getManifestFromContext(ctx *context.Context) (*packages_model.PackageFileDescriptor, error) {
|
||||
opts, err := getBlobSearchOptionsFromContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return workaroundGetContainerBlob(ctx, opts)
|
||||
}
|
||||
|
||||
|
@ -643,18 +657,8 @@ func GetManifest(ctx *context.Context) {
|
|||
// https://github.com/opencontainers/distribution-spec/blob/main/spec.md#deleting-tags
|
||||
// https://github.com/opencontainers/distribution-spec/blob/main/spec.md#deleting-manifests
|
||||
func DeleteManifest(ctx *context.Context) {
|
||||
reference := ctx.Params("reference")
|
||||
|
||||
opts := &container_model.BlobSearchOptions{
|
||||
OwnerID: ctx.Package.Owner.ID,
|
||||
Image: ctx.Params("image"),
|
||||
IsManifest: true,
|
||||
}
|
||||
if oci.Digest(reference).Validate() {
|
||||
opts.Digest = reference
|
||||
} else if oci.Reference(reference).Validate() {
|
||||
opts.Tag = reference
|
||||
} else {
|
||||
opts, err := getBlobSearchOptionsFromContext(ctx)
|
||||
if err != nil {
|
||||
apiErrorDefined(ctx, errManifestUnknown)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -19,14 +19,28 @@ import (
|
|||
"code.gitea.io/gitea/modules/log"
|
||||
packages_module "code.gitea.io/gitea/modules/packages"
|
||||
container_module "code.gitea.io/gitea/modules/packages/container"
|
||||
"code.gitea.io/gitea/modules/packages/container/oci"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
packages_service "code.gitea.io/gitea/services/packages"
|
||||
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
oci "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
func isValidMediaType(mt string) bool {
|
||||
return strings.HasPrefix(mt, "application/vnd.docker.") || strings.HasPrefix(mt, "application/vnd.oci.")
|
||||
}
|
||||
|
||||
func isImageManifestMediaType(mt string) bool {
|
||||
return strings.EqualFold(mt, oci.MediaTypeImageManifest) || strings.EqualFold(mt, "application/vnd.docker.distribution.manifest.v2+json")
|
||||
}
|
||||
|
||||
func isImageIndexMediaType(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 oci.MediaType
|
||||
MediaType string
|
||||
Owner *user_model.User
|
||||
Creator *user_model.User
|
||||
Image string
|
||||
|
@ -36,12 +50,12 @@ type manifestCreationInfo struct {
|
|||
}
|
||||
|
||||
func processManifest(mci *manifestCreationInfo, buf *packages_module.HashedBuffer) (string, error) {
|
||||
var schema oci.SchemaMediaBase
|
||||
if err := json.NewDecoder(buf).Decode(&schema); err != nil {
|
||||
var index oci.Index
|
||||
if err := json.NewDecoder(buf).Decode(&index); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if schema.SchemaVersion != 2 {
|
||||
if index.SchemaVersion != 2 {
|
||||
return "", errUnsupported.WithMessage("Schema version is not supported")
|
||||
}
|
||||
|
||||
|
@ -49,17 +63,17 @@ func processManifest(mci *manifestCreationInfo, buf *packages_module.HashedBuffe
|
|||
return "", err
|
||||
}
|
||||
|
||||
if !mci.MediaType.IsValid() {
|
||||
mci.MediaType = schema.MediaType
|
||||
if !mci.MediaType.IsValid() {
|
||||
if !isValidMediaType(mci.MediaType) {
|
||||
mci.MediaType = index.MediaType
|
||||
if !isValidMediaType(mci.MediaType) {
|
||||
return "", errManifestInvalid.WithMessage("MediaType not recognized")
|
||||
}
|
||||
}
|
||||
|
||||
if mci.MediaType.IsImageManifest() {
|
||||
if isImageManifestMediaType(mci.MediaType) {
|
||||
d, err := processImageManifest(mci, buf)
|
||||
return d, err
|
||||
} else if mci.MediaType.IsImageIndex() {
|
||||
} else if isImageIndexMediaType(mci.MediaType) {
|
||||
d, err := processImageManifestIndex(mci, buf)
|
||||
return d, err
|
||||
}
|
||||
|
@ -204,7 +218,7 @@ func processImageManifestIndex(mci *manifestCreationInfo, buf *packages_module.H
|
|||
}
|
||||
|
||||
for _, manifest := range index.Manifests {
|
||||
if !manifest.MediaType.IsImageManifest() {
|
||||
if !isImageManifestMediaType(manifest.MediaType) {
|
||||
return errManifestInvalid
|
||||
}
|
||||
|
||||
|
@ -348,8 +362,8 @@ func createPackageAndVersion(ctx context.Context, mci *manifestCreationInfo, met
|
|||
}
|
||||
|
||||
type blobReference struct {
|
||||
Digest oci.Digest
|
||||
MediaType oci.MediaType
|
||||
Digest digest.Digest
|
||||
MediaType string
|
||||
Name string
|
||||
File *packages_model.PackageFileDescriptor
|
||||
ExpectedSize int64
|
||||
|
@ -383,7 +397,7 @@ func createFileFromBlobReference(ctx context.Context, pv, uploadVersion *package
|
|||
}
|
||||
|
||||
props := map[string]string{
|
||||
container_module.PropertyMediaType: string(ref.MediaType),
|
||||
container_module.PropertyMediaType: ref.MediaType,
|
||||
container_module.PropertyDigest: string(ref.Digest),
|
||||
}
|
||||
for name, value := range props {
|
||||
|
@ -428,7 +442,7 @@ func createManifestBlob(ctx context.Context, mci *manifestCreationInfo, pv *pack
|
|||
|
||||
manifestDigest := digestFromHashSummer(buf)
|
||||
err = createFileFromBlobReference(ctx, pv, nil, &blobReference{
|
||||
Digest: oci.Digest(manifestDigest),
|
||||
Digest: digest.Digest(manifestDigest),
|
||||
MediaType: mci.MediaType,
|
||||
Name: container_model.ManifestFilename,
|
||||
File: &packages_model.PackageFileDescriptor{Blob: pb},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue