add internal reg request handler chain

this is for internal registry api call, the request should be intercpeted by quota middlerwares, like retag and delete.
Note: The api developer has to know that if the internal registry call in your api, please consider to use
NewRepositoryClientForLocal() to init the repository client, which can handle quota change.

Signed-off-by: wang yan <wangyan@vmware.com>
This commit is contained in:
wang yan 2019-07-30 14:05:57 +08:00
parent dcc79ca2a4
commit 4410cc93f9
12 changed files with 62 additions and 7 deletions

View File

@ -31,6 +31,7 @@ CLAIR_DB_USERNAME={{clair_db_username}}
CLAIR_DB={{clair_db_name}}
CLAIR_DB_SSLMODE={{clair_db_sslmode}}
CORE_URL={{core_url}}
CORE_LOCAL_URL={{core_local_url}}
JOBSERVICE_URL={{jobservice_url}}
CLAIR_URL={{clair_url}}
NOTARY_URL={{notary_url}}

View File

@ -67,6 +67,7 @@ def parse_yaml_config(config_file_path):
'registry_url': "http://registry:5000",
'registry_controller_url': "http://registryctl:8080",
'core_url': "http://core:8080",
'core_local_url': "http://127.0.0.1:8080",
'token_service_url': "http://core:8080/service/token",
'jobservice_url': 'http://jobservice:8080',
'clair_url': 'http://clair:6060',

View File

@ -75,6 +75,7 @@ var (
{Name: common.ClairURL, Scope: SystemScope, Group: ClairGroup, EnvKey: "CLAIR_URL", DefaultValue: "http://clair:6060", ItemType: &StringType{}, Editable: false},
{Name: common.CoreURL, Scope: SystemScope, Group: BasicGroup, EnvKey: "CORE_URL", DefaultValue: "http://core:8080", ItemType: &StringType{}, Editable: false},
{Name: common.CoreLocalURL, Scope: SystemScope, Group: BasicGroup, EnvKey: "CORE_LOCAL_URL", DefaultValue: "http://127.0.0.1:8080", ItemType: &StringType{}, Editable: false},
{Name: common.DatabaseType, Scope: SystemScope, Group: BasicGroup, EnvKey: "DATABASE_TYPE", DefaultValue: "postgresql", ItemType: &StringType{}, Editable: false},
{Name: common.EmailFrom, Scope: UserScope, Group: EmailGroup, EnvKey: "EMAIL_FROM", DefaultValue: "admin <sample_admin@mydomain.com>", ItemType: &StringType{}, Editable: false},

View File

@ -55,6 +55,7 @@ const (
PostGreSQLSSLMode = "postgresql_sslmode"
SelfRegistration = "self_registration"
CoreURL = "core_url"
CoreLocalURL = "core_local_url"
JobServiceURL = "jobservice_url"
LDAPURL = "ldap_url"
LDAPSearchDN = "ldap_search_dn"

View File

@ -238,7 +238,7 @@ func (ra *RepositoryAPI) Delete() {
return
}
rc, err := coreutils.NewRepositoryClientForUI(ra.SecurityCtx.GetUsername(), repoName)
rc, err := coreutils.NewRepositoryClientForLocal(ra.SecurityCtx.GetUsername(), repoName)
if err != nil {
log.Errorf("error occurred while initializing repository client for %s: %v", repoName, err)
ra.SendInternalServerError(errors.New("internal error"))

View File

@ -280,7 +280,11 @@ func InternalJobServiceURL() string {
// InternalCoreURL returns the local harbor core url
func InternalCoreURL() string {
return strings.TrimSuffix(cfgMgr.Get(common.CoreURL).GetString(), "/")
}
// LocalCoreURL returns the local harbor core url
func LocalCoreURL() string {
return cfgMgr.Get(common.CoreLocalURL).GetString()
}
// InternalTokenServiceEndpoint returns token service endpoint for internal communication between Harbor containers

View File

@ -208,6 +208,9 @@ func TestConfig(t *testing.T) {
assert.Equal("http://myjob:8888", InternalJobServiceURL())
assert.Equal("http://myui:8888/service/token", InternalTokenServiceEndpoint())
localCoreURL := LocalCoreURL()
assert.Equal("http://127.0.0.1:8080", localCoreURL)
}
func currPath() string {

View File

@ -28,3 +28,6 @@ const (
// Middlewares with sequential organization
var Middlewares = []string{READONLY, URL, MUITIPLEMANIFEST, LISTREPO, CONTENTTRUST, VULNERABLE, SIZEQUOTA, COUNTQUOTA}
// MiddlewaresLocal ...
var MiddlewaresLocal = []string{SIZEQUOTA, COUNTQUOTA}

View File

@ -16,26 +16,42 @@ package middlewares
import (
"errors"
"github.com/goharbor/harbor/src/common/utils/log"
"github.com/goharbor/harbor/src/core/filter"
"github.com/goharbor/harbor/src/core/middlewares/registryproxy"
"github.com/goharbor/harbor/src/core/middlewares/util"
"net/http"
)
var head http.Handler
var proxy http.Handler
// Init initialize the Proxy instance and handler chain.
func Init() error {
ph := registryproxy.New()
if ph == nil {
proxy = registryproxy.New()
if proxy == nil {
return errors.New("get nil when to create proxy")
}
handlerChain := New(Middlewares).Create()
head = handlerChain.Then(ph)
return nil
}
// Handle handles the request.
func Handle(rw http.ResponseWriter, req *http.Request) {
securityCtx, err := filter.GetSecurityContext(req)
if err != nil {
log.Errorf("failed to get security context in middlerware: %v", err)
// error to get security context, use the default chain.
head = New(Middlewares).Create().Then(proxy)
} else {
// true: the request is from 127.0.0.1, only quota middlewares are applied to request
// false: the request is from outside, all of middlewares are applied to the request.
if securityCtx.IsSolutionUser() {
head = New(MiddlewaresLocal).Create().Then(proxy)
} else {
head = New(Middlewares).Create().Then(proxy)
}
}
customResW := util.NewCustomResponseWriter(rw)
head.ServeHTTP(customResW, req)
}

View File

@ -31,6 +31,7 @@ import (
"github.com/goharbor/harbor/src/pkg/scan/whitelist"
"net/http"
"net/http/httptest"
"os"
"regexp"
"strconv"
"strings"
@ -368,6 +369,16 @@ func GetProjectID(name string) (int64, error) {
// GetRegRedisCon ...
func GetRegRedisCon() (redis.Conn, error) {
// FOR UT
if os.Getenv("UTTEST") == "true" {
return redis.Dial(
"tcp",
fmt.Sprintf("%s:%d", os.Getenv("REDIS_HOST"), 6379),
redis.DialConnectTimeout(DialConnectionTimeout),
redis.DialReadTimeout(DialReadTimeout),
redis.DialWriteTimeout(DialWriteTimeout),
)
}
return redis.DialURL(
config.GetRedisOfRegURL(),
redis.DialConnectTimeout(DialConnectionTimeout),

View File

@ -28,13 +28,13 @@ import (
// Retag tags an image to another
func Retag(srcImage, destImage *models.Image) error {
isSameRepo := getRepoName(srcImage) == getRepoName(destImage)
srcClient, err := NewRepositoryClientForUI("harbor-ui", getRepoName(srcImage))
srcClient, err := NewRepositoryClientForLocal("harbor-ui", getRepoName(srcImage))
if err != nil {
return err
}
destClient := srcClient
if !isSameRepo {
destClient, err = NewRepositoryClientForUI("harbor-ui", getRepoName(destImage))
destClient, err = NewRepositoryClientForLocal("harbor-ui", getRepoName(destImage))
if err != nil {
return err
}

View File

@ -17,6 +17,7 @@ package utils
import (
"net/http"
"os"
"time"
"github.com/goharbor/harbor/src/common/utils/log"
@ -33,7 +34,20 @@ func NewRepositoryClientForUI(username, repository string) (*registry.Repository
if err != nil {
return nil, err
}
return newRepositoryClient(endpoint, username, repository)
}
// NewRepositoryClientForLocal creates a repository client that can only be used to
// access the internal registry with 127.0.0.1
func NewRepositoryClientForLocal(username, repository string) (*registry.Repository, error) {
// The 127.0.0.1:8080 is not reachable as we do not enable core in UT env.
if os.Getenv("UTTEST") == "true" {
return NewRepositoryClientForUI(username, repository)
}
return newRepositoryClient(config.LocalCoreURL(), username, repository)
}
func newRepositoryClient(endpoint, username, repository string) (*registry.Repository, error) {
uam := &auth.UserAgentModifier{
UserAgent: "harbor-registry-client",
}