mirror of
https://github.com/project-zot/zot.git
synced 2024-12-16 21:56:37 -05:00
refactor: move helper functions under common, in usage specific named files (#1540)
Signed-off-by: Alex Stan <alexandrustan96@yahoo.ro>
This commit is contained in:
parent
377aff1853
commit
ea7dbf9e5c
16 changed files with 498 additions and 446 deletions
|
@ -19,6 +19,8 @@ import (
|
|||
"zotregistry.io/zot/errors"
|
||||
"zotregistry.io/zot/pkg/api/config"
|
||||
"zotregistry.io/zot/pkg/api/constants"
|
||||
apiErr "zotregistry.io/zot/pkg/api/errors"
|
||||
"zotregistry.io/zot/pkg/common"
|
||||
localCtx "zotregistry.io/zot/pkg/requestcontext"
|
||||
)
|
||||
|
||||
|
@ -76,7 +78,7 @@ func bearerAuthHandler(ctlr *Controller) mux.MiddlewareFunc {
|
|||
if err != nil {
|
||||
ctlr.Log.Error().Err(err).Msg("issue parsing Authorization header")
|
||||
response.Header().Set("Content-Type", "application/json")
|
||||
WriteJSON(response, http.StatusInternalServerError, NewErrorList(NewError(UNSUPPORTED)))
|
||||
common.WriteJSON(response, http.StatusInternalServerError, apiErr.NewErrorList(apiErr.NewError(apiErr.UNSUPPORTED)))
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -205,7 +207,7 @@ func basicAuthHandler(ctlr *Controller) mux.MiddlewareFunc {
|
|||
isMgmtRequested := request.RequestURI == constants.FullMgmtPrefix
|
||||
|
||||
if request.Header.Get("Authorization") == "" {
|
||||
if anonymousPolicyExists(ctlr.Config.HTTP.AccessControl) || isMgmtRequested {
|
||||
if ctlr.Config.HTTP.AccessControl.AnonymousPolicyExists() || isMgmtRequested {
|
||||
// Process request
|
||||
ctx := getReqContextWithAuthorization("", []string{}, request)
|
||||
next.ServeHTTP(response, request.WithContext(ctx)) //nolint:contextcheck
|
||||
|
@ -225,7 +227,7 @@ func basicAuthHandler(ctlr *Controller) mux.MiddlewareFunc {
|
|||
// some client tools might send Authorization: Basic Og== (decoded into ":")
|
||||
// empty username and password
|
||||
if username == "" && passphrase == "" {
|
||||
if anonymousPolicyExists(ctlr.Config.HTTP.AccessControl) || isMgmtRequested {
|
||||
if ctlr.Config.HTTP.AccessControl.AnonymousPolicyExists() || isMgmtRequested {
|
||||
// Process request
|
||||
ctx := getReqContextWithAuthorization("", []string{}, request)
|
||||
next.ServeHTTP(response, request.WithContext(ctx)) //nolint:contextcheck
|
||||
|
@ -316,7 +318,7 @@ func authFail(w http.ResponseWriter, realm string, delay int) {
|
|||
time.Sleep(time.Duration(delay) * time.Second)
|
||||
w.Header().Set("WWW-Authenticate", realm)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
WriteJSON(w, http.StatusUnauthorized, NewErrorList(NewError(UNAUTHORIZED)))
|
||||
common.WriteJSON(w, http.StatusUnauthorized, apiErr.NewErrorList(apiErr.NewError(apiErr.UNAUTHORIZED)))
|
||||
}
|
||||
|
||||
func getUsernamePasswordBasicAuth(request *http.Request) (string, string, error) {
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
glob "github.com/bmatcuk/doublestar/v4"
|
||||
"github.com/gorilla/mux"
|
||||
|
@ -323,7 +322,7 @@ func AuthzHandler(ctlr *Controller) mux.MiddlewareFunc {
|
|||
|
||||
can := acCtrlr.can(ctx, identity, action, resource) //nolint:contextcheck
|
||||
if !can {
|
||||
authzFail(response, ctlr.Config.HTTP.Realm, ctlr.Config.HTTP.Auth.FailDelay)
|
||||
common.AuthzFail(response, ctlr.Config.HTTP.Realm, ctlr.Config.HTTP.Auth.FailDelay)
|
||||
} else {
|
||||
next.ServeHTTP(response, request.WithContext(ctx)) //nolint:contextcheck
|
||||
}
|
||||
|
@ -335,24 +334,3 @@ func isExtensionURI(requestURI string) bool {
|
|||
return strings.Contains(requestURI, constants.ExtPrefix) ||
|
||||
requestURI == fmt.Sprintf("%s%s", constants.RoutePrefix, constants.ExtCatalogPrefix)
|
||||
}
|
||||
|
||||
func authzFail(w http.ResponseWriter, realm string, delay int) {
|
||||
time.Sleep(time.Duration(delay) * time.Second)
|
||||
w.Header().Set("WWW-Authenticate", realm)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
WriteJSON(w, http.StatusForbidden, NewErrorList(NewError(DENIED)))
|
||||
}
|
||||
|
||||
func anonymousPolicyExists(config *config.AccessControlConfig) bool {
|
||||
if config == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, repository := range config.Repositories {
|
||||
if len(repository.AnonymousPolicy) > 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -106,6 +106,20 @@ type AccessControlConfig struct {
|
|||
Groups Groups
|
||||
}
|
||||
|
||||
func (config *AccessControlConfig) AnonymousPolicyExists() bool {
|
||||
if config == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, repository := range config.Repositories {
|
||||
if len(repository.AnonymousPolicy) > 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
type (
|
||||
Repositories map[string]PolicyGroup
|
||||
Groups map[string]Group
|
||||
|
|
|
@ -178,7 +178,7 @@ func (c *Controller) Run(reloadCtx context.Context) error {
|
|||
if c.Config.HTTP.TLS.CACert != "" {
|
||||
clientAuth := tls.VerifyClientCertIfGiven
|
||||
if (c.Config.HTTP.Auth == nil || c.Config.HTTP.Auth.HTPasswd.Path == "") &&
|
||||
!anonymousPolicyExists(c.Config.HTTP.AccessControl) {
|
||||
!c.Config.HTTP.AccessControl.AnonymousPolicyExists() {
|
||||
clientAuth = tls.RequireAndVerifyClientCert
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ import (
|
|||
"zotregistry.io/zot/pkg/api"
|
||||
"zotregistry.io/zot/pkg/api/config"
|
||||
"zotregistry.io/zot/pkg/api/constants"
|
||||
apiErr "zotregistry.io/zot/pkg/api/errors"
|
||||
"zotregistry.io/zot/pkg/common"
|
||||
extconf "zotregistry.io/zot/pkg/extensions/config"
|
||||
"zotregistry.io/zot/pkg/log"
|
||||
|
@ -798,7 +799,7 @@ func TestBasicAuth(t *testing.T) {
|
|||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized)
|
||||
var e api.Error
|
||||
var e apiErr.Error
|
||||
err = json.Unmarshal(resp.Body(), &e)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
|
@ -1102,7 +1103,7 @@ func TestMultipleInstance(t *testing.T) {
|
|||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized)
|
||||
var e api.Error
|
||||
var e apiErr.Error
|
||||
err = json.Unmarshal(resp.Body(), &e)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
|
@ -1165,7 +1166,7 @@ func TestMultipleInstance(t *testing.T) {
|
|||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized)
|
||||
var e api.Error
|
||||
var e apiErr.Error
|
||||
err = json.Unmarshal(resp.Body(), &e)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
|
@ -1224,7 +1225,7 @@ func TestTLSWithBasicAuth(t *testing.T) {
|
|||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized)
|
||||
var e api.Error
|
||||
var e apiErr.Error
|
||||
err = json.Unmarshal(resp.Body(), &e)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
|
@ -1887,7 +1888,7 @@ func TestBasicAuthWithLDAP(t *testing.T) {
|
|||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized)
|
||||
var e api.Error
|
||||
var e apiErr.Error
|
||||
err = json.Unmarshal(resp.Body(), &e)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
|
@ -2414,7 +2415,7 @@ func TestAuthorizationWithBasicAuth(t *testing.T) {
|
|||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
||||
var apiErr api.Error
|
||||
var apiErr apiErr.Error
|
||||
err = json.Unmarshal(resp.Body(), &apiErr)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
|
@ -2958,7 +2959,7 @@ func TestGetUsername(t *testing.T) {
|
|||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized)
|
||||
|
||||
var e api.Error
|
||||
var e apiErr.Error
|
||||
err = json.Unmarshal(resp.Body(), &e)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
@ -2999,7 +3000,7 @@ func TestAuthorizationWithOnlyAnonymousPolicy(t *testing.T) {
|
|||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, http.StatusOK)
|
||||
var e api.Error
|
||||
var e apiErr.Error
|
||||
err = json.Unmarshal(resp.Body(), &e)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package api
|
||||
package errors
|
||||
|
||||
import (
|
||||
"zotregistry.io/zot/errors"
|
|
@ -1,15 +1,15 @@
|
|||
package api_test
|
||||
package errors_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
|
||||
"zotregistry.io/zot/pkg/api"
|
||||
apiErr "zotregistry.io/zot/pkg/api/errors"
|
||||
)
|
||||
|
||||
func TestUnknownCodeError(t *testing.T) {
|
||||
Convey("Retrieve a new error with unknown code", t, func() {
|
||||
So(func() { _ = api.NewError(123456789, nil) }, ShouldPanic)
|
||||
So(func() { _ = apiErr.NewError(123456789, nil) }, ShouldPanic)
|
||||
})
|
||||
}
|
|
@ -21,7 +21,6 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/opencontainers/distribution-spec/specs-go/v1/extensions"
|
||||
godigest "github.com/opencontainers/go-digest"
|
||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
|
@ -29,6 +28,7 @@ import (
|
|||
|
||||
zerr "zotregistry.io/zot/errors"
|
||||
"zotregistry.io/zot/pkg/api/constants"
|
||||
apiErr "zotregistry.io/zot/pkg/api/errors"
|
||||
zcommon "zotregistry.io/zot/pkg/common"
|
||||
gqlPlayground "zotregistry.io/zot/pkg/debug/gqlplayground"
|
||||
debug "zotregistry.io/zot/pkg/debug/swagger"
|
||||
|
@ -197,7 +197,7 @@ func (rh *RouteHandler) CheckVersionSupport(response http.ResponseWriter, reques
|
|||
}
|
||||
}
|
||||
|
||||
WriteData(response, http.StatusOK, "application/json", []byte{})
|
||||
zcommon.WriteData(response, http.StatusOK, "application/json", []byte{})
|
||||
}
|
||||
|
||||
type ImageTags struct {
|
||||
|
@ -278,7 +278,8 @@ func (rh *RouteHandler) ListTags(response http.ResponseWriter, request *http.Req
|
|||
|
||||
tags, err := imgStore.GetImageTags(name)
|
||||
if err != nil {
|
||||
WriteJSON(response, http.StatusNotFound, NewErrorList(NewError(NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
zcommon.WriteJSON(response, http.StatusNotFound,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -312,7 +313,7 @@ func (rh *RouteHandler) ListTags(response http.ResponseWriter, request *http.Req
|
|||
|
||||
if numTags >= len(tags)-i {
|
||||
pTags.Tags = tags[i+1:]
|
||||
WriteJSON(response, http.StatusOK, pTags)
|
||||
zcommon.WriteJSON(response, http.StatusOK, pTags)
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -327,12 +328,12 @@ func (rh *RouteHandler) ListTags(response http.ResponseWriter, request *http.Req
|
|||
}
|
||||
|
||||
response.Header().Set("Link", fmt.Sprintf("/v2/%s/tags/list?n=%d&last=%s; rel=\"next\"", name, numTags, last))
|
||||
WriteJSON(response, http.StatusOK, pTags)
|
||||
zcommon.WriteJSON(response, http.StatusOK, pTags)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
WriteJSON(response, http.StatusOK, ImageTags{Name: name, Tags: tags})
|
||||
zcommon.WriteJSON(response, http.StatusOK, ImageTags{Name: name, Tags: tags})
|
||||
}
|
||||
|
||||
// CheckManifest godoc
|
||||
|
@ -368,9 +369,9 @@ func (rh *RouteHandler) CheckManifest(response http.ResponseWriter, request *htt
|
|||
|
||||
reference, ok := vars["reference"]
|
||||
if !ok || reference == "" {
|
||||
WriteJSON(response,
|
||||
zcommon.WriteJSON(response,
|
||||
http.StatusNotFound,
|
||||
NewErrorList(NewError(MANIFEST_INVALID, map[string]string{"reference": reference})))
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.MANIFEST_INVALID, map[string]string{"reference": reference})))
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -378,15 +379,15 @@ func (rh *RouteHandler) CheckManifest(response http.ResponseWriter, request *htt
|
|||
content, digest, mediaType, err := getImageManifest(rh, imgStore, name, reference) //nolint:contextcheck
|
||||
if err != nil {
|
||||
if errors.Is(err, zerr.ErrRepoNotFound) { //nolint:gocritic // errorslint conflicts with gocritic:IfElseChain
|
||||
WriteJSON(response, http.StatusNotFound,
|
||||
NewErrorList(NewError(NAME_UNKNOWN, map[string]string{"reference": reference})))
|
||||
zcommon.WriteJSON(response, http.StatusNotFound,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.NAME_UNKNOWN, map[string]string{"reference": reference})))
|
||||
} else if errors.Is(err, zerr.ErrManifestNotFound) {
|
||||
WriteJSON(response, http.StatusNotFound,
|
||||
NewErrorList(NewError(MANIFEST_UNKNOWN, map[string]string{"reference": reference})))
|
||||
zcommon.WriteJSON(response, http.StatusNotFound,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.MANIFEST_UNKNOWN, map[string]string{"reference": reference})))
|
||||
} else {
|
||||
rh.c.Log.Error().Err(err).Msg("unexpected error")
|
||||
WriteJSON(response, http.StatusInternalServerError,
|
||||
NewErrorList(NewError(MANIFEST_INVALID, map[string]string{"reference": reference})))
|
||||
zcommon.WriteJSON(response, http.StatusInternalServerError,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.MANIFEST_INVALID, map[string]string{"reference": reference})))
|
||||
}
|
||||
|
||||
return
|
||||
|
@ -440,9 +441,9 @@ func (rh *RouteHandler) GetManifest(response http.ResponseWriter, request *http.
|
|||
|
||||
reference, ok := vars["reference"]
|
||||
if !ok || reference == "" {
|
||||
WriteJSON(response,
|
||||
zcommon.WriteJSON(response,
|
||||
http.StatusNotFound,
|
||||
NewErrorList(NewError(MANIFEST_UNKNOWN, map[string]string{"reference": reference})))
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.MANIFEST_UNKNOWN, map[string]string{"reference": reference})))
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -450,14 +451,14 @@ func (rh *RouteHandler) GetManifest(response http.ResponseWriter, request *http.
|
|||
content, digest, mediaType, err := getImageManifest(rh, imgStore, name, reference) //nolint: contextcheck
|
||||
if err != nil {
|
||||
if errors.Is(err, zerr.ErrRepoNotFound) { //nolint:gocritic // errorslint conflicts with gocritic:IfElseChain
|
||||
WriteJSON(response, http.StatusNotFound,
|
||||
NewErrorList(NewError(NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
zcommon.WriteJSON(response, http.StatusNotFound,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
} else if errors.Is(err, zerr.ErrRepoBadVersion) {
|
||||
WriteJSON(response, http.StatusNotFound,
|
||||
NewErrorList(NewError(NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
zcommon.WriteJSON(response, http.StatusNotFound,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
} else if errors.Is(err, zerr.ErrManifestNotFound) {
|
||||
WriteJSON(response, http.StatusNotFound,
|
||||
NewErrorList(NewError(MANIFEST_UNKNOWN, map[string]string{"reference": reference})))
|
||||
zcommon.WriteJSON(response, http.StatusNotFound,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.MANIFEST_UNKNOWN, map[string]string{"reference": reference})))
|
||||
} else {
|
||||
rh.c.Log.Error().Err(err).Msg("unexpected error")
|
||||
response.WriteHeader(http.StatusInternalServerError)
|
||||
|
@ -478,7 +479,7 @@ func (rh *RouteHandler) GetManifest(response http.ResponseWriter, request *http.
|
|||
response.Header().Set(constants.DistContentDigestKey, digest.String())
|
||||
response.Header().Set("Content-Length", fmt.Sprintf("%d", len(content)))
|
||||
response.Header().Set("Content-Type", mediaType)
|
||||
WriteData(response, http.StatusOK, mediaType, content)
|
||||
zcommon.WriteData(response, http.StatusOK, mediaType, content)
|
||||
}
|
||||
|
||||
type ImageIndex struct {
|
||||
|
@ -577,7 +578,7 @@ func (rh *RouteHandler) GetReferrers(response http.ResponseWriter, request *http
|
|||
response.Header().Set("OCI-Filters-Applied", strings.Join(artifactTypes, ","))
|
||||
}
|
||||
|
||||
WriteData(response, http.StatusOK, ispec.MediaTypeImageIndex, out)
|
||||
zcommon.WriteData(response, http.StatusOK, ispec.MediaTypeImageIndex, out)
|
||||
}
|
||||
|
||||
// UpdateManifest godoc
|
||||
|
@ -607,9 +608,9 @@ func (rh *RouteHandler) UpdateManifest(response http.ResponseWriter, request *ht
|
|||
|
||||
reference, ok := vars["reference"]
|
||||
if !ok || reference == "" {
|
||||
WriteJSON(response,
|
||||
zcommon.WriteJSON(response,
|
||||
http.StatusNotFound,
|
||||
NewErrorList(NewError(MANIFEST_INVALID, map[string]string{"reference": reference})))
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.MANIFEST_INVALID, map[string]string{"reference": reference})))
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -617,8 +618,8 @@ func (rh *RouteHandler) UpdateManifest(response http.ResponseWriter, request *ht
|
|||
mediaType := request.Header.Get("Content-Type")
|
||||
if !storageCommon.IsSupportedMediaType(mediaType) {
|
||||
// response.WriteHeader(http.StatusUnsupportedMediaType)
|
||||
WriteJSON(response, http.StatusUnsupportedMediaType,
|
||||
NewErrorList(NewError(MANIFEST_INVALID, map[string]string{"mediaType": mediaType})))
|
||||
zcommon.WriteJSON(response, http.StatusUnsupportedMediaType,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.MANIFEST_INVALID, map[string]string{"mediaType": mediaType})))
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -636,23 +637,24 @@ func (rh *RouteHandler) UpdateManifest(response http.ResponseWriter, request *ht
|
|||
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,
|
||||
NewErrorList(NewError(NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
zcommon.WriteJSON(response, http.StatusNotFound,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
} else if errors.Is(err, zerr.ErrManifestNotFound) {
|
||||
WriteJSON(response, http.StatusNotFound,
|
||||
NewErrorList(NewError(MANIFEST_UNKNOWN, map[string]string{"reference": reference})))
|
||||
zcommon.WriteJSON(response, http.StatusNotFound,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.MANIFEST_UNKNOWN, map[string]string{"reference": reference})))
|
||||
} else if errors.Is(err, zerr.ErrBadManifest) {
|
||||
WriteJSON(response, http.StatusBadRequest,
|
||||
NewErrorList(NewError(MANIFEST_INVALID, map[string]string{"reference": reference})))
|
||||
zcommon.WriteJSON(response, http.StatusBadRequest,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.MANIFEST_INVALID, map[string]string{"reference": reference})))
|
||||
} else if errors.Is(err, zerr.ErrBlobNotFound) {
|
||||
WriteJSON(response, http.StatusBadRequest,
|
||||
NewErrorList(NewError(BLOB_UNKNOWN, map[string]string{"blob": digest.String()})))
|
||||
zcommon.WriteJSON(response, http.StatusBadRequest,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.BLOB_UNKNOWN, map[string]string{"blob": digest.String()})))
|
||||
} else if errors.Is(err, zerr.ErrRepoBadVersion) {
|
||||
WriteJSON(response, http.StatusInternalServerError,
|
||||
NewErrorList(NewError(INVALID_INDEX, map[string]string{"name": name})))
|
||||
zcommon.WriteJSON(response, http.StatusInternalServerError,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.INVALID_INDEX, map[string]string{"name": name})))
|
||||
} else if errors.Is(err, zerr.ErrImageLintAnnotations) {
|
||||
WriteJSON(response, http.StatusBadRequest,
|
||||
NewErrorList(NewError(MANIFEST_INVALID, map[string]string{"reference": reference}).WithMessage(err.Error())))
|
||||
zcommon.WriteJSON(response, http.StatusBadRequest,
|
||||
apiErr.NewErrorList(apiErr.NewError(
|
||||
apiErr.MANIFEST_INVALID, map[string]string{"reference": reference}).WithMessage(err.Error())))
|
||||
} else {
|
||||
// could be syscall.EMFILE (Err:0x18 too many opened files), etc
|
||||
rh.c.Log.Error().Err(err).Msg("unexpected error: performing cleanup")
|
||||
|
@ -734,14 +736,14 @@ func (rh *RouteHandler) DeleteManifest(response http.ResponseWriter, request *ht
|
|||
manifestBlob, manifestDigest, mediaType, err := imgStore.GetImageManifest(name, reference)
|
||||
if err != nil {
|
||||
if errors.Is(err, zerr.ErrRepoNotFound) { //nolint:gocritic // errorslint conflicts with gocritic:IfElseChain
|
||||
WriteJSON(response, http.StatusBadRequest,
|
||||
NewErrorList(NewError(NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
zcommon.WriteJSON(response, http.StatusBadRequest,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
} else if errors.Is(err, zerr.ErrManifestNotFound) {
|
||||
WriteJSON(response, http.StatusNotFound,
|
||||
NewErrorList(NewError(MANIFEST_UNKNOWN, map[string]string{"reference": reference})))
|
||||
zcommon.WriteJSON(response, http.StatusNotFound,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.MANIFEST_UNKNOWN, map[string]string{"reference": reference})))
|
||||
} else if errors.Is(err, zerr.ErrBadManifest) {
|
||||
WriteJSON(response, http.StatusBadRequest,
|
||||
NewErrorList(NewError(UNSUPPORTED, map[string]string{"reference": reference})))
|
||||
zcommon.WriteJSON(response, http.StatusBadRequest,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.UNSUPPORTED, map[string]string{"reference": reference})))
|
||||
} else {
|
||||
rh.c.Log.Error().Err(err).Msg("unexpected error")
|
||||
response.WriteHeader(http.StatusInternalServerError)
|
||||
|
@ -753,17 +755,17 @@ func (rh *RouteHandler) DeleteManifest(response http.ResponseWriter, request *ht
|
|||
err = imgStore.DeleteImageManifest(name, reference, detectCollision)
|
||||
if err != nil {
|
||||
if errors.Is(err, zerr.ErrRepoNotFound) { //nolint:gocritic // errorslint conflicts with gocritic:IfElseChain
|
||||
WriteJSON(response, http.StatusBadRequest,
|
||||
NewErrorList(NewError(NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
zcommon.WriteJSON(response, http.StatusBadRequest,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
} else if errors.Is(err, zerr.ErrManifestNotFound) {
|
||||
WriteJSON(response, http.StatusNotFound,
|
||||
NewErrorList(NewError(MANIFEST_UNKNOWN, map[string]string{"reference": reference})))
|
||||
zcommon.WriteJSON(response, http.StatusNotFound,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.MANIFEST_UNKNOWN, map[string]string{"reference": reference})))
|
||||
} else if errors.Is(err, zerr.ErrManifestConflict) {
|
||||
WriteJSON(response, http.StatusConflict,
|
||||
NewErrorList(NewError(MANIFEST_INVALID, map[string]string{"reference": reference})))
|
||||
zcommon.WriteJSON(response, http.StatusConflict,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.MANIFEST_INVALID, map[string]string{"reference": reference})))
|
||||
} else if errors.Is(err, zerr.ErrBadManifest) {
|
||||
WriteJSON(response, http.StatusBadRequest,
|
||||
NewErrorList(NewError(UNSUPPORTED, map[string]string{"reference": reference})))
|
||||
zcommon.WriteJSON(response, http.StatusBadRequest,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.UNSUPPORTED, map[string]string{"reference": reference})))
|
||||
} else {
|
||||
rh.c.Log.Error().Err(err).Msg("unexpected error")
|
||||
response.WriteHeader(http.StatusInternalServerError)
|
||||
|
@ -820,14 +822,16 @@ func (rh *RouteHandler) CheckBlob(response http.ResponseWriter, request *http.Re
|
|||
ok, blen, err := imgStore.CheckBlob(name, digest)
|
||||
if err != nil {
|
||||
if errors.Is(err, zerr.ErrBadBlobDigest) { //nolint:gocritic // errorslint conflicts with gocritic:IfElseChain
|
||||
WriteJSON(response,
|
||||
zcommon.WriteJSON(response,
|
||||
http.StatusBadRequest,
|
||||
NewErrorList(NewError(DIGEST_INVALID, map[string]string{"digest": digest.String()})))
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.DIGEST_INVALID, map[string]string{"digest": digest.String()})))
|
||||
} else if errors.Is(err, zerr.ErrRepoNotFound) {
|
||||
WriteJSON(response, http.StatusNotFound, NewErrorList(NewError(NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
zcommon.WriteJSON(response, http.StatusNotFound,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
} else if errors.Is(err, zerr.ErrBlobNotFound) {
|
||||
WriteJSON(response, http.StatusNotFound, NewErrorList(NewError(BLOB_UNKNOWN,
|
||||
map[string]string{"digest": digest.String()})))
|
||||
zcommon.WriteJSON(response, http.StatusNotFound,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.BLOB_UNKNOWN,
|
||||
map[string]string{"digest": digest.String()})))
|
||||
} else {
|
||||
rh.c.Log.Error().Err(err).Msg("unexpected error")
|
||||
response.WriteHeader(http.StatusInternalServerError)
|
||||
|
@ -837,7 +841,7 @@ func (rh *RouteHandler) CheckBlob(response http.ResponseWriter, request *http.Re
|
|||
}
|
||||
|
||||
if !ok {
|
||||
WriteJSON(response, http.StatusNotFound, NewErrorList(NewError(BLOB_UNKNOWN,
|
||||
zcommon.WriteJSON(response, http.StatusNotFound, apiErr.NewErrorList(apiErr.NewError(apiErr.BLOB_UNKNOWN,
|
||||
map[string]string{"digest": digest.String()})))
|
||||
|
||||
return
|
||||
|
@ -968,17 +972,17 @@ func (rh *RouteHandler) GetBlob(response http.ResponseWriter, request *http.Requ
|
|||
|
||||
if err != nil {
|
||||
if errors.Is(err, zerr.ErrBadBlobDigest) { //nolint:gocritic // errorslint conflicts with gocritic:IfElseChain
|
||||
WriteJSON(response,
|
||||
zcommon.WriteJSON(response,
|
||||
http.StatusBadRequest,
|
||||
NewErrorList(NewError(DIGEST_INVALID, map[string]string{"digest": digest.String()})))
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.DIGEST_INVALID, map[string]string{"digest": digest.String()})))
|
||||
} else if errors.Is(err, zerr.ErrRepoNotFound) {
|
||||
WriteJSON(response,
|
||||
zcommon.WriteJSON(response,
|
||||
http.StatusNotFound,
|
||||
NewErrorList(NewError(NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
} else if errors.Is(err, zerr.ErrBlobNotFound) {
|
||||
WriteJSON(response,
|
||||
zcommon.WriteJSON(response,
|
||||
http.StatusNotFound,
|
||||
NewErrorList(NewError(BLOB_UNKNOWN, map[string]string{"digest": digest.String()})))
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.BLOB_UNKNOWN, map[string]string{"digest": digest.String()})))
|
||||
} else {
|
||||
rh.c.Log.Error().Err(err).Msg("unexpected error")
|
||||
response.WriteHeader(http.StatusInternalServerError)
|
||||
|
@ -1037,17 +1041,17 @@ func (rh *RouteHandler) DeleteBlob(response http.ResponseWriter, request *http.R
|
|||
err = imgStore.DeleteBlob(name, digest)
|
||||
if err != nil {
|
||||
if errors.Is(err, zerr.ErrBadBlobDigest) { //nolint:gocritic // errorslint conflicts with gocritic:IfElseChain
|
||||
WriteJSON(response,
|
||||
zcommon.WriteJSON(response,
|
||||
http.StatusBadRequest,
|
||||
NewErrorList(NewError(DIGEST_INVALID, map[string]string{"digest": digest.String()})))
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.DIGEST_INVALID, map[string]string{"digest": digest.String()})))
|
||||
} else if errors.Is(err, zerr.ErrRepoNotFound) {
|
||||
WriteJSON(response,
|
||||
zcommon.WriteJSON(response,
|
||||
http.StatusNotFound,
|
||||
NewErrorList(NewError(NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
} else if errors.Is(err, zerr.ErrBlobNotFound) {
|
||||
WriteJSON(response,
|
||||
zcommon.WriteJSON(response,
|
||||
http.StatusNotFound,
|
||||
NewErrorList(NewError(BLOB_UNKNOWN, map[string]string{".String()": digest.String()})))
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.BLOB_UNKNOWN, map[string]string{".String()": digest.String()})))
|
||||
} else {
|
||||
rh.c.Log.Error().Err(err).Msg("unexpected error")
|
||||
response.WriteHeader(http.StatusInternalServerError)
|
||||
|
@ -1100,7 +1104,8 @@ func (rh *RouteHandler) CreateBlobUpload(response http.ResponseWriter, request *
|
|||
upload, err := imgStore.NewBlobUpload(name)
|
||||
if err != nil {
|
||||
if errors.Is(err, zerr.ErrRepoNotFound) {
|
||||
WriteJSON(response, http.StatusNotFound, NewErrorList(NewError(NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
zcommon.WriteJSON(response, http.StatusNotFound,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
} else {
|
||||
rh.c.Log.Error().Err(err).Msg("unexpected error")
|
||||
response.WriteHeader(http.StatusInternalServerError)
|
||||
|
@ -1155,8 +1160,8 @@ func (rh *RouteHandler) CreateBlobUpload(response http.ResponseWriter, request *
|
|||
contentLength, err := strconv.ParseInt(request.Header.Get("Content-Length"), 10, 64)
|
||||
if err != nil || contentLength <= 0 {
|
||||
rh.c.Log.Warn().Str("actual", request.Header.Get("Content-Length")).Msg("invalid content length")
|
||||
WriteJSON(response, http.StatusBadRequest,
|
||||
NewErrorList(NewError(BLOB_UPLOAD_INVALID, map[string]string{"digest": digest.String()})))
|
||||
zcommon.WriteJSON(response, http.StatusBadRequest,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.BLOB_UPLOAD_INVALID, map[string]string{"digest": digest.String()})))
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -1186,7 +1191,8 @@ func (rh *RouteHandler) CreateBlobUpload(response http.ResponseWriter, request *
|
|||
upload, err := imgStore.NewBlobUpload(name)
|
||||
if err != nil {
|
||||
if errors.Is(err, zerr.ErrRepoNotFound) {
|
||||
WriteJSON(response, http.StatusNotFound, NewErrorList(NewError(NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
zcommon.WriteJSON(response, http.StatusNotFound,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
} else {
|
||||
rh.c.Log.Error().Err(err).Msg("unexpected error")
|
||||
response.WriteHeader(http.StatusInternalServerError)
|
||||
|
@ -1235,17 +1241,17 @@ func (rh *RouteHandler) GetBlobUpload(response http.ResponseWriter, request *htt
|
|||
size, err := imgStore.GetBlobUpload(name, sessionID)
|
||||
if err != nil {
|
||||
if errors.Is(err, zerr.ErrBadUploadRange) { //nolint:gocritic // errorslint conflicts with gocritic:IfElseChain
|
||||
WriteJSON(response, http.StatusBadRequest,
|
||||
NewErrorList(NewError(BLOB_UPLOAD_INVALID, map[string]string{"session_id": sessionID})))
|
||||
zcommon.WriteJSON(response, http.StatusBadRequest,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.BLOB_UPLOAD_INVALID, map[string]string{"session_id": sessionID})))
|
||||
} else if errors.Is(err, zerr.ErrBadBlobDigest) {
|
||||
WriteJSON(response, http.StatusBadRequest,
|
||||
NewErrorList(NewError(BLOB_UPLOAD_INVALID, map[string]string{"session_id": sessionID})))
|
||||
zcommon.WriteJSON(response, http.StatusBadRequest,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.BLOB_UPLOAD_INVALID, map[string]string{"session_id": sessionID})))
|
||||
} else if errors.Is(err, zerr.ErrRepoNotFound) {
|
||||
WriteJSON(response, http.StatusNotFound,
|
||||
NewErrorList(NewError(NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
zcommon.WriteJSON(response, http.StatusNotFound,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
} else if errors.Is(err, zerr.ErrUploadNotFound) {
|
||||
WriteJSON(response, http.StatusNotFound,
|
||||
NewErrorList(NewError(BLOB_UPLOAD_UNKNOWN, map[string]string{"session_id": sessionID})))
|
||||
zcommon.WriteJSON(response, http.StatusNotFound,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.BLOB_UPLOAD_UNKNOWN, map[string]string{"session_id": sessionID})))
|
||||
} else {
|
||||
rh.c.Log.Error().Err(err).Msg("unexpected error")
|
||||
response.WriteHeader(http.StatusInternalServerError)
|
||||
|
@ -1325,14 +1331,14 @@ func (rh *RouteHandler) PatchBlobUpload(response http.ResponseWriter, request *h
|
|||
|
||||
if err != nil {
|
||||
if errors.Is(err, zerr.ErrBadUploadRange) { //nolint:gocritic // errorslint conflicts with gocritic:IfElseChain
|
||||
WriteJSON(response, http.StatusRequestedRangeNotSatisfiable,
|
||||
NewErrorList(NewError(BLOB_UPLOAD_INVALID, map[string]string{"session_id": sessionID})))
|
||||
zcommon.WriteJSON(response, http.StatusRequestedRangeNotSatisfiable,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.BLOB_UPLOAD_INVALID, map[string]string{"session_id": sessionID})))
|
||||
} else if errors.Is(err, zerr.ErrRepoNotFound) {
|
||||
WriteJSON(response, http.StatusNotFound,
|
||||
NewErrorList(NewError(NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
zcommon.WriteJSON(response, http.StatusNotFound,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
} else if errors.Is(err, zerr.ErrUploadNotFound) {
|
||||
WriteJSON(response, http.StatusNotFound,
|
||||
NewErrorList(NewError(BLOB_UPLOAD_UNKNOWN, map[string]string{"session_id": sessionID})))
|
||||
zcommon.WriteJSON(response, http.StatusNotFound,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.BLOB_UPLOAD_UNKNOWN, map[string]string{"session_id": sessionID})))
|
||||
} else {
|
||||
// could be io.ErrUnexpectedEOF, syscall.EMFILE (Err:0x18 too many opened files), etc
|
||||
rh.c.Log.Error().Err(err).Msg("unexpected error: removing .uploads/ files")
|
||||
|
@ -1445,14 +1451,14 @@ func (rh *RouteHandler) UpdateBlobUpload(response http.ResponseWriter, request *
|
|||
_, err = imgStore.PutBlobChunk(name, sessionID, from, to, request.Body)
|
||||
if err != nil {
|
||||
if errors.Is(err, zerr.ErrBadUploadRange) { //nolint:gocritic // errorslint conflicts with gocritic:IfElseChain
|
||||
WriteJSON(response, http.StatusBadRequest,
|
||||
NewErrorList(NewError(BLOB_UPLOAD_INVALID, map[string]string{"session_id": sessionID})))
|
||||
zcommon.WriteJSON(response, http.StatusBadRequest,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.BLOB_UPLOAD_INVALID, map[string]string{"session_id": sessionID})))
|
||||
} else if errors.Is(err, zerr.ErrRepoNotFound) {
|
||||
WriteJSON(response, http.StatusNotFound,
|
||||
NewErrorList(NewError(NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
zcommon.WriteJSON(response, http.StatusNotFound,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
} else if errors.Is(err, zerr.ErrUploadNotFound) {
|
||||
WriteJSON(response, http.StatusNotFound,
|
||||
NewErrorList(NewError(BLOB_UPLOAD_UNKNOWN, map[string]string{"session_id": sessionID})))
|
||||
zcommon.WriteJSON(response, http.StatusNotFound,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.BLOB_UPLOAD_UNKNOWN, map[string]string{"session_id": sessionID})))
|
||||
} else {
|
||||
// could be io.ErrUnexpectedEOF, syscall.EMFILE (Err:0x18 too many opened files), etc
|
||||
rh.c.Log.Error().Err(err).Msg("unexpected error: removing .uploads/ files")
|
||||
|
@ -1472,17 +1478,17 @@ finish:
|
|||
// blob chunks already transferred, just finish
|
||||
if err := imgStore.FinishBlobUpload(name, sessionID, request.Body, digest); err != nil {
|
||||
if errors.Is(err, zerr.ErrBadBlobDigest) { //nolint:gocritic // errorslint conflicts with gocritic:IfElseChain
|
||||
WriteJSON(response, http.StatusBadRequest,
|
||||
NewErrorList(NewError(DIGEST_INVALID, map[string]string{"digest": digest.String()})))
|
||||
zcommon.WriteJSON(response, http.StatusBadRequest,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.DIGEST_INVALID, map[string]string{"digest": digest.String()})))
|
||||
} else if errors.Is(err, zerr.ErrBadUploadRange) {
|
||||
WriteJSON(response, http.StatusBadRequest,
|
||||
NewErrorList(NewError(BLOB_UPLOAD_INVALID, map[string]string{"session_id": sessionID})))
|
||||
zcommon.WriteJSON(response, http.StatusBadRequest,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.BLOB_UPLOAD_INVALID, map[string]string{"session_id": sessionID})))
|
||||
} else if errors.Is(err, zerr.ErrRepoNotFound) {
|
||||
WriteJSON(response, http.StatusNotFound,
|
||||
NewErrorList(NewError(NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
zcommon.WriteJSON(response, http.StatusNotFound,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
} else if errors.Is(err, zerr.ErrUploadNotFound) {
|
||||
WriteJSON(response, http.StatusNotFound,
|
||||
NewErrorList(NewError(BLOB_UPLOAD_UNKNOWN, map[string]string{"session_id": sessionID})))
|
||||
zcommon.WriteJSON(response, http.StatusNotFound,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.BLOB_UPLOAD_UNKNOWN, map[string]string{"session_id": sessionID})))
|
||||
} else {
|
||||
// could be io.ErrUnexpectedEOF, syscall.EMFILE (Err:0x18 too many opened files), etc
|
||||
rh.c.Log.Error().Err(err).Msg("unexpected error: removing .uploads/ files")
|
||||
|
@ -1535,11 +1541,11 @@ func (rh *RouteHandler) DeleteBlobUpload(response http.ResponseWriter, request *
|
|||
|
||||
if err := imgStore.DeleteBlobUpload(name, sessionID); err != nil {
|
||||
if errors.Is(err, zerr.ErrRepoNotFound) { //nolint:gocritic // errorslint conflicts with gocritic:IfElseChain
|
||||
WriteJSON(response, http.StatusNotFound,
|
||||
NewErrorList(NewError(NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
zcommon.WriteJSON(response, http.StatusNotFound,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.NAME_UNKNOWN, map[string]string{"name": name})))
|
||||
} else if errors.Is(err, zerr.ErrUploadNotFound) {
|
||||
WriteJSON(response, http.StatusNotFound,
|
||||
NewErrorList(NewError(BLOB_UPLOAD_UNKNOWN, map[string]string{"session_id": sessionID})))
|
||||
zcommon.WriteJSON(response, http.StatusNotFound,
|
||||
apiErr.NewErrorList(apiErr.NewError(apiErr.BLOB_UPLOAD_UNKNOWN, map[string]string{"session_id": sessionID})))
|
||||
} else {
|
||||
rh.c.Log.Error().Err(err).Msg("unexpected error")
|
||||
response.WriteHeader(http.StatusInternalServerError)
|
||||
|
@ -1619,7 +1625,7 @@ func (rh *RouteHandler) ListRepositories(response http.ResponseWriter, request *
|
|||
|
||||
is := RepositoryList{Repositories: repos}
|
||||
|
||||
WriteJSON(response, http.StatusOK, is)
|
||||
zcommon.WriteJSON(response, http.StatusOK, is)
|
||||
}
|
||||
|
||||
// ListExtensions godoc
|
||||
|
@ -1639,12 +1645,12 @@ func (rh *RouteHandler) ListExtensions(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
extensionList := ext.GetExtensions(rh.c.Config)
|
||||
|
||||
WriteJSON(w, http.StatusOK, extensionList)
|
||||
zcommon.WriteJSON(w, http.StatusOK, extensionList)
|
||||
}
|
||||
|
||||
func (rh *RouteHandler) GetMetrics(w http.ResponseWriter, r *http.Request) {
|
||||
m := rh.c.Metrics.ReceiveMetrics()
|
||||
WriteJSON(w, http.StatusOK, m)
|
||||
zcommon.WriteJSON(w, http.StatusOK, m)
|
||||
}
|
||||
|
||||
// helper routines
|
||||
|
@ -1670,23 +1676,6 @@ func getContentRange(r *http.Request) (int64 /* from */, int64 /* to */, error)
|
|||
return rangeStart, rangeEnd, nil
|
||||
}
|
||||
|
||||
func WriteJSON(response http.ResponseWriter, status int, data interface{}) {
|
||||
json := jsoniter.ConfigCompatibleWithStandardLibrary
|
||||
|
||||
body, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
WriteData(response, status, constants.DefaultMediaType, body)
|
||||
}
|
||||
|
||||
func WriteData(w http.ResponseWriter, status int, mediaType string, data []byte) {
|
||||
w.Header().Set("Content-Type", mediaType)
|
||||
w.WriteHeader(status)
|
||||
_, _ = w.Write(data)
|
||||
}
|
||||
|
||||
func WriteDataFromReader(response http.ResponseWriter, status int, length int64, mediaType string,
|
||||
reader io.Reader, logger log.Logger,
|
||||
) {
|
||||
|
@ -1834,7 +1823,7 @@ func (rh *RouteHandler) GetOrasReferrers(response http.ResponseWriter, request *
|
|||
|
||||
rs := ReferenceList{References: refs}
|
||||
|
||||
WriteJSON(response, http.StatusOK, rs)
|
||||
zcommon.WriteJSON(response, http.StatusOK, rs)
|
||||
}
|
||||
|
||||
// GetBlobUploadSessionLocation returns actual blob location to start/resume uploading blobs.
|
||||
|
|
|
@ -1,26 +1,14 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
|
||||
"zotregistry.io/zot/pkg/log"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -32,10 +20,6 @@ const (
|
|||
caCertFilename = "ca.crt"
|
||||
)
|
||||
|
||||
func AllowedMethods(methods ...string) []string {
|
||||
return append(methods, http.MethodOptions)
|
||||
}
|
||||
|
||||
func Contains[T comparable](elems []T, v T) bool {
|
||||
for _, s := range elems {
|
||||
if v == s {
|
||||
|
@ -70,162 +54,10 @@ func RemoveFrom(inputSlice []string, item string) []string {
|
|||
return newSlice
|
||||
}
|
||||
|
||||
func GetTLSConfig(certsPath string, caCertPool *x509.CertPool) (*tls.Config, error) {
|
||||
clientCert := filepath.Join(certsPath, clientCertFilename)
|
||||
clientKey := filepath.Join(certsPath, clientKeyFilename)
|
||||
caCertFile := filepath.Join(certsPath, caCertFilename)
|
||||
|
||||
cert, err := tls.LoadX509KeyPair(clientCert, clientKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
caCert, err := os.ReadFile(caCertFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
caCertPool.AppendCertsFromPEM(caCert)
|
||||
|
||||
return &tls.Config{
|
||||
Certificates: []tls.Certificate{cert},
|
||||
RootCAs: caCertPool,
|
||||
MinVersion: tls.VersionTLS12,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func loadPerHostCerts(caCertPool *x509.CertPool, host string) *tls.Config {
|
||||
// Check if the /home/user/.config/containers/certs.d/$IP:$PORT dir exists
|
||||
home := os.Getenv("HOME")
|
||||
clientCertsDir := filepath.Join(home, homeCertsDir, host)
|
||||
|
||||
if DirExists(clientCertsDir) {
|
||||
tlsConfig, err := GetTLSConfig(clientCertsDir, caCertPool)
|
||||
|
||||
if err == nil {
|
||||
return tlsConfig
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the /etc/containers/certs.d/$IP:$PORT dir exists
|
||||
clientCertsDir = filepath.Join(certsPath, host)
|
||||
if DirExists(clientCertsDir) {
|
||||
tlsConfig, err := GetTLSConfig(clientCertsDir, caCertPool)
|
||||
|
||||
if err == nil {
|
||||
return tlsConfig
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateHTTPClient(verifyTLS bool, host string, certDir string) (*http.Client, error) {
|
||||
htr := http.DefaultTransport.(*http.Transport).Clone() //nolint: forcetypeassert
|
||||
if !verifyTLS {
|
||||
htr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} //nolint: gosec
|
||||
|
||||
return &http.Client{
|
||||
Timeout: httpTimeout,
|
||||
Transport: htr,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Add a copy of the system cert pool
|
||||
caCertPool, _ := x509.SystemCertPool()
|
||||
|
||||
tlsConfig := loadPerHostCerts(caCertPool, host)
|
||||
if tlsConfig == nil {
|
||||
tlsConfig = &tls.Config{RootCAs: caCertPool, MinVersion: tls.VersionTLS12}
|
||||
}
|
||||
|
||||
htr.TLSClientConfig = tlsConfig
|
||||
|
||||
if certDir != "" {
|
||||
clientCert := path.Join(certDir, "client.cert")
|
||||
clientKey := path.Join(certDir, "client.key")
|
||||
caCertPath := path.Join(certDir, "ca.crt")
|
||||
|
||||
caCert, err := os.ReadFile(caCertPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
caCertPool.AppendCertsFromPEM(caCert)
|
||||
|
||||
cert, err := tls.LoadX509KeyPair(clientCert, clientKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
htr.TLSClientConfig.Certificates = append(htr.TLSClientConfig.Certificates, cert)
|
||||
}
|
||||
|
||||
return &http.Client{
|
||||
Timeout: httpTimeout,
|
||||
Transport: htr,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func TypeOf(v interface{}) string {
|
||||
return fmt.Sprintf("%T", v)
|
||||
}
|
||||
|
||||
func MakeHTTPGetRequest(httpClient *http.Client, username string, password string, resultPtr interface{},
|
||||
blobURL string, mediaType string, log log.Logger,
|
||||
) ([]byte, string, int, error) {
|
||||
req, err := http.NewRequest(http.MethodGet, blobURL, nil) //nolint
|
||||
if err != nil {
|
||||
return nil, "", 0, err
|
||||
}
|
||||
|
||||
if mediaType != "" {
|
||||
req.Header.Set("Accept", mediaType)
|
||||
}
|
||||
|
||||
if username != "" && password != "" {
|
||||
req.SetBasicAuth(username, password)
|
||||
}
|
||||
|
||||
resp, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
log.Error().Str("errorType", TypeOf(err)).
|
||||
Err(err).Str("blobURL", blobURL).Msg("couldn't get blob")
|
||||
|
||||
return nil, "", -1, err
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Error().Str("errorType", TypeOf(err)).
|
||||
Err(err).Str("blobURL", blobURL).Msg("couldn't get blob")
|
||||
|
||||
return nil, "", resp.StatusCode, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
log.Error().Str("status code", fmt.Sprint(resp.StatusCode)).
|
||||
Err(err).Str("blobURL", blobURL).Msg("couldn't get blob")
|
||||
|
||||
return nil, "", resp.StatusCode, errors.New(string(body)) //nolint:goerr113
|
||||
}
|
||||
|
||||
// read blob
|
||||
if len(body) > 0 {
|
||||
err = json.Unmarshal(body, &resultPtr)
|
||||
if err != nil {
|
||||
log.Error().Str("errorType", TypeOf(err)).Str("blobURL", blobURL).
|
||||
Err(err).Msg("couldn't unmarshal remote blob")
|
||||
|
||||
return body, "", resp.StatusCode, err
|
||||
}
|
||||
}
|
||||
|
||||
return body, resp.Header.Get("Content-Type"), resp.StatusCode, err
|
||||
}
|
||||
|
||||
func DirExists(d string) bool {
|
||||
if !utf8.ValidString(d) {
|
||||
return false
|
||||
|
@ -269,38 +101,3 @@ func MarshalThroughStruct(obj interface{}, throughStruct interface{}) ([]byte, e
|
|||
|
||||
return toJSON, nil
|
||||
}
|
||||
|
||||
func GetManifestArtifactType(manifestContent ispec.Manifest) string {
|
||||
if manifestContent.ArtifactType != "" {
|
||||
return manifestContent.ArtifactType
|
||||
}
|
||||
|
||||
return manifestContent.Config.MediaType
|
||||
}
|
||||
|
||||
func AddExtensionSecurityHeaders() mux.MiddlewareFunc { //nolint:varnamelen
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
|
||||
resp.Header().Set("X-Content-Type-Options", "nosniff")
|
||||
|
||||
next.ServeHTTP(resp, req)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func ACHeadersHandler(allowedMethods ...string) mux.MiddlewareFunc {
|
||||
headerValue := strings.Join(allowedMethods, ",")
|
||||
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
|
||||
resp.Header().Set("Access-Control-Allow-Methods", headerValue)
|
||||
resp.Header().Set("Access-Control-Allow-Headers", "Authorization,content-type")
|
||||
|
||||
if req.Method == http.MethodOptions {
|
||||
return
|
||||
}
|
||||
|
||||
next.ServeHTTP(resp, req)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,14 @@
|
|||
package common_test
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
|
||||
"zotregistry.io/zot/pkg/api"
|
||||
"zotregistry.io/zot/pkg/api/config"
|
||||
"zotregistry.io/zot/pkg/common"
|
||||
"zotregistry.io/zot/pkg/log"
|
||||
"zotregistry.io/zot/pkg/test"
|
||||
)
|
||||
|
||||
func TestCommon(t *testing.T) {
|
||||
|
@ -46,21 +41,6 @@ func TestCommon(t *testing.T) {
|
|||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("test getTLSConfig()", t, func() {
|
||||
caCertPool, _ := x509.SystemCertPool()
|
||||
tlsConfig, err := common.GetTLSConfig("wrongPath", caCertPool)
|
||||
So(tlsConfig, ShouldBeNil)
|
||||
So(err, ShouldNotBeNil)
|
||||
|
||||
tempDir := t.TempDir()
|
||||
err = test.CopyFiles("../../test/data", tempDir)
|
||||
So(err, ShouldBeNil)
|
||||
err = os.Chmod(path.Join(tempDir, "ca.crt"), 0o000)
|
||||
So(err, ShouldBeNil)
|
||||
_, err = common.GetTLSConfig(tempDir, caCertPool)
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("test dirExists()", t, func() {
|
||||
exists := common.DirExists("testdir")
|
||||
So(exists, ShouldBeFalse)
|
||||
|
@ -72,61 +52,8 @@ func TestCommon(t *testing.T) {
|
|||
So(isDir, ShouldBeFalse)
|
||||
})
|
||||
|
||||
Convey("test CreateHTTPClient() no permissions on certificate", t, func() {
|
||||
tempDir := t.TempDir()
|
||||
err := test.CopyFiles("../../test/data", tempDir)
|
||||
So(err, ShouldBeNil)
|
||||
err = os.Chmod(path.Join(tempDir, "ca.crt"), 0o000)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
_, err = common.CreateHTTPClient(true, "localhost", tempDir)
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("test CreateHTTPClient() no permissions on key", t, func() {
|
||||
tempDir := t.TempDir()
|
||||
err := test.CopyFiles("../../test/data", tempDir)
|
||||
So(err, ShouldBeNil)
|
||||
err = os.Chmod(path.Join(tempDir, "client.key"), 0o000)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
_, err = common.CreateHTTPClient(true, "localhost", tempDir)
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("test MakeHTTPGetRequest() no permissions on key", t, func() {
|
||||
port := test.GetFreePort()
|
||||
baseURL := test.GetBaseURL(port)
|
||||
|
||||
conf := config.New()
|
||||
conf.HTTP.Port = port
|
||||
|
||||
ctlr := api.NewController(conf)
|
||||
tempDir := t.TempDir()
|
||||
err := test.CopyFiles("../../test/data", tempDir)
|
||||
So(err, ShouldBeNil)
|
||||
ctlr.Config.Storage.RootDirectory = tempDir
|
||||
|
||||
cm := test.NewControllerManager(ctlr)
|
||||
cm.StartServer()
|
||||
defer cm.StopServer()
|
||||
test.WaitTillServerReady(baseURL)
|
||||
|
||||
var resultPtr interface{}
|
||||
httpClient, err := common.CreateHTTPClient(true, "localhost", tempDir)
|
||||
So(err, ShouldBeNil)
|
||||
_, _, _, err = common.MakeHTTPGetRequest(httpClient, "", "",
|
||||
resultPtr, baseURL+"/v2/", ispec.MediaTypeImageManifest, log.NewLogger("", ""))
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("Index func", t, func() {
|
||||
So(common.Index([]string{"a", "b"}, "b"), ShouldEqual, 1)
|
||||
So(common.Index([]string{"a", "b"}, "c"), ShouldEqual, -1)
|
||||
})
|
||||
Convey("Test image dir and digest", t, func() {
|
||||
repo, digest := common.GetImageDirAndDigest("image")
|
||||
So(repo, ShouldResemble, "image")
|
||||
So(digest, ShouldResemble, "")
|
||||
})
|
||||
}
|
||||
|
|
168
pkg/common/http_client.go
Normal file
168
pkg/common/http_client.go
Normal file
|
@ -0,0 +1,168 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
||||
"zotregistry.io/zot/pkg/log"
|
||||
)
|
||||
|
||||
func GetTLSConfig(certsPath string, caCertPool *x509.CertPool) (*tls.Config, error) {
|
||||
clientCert := filepath.Join(certsPath, clientCertFilename)
|
||||
clientKey := filepath.Join(certsPath, clientKeyFilename)
|
||||
caCertFile := filepath.Join(certsPath, caCertFilename)
|
||||
|
||||
cert, err := tls.LoadX509KeyPair(clientCert, clientKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
caCert, err := os.ReadFile(caCertFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
caCertPool.AppendCertsFromPEM(caCert)
|
||||
|
||||
return &tls.Config{
|
||||
Certificates: []tls.Certificate{cert},
|
||||
RootCAs: caCertPool,
|
||||
MinVersion: tls.VersionTLS12,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func loadPerHostCerts(caCertPool *x509.CertPool, host string) *tls.Config {
|
||||
// Check if the /home/user/.config/containers/certs.d/$IP:$PORT dir exists
|
||||
home := os.Getenv("HOME")
|
||||
clientCertsDir := filepath.Join(home, homeCertsDir, host)
|
||||
|
||||
if DirExists(clientCertsDir) {
|
||||
tlsConfig, err := GetTLSConfig(clientCertsDir, caCertPool)
|
||||
|
||||
if err == nil {
|
||||
return tlsConfig
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the /etc/containers/certs.d/$IP:$PORT dir exists
|
||||
clientCertsDir = filepath.Join(certsPath, host)
|
||||
if DirExists(clientCertsDir) {
|
||||
tlsConfig, err := GetTLSConfig(clientCertsDir, caCertPool)
|
||||
|
||||
if err == nil {
|
||||
return tlsConfig
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateHTTPClient(verifyTLS bool, host string, certDir string) (*http.Client, error) {
|
||||
htr := http.DefaultTransport.(*http.Transport).Clone() //nolint: forcetypeassert
|
||||
if !verifyTLS {
|
||||
htr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} //nolint: gosec
|
||||
|
||||
return &http.Client{
|
||||
Timeout: httpTimeout,
|
||||
Transport: htr,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Add a copy of the system cert pool
|
||||
caCertPool, _ := x509.SystemCertPool()
|
||||
|
||||
tlsConfig := loadPerHostCerts(caCertPool, host)
|
||||
if tlsConfig == nil {
|
||||
tlsConfig = &tls.Config{RootCAs: caCertPool, MinVersion: tls.VersionTLS12}
|
||||
}
|
||||
|
||||
htr.TLSClientConfig = tlsConfig
|
||||
|
||||
if certDir != "" {
|
||||
clientCert := path.Join(certDir, "client.cert")
|
||||
clientKey := path.Join(certDir, "client.key")
|
||||
caCertPath := path.Join(certDir, "ca.crt")
|
||||
|
||||
caCert, err := os.ReadFile(caCertPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
caCertPool.AppendCertsFromPEM(caCert)
|
||||
|
||||
cert, err := tls.LoadX509KeyPair(clientCert, clientKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
htr.TLSClientConfig.Certificates = append(htr.TLSClientConfig.Certificates, cert)
|
||||
}
|
||||
|
||||
return &http.Client{
|
||||
Timeout: httpTimeout,
|
||||
Transport: htr,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func MakeHTTPGetRequest(httpClient *http.Client, username string, password string, resultPtr interface{},
|
||||
blobURL string, mediaType string, log log.Logger,
|
||||
) ([]byte, string, int, error) {
|
||||
req, err := http.NewRequest(http.MethodGet, blobURL, nil) //nolint
|
||||
if err != nil {
|
||||
return nil, "", 0, err
|
||||
}
|
||||
|
||||
if mediaType != "" {
|
||||
req.Header.Set("Accept", mediaType)
|
||||
}
|
||||
|
||||
if username != "" && password != "" {
|
||||
req.SetBasicAuth(username, password)
|
||||
}
|
||||
|
||||
resp, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
log.Error().Str("errorType", TypeOf(err)).
|
||||
Err(err).Str("blobURL", blobURL).Msg("couldn't get blob")
|
||||
|
||||
return nil, "", -1, err
|
||||
}
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Error().Str("errorType", TypeOf(err)).
|
||||
Err(err).Str("blobURL", blobURL).Msg("couldn't get blob")
|
||||
|
||||
return nil, "", resp.StatusCode, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
log.Error().Str("status code", fmt.Sprint(resp.StatusCode)).
|
||||
Err(err).Str("blobURL", blobURL).Msg("couldn't get blob")
|
||||
|
||||
return nil, "", resp.StatusCode, errors.New(string(body)) //nolint:goerr113
|
||||
}
|
||||
|
||||
// read blob
|
||||
if len(body) > 0 {
|
||||
err = json.Unmarshal(body, &resultPtr)
|
||||
if err != nil {
|
||||
log.Error().Str("errorType", TypeOf(err)).Str("blobURL", blobURL).
|
||||
Err(err).Msg("couldn't unmarshal remote blob")
|
||||
|
||||
return body, "", resp.StatusCode, err
|
||||
}
|
||||
}
|
||||
|
||||
return body, resp.Header.Get("Content-Type"), resp.StatusCode, err
|
||||
}
|
82
pkg/common/http_client_test.go
Normal file
82
pkg/common/http_client_test.go
Normal file
|
@ -0,0 +1,82 @@
|
|||
package common_test
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
|
||||
"zotregistry.io/zot/pkg/api"
|
||||
"zotregistry.io/zot/pkg/api/config"
|
||||
"zotregistry.io/zot/pkg/common"
|
||||
"zotregistry.io/zot/pkg/log"
|
||||
"zotregistry.io/zot/pkg/test"
|
||||
)
|
||||
|
||||
func TestHTTPClient(t *testing.T) {
|
||||
Convey("test getTLSConfig()", t, func() {
|
||||
caCertPool, _ := x509.SystemCertPool()
|
||||
tlsConfig, err := common.GetTLSConfig("wrongPath", caCertPool)
|
||||
So(tlsConfig, ShouldBeNil)
|
||||
So(err, ShouldNotBeNil)
|
||||
|
||||
tempDir := t.TempDir()
|
||||
err = test.CopyFiles("../../test/data", tempDir)
|
||||
So(err, ShouldBeNil)
|
||||
err = os.Chmod(path.Join(tempDir, "ca.crt"), 0o000)
|
||||
So(err, ShouldBeNil)
|
||||
_, err = common.GetTLSConfig(tempDir, caCertPool)
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("test CreateHTTPClient() no permissions on certificate", t, func() {
|
||||
tempDir := t.TempDir()
|
||||
err := test.CopyFiles("../../test/data", tempDir)
|
||||
So(err, ShouldBeNil)
|
||||
err = os.Chmod(path.Join(tempDir, "ca.crt"), 0o000)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
_, err = common.CreateHTTPClient(true, "localhost", tempDir)
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("test CreateHTTPClient() no permissions on key", t, func() {
|
||||
tempDir := t.TempDir()
|
||||
err := test.CopyFiles("../../test/data", tempDir)
|
||||
So(err, ShouldBeNil)
|
||||
err = os.Chmod(path.Join(tempDir, "client.key"), 0o000)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
_, err = common.CreateHTTPClient(true, "localhost", tempDir)
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("test MakeHTTPGetRequest() no permissions on key", t, func() {
|
||||
port := test.GetFreePort()
|
||||
baseURL := test.GetBaseURL(port)
|
||||
|
||||
conf := config.New()
|
||||
conf.HTTP.Port = port
|
||||
|
||||
ctlr := api.NewController(conf)
|
||||
tempDir := t.TempDir()
|
||||
err := test.CopyFiles("../../test/data", tempDir)
|
||||
So(err, ShouldBeNil)
|
||||
ctlr.Config.Storage.RootDirectory = tempDir
|
||||
|
||||
cm := test.NewControllerManager(ctlr)
|
||||
cm.StartServer()
|
||||
defer cm.StopServer()
|
||||
test.WaitTillServerReady(baseURL)
|
||||
|
||||
var resultPtr interface{}
|
||||
httpClient, err := common.CreateHTTPClient(true, "localhost", tempDir)
|
||||
So(err, ShouldBeNil)
|
||||
_, _, _, err = common.MakeHTTPGetRequest(httpClient, "", "",
|
||||
resultPtr, baseURL+"/v2/", ispec.MediaTypeImageManifest, log.NewLogger("", ""))
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
}
|
68
pkg/common/http_server.go
Normal file
68
pkg/common/http_server.go
Normal file
|
@ -0,0 +1,68 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
|
||||
"zotregistry.io/zot/pkg/api/constants"
|
||||
apiErr "zotregistry.io/zot/pkg/api/errors"
|
||||
)
|
||||
|
||||
func AllowedMethods(methods ...string) []string {
|
||||
return append(methods, http.MethodOptions)
|
||||
}
|
||||
|
||||
func AddExtensionSecurityHeaders() mux.MiddlewareFunc { //nolint:varnamelen
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
|
||||
resp.Header().Set("X-Content-Type-Options", "nosniff")
|
||||
|
||||
next.ServeHTTP(resp, req)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func ACHeadersHandler(allowedMethods ...string) mux.MiddlewareFunc {
|
||||
headerValue := strings.Join(allowedMethods, ",")
|
||||
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
|
||||
resp.Header().Set("Access-Control-Allow-Methods", headerValue)
|
||||
resp.Header().Set("Access-Control-Allow-Headers", "Authorization,content-type")
|
||||
|
||||
if req.Method == http.MethodOptions {
|
||||
return
|
||||
}
|
||||
|
||||
next.ServeHTTP(resp, req)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func AuthzFail(w http.ResponseWriter, realm string, delay int) {
|
||||
time.Sleep(time.Duration(delay) * time.Second)
|
||||
w.Header().Set("WWW-Authenticate", realm)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
WriteJSON(w, http.StatusForbidden, apiErr.NewErrorList(apiErr.NewError(apiErr.DENIED)))
|
||||
}
|
||||
|
||||
func WriteJSON(response http.ResponseWriter, status int, data interface{}) {
|
||||
json := jsoniter.ConfigCompatibleWithStandardLibrary
|
||||
|
||||
body, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
WriteData(response, status, constants.DefaultMediaType, body)
|
||||
}
|
||||
|
||||
func WriteData(w http.ResponseWriter, status int, mediaType string, data []byte) {
|
||||
w.Header().Set("Content-Type", mediaType)
|
||||
w.WriteHeader(status)
|
||||
_, _ = w.Write(data)
|
||||
}
|
|
@ -48,6 +48,14 @@ func GetImageDirAndReference(imageName string) (string, string, bool) {
|
|||
return repo, tag, true
|
||||
}
|
||||
|
||||
func GetManifestArtifactType(manifestContent ispec.Manifest) string {
|
||||
if manifestContent.ArtifactType != "" {
|
||||
return manifestContent.ArtifactType
|
||||
}
|
||||
|
||||
return manifestContent.Config.MediaType
|
||||
}
|
||||
|
||||
// GetImageLastUpdated This method will return last updated timestamp.
|
||||
// The Created timestamp is used, but if it is missing, look at the
|
||||
// history field and, if provided, return the timestamp of last entry in history.
|
17
pkg/common/oci_test.go
Normal file
17
pkg/common/oci_test.go
Normal file
|
@ -0,0 +1,17 @@
|
|||
package common_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
|
||||
"zotregistry.io/zot/pkg/common"
|
||||
)
|
||||
|
||||
func TestOCI(t *testing.T) {
|
||||
Convey("Test image dir and digest", t, func() {
|
||||
repo, digest := common.GetImageDirAndDigest("image")
|
||||
So(repo, ShouldResemble, "image")
|
||||
So(digest, ShouldResemble, "")
|
||||
})
|
||||
}
|
|
@ -24,6 +24,7 @@ import (
|
|||
"zotregistry.io/zot/pkg/api"
|
||||
"zotregistry.io/zot/pkg/api/config"
|
||||
"zotregistry.io/zot/pkg/api/constants"
|
||||
apiErr "zotregistry.io/zot/pkg/api/errors"
|
||||
extconf "zotregistry.io/zot/pkg/extensions/config"
|
||||
"zotregistry.io/zot/pkg/extensions/monitoring"
|
||||
cveinfo "zotregistry.io/zot/pkg/extensions/search/cve"
|
||||
|
@ -537,7 +538,7 @@ func TestCVESearch(t *testing.T) {
|
|||
So(err, ShouldBeNil)
|
||||
So(resp, ShouldNotBeNil)
|
||||
So(resp.StatusCode(), ShouldEqual, 401)
|
||||
var apiErr api.Error
|
||||
var apiErr apiErr.Error
|
||||
err = json.Unmarshal(resp.Body(), &apiErr)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
|
|
Loading…
Reference in a new issue