From 9d7a18a0a39d0a56933b14649e4de6572906603d Mon Sep 17 00:00:00 2001 From: Tan Jiang Date: Wed, 16 Nov 2016 20:31:04 +0800 Subject: [PATCH] fix issue in golint, support project creation restriction at backend --- make/common/templates/ui/env | 2 +- make/harbor.cfg | 3 +++ make/prepare | 6 ++++++ src/common/config/config.go | 21 +++++++++++++------ src/common/dao/base.go | 2 +- src/ui/api/project.go | 13 ++++++++++-- src/ui/api/repository.go | 10 ++++----- src/ui/api/target.go | 7 +++---- src/ui/api/user.go | 17 ++++----------- src/ui/api/utils.go | 35 +++++++++---------------------- src/ui/auth/ldap/ldap.go | 18 ++++++++-------- src/ui/config/config.go | 26 ++++++++++++++++++++--- src/ui/config/config_test.go | 14 +++++++++---- src/ui/controllers/base.go | 11 +++++----- src/ui/controllers/password.go | 1 - src/ui/controllers/repository.go | 6 ++++-- src/ui/main.go | 7 ++++--- src/ui/service/token/authutils.go | 26 ++++------------------- src/ui/service/utils/utils.go | 4 ++-- 19 files changed, 120 insertions(+), 109 deletions(-) diff --git a/make/common/templates/ui/env b/make/common/templates/ui/env index 8af46020a..e4feedc2e 100644 --- a/make/common/templates/ui/env +++ b/make/common/templates/ui/env @@ -26,4 +26,4 @@ EXT_ENDPOINT=$ui_url TOKEN_ENDPOINT=http://ui VERIFY_REMOTE_CERT=$verify_remote_cert TOKEN_EXPIRATION=$token_expiration -CREATE_PROJECT_RESTRICTION=$create_project_restriction +PROJECT_CREATION_RESTRICTION=$project_creation_restriction diff --git a/make/harbor.cfg b/make/harbor.cfg index 4a2e935ea..8444beaeb 100644 --- a/make/harbor.cfg +++ b/make/harbor.cfg @@ -83,6 +83,9 @@ crt_organizationalunit = organizational unit crt_commonname = example.com crt_email = example@example.com +#The flag to control what users have permission to create projects +#Be default everyone can create a project, set to "adminonly" such that only admin can create project. +project_creation_restriction = adminonly #The path of cert and key files for nginx, they are applied only the protocol is set to https ssl_cert = /data/server.crt diff --git a/make/prepare b/make/prepare index 02f180ff1..b2ec7254f 100755 --- a/make/prepare +++ b/make/prepare @@ -32,6 +32,10 @@ def validate(conf): cert_key_path = rcp.get("configuration", "ssl_cert_key") if not os.path.isfile(cert_key_path): raise Exception("Error: The path for certificate key: %s is invalid" % cert_key_path) + project_creation = rcp.get("configuration", "project_creation_restriction") + + if project_creation != "everyone" and project_creation != "adminonly": + raise Exception("Error invalid value for project_creation_restriction: %s" % project_creation) def get_secret_key(path): key_file = os.path.join(path, "secretkey") @@ -115,6 +119,7 @@ crt_email = rcp.get("configuration", "crt_email") max_job_workers = rcp.get("configuration", "max_job_workers") token_expiration = rcp.get("configuration", "token_expiration") verify_remote_cert = rcp.get("configuration", "verify_remote_cert") +proj_cre_restriction = rcp.get("configuration", "project_creation_restriction") #secret_key = rcp.get("configuration", "secret_key") secret_key = get_secret_key(args.data_volume) ######## @@ -200,6 +205,7 @@ render(os.path.join(templates_dir, "ui", "env"), ui_secret=ui_secret, secret_key=secret_key, verify_remote_cert=verify_remote_cert, + project_creation_restriction=proj_cre_restriction, token_expiration=token_expiration) render(os.path.join(templates_dir, "ui", "app.conf"), diff --git a/src/common/config/config.go b/src/common/config/config.go index 2615bb0fd..48f837dd5 100644 --- a/src/common/config/config.go +++ b/src/common/config/config.go @@ -12,6 +12,8 @@ See the License for the specific language governing permissions and limitations under the License. */ + +// Package config provide methods to get the configurations reqruied by code in src/common package config import ( @@ -20,8 +22,8 @@ import ( "strings" ) -// ConfigLoader is the interface to load configurations -type ConfigLoader interface { +// ConfLoader is the interface to load configurations +type ConfLoader interface { // Load will load configuration from different source into a string map, the values in the map will be parsed in to configurations. Load() (map[string]string, error) @@ -41,18 +43,22 @@ func (ec *EnvConfigLoader) Load() (map[string]string, error) { return m, nil } -// ConfigParser -type ConfigParser interface { +// ConfParser ... +type ConfParser interface { + //Parse parse the input raw map into a config map Parse(raw map[string]string, config map[string]interface{}) error } +// Config wraps a map for the processed configuration values, +// and loader parser to read configuration from external source and process the values. type Config struct { Config map[string]interface{} - Loader ConfigLoader - Parser ConfigParser + Loader ConfLoader + Parser ConfParser } +// Load reload the configurations func (conf *Config) Load() error { rawMap, err := conf.Loader.Load() if err != nil { @@ -62,6 +68,7 @@ func (conf *Config) Load() error { return err } +// MySQLSetting wraps the settings of a MySQL DB type MySQLSetting struct { Database string User string @@ -70,6 +77,7 @@ type MySQLSetting struct { Port string } +// SQLiteSetting wraps the settings of a SQLite DB type SQLiteSetting struct { FilePath string } @@ -165,6 +173,7 @@ func TokenEndpoint() string { return commonConfig.Config["token_endpoint"].(string) } +// LogLevel returns the log level in string format. func LogLevel() string { return commonConfig.Config["log_level"].(string) } diff --git a/src/common/dao/base.go b/src/common/dao/base.go index c974cca6e..13dc1c3ae 100644 --- a/src/common/dao/base.go +++ b/src/common/dao/base.go @@ -54,7 +54,7 @@ func getDatabase() (db Database, err error) { switch config.Database() { case "", "mysql": db = NewMySQL(config.MySQL().Host, config.MySQL().Port, config.MySQL().User, - config.MySQL().Port, config.MySQL().Database) + config.MySQL().Password, config.MySQL().Database) case "sqlite": db = NewSQLite(config.SQLite().FilePath) default: diff --git a/src/ui/api/project.go b/src/ui/api/project.go index d4212f762..7ba50fa3b 100644 --- a/src/ui/api/project.go +++ b/src/ui/api/project.go @@ -24,6 +24,7 @@ import ( "github.com/vmware/harbor/src/common/dao" "github.com/vmware/harbor/src/common/models" "github.com/vmware/harbor/src/common/utils/log" + "github.com/vmware/harbor/src/ui/config" "strconv" "time" @@ -72,11 +73,19 @@ func (p *ProjectAPI) Prepare() { // Post ... func (p *ProjectAPI) Post() { p.userID = p.ValidateUser() - + isSysAdmin, err := dao.IsAdminRole(p.userID) + if err != nil { + log.Errorf("Failed to check admin role: %v", err) + } + if !isSysAdmin && config.OnlyAdminCreateProject() { + log.Errorf("Only sys admin can create project") + p.RenderError(http.StatusForbidden, "Only system admin can create project") + return + } var req projectReq p.DecodeJSONReq(&req) public := req.Public - err := validateProjectReq(req) + err = validateProjectReq(req) if err != nil { log.Errorf("Invalid project request, error: %v", err) p.RenderError(http.StatusBadRequest, fmt.Sprintf("invalid request: %v", err)) diff --git a/src/ui/api/repository.go b/src/ui/api/repository.go index 867988c3d..3a885de8b 100644 --- a/src/ui/api/repository.go +++ b/src/ui/api/repository.go @@ -19,23 +19,23 @@ import ( "fmt" "io/ioutil" "net/http" - "os" "sort" "github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/manifest/schema2" + "github.com/vmware/harbor/src/common/api" "github.com/vmware/harbor/src/common/dao" "github.com/vmware/harbor/src/common/models" + "github.com/vmware/harbor/src/common/utils/log" + "github.com/vmware/harbor/src/common/utils/registry" "github.com/vmware/harbor/src/ui/service/cache" svc_utils "github.com/vmware/harbor/src/ui/service/utils" - "github.com/vmware/harbor/src/common/utils/log" - "github.com/vmware/harbor/src/common/api" - "github.com/vmware/harbor/src/common/utils/registry" registry_error "github.com/vmware/harbor/src/common/utils/registry/error" "github.com/vmware/harbor/src/common/utils" "github.com/vmware/harbor/src/common/utils/registry/auth" + "github.com/vmware/harbor/src/ui/config" ) // RepositoryAPI handles request to /api/repositories /api/repositories/tags /api/repositories/manifests, the parm has to be put @@ -361,7 +361,7 @@ func (ra *RepositoryAPI) GetManifests() { } func (ra *RepositoryAPI) initRepositoryClient(repoName string) (r *registry.Repository, err error) { - endpoint := os.Getenv("REGISTRY_URL") + endpoint := config.InternalRegistryURL() username, password, ok := ra.Ctx.Request.BasicAuth() if ok { diff --git a/src/ui/api/target.go b/src/ui/api/target.go index aa19d28f0..abe59a09c 100644 --- a/src/ui/api/target.go +++ b/src/ui/api/target.go @@ -20,17 +20,17 @@ import ( "net" "net/http" "net/url" - "os" "strconv" + "github.com/vmware/harbor/src/common/api" "github.com/vmware/harbor/src/common/dao" "github.com/vmware/harbor/src/common/models" "github.com/vmware/harbor/src/common/utils" "github.com/vmware/harbor/src/common/utils/log" - "github.com/vmware/harbor/src/common/api" "github.com/vmware/harbor/src/common/utils/registry" "github.com/vmware/harbor/src/common/utils/registry/auth" registry_error "github.com/vmware/harbor/src/common/utils/registry/error" + "github.com/vmware/harbor/src/ui/config" ) // TargetAPI handles request to /api/targets/ping /api/targets/{} @@ -41,8 +41,7 @@ type TargetAPI struct { // Prepare validates the user func (t *TargetAPI) Prepare() { - //TODO:move to config - t.secretKey = os.Getenv("SECRET_KEY") + t.secretKey = config.SecretKey() userID := t.ValidateUser() isSysAdmin, err := dao.IsAdminRole(userID) diff --git a/src/ui/api/user.go b/src/ui/api/user.go index 3a0387390..fbed94d3a 100644 --- a/src/ui/api/user.go +++ b/src/ui/api/user.go @@ -18,7 +18,6 @@ package api import ( "fmt" "net/http" - "os" "regexp" "strconv" "strings" @@ -27,6 +26,7 @@ import ( "github.com/vmware/harbor/src/common/dao" "github.com/vmware/harbor/src/common/models" "github.com/vmware/harbor/src/common/utils/log" + "github.com/vmware/harbor/src/ui/config" ) // UserAPI handles request to /api/users/{} @@ -47,16 +47,9 @@ type passwordReq struct { // Prepare validates the URL and parms func (ua *UserAPI) Prepare() { - authMode := strings.ToLower(os.Getenv("AUTH_MODE")) - if authMode == "" { - authMode = "db_auth" - } - ua.AuthMode = authMode + ua.AuthMode = config.AuthMode() - selfRegistration := strings.ToLower(os.Getenv("SELF_REGISTRATION")) - if selfRegistration == "on" { - ua.SelfRegistration = true - } + ua.SelfRegistration = config.SelfRegistration() if ua.Ctx.Input.IsPost() { sessionUserID := ua.GetSession("userId") @@ -241,9 +234,7 @@ func (ua *UserAPI) Delete() { return } - // TODO read from conifg - authMode := os.Getenv("AUTH_MODE") - if authMode == "ldap_auth" { + if config.AuthMode() == "ldap_auth" { ua.CustomAbort(http.StatusForbidden, "user can not be deleted in LDAP authentication mode") } diff --git a/src/ui/api/utils.go b/src/ui/api/utils.go index 42acfe75b..185db1f18 100644 --- a/src/ui/api/utils.go +++ b/src/ui/api/utils.go @@ -22,18 +22,18 @@ import ( "io/ioutil" "net" "net/http" - "os" "sort" "strings" "time" "github.com/vmware/harbor/src/common/dao" "github.com/vmware/harbor/src/common/models" - "github.com/vmware/harbor/src/ui/service/cache" "github.com/vmware/harbor/src/common/utils" "github.com/vmware/harbor/src/common/utils/log" "github.com/vmware/harbor/src/common/utils/registry" registry_error "github.com/vmware/harbor/src/common/utils/registry/error" + "github.com/vmware/harbor/src/ui/config" + "github.com/vmware/harbor/src/ui/service/cache" ) func checkProjectPermission(userID int, projectID int64) bool { @@ -233,9 +233,8 @@ func postReplicationAction(policyID int64, acton string) error { func addAuthentication(req *http.Request) { if req != nil { req.AddCookie(&http.Cookie{ - Name: models.UISecretCookie, - // TODO read secret from config - Value: os.Getenv("UI_SECRET"), + Name: models.UISecretCookie, + Value: config.UISecret(), }) } } @@ -351,8 +350,7 @@ func diffRepos(reposInRegistry []string, reposInDB []string) ([]string, []string } // TODO remove the workaround when the bug of registry is fixed - // TODO read it from config - endpoint := os.Getenv("REGISTRY_URL") + endpoint := config.InternalRegistryURL() client, err := cache.NewRepositoryClient(endpoint, true, "admin", repoInR, "repository", repoInR) if err != nil { @@ -374,8 +372,7 @@ func diffRepos(reposInRegistry []string, reposInDB []string) ([]string, []string j++ } else { // TODO remove the workaround when the bug of registry is fixed - // TODO read it from config - endpoint := os.Getenv("REGISTRY_URL") + endpoint := config.InternalRegistryURL() client, err := cache.NewRepositoryClient(endpoint, true, "admin", repoInR, "repository", repoInR) if err != nil { @@ -425,7 +422,7 @@ func projectExists(repository string) (bool, error) { } func initRegistryClient() (r *registry.Registry, err error) { - endpoint := os.Getenv("REGISTRY_URL") + endpoint := config.InternalRegistryURL() addr := endpoint if strings.Contains(endpoint, "/") { @@ -462,32 +459,20 @@ func initRegistryClient() (r *registry.Registry, err error) { } func buildReplicationURL() string { - url := getJobServiceURL() + url := config.InternalJobServiceURL() return fmt.Sprintf("%s/api/jobs/replication", url) } func buildJobLogURL(jobID string) string { - url := getJobServiceURL() + url := config.InternalJobServiceURL() return fmt.Sprintf("%s/api/jobs/replication/%s/log", url, jobID) } func buildReplicationActionURL() string { - url := getJobServiceURL() + url := config.InternalJobServiceURL() return fmt.Sprintf("%s/api/jobs/replication/actions", url) } -func getJobServiceURL() string { - url := os.Getenv("JOB_SERVICE_URL") - url = strings.TrimSpace(url) - url = strings.TrimRight(url, "/") - - if len(url) == 0 { - url = "http://jobservice" - } - - return url -} - func getReposByProject(name string, keyword ...string) ([]string, error) { repositories := []string{} diff --git a/src/ui/auth/ldap/ldap.go b/src/ui/auth/ldap/ldap.go index 6193485f1..46c563cbe 100644 --- a/src/ui/auth/ldap/ldap.go +++ b/src/ui/auth/ldap/ldap.go @@ -18,14 +18,14 @@ package ldap import ( "errors" "fmt" - "os" "strings" "github.com/vmware/harbor/src/common/utils/log" - "github.com/vmware/harbor/src/ui/auth" "github.com/vmware/harbor/src/common/dao" "github.com/vmware/harbor/src/common/models" + "github.com/vmware/harbor/src/ui/auth" + "github.com/vmware/harbor/src/ui/config" "github.com/mqu/openldap" ) @@ -46,7 +46,7 @@ func (l *Auth) Authenticate(m models.AuthModel) (*models.User, error) { return nil, fmt.Errorf("the principal contains meta char: %q", c) } } - ldapURL := os.Getenv("LDAP_URL") + ldapURL := config.LDAP().URL if ldapURL == "" { return nil, errors.New("can not get any available LDAP_URL") } @@ -57,16 +57,16 @@ func (l *Auth) Authenticate(m models.AuthModel) (*models.User, error) { } ldap.SetOption(openldap.LDAP_OPT_PROTOCOL_VERSION, openldap.LDAP_VERSION3) - ldapBaseDn := os.Getenv("LDAP_BASE_DN") + ldapBaseDn := config.LDAP().BaseDn if ldapBaseDn == "" { return nil, errors.New("can not get any available LDAP_BASE_DN") } log.Debug("baseDn:", ldapBaseDn) - ldapSearchDn := os.Getenv("LDAP_SEARCH_DN") + ldapSearchDn := config.LDAP().SearchDn if ldapSearchDn != "" { log.Debug("Search DN: ", ldapSearchDn) - ldapSearchPwd := os.Getenv("LDAP_SEARCH_PWD") + ldapSearchPwd := config.LDAP().SearchPwd err = ldap.Bind(ldapSearchDn, ldapSearchPwd) if err != nil { log.Debug("Bind search dn error", err) @@ -74,8 +74,8 @@ func (l *Auth) Authenticate(m models.AuthModel) (*models.User, error) { } } - attrName := os.Getenv("LDAP_UID") - filter := os.Getenv("LDAP_FILTER") + attrName := config.LDAP().UID + filter := config.LDAP().Filter if filter != "" { filter = "(&" + filter + "(" + attrName + "=" + m.Principal + "))" } else { @@ -83,7 +83,7 @@ func (l *Auth) Authenticate(m models.AuthModel) (*models.User, error) { } log.Debug("one or more filter", filter) - ldapScope := os.Getenv("LDAP_SCOPE") + ldapScope := config.LDAP().Scope var scope int if ldapScope == "1" { scope = openldap.LDAP_SCOPE_BASE diff --git a/src/ui/config/config.go b/src/ui/config/config.go index 241e12e99..783779c4d 100644 --- a/src/ui/config/config.go +++ b/src/ui/config/config.go @@ -12,6 +12,8 @@ See the License for the specific language governing permissions and limitations under the License. */ + +// Package config provides methods to get configurations required by code in src/ui package config import ( @@ -22,6 +24,7 @@ import ( "github.com/vmware/harbor/src/common/utils/log" ) +// LDAPSetting wraps the setting of an LDAP server type LDAPSetting struct { URL string BaseDn string @@ -50,7 +53,7 @@ func (up *uiParser) Parse(raw map[string]string, config map[string]interface{}) config["ldap"] = setting } config["auth_mode"] = mode - var tokenExpiration int = 30 //minutes + var tokenExpiration = 30 //minutes if len(raw["TOKEN_EXPIRATION"]) > 0 { i, err := strconv.Atoi(raw["TOKEN_EXPIRATION"]) if err != nil { @@ -67,7 +70,7 @@ func (up *uiParser) Parse(raw map[string]string, config map[string]interface{}) config["ui_secret"] = raw["UI_SECRET"] config["secret_key"] = raw["SECRET_KEY"] config["self_registration"] = raw["SELF_REGISTRATION"] != "off" - config["admin_create_project"] = strings.ToLower(raw["PROJECT_CREATE_RESTRICTION"]) == "adminonly" + config["admin_create_project"] = strings.ToLower(raw["PROJECT_CREATION_RESTRICTION"]) == "adminonly" registryURL := raw["REGISTRY_URL"] registryURL = strings.TrimRight(registryURL, "/") config["internal_registry_url"] = registryURL @@ -80,7 +83,7 @@ func (up *uiParser) Parse(raw map[string]string, config map[string]interface{}) var uiConfig *commonConfig.Config func init() { - uiKeys := []string{"AUTH_MODE", "LDAP_URL", "LDAP_BASE_DN", "LDAP_SEARCH_DN", "LDAP_SEARCH_PWD", "LDAP_UID", "LDAP_FILTER", "LDAP_SCOPE", "TOKEN_EXPIRATION", "HARBOR_ADMIN_PASSWORD", "EXT_REG_URL", "UI_SECRET", "SECRET_KEY", "SELF_REGISTRATION", "PROJECT_CREATE_RESTRICTION", "REGISTRY_URL", "JOB_SERVICE_URL"} + uiKeys := []string{"AUTH_MODE", "LDAP_URL", "LDAP_BASE_DN", "LDAP_SEARCH_DN", "LDAP_SEARCH_PWD", "LDAP_UID", "LDAP_FILTER", "LDAP_SCOPE", "TOKEN_EXPIRATION", "HARBOR_ADMIN_PASSWORD", "EXT_REG_URL", "UI_SECRET", "SECRET_KEY", "SELF_REGISTRATION", "PROJECT_CREATION_RESTRICTION", "REGISTRY_URL", "JOB_SERVICE_URL"} uiConfig = &commonConfig.Config{ Config: make(map[string]interface{}), Loader: &commonConfig.EnvConfigLoader{Keys: uiKeys}, @@ -91,45 +94,62 @@ func init() { } } +// Reload ... func Reload() error { return uiConfig.Load() } +// AuthMode ... func AuthMode() string { return uiConfig.Config["auth_mode"].(string) } + +// LDAP returns the setting of ldap server func LDAP() LDAPSetting { return uiConfig.Config["ldap"].(LDAPSetting) } +// TokenExpiration returns the token expiration time (in minute) func TokenExpiration() int { return uiConfig.Config["token_exp"].(int) } +// ExtRegistryURL returns the registry URL to exposed to external client func ExtRegistryURL() string { return uiConfig.Config["ext_reg_url"].(string) } +// UISecret returns the value of UI secret cookie, used for communication between UI and JobService func UISecret() string { return uiConfig.Config["ui_secret"].(string) } +// SecretKey returns the secret key to encrypt the password of target func SecretKey() string { return uiConfig.Config["secret_key"].(string) } +// SelfRegistration returns the enablement of self registration func SelfRegistration() bool { return uiConfig.Config["self_registration"].(bool) } +// InternalRegistryURL returns registry URL for internal communication between Harbor containers func InternalRegistryURL() string { return uiConfig.Config["internal_registry_url"].(string) } +// InternalJobServiceURL returns jobservice URL for internal communication between Harbor containers func InternalJobServiceURL() string { return uiConfig.Config["internal_jobservice_url"].(string) } +// InitialAdminPassword returns the initial password for administrator +func InitialAdminPassword() string { + return uiConfig.Config["admin_password"].(string) +} + +// OnlyAdminCreateProject returns the flag to restrict that only sys admin can create project func OnlyAdminCreateProject() bool { return uiConfig.Config["admin_create_project"].(bool) } diff --git a/src/ui/config/config_test.go b/src/ui/config/config_test.go index 43a57a788..a8b6df618 100644 --- a/src/ui/config/config_test.go +++ b/src/ui/config/config_test.go @@ -37,7 +37,7 @@ var ( uiSecret = "ffadsdfsdf" secretKey = "keykey" selfRegistration = "off" - projectCreationRestriction = "everyone" + projectCreationRestriction = "adminonly" internalRegistryURL = "http://registry:5000" jobServiceURL = "http://jobservice" ) @@ -58,7 +58,7 @@ func TestMain(m *testing.M) { os.Setenv("UI_SECRET", uiSecret) os.Setenv("SECRET_KEY", secretKey) os.Setenv("SELF_REGISTRATION", selfRegistration) - os.Setenv("CREATE_PROJECT_RESTRICTION", projectCreationRestriction) + os.Setenv("PROJECT_CREATION_RESTRICTION", projectCreationRestriction) os.Setenv("REGISTRY_URL", internalRegistryURL) os.Setenv("JOB_SERVICE_URL", jobServiceURL) @@ -132,7 +132,13 @@ func TestSecrets(t *testing.T) { } func TestProjectCreationRestrict(t *testing.T) { - if OnlyAdminCreateProject() { - t.Errorf("Expected OnlyAdminCreateProject to be false") + if !OnlyAdminCreateProject() { + t.Errorf("Expected OnlyAdminCreateProject to be true") + } +} + +func TestInitAdminPassword(t *testing.T) { + if InitialAdminPassword() != adminPassword { + t.Errorf("Expected adminPassword: %s, in fact: %s", adminPassword, InitialAdminPassword) } } diff --git a/src/ui/controllers/base.go b/src/ui/controllers/base.go index fdfaa6b6b..beaa10cf8 100644 --- a/src/ui/controllers/base.go +++ b/src/ui/controllers/base.go @@ -12,6 +12,7 @@ import ( "github.com/vmware/harbor/src/common/models" "github.com/vmware/harbor/src/common/utils/log" "github.com/vmware/harbor/src/ui/auth" + "github.com/vmware/harbor/src/ui/config" ) // BaseController wraps common methods such as i18n support, forward, which can be leveraged by other UI render controllers. @@ -99,7 +100,7 @@ func (b *BaseController) Prepare() { b.Data["CurLang"] = curLang.Name b.Data["RestLangs"] = restLangs - authMode := strings.ToLower(os.Getenv("AUTH_MODE")) + authMode := config.AuthMode() if authMode == "" { authMode = "db_auth" } @@ -116,11 +117,9 @@ func (b *BaseController) Prepare() { b.UseCompressedJS = false } - selfRegistration := strings.ToLower(os.Getenv("SELF_REGISTRATION")) - if selfRegistration == "on" { - b.SelfRegistration = true - } - b.Data["SelfRegistration"] = b.SelfRegistration + b.SelfRegistration = config.SelfRegistration() + + b.Data["SelfRegistration"] = config.SelfRegistration() } // Forward to setup layout and template for content for a page. diff --git a/src/ui/controllers/password.go b/src/ui/controllers/password.go index e026ab20f..c3dce0801 100644 --- a/src/ui/controllers/password.go +++ b/src/ui/controllers/password.go @@ -3,7 +3,6 @@ package controllers import ( "bytes" "net/http" - "os" "regexp" "text/template" diff --git a/src/ui/controllers/repository.go b/src/ui/controllers/repository.go index 58ad4dc7e..b85ad8782 100644 --- a/src/ui/controllers/repository.go +++ b/src/ui/controllers/repository.go @@ -1,6 +1,8 @@ package controllers -import "os" +import ( + "github.com/vmware/harbor/src/ui/config" +) // RepositoryController handles request to /repository type RepositoryController struct { @@ -9,6 +11,6 @@ type RepositoryController struct { // Get renders repository page func (rc *RepositoryController) Get() { - rc.Data["HarborRegUrl"] = os.Getenv("HARBOR_REG_URL") + rc.Data["HarborRegUrl"] = config.ExtRegistryURL() rc.Forward("page_title_repository", "repository.htm") } diff --git a/src/ui/main.go b/src/ui/main.go index d355a11cc..6c4427279 100644 --- a/src/ui/main.go +++ b/src/ui/main.go @@ -25,11 +25,12 @@ import ( "github.com/astaxie/beego" _ "github.com/astaxie/beego/session/redis" + "github.com/vmware/harbor/src/common/dao" + "github.com/vmware/harbor/src/common/models" "github.com/vmware/harbor/src/ui/api" _ "github.com/vmware/harbor/src/ui/auth/db" _ "github.com/vmware/harbor/src/ui/auth/ldap" - "github.com/vmware/harbor/src/common/dao" - "github.com/vmware/harbor/src/common/models" + "github.com/vmware/harbor/src/ui/config" ) const ( @@ -76,7 +77,7 @@ func main() { dao.InitDatabase() - if err := updateInitPassword(adminUserID, os.Getenv("HARBOR_ADMIN_PASSWORD")); err != nil { + if err := updateInitPassword(adminUserID, config.InitialAdminPassword()); err != nil { log.Error(err) } initRouters() diff --git a/src/ui/service/token/authutils.go b/src/ui/service/token/authutils.go index 63e884f5b..1e687365b 100644 --- a/src/ui/service/token/authutils.go +++ b/src/ui/service/token/authutils.go @@ -21,13 +21,12 @@ import ( "encoding/base64" "encoding/json" "fmt" - "os" - "strconv" "strings" "time" "github.com/vmware/harbor/src/common/dao" "github.com/vmware/harbor/src/common/utils/log" + "github.com/vmware/harbor/src/ui/config" "github.com/docker/distribution/registry/auth/token" "github.com/docker/libtrust" @@ -38,27 +37,10 @@ const ( privateKey = "/etc/ui/private_key.pem" ) -var ( - expiration = 30 //minutes -) +var expiration int //minutes func init() { - // TODO read it from config - expi := os.Getenv("TOKEN_EXPIRATION") - if len(expi) != 0 { - i, err := strconv.Atoi(expi) - if err != nil { - log.Errorf("failed to parse token expiration: %v, using default value: %d minutes", err, expiration) - return - } - - if i <= 0 { - log.Warningf("invalid token expiration, using default value: %d minutes", expiration) - return - } - - expiration = i - } + expiration = config.TokenExpiration() log.Infof("token expiration: %d minutes", expiration) } @@ -109,7 +91,7 @@ func FilterAccess(username string, a *token.ResourceActions) { repoLength := len(repoSplit) if repoLength > 1 { //Only check the permission when the requested image has a namespace, i.e. project var projectName string - registryURL := os.Getenv("HARBOR_REG_URL") + registryURL := config.ExtRegistryURL() if repoSplit[0] == registryURL { projectName = repoSplit[1] log.Infof("Detected Registry URL in Project Name. Assuming this is a notary request and setting Project Name as %s\n", projectName) diff --git a/src/ui/service/utils/utils.go b/src/ui/service/utils/utils.go index b64fb98cf..007b9b720 100644 --- a/src/ui/service/utils/utils.go +++ b/src/ui/service/utils/utils.go @@ -18,14 +18,14 @@ package utils import ( "net/http" - "os" "github.com/vmware/harbor/src/common/utils/log" + "github.com/vmware/harbor/src/ui/config" ) // VerifySecret verifies the UI_SECRET cookie in a http request. func VerifySecret(r *http.Request) bool { - secret := os.Getenv("UI_SECRET") + secret := config.UISecret() c, err := r.Cookie("uisecret") if err != nil { log.Warningf("Failed to get secret cookie, error: %v", err)