mirror of
https://github.com/goharbor/harbor.git
synced 2024-12-23 17:17:46 +01:00
Merge pull request #10490 from wy65701436/middleware-readonly
move readonly middleware to new v2 handler
This commit is contained in:
commit
6e3733aa7f
@ -89,6 +89,9 @@ const (
|
||||
PreconditionCode = "PRECONDITION"
|
||||
// GeneralCode ...
|
||||
GeneralCode = "UNKNOWN"
|
||||
|
||||
// DENIED it's used by middleware(readonly, vul and content trust) and returned to docker client to index the request is denied.
|
||||
DENIED = "DENIED"
|
||||
)
|
||||
|
||||
// New ...
|
||||
|
27
src/server/middleware/readonly.go
Normal file
27
src/server/middleware/readonly.go
Normal file
@ -0,0 +1,27 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/goharbor/harbor/src/common/utils/log"
|
||||
"github.com/goharbor/harbor/src/core/config"
|
||||
internal_errors "github.com/goharbor/harbor/src/internal/error"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type readonlyHandler struct {
|
||||
next http.Handler
|
||||
}
|
||||
|
||||
// ReadOnly middleware reject request when harbor set to readonly
|
||||
func ReadOnly() func(http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||
if config.ReadOnly() {
|
||||
log.Warningf("The request is prohibited in readonly mode, url is: %s", req.URL.Path)
|
||||
pkgE := internal_errors.New(nil).WithCode(internal_errors.DENIED).WithMessage("The system is in read only mode. Any modification is prohibited.")
|
||||
http.Error(rw, internal_errors.NewErrs(pkgE).Error(), http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(rw, req)
|
||||
})
|
||||
}
|
||||
}
|
50
src/server/middleware/readonly_test.go
Normal file
50
src/server/middleware/readonly_test.go
Normal file
@ -0,0 +1,50 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/goharbor/harbor/src/common"
|
||||
config2 "github.com/goharbor/harbor/src/common/config"
|
||||
"github.com/goharbor/harbor/src/core/config"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
conf := map[string]interface{}{
|
||||
common.ReadOnly: "true",
|
||||
}
|
||||
kp := &config2.PresetKeyProvider{Key: "naa4JtarA1Zsc3uY"}
|
||||
config.InitWithSettings(conf, kp)
|
||||
result := m.Run()
|
||||
if result != 0 {
|
||||
os.Exit(result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadOnly(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
next := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(200)
|
||||
})
|
||||
|
||||
// delete
|
||||
req := httptest.NewRequest(http.MethodDelete, "/readonly1", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
ReadOnly()(next).ServeHTTP(rec, req)
|
||||
assert.Equal(rec.Code, http.StatusForbidden)
|
||||
|
||||
update := map[string]interface{}{
|
||||
common.ReadOnly: "false",
|
||||
}
|
||||
config.GetCfgManager().UpdateConfig(update)
|
||||
|
||||
req2 := httptest.NewRequest(http.MethodDelete, "/readonly2", nil)
|
||||
rec2 := httptest.NewRecorder()
|
||||
ReadOnly()(next).ServeHTTP(rec2, req2)
|
||||
assert.Equal(rec2.Code, http.StatusOK)
|
||||
|
||||
}
|
22
src/server/registry/blob/blob.go
Normal file
22
src/server/registry/blob/blob.go
Normal file
@ -0,0 +1,22 @@
|
||||
package blob
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
)
|
||||
|
||||
// NewHandler returns the handler to handler catalog request
|
||||
func NewHandler(proxy *httputil.ReverseProxy) http.Handler {
|
||||
return &handler{
|
||||
proxy: proxy,
|
||||
}
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
proxy *httputil.ReverseProxy
|
||||
}
|
||||
|
||||
// ServeHTTP ...
|
||||
func (h *handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
h.proxy.ServeHTTP(w, req)
|
||||
}
|
1
src/server/registry/blob/blob_test.go
Normal file
1
src/server/registry/blob/blob_test.go
Normal file
@ -0,0 +1 @@
|
||||
package blob
|
@ -16,6 +16,8 @@ package registry
|
||||
|
||||
import (
|
||||
"github.com/goharbor/harbor/src/pkg/project"
|
||||
"github.com/goharbor/harbor/src/server/middleware"
|
||||
"github.com/goharbor/harbor/src/server/registry/blob"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
@ -45,14 +47,20 @@ func New(url *url.URL) http.Handler {
|
||||
// handle manifest
|
||||
// TODO maybe we should split it into several sub routers based on the method
|
||||
manifestRouter := rootRouter.Path("/v2/{name:.*}/manifests/{reference}").Subrouter()
|
||||
manifestRouter.NewRoute().Methods(http.MethodGet, http.MethodHead, http.MethodPut, http.MethodDelete).
|
||||
Handler(manifest.NewHandler(project.Mgr, proxy))
|
||||
manifestRouter.NewRoute().Methods(http.MethodGet).Handler(manifest.NewHandler(project.Mgr, proxy))
|
||||
manifestRouter.NewRoute().Methods(http.MethodHead).Handler(manifest.NewHandler(project.Mgr, proxy))
|
||||
manifestRouter.NewRoute().Methods(http.MethodPut).Handler(middleware.WithMiddlewares(manifest.NewHandler(project.Mgr, proxy), middleware.ReadOnly()))
|
||||
manifestRouter.NewRoute().Methods(http.MethodDelete).Handler(middleware.WithMiddlewares(manifest.NewHandler(project.Mgr, proxy), middleware.ReadOnly()))
|
||||
|
||||
// handle blob
|
||||
// as we need to apply middleware to the blob requests, so create a sub router to handle the blob APIs
|
||||
blobRouter := rootRouter.PathPrefix("/v2/{name:.*}/blobs/").Subrouter()
|
||||
blobRouter.NewRoute().Methods(http.MethodGet, http.MethodHead, http.MethodPost, http.MethodPut, http.MethodPatch, http.MethodDelete).
|
||||
Handler(proxy)
|
||||
blobRouter.NewRoute().Methods(http.MethodGet).Handler(blob.NewHandler(proxy))
|
||||
blobRouter.NewRoute().Methods(http.MethodHead).Handler(blob.NewHandler(proxy))
|
||||
blobRouter.NewRoute().Methods(http.MethodPost).Handler(middleware.WithMiddlewares(blob.NewHandler(proxy), middleware.ReadOnly()))
|
||||
blobRouter.NewRoute().Methods(http.MethodPut).Handler(middleware.WithMiddlewares(blob.NewHandler(proxy), middleware.ReadOnly()))
|
||||
blobRouter.NewRoute().Methods(http.MethodPatch).Handler(middleware.WithMiddlewares(blob.NewHandler(proxy), middleware.ReadOnly()))
|
||||
blobRouter.NewRoute().Methods(http.MethodDelete).Handler(middleware.WithMiddlewares(blob.NewHandler(proxy), middleware.ReadOnly()))
|
||||
|
||||
// all other APIs are proxy to the backend docker registry
|
||||
rootRouter.PathPrefix("/").Handler(proxy)
|
||||
|
Loading…
Reference in New Issue
Block a user