Remove the readonly filter (#10944)

Remove the readonly filter as we have introduced readonly middleware

Signed-off-by: Wenkai Yin <yinw@vmware.com>
This commit is contained in:
He Weiwei 2020-03-05 18:59:35 +08:00 committed by GitHub
parent d21318dfcf
commit c8ca6a5ccf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 0 additions and 199 deletions

View File

@ -1,95 +0,0 @@
// Copyright 2018 Project Harbor Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package filter
import (
"net/http"
"regexp"
"github.com/astaxie/beego/context"
"github.com/goharbor/harbor/src/common/utils/log"
"github.com/goharbor/harbor/src/core/config"
)
const (
repoURL = `^/api/repositories/((?:[a-z0-9]+(?:[._-][a-z0-9]+)*/)+)(?:[a-z0-9]+(?:[._-][a-z0-9]+)*)$`
tagsURL = `^/api/repositories/((?:[a-z0-9]+(?:[._-][a-z0-9]+)*/)+)tags$`
tagURL = `^/api/repositories/((?:[a-z0-9]+(?:[._-][a-z0-9]+)*/)+)tags/([\w][\w.-]{0,127})$`
labelURL = `^/api/repositories/((?:[a-z0-9]+(?:[._-][a-z0-9]+)*/)+)tags/([\w][\w.-]{0,127})/labels/[0-9]+$`
)
// ReadonlyFilter filters the deletion or creation (e.g. retag) of repo/tag requests and returns 503.
func ReadonlyFilter(ctx *context.Context) {
filter(ctx.Request, ctx.ResponseWriter)
}
func filter(req *http.Request, resp http.ResponseWriter) {
if !config.ReadOnly() {
return
}
if matchRepoTagDelete(req) || matchRetag(req) {
resp.WriteHeader(http.StatusServiceUnavailable)
_, err := resp.Write([]byte("The system is in read only mode. Any modification is prohibited."))
if err != nil {
log.Errorf("failed to write response body: %v", err)
}
}
}
// matchRepoTagDelete checks whether a request is a repository or tag deletion request,
// it should be blocked in read-only mode.
func matchRepoTagDelete(req *http.Request) bool {
if req.Method != http.MethodDelete {
return false
}
if inWhiteList(req) {
return false
}
re := regexp.MustCompile(tagURL)
s := re.FindStringSubmatch(req.URL.Path)
if len(s) == 3 {
return true
}
re = regexp.MustCompile(repoURL)
s = re.FindStringSubmatch(req.URL.Path)
if len(s) == 2 {
return true
}
return false
}
// matchRetag checks whether a request is a retag request, it should be blocked in read-only mode.
func matchRetag(req *http.Request) bool {
if req.Method != http.MethodPost {
return false
}
re := regexp.MustCompile(tagsURL)
return re.MatchString(req.URL.Path)
}
func inWhiteList(req *http.Request) bool {
re := regexp.MustCompile(labelURL)
s := re.FindStringSubmatch(req.URL.Path)
if len(s) == 3 {
return true
}
return false
}

View File

@ -1,78 +0,0 @@
// Copyright 2018 Project Harbor Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package filter
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/goharbor/harbor/src/common"
"github.com/goharbor/harbor/src/core/config"
"github.com/stretchr/testify/assert"
)
func TestReadonlyFilter(t *testing.T) {
var defaultConfig = map[string]interface{}{
common.ReadOnly: true,
}
config.Upload(defaultConfig)
assert := assert.New(t)
req1, _ := http.NewRequest("DELETE", "http://127.0.0.1:5000/api/repositories/library/ubuntu", nil)
rec := httptest.NewRecorder()
filter(req1, rec)
assert.Equal(http.StatusServiceUnavailable, rec.Code)
req2, _ := http.NewRequest("DELETE", "http://127.0.0.1:5000/api/repositories/library/hello-world", nil)
rec = httptest.NewRecorder()
filter(req2, rec)
assert.Equal(http.StatusServiceUnavailable, rec.Code)
req3, _ := http.NewRequest("DELETE", "http://127.0.0.1:5000/api/repositories/library/hello-world/tags/14.04", nil)
rec = httptest.NewRecorder()
filter(req3, rec)
assert.Equal(http.StatusServiceUnavailable, rec.Code)
req4, _ := http.NewRequest("DELETE", "http://127.0.0.1:5000/api/repositories/library/hello-world/tags/latest", nil)
rec = httptest.NewRecorder()
filter(req4, rec)
assert.Equal(http.StatusServiceUnavailable, rec.Code)
req5, _ := http.NewRequest("DELETE", "http://127.0.0.1:5000/api/repositories/library/vmware/hello-world", nil)
rec = httptest.NewRecorder()
filter(req5, rec)
assert.Equal(http.StatusServiceUnavailable, rec.Code)
req6, _ := http.NewRequest("POST", "http://127.0.0.1:5000/api/repositories/library/hello-world/tags", nil)
rec = httptest.NewRecorder()
filter(req6, rec)
assert.Equal(http.StatusServiceUnavailable, rec.Code)
}
func TestMatchRetag(t *testing.T) {
req1, _ := http.NewRequest("POST", "http://127.0.0.1:5000/api/repositories/library/hello-world/tags", nil)
assert.True(t, matchRetag(req1))
req2, _ := http.NewRequest("POST", "http://127.0.0.1:5000/api/repositories/library/hello-world/tags/v1.0", nil)
assert.False(t, matchRetag(req2))
req3, _ := http.NewRequest("GET", "http://127.0.0.1:5000/api/repositories/library/hello-world/tags", nil)
assert.False(t, matchRetag(req3))
req4, _ := http.NewRequest("POST", "http://127.0.0.1:5000/api/repositories/library/hello-world", nil)
assert.False(t, matchRetag(req4))
}

View File

@ -21,7 +21,6 @@ import (
"strings"
beegoctx "github.com/astaxie/beego/context"
"github.com/docker/distribution/reference"
"github.com/goharbor/harbor/src/common"
"github.com/goharbor/harbor/src/common/api"
"github.com/goharbor/harbor/src/common/dao"
@ -60,30 +59,6 @@ const (
var (
reqCtxModifiers []ReqCtxModifier
// basic auth request context modifier only takes effect on the patterns
// in the slice
basicAuthReqPatterns = []*pathMethod{
// create project
{
path: "/api/projects",
method: http.MethodPost,
},
// token service
{
path: "/service/token",
method: http.MethodGet,
},
// delete repository
{
path: "/api/repositories/" + reference.NameRegexp.String(),
method: http.MethodDelete,
},
// delete tag
{
path: "/api/repositories/" + reference.NameRegexp.String() + "/tags/" + reference.TagRegexp.String(),
method: http.MethodDelete,
},
}
)
// Init ReqCtxMofiers list

View File

@ -229,7 +229,6 @@ func main() {
filter.Init()
beego.InsertFilter("/api/*", beego.BeforeStatic, filter.SessionCheck)
beego.InsertFilter("/*", beego.BeforeRouter, filter.SecurityFilter)
beego.InsertFilter("/*", beego.BeforeRouter, filter.ReadonlyFilter)
server.RegisterRoutes()