This commit is contained in:
Wenkai Yin 2017-02-13 17:05:25 +08:00
parent 6dc6b4fa79
commit 06519bb3f2
17 changed files with 166 additions and 119 deletions

View File

@ -3,7 +3,7 @@ services:
log: log:
build: build:
context: ../../ context: ../../
dockerfile: make/ubuntu/log/Dockerfile dockerfile: make/photon/log/Dockerfile
restart: always restart: always
volumes: volumes:
- /var/log/harbor/:/var/log/docker/ - /var/log/harbor/:/var/log/docker/

View File

@ -78,7 +78,7 @@ func getCfgStore() string {
//read the following attrs from env every time boots up //read the following attrs from env every time boots up
func readFromEnv(cfg map[string]interface{}) error { func readFromEnv(cfg map[string]interface{}) error {
cfg[comcfg.DomainName] = os.Getenv("EXT_ENDPOINT") cfg[comcfg.ExtEndpoint] = os.Getenv("EXT_ENDPOINT")
cfg[comcfg.DatabaseType] = os.Getenv("DATABASE_TYPE") cfg[comcfg.DatabaseType] = os.Getenv("DATABASE_TYPE")
cfg[comcfg.MySQLHost] = os.Getenv("MYSQL_HOST") cfg[comcfg.MySQLHost] = os.Getenv("MYSQL_HOST")

View File

@ -40,7 +40,7 @@ const (
LDAPScopeOnelevel = "2" LDAPScopeOnelevel = "2"
LDAPScopeSubtree = "3" LDAPScopeSubtree = "3"
DomainName = "domain_name" ExtEndpoint = "ext_endpoint"
AUTHMode = "auth_mode" AUTHMode = "auth_mode"
DatabaseType = "database_type" DatabaseType = "database_type"
MySQLHost = "mysql_host" MySQLHost = "mysql_host"

View File

@ -21,7 +21,6 @@ import (
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"net/url" "net/url"
"os"
"strings" "strings"
"sync" "sync"
"time" "time"
@ -134,19 +133,24 @@ func (t *tokenAuthorizer) updateCachedToken(token string, expiresIn int) {
// Implements interface Authorizer // Implements interface Authorizer
type standardTokenAuthorizer struct { type standardTokenAuthorizer struct {
tokenAuthorizer tokenAuthorizer
client *http.Client client *http.Client
credential Credential credential Credential
tokenServiceEndpoint string
} }
// NewStandardTokenAuthorizer returns a standard token authorizer. The authorizer will request a token // NewStandardTokenAuthorizer returns a standard token authorizer. The authorizer will request a token
// from token server and add it to the origin request // from token server and add it to the origin request
func NewStandardTokenAuthorizer(credential Credential, insecure bool, scopeType, scopeName string, scopeActions ...string) Authorizer { // If tokenServiceURL is set, the token request will be sent to it instead of the server get from authorizer
// The usage please refer to the function tokenURL
func NewStandardTokenAuthorizer(credential Credential, insecure bool,
tokenServiceEndpoint string, scopeType, scopeName string, scopeActions ...string) Authorizer {
authorizer := &standardTokenAuthorizer{ authorizer := &standardTokenAuthorizer{
client: &http.Client{ client: &http.Client{
Transport: registry.GetHTTPTransport(insecure), Transport: registry.GetHTTPTransport(insecure),
Timeout: 30 * time.Second, Timeout: 30 * time.Second,
}, },
credential: credential, credential: credential,
tokenServiceEndpoint: tokenServiceEndpoint,
} }
if len(scopeType) != 0 || len(scopeName) != 0 { if len(scopeType) != 0 || len(scopeName) != 0 {
@ -163,7 +167,7 @@ func NewStandardTokenAuthorizer(credential Credential, insecure bool, scopeType,
} }
func (s *standardTokenAuthorizer) generateToken(realm, service string, scopes []string) (token string, expiresIn int, issuedAt *time.Time, err error) { func (s *standardTokenAuthorizer) generateToken(realm, service string, scopes []string) (token string, expiresIn int, issuedAt *time.Time, err error) {
realm = tokenURL(realm) realm = s.tokenURL(realm)
u, err := url.Parse(realm) u, err := url.Parse(realm)
if err != nil { if err != nil {
@ -230,17 +234,15 @@ func (s *standardTokenAuthorizer) generateToken(realm, service string, scopes []
// when the registry client is used inside Harbor, the token request // when the registry client is used inside Harbor, the token request
// can be posted to token service directly rather than going through nginx. // can be posted to token service directly rather than going through nginx.
// this solution can resolve two problems: // If realm is set as the internal url of token service, this can resolve
// two problems:
// 1. performance issue // 1. performance issue
// 2. the realm field returned by registry is an IP which can not reachable // 2. the realm field returned by registry is an IP which can not reachable
// inside Harbor // inside Harbor
func tokenURL(realm string) string { func (s *standardTokenAuthorizer) tokenURL(realm string) string {
if len(s.tokenServiceEndpoint) != 0 {
domainName := os.Getenv("DOMAIN_NAME") return s.tokenServiceEndpoint
if len(domainName) != 0 && strings.Contains(realm, domainName) {
realm = "http://ui/service/token"
} }
return realm return realm
} }

View File

@ -40,7 +40,7 @@ func TestAuthorizeOfStandardTokenAuthorizer(t *testing.T) {
}) })
defer server.Close() defer server.Close()
authorizer := NewStandardTokenAuthorizer(nil, false, "repository", "library/ubuntu", "pull") authorizer := NewStandardTokenAuthorizer(nil, false, "", "repository", "library/ubuntu", "pull")
req, err := http.NewRequest("GET", "http://registry", nil) req, err := http.NewRequest("GET", "http://registry", nil)
if err != nil { if err != nil {
t.Fatalf("failed to create request: %v", err) t.Fatalf("failed to create request: %v", err)

View File

@ -23,47 +23,53 @@ import (
"github.com/vmware/harbor/src/common/config" "github.com/vmware/harbor/src/common/config"
) )
var adminServerDefaultConfig = map[string]interface{}{
config.ExtEndpoint: "host01.com",
config.AUTHMode: config.DBAuth,
config.DatabaseType: "mysql",
config.MySQLHost: "127.0.0.1",
config.MySQLPort: 3306,
config.MySQLUsername: "user01",
config.MySQLPassword: "password",
config.MySQLDatabase: "registry",
config.SQLiteFile: "/tmp/registry.db",
config.SelfRegistration: true,
config.LDAPURL: "ldap://127.0.0.1",
config.LDAPSearchDN: "uid=searchuser,ou=people,dc=mydomain,dc=com",
config.LDAPSearchPwd: "password",
config.LDAPBaseDN: "ou=people,dc=mydomain,dc=com",
config.LDAPUID: "uid",
config.LDAPFilter: "",
config.LDAPScope: 3,
config.LDAPTimeout: 30,
config.TokenServiceURL: "http://token_service",
config.RegistryURL: "http://registry",
config.EmailHost: "127.0.0.1",
config.EmailPort: 25,
config.EmailUsername: "user01",
config.EmailPassword: "password",
config.EmailFrom: "from",
config.EmailSSL: true,
config.EmailIdentity: "",
config.ProjectCreationRestriction: config.ProCrtRestrAdmOnly,
config.VerifyRemoteCert: false,
config.MaxJobWorkers: 3,
config.TokenExpiration: 30,
config.CfgExpiration: 5,
config.JobLogDir: "/var/log/jobs",
config.UseCompressedJS: true,
config.SecretKey: "secret",
config.AdminInitialPassword: "password",
}
// NewAdminserver returns a mock admin server // NewAdminserver returns a mock admin server
func NewAdminserver() (*httptest.Server, error) { func NewAdminserver(config map[string]interface{}) (*httptest.Server, error) {
m := []*RequestHandlerMapping{} m := []*RequestHandlerMapping{}
b, err := json.Marshal(map[string]interface{}{ if config == nil {
config.DomainName: "host01.com", config = adminServerDefaultConfig
config.AUTHMode: config.DBAuth, }
config.DatabaseType: "mysql",
config.MySQLHost: "127.0.0.1", b, err := json.Marshal(config)
config.MySQLPort: 3306,
config.MySQLUsername: "user01",
config.MySQLPassword: "password",
config.MySQLDatabase: "registry",
config.SQLiteFile: "/tmp/registry.db",
config.SelfRegistration: true,
config.LDAPURL: "ldap://127.0.0.1",
config.LDAPSearchDN: "uid=searchuser,ou=people,dc=mydomain,dc=com",
config.LDAPSearchPwd: "password",
config.LDAPBaseDN: "ou=people,dc=mydomain,dc=com",
config.LDAPUID: "uid",
config.LDAPFilter: "",
config.LDAPScope: 3,
config.LDAPTimeout: 30,
config.TokenServiceURL: "http://token_service",
config.RegistryURL: "http://registry",
config.EmailHost: "127.0.0.1",
config.EmailPort: 25,
config.EmailUsername: "user01",
config.EmailPassword: "password",
config.EmailFrom: "from",
config.EmailSSL: true,
config.EmailIdentity: "",
config.ProjectCreationRestriction: config.ProCrtRestrAdmOnly,
config.VerifyRemoteCert: false,
config.MaxJobWorkers: 3,
config.TokenExpiration: 30,
config.CfgExpiration: 5,
config.JobLogDir: "/var/log/jobs",
config.UseCompressedJS: true,
config.SecretKey: "secret",
config.AdminInitialPassword: "password",
})
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -121,11 +121,16 @@ func UISecret() string {
return os.Getenv("UI_SECRET") return os.Getenv("UI_SECRET")
} }
// DomainName ... // ExtEndpoint ...
func DomainName() (string, error) { func ExtEndpoint() (string, error) {
cfg, err := mg.Get() cfg, err := mg.Get()
if err != nil { if err != nil {
return "", err return "", err
} }
return cfg[comcfg.DomainName].(string), nil return cfg[comcfg.ExtEndpoint].(string), nil
}
// InternalTokenServiceEndpoint ...
func InternalTokenServiceEndpoint() string {
return "http://ui/service/token"
} }

View File

@ -24,7 +24,7 @@ import (
// test functions under package jobservice/config // test functions under package jobservice/config
func TestConfig(t *testing.T) { func TestConfig(t *testing.T) {
server, err := test.NewAdminserver() server, err := test.NewAdminserver(nil)
if err != nil { if err != nil {
t.Fatalf("failed to create a mock admin server: %v", err) t.Fatalf("failed to create a mock admin server: %v", err)
} }
@ -53,8 +53,6 @@ func TestConfig(t *testing.T) {
t.Fatalf("failed to get max job workers: %v", err) t.Fatalf("failed to get max job workers: %v", err)
} }
LocalUIURL()
if _, err := LocalRegURL(); err != nil { if _, err := LocalRegURL(); err != nil {
t.Fatalf("failed to get registry URL: %v", err) t.Fatalf("failed to get registry URL: %v", err)
} }
@ -67,5 +65,11 @@ func TestConfig(t *testing.T) {
t.Fatalf("failed to get secret key: %v", err) t.Fatalf("failed to get secret key: %v", err)
} }
UISecret() if len(InternalTokenServiceEndpoint()) == 0 {
t.Error("the internal token service endpoint is null")
}
if _, err := ExtEndpoint(); err != nil {
t.Fatalf("failed to get ext endpoint: %v", err)
}
} }

View File

@ -139,7 +139,7 @@ func (i *Initializer) enter() (string, error) {
c := &http.Cookie{Name: models.UISecretCookie, Value: i.srcSecret} c := &http.Cookie{Name: models.UISecretCookie, Value: i.srcSecret}
srcCred := auth.NewCookieCredential(c) srcCred := auth.NewCookieCredential(c)
srcClient, err := newRepositoryClient(i.srcURL, i.insecure, srcCred, srcClient, err := newRepositoryClient(i.srcURL, i.insecure, srcCred,
i.repository, "repository", i.repository, "pull", "push", "*") config.InternalTokenServiceEndpoint(), i.repository, "repository", i.repository, "pull", "push", "*")
if err != nil { if err != nil {
i.logger.Errorf("an error occurred while creating source repository client: %v", err) i.logger.Errorf("an error occurred while creating source repository client: %v", err)
return "", err return "", err
@ -148,7 +148,7 @@ func (i *Initializer) enter() (string, error) {
dstCred := auth.NewBasicAuthCredential(i.dstUsr, i.dstPwd) dstCred := auth.NewBasicAuthCredential(i.dstUsr, i.dstPwd)
dstClient, err := newRepositoryClient(i.dstURL, i.insecure, dstCred, dstClient, err := newRepositoryClient(i.dstURL, i.insecure, dstCred,
i.repository, "repository", i.repository, "pull", "push", "*") "", i.repository, "repository", i.repository, "pull", "push", "*")
if err != nil { if err != nil {
i.logger.Errorf("an error occurred while creating destination repository client: %v", err) i.logger.Errorf("an error occurred while creating destination repository client: %v", err)
return "", err return "", err
@ -459,10 +459,11 @@ func (m *ManifestPusher) enter() (string, error) {
return StatePullManifest, nil return StatePullManifest, nil
} }
func newRepositoryClient(endpoint string, insecure bool, credential auth.Credential, repository, scopeType, scopeName string, func newRepositoryClient(endpoint string, insecure bool, credential auth.Credential,
tokenServiceEndpoint, repository, scopeType, scopeName string,
scopeActions ...string) (*registry.Repository, error) { scopeActions ...string) (*registry.Repository, error) {
domain, err := config.DomainName() domain, err := config.ExtEndpoint()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -470,7 +471,8 @@ func newRepositoryClient(endpoint string, insecure bool, credential auth.Credent
return nil, err return nil, err
} }
authorizer := auth.NewStandardTokenAuthorizer(credential, insecure, scopeType, scopeName, scopeActions...) authorizer := auth.NewStandardTokenAuthorizer(credential, insecure,
tokenServiceEndpoint, scopeType, scopeName, scopeActions...)
store, err := auth.NewAuthorizerStore(endpoint, insecure, authorizer) store, err := auth.NewAuthorizerStore(endpoint, insecure, authorizer)
if err != nil { if err != nil {

View File

@ -119,7 +119,14 @@ func (c *ConfigAPI) Put() {
} }
} }
if err := validateCfg(cfg); err != nil { isSysErr, err := validateCfg(cfg)
if err != nil {
if isSysErr {
log.Errorf("failed to validate configurations: %v", err)
c.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
}
c.CustomAbort(http.StatusBadRequest, err.Error()) c.CustomAbort(http.StatusBadRequest, err.Error())
} }
@ -162,42 +169,68 @@ func (c *ConfigAPI) Put() {
} }
} }
func validateCfg(c map[string]string) error { func validateCfg(c map[string]string) (bool, error) {
isSysErr := false
mode, err := config.AuthMode()
if err != nil {
isSysErr = true
return isSysErr, err
}
if value, ok := c[comcfg.AUTHMode]; ok { if value, ok := c[comcfg.AUTHMode]; ok {
if value != comcfg.DBAuth && value != comcfg.LDAPAuth { if value != comcfg.DBAuth && value != comcfg.LDAPAuth {
return fmt.Errorf("invalid %s, shoud be %s or %s", comcfg.AUTHMode, comcfg.DBAuth, comcfg.LDAPAuth) return isSysErr, fmt.Errorf("invalid %s, shoud be %s or %s", comcfg.AUTHMode, comcfg.DBAuth, comcfg.LDAPAuth)
}
mode = value
}
if mode == comcfg.LDAPAuth {
ldap, err := config.LDAP()
if err != nil {
isSysErr = true
return isSysErr, err
} }
if value == comcfg.LDAPAuth { if len(ldap.URL) == 0 {
if _, ok := c[comcfg.LDAPURL]; !ok { if _, ok := c[comcfg.LDAPURL]; !ok {
return fmt.Errorf("%s is missing", comcfg.LDAPURL) return isSysErr, fmt.Errorf("%s is missing", comcfg.LDAPURL)
} }
}
if len(ldap.BaseDN) == 0 {
if _, ok := c[comcfg.LDAPBaseDN]; !ok { if _, ok := c[comcfg.LDAPBaseDN]; !ok {
return fmt.Errorf("%s is missing", comcfg.LDAPBaseDN) return isSysErr, fmt.Errorf("%s is missing", comcfg.LDAPBaseDN)
} }
}
if len(ldap.UID) == 0 {
if _, ok := c[comcfg.LDAPUID]; !ok { if _, ok := c[comcfg.LDAPUID]; !ok {
return fmt.Errorf("%s is missing", comcfg.LDAPUID) return isSysErr, fmt.Errorf("%s is missing", comcfg.LDAPUID)
} }
}
if ldap.Scope == 0 {
if _, ok := c[comcfg.LDAPScope]; !ok { if _, ok := c[comcfg.LDAPScope]; !ok {
return fmt.Errorf("%s is missing", comcfg.LDAPScope) return isSysErr, fmt.Errorf("%s is missing", comcfg.LDAPScope)
} }
} }
} }
log.Infof("===========%v", c)
if ldapURL, ok := c[comcfg.LDAPURL]; ok && len(ldapURL) == 0 { if ldapURL, ok := c[comcfg.LDAPURL]; ok && len(ldapURL) == 0 {
return fmt.Errorf("%s is empty", comcfg.LDAPURL) return isSysErr, fmt.Errorf("%s is empty", comcfg.LDAPURL)
} }
if baseDN, ok := c[comcfg.LDAPBaseDN]; ok && len(baseDN) == 0 { if baseDN, ok := c[comcfg.LDAPBaseDN]; ok && len(baseDN) == 0 {
return fmt.Errorf("%s is empty", comcfg.LDAPBaseDN) return isSysErr, fmt.Errorf("%s is empty", comcfg.LDAPBaseDN)
} }
if uID, ok := c[comcfg.LDAPUID]; ok && len(uID) == 0 { if uID, ok := c[comcfg.LDAPUID]; ok && len(uID) == 0 {
return fmt.Errorf("%s is empty", comcfg.LDAPUID) return isSysErr, fmt.Errorf("%s is empty", comcfg.LDAPUID)
} }
if scope, ok := c[comcfg.LDAPScope]; ok && if scope, ok := c[comcfg.LDAPScope]; ok &&
scope != comcfg.LDAPScopeBase && scope != comcfg.LDAPScopeBase &&
scope != comcfg.LDAPScopeOnelevel && scope != comcfg.LDAPScopeOnelevel &&
scope != comcfg.LDAPScopeSubtree { scope != comcfg.LDAPScopeSubtree {
return fmt.Errorf("invalid %s, should be %s, %s or %s", return isSysErr, fmt.Errorf("invalid %s, should be %s, %s or %s",
comcfg.LDAPScope, comcfg.LDAPScope,
comcfg.LDAPScopeBase, comcfg.LDAPScopeBase,
comcfg.LDAPScopeOnelevel, comcfg.LDAPScopeOnelevel,
@ -205,41 +238,41 @@ func validateCfg(c map[string]string) error {
} }
if timeout, ok := c[comcfg.LDAPTimeout]; ok { if timeout, ok := c[comcfg.LDAPTimeout]; ok {
if t, err := strconv.Atoi(timeout); err != nil || t < 0 { if t, err := strconv.Atoi(timeout); err != nil || t < 0 {
return fmt.Errorf("invalid %s", comcfg.LDAPTimeout) return isSysErr, fmt.Errorf("invalid %s", comcfg.LDAPTimeout)
} }
} }
if self, ok := c[comcfg.SelfRegistration]; ok && if self, ok := c[comcfg.SelfRegistration]; ok &&
self != "0" && self != "1" { self != "0" && self != "1" {
return fmt.Errorf("%s should be %s or %s", return isSysErr, fmt.Errorf("%s should be %s or %s",
comcfg.SelfRegistration, "0", "1") comcfg.SelfRegistration, "0", "1")
} }
if port, ok := c[comcfg.EmailPort]; ok { if port, ok := c[comcfg.EmailPort]; ok {
if p, err := strconv.Atoi(port); err != nil || p < 0 || p > 65535 { if p, err := strconv.Atoi(port); err != nil || p < 0 || p > 65535 {
return fmt.Errorf("invalid %s", comcfg.EmailPort) return isSysErr, fmt.Errorf("invalid %s", comcfg.EmailPort)
} }
} }
if ssl, ok := c[comcfg.EmailSSL]; ok && ssl != "0" && ssl != "1" { if ssl, ok := c[comcfg.EmailSSL]; ok && ssl != "0" && ssl != "1" {
return fmt.Errorf("%s should be %s or %s", comcfg.EmailSSL, "0", "1") return isSysErr, fmt.Errorf("%s should be %s or %s", comcfg.EmailSSL, "0", "1")
} }
if crt, ok := c[comcfg.ProjectCreationRestriction]; ok && if crt, ok := c[comcfg.ProjectCreationRestriction]; ok &&
crt != comcfg.ProCrtRestrEveryone && crt != comcfg.ProCrtRestrEveryone &&
crt != comcfg.ProCrtRestrAdmOnly { crt != comcfg.ProCrtRestrAdmOnly {
return fmt.Errorf("invalid %s, should be %s or %s", return isSysErr, fmt.Errorf("invalid %s, should be %s or %s",
comcfg.ProjectCreationRestriction, comcfg.ProjectCreationRestriction,
comcfg.ProCrtRestrAdmOnly, comcfg.ProCrtRestrAdmOnly,
comcfg.ProCrtRestrEveryone) comcfg.ProCrtRestrEveryone)
} }
if verify, ok := c[comcfg.VerifyRemoteCert]; ok && verify != "0" && verify != "1" { if verify, ok := c[comcfg.VerifyRemoteCert]; ok && verify != "0" && verify != "1" {
return fmt.Errorf("invalid %s, should be %s or %s", return isSysErr, fmt.Errorf("invalid %s, should be %s or %s",
comcfg.VerifyRemoteCert, "0", "1") comcfg.VerifyRemoteCert, "0", "1")
} }
return nil return isSysErr, nil
} }
//encode passwords and convert map[string]string to map[string]interface{} //encode passwords and convert map[string]string to map[string]interface{}

View File

@ -19,7 +19,6 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"os"
"sort" "sort"
"github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/manifest/schema1"
@ -444,15 +443,8 @@ func newRepositoryClient(endpoint string, insecure bool, username, password, rep
credential := auth.NewBasicAuthCredential(username, password) credential := auth.NewBasicAuthCredential(username, password)
domain, err := config.DomainName() authorizer := auth.NewStandardTokenAuthorizer(credential, insecure,
if err != nil { config.InternalTokenServiceEndpoint(), scopeType, scopeName, scopeActions...)
return nil, err
}
if err := os.Setenv("DOMAIN_NAME", domain); err != nil {
return nil, err
}
authorizer := auth.NewStandardTokenAuthorizer(credential, insecure, scopeType, scopeName, scopeActions...)
store, err := auth.NewAuthorizerStore(endpoint, insecure, authorizer) store, err := auth.NewAuthorizerStore(endpoint, insecure, authorizer)
if err != nil { if err != nil {

View File

@ -20,7 +20,6 @@ import (
"net" "net"
"net/http" "net/http"
"net/url" "net/url"
"os"
"strconv" "strconv"
"github.com/vmware/harbor/src/common/api" "github.com/vmware/harbor/src/common/api"
@ -342,15 +341,8 @@ func newRegistryClient(endpoint string, insecure bool, username, password, scope
scopeActions ...string) (*registry.Registry, error) { scopeActions ...string) (*registry.Registry, error) {
credential := auth.NewBasicAuthCredential(username, password) credential := auth.NewBasicAuthCredential(username, password)
domain, err := config.DomainName() authorizer := auth.NewStandardTokenAuthorizer(credential, insecure,
if err != nil { "", scopeType, scopeName, scopeActions...)
return nil, err
}
if err := os.Setenv("DOMAIN_NAME", domain); err != nil {
return nil, err
}
authorizer := auth.NewStandardTokenAuthorizer(credential, insecure, scopeType, scopeName, scopeActions...)
store, err := auth.NewAuthorizerStore(endpoint, insecure, authorizer) store, err := auth.NewAuthorizerStore(endpoint, insecure, authorizer)
if err != nil { if err != nil {

View File

@ -114,13 +114,13 @@ func TokenExpiration() (int, error) {
return int(cfg[comcfg.TokenExpiration].(float64)), nil return int(cfg[comcfg.TokenExpiration].(float64)), nil
} }
// DomainName returns the external URL of Harbor: protocal://host:port // ExtEndpoint returns the external URL of Harbor: protocal://host:port
func DomainName() (string, error) { func ExtEndpoint() (string, error) {
cfg, err := mg.Get() cfg, err := mg.Get()
if err != nil { if err != nil {
return "", err return "", err
} }
return cfg[comcfg.DomainName].(string), nil return cfg[comcfg.ExtEndpoint].(string), nil
} }
// SecretKey returns the secret key to encrypt the password of target // SecretKey returns the secret key to encrypt the password of target
@ -155,6 +155,11 @@ func InternalJobServiceURL() string {
return "http://jobservice" return "http://jobservice"
} }
// InternalTokenServiceEndpoint returns token service endpoint for internal communication between Harbor containers
func InternalTokenServiceEndpoint() string {
return "http://ui/service/token"
}
// InitialAdminPassword returns the initial password for administrator // InitialAdminPassword returns the initial password for administrator
func InitialAdminPassword() (string, error) { func InitialAdminPassword() (string, error) {
cfg, err := mg.Get() cfg, err := mg.Get()

View File

@ -23,7 +23,7 @@ import (
// test functions under package ui/config // test functions under package ui/config
func TestConfig(t *testing.T) { func TestConfig(t *testing.T) {
server, err := test.NewAdminserver() server, err := test.NewAdminserver(nil)
if err != nil { if err != nil {
t.Fatalf("failed to create a mock admin server: %v", err) t.Fatalf("failed to create a mock admin server: %v", err)
} }
@ -68,7 +68,7 @@ func TestConfig(t *testing.T) {
t.Fatalf("failed to get token expiration: %v", err) t.Fatalf("failed to get token expiration: %v", err)
} }
if _, err := DomainName(); err != nil { if _, err := ExtEndpoint(); err != nil {
t.Fatalf("failed to get domain name: %v", err) t.Fatalf("failed to get domain name: %v", err)
} }
@ -84,9 +84,17 @@ func TestConfig(t *testing.T) {
t.Fatalf("failed to get registry URL: %v", err) t.Fatalf("failed to get registry URL: %v", err)
} }
InternalJobServiceURL() if len(InternalJobServiceURL()) == 0 {
t.Error("the internal job service url is null")
}
InitialAdminPassword() if len(InternalTokenServiceEndpoint()) == 0 {
t.Error("the internal token service endpoint is null")
}
if _, err := InitialAdminPassword(); err != nil {
t.Fatalf("failed to get initial admin password: %v", err)
}
if _, err := OnlyAdminCreateProject(); err != nil { if _, err := OnlyAdminCreateProject(); err != nil {
t.Fatalf("failed to get onldy admin create project: %v", err) t.Fatalf("failed to get onldy admin create project: %v", err)
@ -103,6 +111,4 @@ func TestConfig(t *testing.T) {
if _, err := Database(); err != nil { if _, err := Database(); err != nil {
t.Fatalf("failed to get database: %v", err) t.Fatalf("failed to get database: %v", err)
} }
UISecret()
} }

View File

@ -49,7 +49,7 @@ func (cc *CommonController) SendEmail() {
message := new(bytes.Buffer) message := new(bytes.Buffer)
harborURL, err := config.DomainName() harborURL, err := config.ExtEndpoint()
if err != nil { if err != nil {
log.Errorf("failed to get domain name: %v", err) log.Errorf("failed to get domain name: %v", err)
cc.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) cc.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))

View File

@ -15,7 +15,7 @@ type RepositoryController struct {
// Get renders repository page // Get renders repository page
func (rc *RepositoryController) Get() { func (rc *RepositoryController) Get() {
url, err := config.DomainName() url, err := config.ExtEndpoint()
if err != nil { if err != nil {
log.Errorf("failed to get domain name: %v", err) log.Errorf("failed to get domain name: %v", err)
rc.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) rc.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))

View File

@ -84,7 +84,7 @@ func FilterAccess(username string, a *token.ResourceActions) {
repoLength := len(repoSplit) repoLength := len(repoSplit)
if repoLength > 1 { //Only check the permission when the requested image has a namespace, i.e. project if repoLength > 1 { //Only check the permission when the requested image has a namespace, i.e. project
var projectName string var projectName string
registryURL, err := config.DomainName() registryURL, err := config.ExtEndpoint()
if err != nil { if err != nil {
log.Errorf("failed to get domain name: %v", err) log.Errorf("failed to get domain name: %v", err)
return return