diff --git a/API/harbor/swagger.yaml b/API/harbor/swagger.yaml index f0f8ecc13..a01899ec2 100644 --- a/API/harbor/swagger.yaml +++ b/API/harbor/swagger.yaml @@ -5314,12 +5314,6 @@ definitions: with_clair: type: boolean description: If the Harbor instance is deployed with nested clair. - with_admiral: - type: boolean - description: If the Harbor instance is deployed with Admiral. - admiral_endpoint: - type: string - description: The url of the endpoint of admiral instance. registry_url: type: string description: The url of registry against which the docker command should be issued. diff --git a/make/photon/prepare/templates/core/env.jinja b/make/photon/prepare/templates/core/env.jinja index 19a8e6da6..c056a3f2b 100644 --- a/make/photon/prepare/templates/core/env.jinja +++ b/make/photon/prepare/templates/core/env.jinja @@ -24,7 +24,6 @@ HARBOR_ADMIN_PASSWORD={{harbor_admin_password}} MAX_JOB_WORKERS={{max_job_workers}} CORE_SECRET={{core_secret}} JOBSERVICE_SECRET={{jobservice_secret}} -ADMIRAL_URL={{admiral_url}} WITH_NOTARY={{with_notary}} WITH_CLAIR={{with_clair}} CLAIR_DB_PASSWORD={{clair_db_password}} diff --git a/make/photon/prepare/templates/docker_compose/docker-compose.yml.jinja b/make/photon/prepare/templates/docker_compose/docker-compose.yml.jinja index c132db764..1aabb6f8b 100644 --- a/make/photon/prepare/templates/docker_compose/docker-compose.yml.jinja +++ b/make/photon/prepare/templates/docker_compose/docker-compose.yml.jinja @@ -142,7 +142,6 @@ services: - SETUID volumes: - {{data_volume}}/ca_download/:/etc/core/ca/:z - - {{data_volume}}/psc/:/etc/core/token/:z - {{data_volume}}/:/data/:z - ./common/config/core/certificates/:/etc/core/certificates/:z - type: bind diff --git a/make/photon/prepare/utils/configs.py b/make/photon/prepare/utils/configs.py index 9d2e91413..e005ff1b7 100644 --- a/make/photon/prepare/utils/configs.py +++ b/make/photon/prepare/utils/configs.py @@ -310,9 +310,6 @@ def parse_yaml_config(config_file_path, with_notary, with_clair, with_chartmuseu # auto generated secret string for core config_dict['core_secret'] = generate_random_string(16) - # Admiral configs - config_dict['admiral_url'] = configs.get("admiral_url") or "" - # UAA configs config_dict['uaa'] = configs.get('uaa') or {} diff --git a/make/photon/prepare/utils/core.py b/make/photon/prepare/utils/core.py index f6fff0d55..a1dd7aa46 100644 --- a/make/photon/prepare/utils/core.py +++ b/make/photon/prepare/utils/core.py @@ -11,11 +11,9 @@ core_conf_template_path = os.path.join(templates_dir, "core", "app.conf.jinja") core_conf = os.path.join(config_dir, "core", "app.conf") ca_download_dir = os.path.join(data_dir, 'ca_download') -psc_dir = os.path.join(data_dir, 'psc') def prepare_core(config_dict, with_notary, with_clair, with_chartmuseum): - prepare_dir(psc_dir, uid=DEFAULT_UID, gid=DEFAULT_GID) prepare_dir(ca_download_dir, uid=DEFAULT_UID, gid=DEFAULT_GID) prepare_dir(core_config_dir) # Render Core diff --git a/src/common/config/metadata/metadata_test.go b/src/common/config/metadata/metadata_test.go index a21660656..6d0bcd6bf 100644 --- a/src/common/config/metadata/metadata_test.go +++ b/src/common/config/metadata/metadata_test.go @@ -15,21 +15,21 @@ package metadata import ( - "github.com/goharbor/harbor/src/common" "testing" + + "github.com/goharbor/harbor/src/common" ) func TestCfgMetaData_InitFromArray(t *testing.T) { testArray := []Item{ {Scope: SystemScope, Group: BasicGroup, EnvKey: "HARBOR_ADMIN_PASSWORD", DefaultValue: "", Name: common.AdminInitialPassword, ItemType: &PasswordType{}, Editable: true}, - {Scope: SystemScope, Group: BasicGroup, EnvKey: "ADMIRAL_URL", DefaultValue: "NA", Name: common.AdmiralEndpoint, ItemType: &StringType{}, Editable: false}, {Scope: UserScope, Group: BasicGroup, EnvKey: "AUTH_MODE", DefaultValue: "db_auth", Name: common.AUTHMode, ItemType: &StringType{}, Editable: false}, {Scope: SystemScope, Group: BasicGroup, EnvKey: "CHART_REPOSITORY_URL", DefaultValue: "http://chartmuseum:9999", Name: common.ChartRepoURL, ItemType: &StringType{}, Editable: false}, } curInst := Instance() curInst.initFromArray(testArray) - if len(metaDataInstance.metaMap) != 4 { + if len(metaDataInstance.metaMap) != 3 { t.Errorf("Can not initial metadata, size %v", len(metaDataInstance.metaMap)) } item, ok := curInst.GetByName(common.AdminInitialPassword) diff --git a/src/common/config/metadata/metadatalist.go b/src/common/config/metadata/metadatalist.go index 85a5dfa4e..ff268d6a6 100644 --- a/src/common/config/metadata/metadatalist.go +++ b/src/common/config/metadata/metadatalist.go @@ -62,7 +62,6 @@ var ( ConfigList = []Item{ {Name: common.AdminInitialPassword, Scope: SystemScope, Group: BasicGroup, EnvKey: "HARBOR_ADMIN_PASSWORD", DefaultValue: "", ItemType: &PasswordType{}, Editable: true}, - {Name: common.AdmiralEndpoint, Scope: SystemScope, Group: BasicGroup, EnvKey: "ADMIRAL_URL", DefaultValue: "", ItemType: &StringType{}, Editable: false}, {Name: common.AUTHMode, Scope: UserScope, Group: BasicGroup, EnvKey: "AUTH_MODE", DefaultValue: "db_auth", ItemType: &AuthModeType{}, Editable: false}, {Name: common.ChartRepoURL, Scope: SystemScope, Group: BasicGroup, EnvKey: "CHART_REPOSITORY_URL", DefaultValue: "http://chartmuseum:9999", ItemType: &StringType{}, Editable: false}, diff --git a/src/common/const.go b/src/common/const.go index 9ae956d11..d890da7e2 100755 --- a/src/common/const.go +++ b/src/common/const.go @@ -87,7 +87,6 @@ const ( MaxJobWorkers = "max_job_workers" TokenExpiration = "token_expiration" AdminInitialPassword = "admin_initial_password" - AdmiralEndpoint = "admiral_url" WithNotary = "with_notary" WithClair = "with_clair" ScanAllPolicy = "scan_all_policy" diff --git a/src/common/dao/repository.go b/src/common/dao/repository.go index abb859525..ae1d39a58 100644 --- a/src/common/dao/repository.go +++ b/src/common/dao/repository.go @@ -183,8 +183,6 @@ func repositoryQueryConditions(query ...*models.RepositoryQuery) (string, []inte } if len(q.ProjectName) > 0 { - // use "like" rather than "table joining" because that - // in integration mode the projects are saved in Admiral side sql += `and r.name like ? ` params = append(params, q.ProjectName+"/%") } diff --git a/src/common/security/admiral/authcontext/authcontext.go b/src/common/security/admiral/authcontext/authcontext.go deleted file mode 100644 index efc8cf881..000000000 --- a/src/common/security/admiral/authcontext/authcontext.go +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright 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 authcontext - -import ( - "bytes" - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "strconv" - "strings" - - "github.com/goharbor/harbor/src/common" - commonhttp "github.com/goharbor/harbor/src/common/http" - "github.com/goharbor/harbor/src/common/models" - "github.com/goharbor/harbor/src/common/utils" - "github.com/goharbor/harbor/src/common/utils/log" -) - -const ( - // AuthTokenHeader is the key of auth token header - AuthTokenHeader = "x-xenon-auth-token" - sysAdminRole = "CLOUD_ADMIN" - projectAdminRole = "PROJECT_ADMIN" - developerRole = "PROJECT_MEMBER" - guestRole = "PROJECT_VIEWER" -) - -type project struct { - SelfLink string `json:"documentSelfLink"` - Name string `json:"name"` - Roles []string `json:"roles"` - Properties map[string]string `json:"customProperties"` -} - -// AuthContext ... -type AuthContext struct { - PrincipalID string `json:"id"` - Name string `json:"name"` - Email string `json:"email"` - Roles []string `json:"roles"` - Projects []*project `json:"projects"` -} - -// IsSysAdmin ... -func (a *AuthContext) IsSysAdmin() bool { - for _, role := range a.Roles { - if role == sysAdminRole { - return true - } - } - return false -} - -// GetProjectRoles ... -func (a *AuthContext) GetProjectRoles(projectIDOrName interface{}) []int { - id, name, err := utils.ParseProjectIDOrName(projectIDOrName) - if err != nil { - log.Errorf("failed to parse project ID or name: %v", err) - return []int{} - } - - roles := []string{} - for _, project := range a.Projects { - p := convertProject(project) - if id != 0 && p.ProjectID == id || len(name) > 0 && p.Name == name { - roles = append(roles, project.Roles...) - break - } - } - - return convertRoles(roles) -} - -// GetMyProjects returns all projects which the user is a member of -func (a *AuthContext) GetMyProjects() []*models.Project { - projects := []*models.Project{} - for _, project := range a.Projects { - projects = append(projects, convertProject(project)) - } - return projects -} - -// convert project returned by Admiral to project used in Harbor -func convertProject(p *project) *models.Project { - project := &models.Project{ - Name: p.Name, - } - - index := "" - if p.Properties != nil { - index = p.Properties["__projectIndex"] - } - - if len(index) == 0 { - log.Errorf("property __projectIndex not found when parsing project") - return project - } - - id, err := strconv.ParseInt(index, 10, 64) - if err != nil { - log.Errorf("failed to parse __projectIndex %s: %v", index, err) - return project - } - - project.ProjectID = id - return project -} - -// convert roles defined by Admiral to roles used in Harbor -func convertRoles(roles []string) []int { - list := []int{} - for _, role := range roles { - switch role { - case projectAdminRole: - list = append(list, common.RoleProjectAdmin) - case developerRole: - list = append(list, common.RoleDeveloper) - case guestRole: - list = append(list, common.RoleGuest) - default: - log.Warningf("unknow role: %s", role) - } - } - - return list -} - -// GetAuthCtx returns the auth context of the current user -func GetAuthCtx(client *http.Client, url, token string) (*AuthContext, error) { - req, err := http.NewRequest(http.MethodGet, buildCurrentUserAuthCtxURL(url), nil) - if err != nil { - return nil, err - } - - req.Header.Add(AuthTokenHeader, token) - - return send(client, req) -} - -// Login with credential and returns auth context and error -func Login(client *http.Client, url, username, password, token string) (*AuthContext, error) { - data, err := json.Marshal(&struct { - Password string `json:"password"` - }{ - Password: password, - }) - if err != nil { - return nil, err - } - - req, err := http.NewRequest(http.MethodPost, buildLoginURL(url, username), bytes.NewBuffer(data)) - if err != nil { - return nil, err - } - - req.Header.Add(AuthTokenHeader, token) - - return send(client, req) -} - -func send(client *http.Client, req *http.Request) (*AuthContext, error) { - resp, err := client.Do(req) - if err != nil { - log.Debugf("\"%s %s\" failed", req.Method, req.URL.String()) - return nil, err - } - defer resp.Body.Close() - log.Debugf("\"%s %s\" %d", req.Method, req.URL.String(), resp.StatusCode) - - data, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, err - } - - if resp.StatusCode != http.StatusOK { - return nil, &commonhttp.Error{ - Code: resp.StatusCode, - Message: string(data), - } - } - - ctx := &AuthContext{} - if err = json.Unmarshal(data, ctx); err != nil { - return nil, err - } - - return ctx, nil -} - -func buildCurrentUserAuthCtxURL(url string) string { - return strings.TrimRight(url, "/") + "/auth/session" -} - -func buildLoginURL(url, principalID string) string { - return fmt.Sprintf("%s/auth/idm/principals/%s/security-context", - strings.TrimRight(url, "/"), principalID) -} diff --git a/src/common/security/admiral/authcontext/authcontext_test.go b/src/common/security/admiral/authcontext/authcontext_test.go deleted file mode 100644 index a96870966..000000000 --- a/src/common/security/admiral/authcontext/authcontext_test.go +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 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 authcontext - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestIsSysAdmin(t *testing.T) { - // nil roles - ctx := &AuthContext{} - assert.False(t, ctx.IsSysAdmin()) - - // has no admin role - ctx = &AuthContext{ - Roles: []string{projectAdminRole, developerRole, guestRole}, - } - assert.False(t, ctx.IsSysAdmin()) - - // has admin role - ctx = &AuthContext{ - Roles: []string{sysAdminRole}, - } - assert.True(t, ctx.IsSysAdmin()) -} - -func TestGetProjectRoles(t *testing.T) { - ctx := &AuthContext{ - Projects: []*project{ - { - Name: "project", - Roles: []string{projectAdminRole, developerRole, guestRole}, - Properties: map[string]string{"__projectIndex": "9"}, - }, - }, - } - - // test with name - roles := ctx.GetProjectRoles("project") - assert.Equal(t, 3, len(roles)) - - // test with ID - roles = ctx.GetProjectRoles(9) - assert.Equal(t, 3, len(roles)) -} - -func TestGetMyProjects(t *testing.T) { - ctx := &AuthContext{ - Projects: []*project{ - { - Name: "project1", - Roles: []string{projectAdminRole}, - }, - { - Name: "project2", - Roles: []string{developerRole}, - }, - }, - } - - projects := ctx.GetMyProjects() - assert.Equal(t, 2, len(projects)) -} diff --git a/src/common/security/admiral/context.go b/src/common/security/admiral/context.go deleted file mode 100644 index fcc0a069f..000000000 --- a/src/common/security/admiral/context.go +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 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 admiral - -import ( - "github.com/goharbor/harbor/src/common/models" - "github.com/goharbor/harbor/src/common/rbac" - "github.com/goharbor/harbor/src/common/rbac/project" - "github.com/goharbor/harbor/src/common/security/admiral/authcontext" - "github.com/goharbor/harbor/src/core/promgr" -) - -// SecurityContext implements security.Context interface based on -// auth context and project manager -type SecurityContext struct { - ctx *authcontext.AuthContext - pm promgr.ProjectManager -} - -// NewSecurityContext ... -func NewSecurityContext(ctx *authcontext.AuthContext, pm promgr.ProjectManager) *SecurityContext { - return &SecurityContext{ - ctx: ctx, - pm: pm, - } -} - -// IsAuthenticated returns true if the user has been authenticated -func (s *SecurityContext) IsAuthenticated() bool { - if s.ctx == nil { - return false - } - return len(s.ctx.PrincipalID) > 0 -} - -// GetUsername returns the username of the authenticated user -// It returns null if the user has not been authenticated -func (s *SecurityContext) GetUsername() string { - if !s.IsAuthenticated() { - return "" - } - return s.ctx.PrincipalID -} - -// IsSysAdmin returns whether the authenticated user is system admin -// It returns false if the user has not been authenticated -func (s *SecurityContext) IsSysAdmin() bool { - if !s.IsAuthenticated() { - return false - } - - return s.ctx.IsSysAdmin() -} - -// IsSolutionUser ... -func (s *SecurityContext) IsSolutionUser() bool { - return false -} - -// Can returns whether the user can do action on resource -func (s *SecurityContext) Can(action rbac.Action, resource rbac.Resource) bool { - ns, err := resource.GetNamespace() - if err == nil { - switch ns.Kind() { - case "project": - projectID := ns.Identity().(int64) - isPublicProject, _ := s.pm.IsPublic(projectID) - projectNamespace := rbac.NewProjectNamespace(projectID, isPublicProject) - user := project.NewUser(s, projectNamespace, s.GetProjectRoles(projectID)...) - return rbac.HasPermission(user, resource, action) - } - } - - return false -} - -// GetMyProjects ... -func (s *SecurityContext) GetMyProjects() ([]*models.Project, error) { - return s.ctx.GetMyProjects(), nil -} - -// GetProjectRoles ... -func (s *SecurityContext) GetProjectRoles(projectIDOrName interface{}) []int { - if !s.IsAuthenticated() || projectIDOrName == nil { - return []int{} - } - - return s.ctx.GetProjectRoles(projectIDOrName) -} diff --git a/src/common/security/admiral/context_test.go b/src/common/security/admiral/context_test.go deleted file mode 100644 index ec624eb10..000000000 --- a/src/common/security/admiral/context_test.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 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 admiral diff --git a/src/common/utils/ldap/ldap_test.go b/src/common/utils/ldap/ldap_test.go index e7b3344a6..4eb21bb8e 100644 --- a/src/common/utils/ldap/ldap_test.go +++ b/src/common/utils/ldap/ldap_test.go @@ -66,7 +66,6 @@ var defaultConfigWithVerifyCert = map[string]interface{}{ common.MaxJobWorkers: 3, common.TokenExpiration: 30, common.AdminInitialPassword: "password", - common.AdmiralEndpoint: "http://www.vmware.com", common.WithNotary: false, common.WithClair: false, } @@ -85,9 +84,7 @@ func TestMain(m *testing.M) { log.Fatalf("failed to set env %s: %v", "KEY_PATH", err) } - if err := uiConfig.Init(); err != nil { - log.Fatalf("failed to initialize configurations: %v", err) - } + uiConfig.Init() uiConfig.Upload(ldapTestConfig) diff --git a/src/common/utils/notary/helper_test.go b/src/common/utils/notary/helper_test.go index a0c2a1f34..56bd0b958 100644 --- a/src/common/utils/notary/helper_test.go +++ b/src/common/utils/notary/helper_test.go @@ -30,7 +30,6 @@ import ( "testing" "github.com/goharbor/harbor/src/common" - "github.com/goharbor/harbor/src/common/utils/log" ) var endpoint = "10.117.4.142" @@ -45,9 +44,7 @@ func TestMain(m *testing.M) { common.TokenExpiration: 30, } - if err := config.Init(); err != nil { - log.Fatalf("failed to initialize config: %v", err) - } + config.Init() test.InitDatabaseFromEnv() config.Upload(defaultConfig) notaryCachePath = "/tmp/notary" diff --git a/src/common/utils/test/config.go b/src/common/utils/test/config.go index 2ea050d07..6569b1045 100644 --- a/src/common/utils/test/config.go +++ b/src/common/utils/test/config.go @@ -54,7 +54,6 @@ var defaultConfig = map[string]interface{}{ common.MaxJobWorkers: 3, common.TokenExpiration: 30, common.AdminInitialPassword: "password", - common.AdmiralEndpoint: "", common.WithNotary: false, common.WithClair: false, common.ClairDBUsername: "postgres", diff --git a/src/core/api/project.go b/src/core/api/project.go index 791d0834d..6ed8ee4cc 100644 --- a/src/core/api/project.go +++ b/src/core/api/project.go @@ -98,17 +98,11 @@ func (p *ProjectAPI) Post() { p.SendUnAuthorizedError(errors.New("Unauthorized")) return } - var onlyAdmin bool - var err error - if config.WithAdmiral() { - onlyAdmin = true - } else { - onlyAdmin, err = config.OnlyAdminCreateProject() - if err != nil { - log.Errorf("failed to determine whether only admin can create projects: %v", err) - p.SendInternalServerError(fmt.Errorf("failed to determine whether only admin can create projects: %v", err)) - return - } + onlyAdmin, err := config.OnlyAdminCreateProject() + if err != nil { + log.Errorf("failed to determine whether only admin can create projects: %v", err) + p.SendInternalServerError(fmt.Errorf("failed to determine whether only admin can create projects: %v", err)) + return } if onlyAdmin && !(p.SecurityCtx.IsSysAdmin() || p.SecurityCtx.IsSolutionUser()) { @@ -400,46 +394,43 @@ func (p *ProjectAPI) List() { query.Public = &pub } - // standalone, filter projects according to the privilleges of the user first - if !config.WithAdmiral() { - var projects []*models.Project - if !p.SecurityCtx.IsAuthenticated() { - // not login, only get public projects + var projects []*models.Project + if !p.SecurityCtx.IsAuthenticated() { + // not login, only get public projects + pros, err := p.ProjectMgr.GetPublic() + if err != nil { + p.SendInternalServerError(fmt.Errorf("failed to get public projects: %v", err)) + return + } + projects = []*models.Project{} + projects = append(projects, pros...) + } else { + if !(p.SecurityCtx.IsSysAdmin() || p.SecurityCtx.IsSolutionUser()) { + projects = []*models.Project{} + // login, but not system admin or solution user, get public projects and + // projects that the user is member of pros, err := p.ProjectMgr.GetPublic() if err != nil { p.SendInternalServerError(fmt.Errorf("failed to get public projects: %v", err)) return } - projects = []*models.Project{} projects = append(projects, pros...) - } else { - if !(p.SecurityCtx.IsSysAdmin() || p.SecurityCtx.IsSolutionUser()) { - projects = []*models.Project{} - // login, but not system admin or solution user, get public projects and - // projects that the user is member of - pros, err := p.ProjectMgr.GetPublic() - if err != nil { - p.SendInternalServerError(fmt.Errorf("failed to get public projects: %v", err)) - return - } - projects = append(projects, pros...) - mps, err := p.SecurityCtx.GetMyProjects() - if err != nil { - p.SendInternalServerError(fmt.Errorf("failed to list projects: %v", err)) - return - } - projects = append(projects, mps...) + mps, err := p.SecurityCtx.GetMyProjects() + if err != nil { + p.SendInternalServerError(fmt.Errorf("failed to list projects: %v", err)) + return } + projects = append(projects, mps...) } - // Query projects by user group + } + // Query projects by user group - if projects != nil { - projectIDs := []int64{} - for _, project := range projects { - projectIDs = append(projectIDs, project.ProjectID) - } - query.ProjectIDs = projectIDs + if projects != nil { + projectIDs := []int64{} + for _, project := range projects { + projectIDs = append(projectIDs, project.ProjectID) } + query.ProjectIDs = projectIDs } result, err := p.ProjectMgr.List(query) diff --git a/src/core/api/systeminfo.go b/src/core/api/systeminfo.go index f1f7f311b..8da90ec31 100644 --- a/src/core/api/systeminfo.go +++ b/src/core/api/systeminfo.go @@ -52,8 +52,6 @@ type Storage struct { // GeneralInfo wraps common systeminfo for anonymous request type GeneralInfo struct { WithNotary bool `json:"with_notary"` - WithAdmiral bool `json:"with_admiral"` - AdmiralEndpoint string `json:"admiral_endpoint"` AuthMode string `json:"auth_mode"` AuthProxySettings *models.HTTPAuthProxy `json:"authproxy_settings,omitempty"` RegistryURL string `json:"registry_url"` @@ -135,8 +133,6 @@ func (sia *SystemInfoAPI) GetGeneralInfo() { enableCADownload := caStatErr == nil && strings.HasPrefix(extURL, "https://") harborVersion := sia.getVersion() info := GeneralInfo{ - AdmiralEndpoint: utils.SafeCastString(cfg[common.AdmiralEndpoint]), - WithAdmiral: config.WithAdmiral(), WithNotary: config.WithNotary(), AuthMode: utils.SafeCastString(cfg[common.AUTHMode]), ProjectCreationRestrict: utils.SafeCastString(cfg[common.ProjectCreationRestriction]), diff --git a/src/core/auth/db/db_test.go b/src/core/auth/db/db_test.go index ec3ffd2b4..b76d8e08f 100644 --- a/src/core/auth/db/db_test.go +++ b/src/core/auth/db/db_test.go @@ -63,9 +63,7 @@ func TestMain(m *testing.M) { log.Fatalf("failed to set env %s: %v", "KEY_PATH", err) } - if err := coreConfig.Init(); err != nil { - log.Fatalf("failed to initialize configurations: %v", err) - } + coreConfig.Init() config.Upload(testConfig) retCode := m.Run() diff --git a/src/core/auth/uaa/uaa_test.go b/src/core/auth/uaa/uaa_test.go index a62bd7d7d..624a32320 100644 --- a/src/core/auth/uaa/uaa_test.go +++ b/src/core/auth/uaa/uaa_test.go @@ -28,12 +28,9 @@ import ( func TestMain(m *testing.M) { test.InitDatabaseFromEnv() - err := config.Init() - if err != nil { - panic(err) - } + config.Init() - err = dao.ClearTable("project_member") + err := dao.ClearTable("project_member") if err != nil { panic(err) } diff --git a/src/core/config/config.go b/src/core/config/config.go index fe0e2b7a4..e73c0babf 100755 --- a/src/core/config/config.go +++ b/src/core/config/config.go @@ -18,12 +18,7 @@ package config import ( - "crypto/tls" - "crypto/x509" "errors" - "fmt" - "io/ioutil" - "net/http" "os" "strings" @@ -33,14 +28,11 @@ import ( "github.com/goharbor/harbor/src/common/secret" "github.com/goharbor/harbor/src/common/utils/log" "github.com/goharbor/harbor/src/core/promgr" - "github.com/goharbor/harbor/src/core/promgr/pmsdriver" - "github.com/goharbor/harbor/src/core/promgr/pmsdriver/admiral" "github.com/goharbor/harbor/src/core/promgr/pmsdriver/local" ) const ( defaultKeyPath = "/etc/core/key" - defaultTokenFilePath = "/etc/core/token/tokens.properties" defaultRegistryTokenPrivateKeyPath = "/etc/core/private_key.pem" // SessionCookieName is the name of the cookie for session ID @@ -53,18 +45,13 @@ var ( // GlobalProjectMgr is initialized based on the deploy mode GlobalProjectMgr promgr.ProjectManager keyProvider comcfg.KeyProvider - // AdmiralClient is initialized only under integration deploy mode - // and can be passed to project manager as a parameter - AdmiralClient *http.Client - // TokenReader is used in integration mode to read token - TokenReader admiral.TokenReader // defined as a var for testing. defaultCACertPath = "/etc/core/ca/ca.crt" cfgMgr *comcfg.CfgManager ) // Init configurations -func Init() error { +func Init() { // init key provider initKeyProvider() @@ -73,13 +60,9 @@ func Init() error { log.Info("init secret store") // init secret store initSecretStore() - log.Info("init project manager based on deploy mode") - // init project manager based on deploy mode - if err := initProjectManager(); err != nil { - log.Errorf("Failed to initialise project manager, error: %v", err) - return err - } - return nil + log.Info("init project manager") + // init project manager + initProjectManager() } // InitWithSettings init config with predefined configs, and optionally overwrite the keyprovider @@ -108,46 +91,9 @@ func initSecretStore() { SecretStore = secret.NewStore(m) } -func initProjectManager() error { - var driver pmsdriver.PMSDriver - if WithAdmiral() { - log.Debugf("Initialising Admiral client with certificate: %s", defaultCACertPath) - content, err := ioutil.ReadFile(defaultCACertPath) - if err != nil { - return err - } - pool := x509.NewCertPool() - if ok := pool.AppendCertsFromPEM(content); !ok { - return fmt.Errorf("failed to append cert content into cert worker") - } - AdmiralClient = &http.Client{ - Transport: &http.Transport{ - Proxy: http.ProxyFromEnvironment, - TLSClientConfig: &tls.Config{ - RootCAs: pool, - }, - }, - } - - // integration with admiral - log.Info("initializing the project manager based on PMS...") - path := os.Getenv("SERVICE_TOKEN_FILE_PATH") - if len(path) == 0 { - path = defaultTokenFilePath - } - log.Infof("service token file path: %s", path) - TokenReader = &admiral.FileTokenReader{ - Path: path, - } - driver = admiral.NewDriver(AdmiralClient, AdmiralEndpoint(), TokenReader) - } else { - // standalone - log.Info("initializing the project manager based on local database...") - driver = local.NewDriver() - } - GlobalProjectMgr = promgr.NewDefaultProjectManager(driver, true) - return nil - +func initProjectManager() { + log.Info("initializing the project manager based on local database...") + GlobalProjectMgr = promgr.NewDefaultProjectManager(local.NewDriver(), true) } // GetCfgManager return the current config manager @@ -393,19 +339,6 @@ func ClairAdapterEndpoint() string { return cfgMgr.Get(common.ClairAdapterURL).GetString() } -// AdmiralEndpoint returns the URL of admiral, if Harbor is not deployed with admiral it should return an empty string. -func AdmiralEndpoint() string { - if cfgMgr.Get(common.AdmiralEndpoint).GetString() == "NA" { - return "" - } - return cfgMgr.Get(common.AdmiralEndpoint).GetString() -} - -// WithAdmiral returns a bool to indicate if Harbor's deployed with admiral. -func WithAdmiral() bool { - return len(AdmiralEndpoint()) > 0 -} - // UAASettings returns the UAASettings to access UAA service. func UAASettings() (*models.UAASettings, error) { err := cfgMgr.Load() diff --git a/src/core/config/config_test.go b/src/core/config/config_test.go index b4e5f4bd3..8312509b0 100644 --- a/src/core/config/config_test.go +++ b/src/core/config/config_test.go @@ -32,7 +32,6 @@ func TestConfig(t *testing.T) { dao.PrepareTestData([]string{"delete from properties where k='scan_all_policy'"}, []string{}) defaultCACertPath = path.Join(currPath(), "test", "ca.crt") c := map[string]interface{}{ - common.AdmiralEndpoint: "https://www.vmware.com", common.WithClair: false, common.WithChartMuseum: false, common.WithNotary: false, @@ -59,9 +58,7 @@ func TestConfig(t *testing.T) { } defer os.Setenv("TOKEN_PRIVATE_KEY_PATH", oriKeyPath) - if err := Init(); err != nil { - t.Fatalf("failed to initialize configurations: %v", err) - } + Init() if err := Load(); err != nil { t.Fatalf("failed to load configurations: %v", err) @@ -143,7 +140,6 @@ func TestConfig(t *testing.T) { t.Fatalf("failed to get clair DB %v", err) } defaultConfig := test.GetDefaultConfigMap() - defaultConfig[common.AdmiralEndpoint] = "http://www.vmware.com" Upload(defaultConfig) assert.Equal(defaultConfig[common.ClairDB], clairDB.Database) assert.Equal(defaultConfig[common.ClairDBUsername], clairDB.Username) @@ -160,15 +156,9 @@ func TestConfig(t *testing.T) { if WithClair() { t.Errorf("WithClair should be false") } - if !WithAdmiral() { - t.Errorf("WithAdmiral should be true") - } if ReadOnly() { t.Errorf("ReadOnly should be false") } - if AdmiralEndpoint() != "http://www.vmware.com" { - t.Errorf("Unexpected admiral endpoint: %s", AdmiralEndpoint()) - } extURL, err := ExtURL() if err != nil { diff --git a/src/core/filter/security.go b/src/core/filter/security.go index 86c1a568f..3572133e8 100644 --- a/src/core/filter/security.go +++ b/src/core/filter/security.go @@ -17,9 +17,8 @@ package filter import ( "context" "fmt" - "github.com/goharbor/harbor/src/common/utils/oidc" "net/http" - "regexp" + "strings" beegoctx "github.com/astaxie/beego/context" "github.com/docker/distribution/reference" @@ -29,18 +28,14 @@ import ( "github.com/goharbor/harbor/src/common/models" secstore "github.com/goharbor/harbor/src/common/secret" "github.com/goharbor/harbor/src/common/security" - admr "github.com/goharbor/harbor/src/common/security/admiral" - "github.com/goharbor/harbor/src/common/security/admiral/authcontext" "github.com/goharbor/harbor/src/common/security/local" robotCtx "github.com/goharbor/harbor/src/common/security/robot" "github.com/goharbor/harbor/src/common/security/secret" "github.com/goharbor/harbor/src/common/utils/log" + "github.com/goharbor/harbor/src/common/utils/oidc" "github.com/goharbor/harbor/src/core/auth" "github.com/goharbor/harbor/src/core/config" "github.com/goharbor/harbor/src/core/promgr" - "github.com/goharbor/harbor/src/core/promgr/pmsdriver/admiral" - "strings" - "github.com/goharbor/harbor/src/pkg/authproxy" "github.com/goharbor/harbor/src/pkg/robot" pkg_token "github.com/goharbor/harbor/src/pkg/token" @@ -95,17 +90,6 @@ var ( // Init ReqCtxMofiers list func Init() { - // integration with admiral - if config.WithAdmiral() { - reqCtxModifiers = []ReqCtxModifier{ - &secretReqCtxModifier{config.SecretStore}, - &tokenReqCtxModifier{}, - &basicAuthReqCtxModifier{}, - &unauthorizedReqCtxModifier{}} - return - } - - // standalone reqCtxModifiers = []ReqCtxModifier{ &configCtxModifier{}, &secretReqCtxModifier{config.SecretStore}, @@ -375,53 +359,6 @@ func (b *basicAuthReqCtxModifier) Modify(ctx *beegoctx.Context) bool { } log.Debug("got user information via basic auth") - // integration with admiral - if config.WithAdmiral() { - // Can't get a token from Admiral's login API, we can only - // create a project manager with the token of the solution user. - // That way may cause some wrong permission promotion in some API - // calls, so we just handle the requests which are necessary - match := false - var err error - path := ctx.Request.URL.Path - for _, pattern := range basicAuthReqPatterns { - match, err = regexp.MatchString(pattern.path, path) - if err != nil { - log.Errorf("failed to match %s with pattern %s", path, pattern) - continue - } - if match { - break - } - } - if !match { - log.Debugf("basic auth is not supported for request %s %s, skip", - ctx.Request.Method, ctx.Request.URL.Path) - return false - } - - token, err := config.TokenReader.ReadToken() - if err != nil { - log.Errorf("failed to read solution user token: %v", err) - return false - } - authCtx, err := authcontext.Login(config.AdmiralClient, - config.AdmiralEndpoint(), username, password, token) - if err != nil { - log.Errorf("failed to authenticate %s: %v", username, err) - return false - } - - log.Debug("using global project manager...") - pm := config.GlobalProjectMgr - log.Debug("creating admiral security context...") - securCtx := admr.NewSecurityContext(authCtx, pm) - - setSecurCtxAndPM(ctx.Request, securCtx, pm) - return true - } - - // standalone user, err := auth.Login(models.AuthModel{ Principal: username, Password: password, @@ -466,61 +403,15 @@ func (s *sessionReqCtxModifier) Modify(ctx *beegoctx.Context) bool { return true } -type tokenReqCtxModifier struct{} - -func (t *tokenReqCtxModifier) Modify(ctx *beegoctx.Context) bool { - token := ctx.Request.Header.Get(authcontext.AuthTokenHeader) - if len(token) == 0 { - return false - } - - log.Debug("got token from request") - - authContext, err := authcontext.GetAuthCtx(config.AdmiralClient, - config.AdmiralEndpoint(), token) - if err != nil { - log.Errorf("failed to get auth context: %v", err) - return false - } - - log.Debug("creating PMS project manager...") - driver := admiral.NewDriver(config.AdmiralClient, - config.AdmiralEndpoint(), &admiral.RawTokenReader{ - Token: token, - }) - - pm := promgr.NewDefaultProjectManager(driver, false) - - log.Debug("creating admiral security context...") - securCtx := admr.NewSecurityContext(authContext, pm) - setSecurCtxAndPM(ctx.Request, securCtx, pm) - - return true -} - // use this one as the last modifier in the modifier list for unauthorized request type unauthorizedReqCtxModifier struct{} func (u *unauthorizedReqCtxModifier) Modify(ctx *beegoctx.Context) bool { log.Debug("user information is nil") - - var securCtx security.Context - var pm promgr.ProjectManager - if config.WithAdmiral() { - // integration with admiral - log.Debug("creating PMS project manager...") - driver := admiral.NewDriver(config.AdmiralClient, - config.AdmiralEndpoint(), nil) - pm = promgr.NewDefaultProjectManager(driver, false) - log.Debug("creating admiral security context...") - securCtx = admr.NewSecurityContext(nil, pm) - } else { - // standalone - log.Debug("using local database project manager") - pm = config.GlobalProjectMgr - log.Debug("creating local database security context...") - securCtx = local.NewSecurityContext(nil, pm) - } + log.Debug("using local database project manager") + pm := config.GlobalProjectMgr + log.Debug("creating local database security context...") + securCtx := local.NewSecurityContext(nil, pm) setSecurCtxAndPM(ctx.Request, securCtx, pm) return true } diff --git a/src/core/main.go b/src/core/main.go index 524af6f0e..53a9a7f65 100755 --- a/src/core/main.go +++ b/src/core/main.go @@ -175,9 +175,7 @@ func main() { beego.AddTemplateExt("htm") log.Info("initializing configurations...") - if err := config.Init(); err != nil { - log.Fatalf("failed to initialize configurations: %v", err) - } + config.Init() log.Info("configurations initialization completed") token.InitCreators() database, err := config.Database() diff --git a/src/core/middlewares/contenttrust/handler_test.go b/src/core/middlewares/contenttrust/handler_test.go index d7767cac1..910f6f00b 100644 --- a/src/core/middlewares/contenttrust/handler_test.go +++ b/src/core/middlewares/contenttrust/handler_test.go @@ -15,20 +15,19 @@ package contenttrust import ( + "net/http/httptest" + "os" + "testing" + "github.com/goharbor/harbor/src/common" notarytest "github.com/goharbor/harbor/src/common/utils/notary/test" "github.com/goharbor/harbor/src/core/config" "github.com/goharbor/harbor/src/core/middlewares/util" "github.com/stretchr/testify/assert" - "net/http/httptest" - "os" - "testing" ) var endpoint = "10.117.4.142" var notaryServer *httptest.Server - -var admiralEndpoint = "http://127.0.0.1:8282" var token = "" func TestMain(m *testing.M) { diff --git a/src/core/middlewares/util/util_test.go b/src/core/middlewares/util/util_test.go index 2cfe9899a..8263cfe82 100644 --- a/src/core/middlewares/util/util_test.go +++ b/src/core/middlewares/util/util_test.go @@ -146,7 +146,7 @@ func TestMatchPushManifest(t *testing.T) { } func TestPMSPolicyChecker(t *testing.T) { - var defaultConfigAdmiral = map[string]interface{}{ + var defaultConfig = map[string]interface{}{ common.ExtEndpoint: "https://" + endpoint, common.WithNotary: true, common.TokenExpiration: 30, @@ -158,11 +158,9 @@ func TestPMSPolicyChecker(t *testing.T) { common.PostGreSQLDatabase: "registry", } - if err := config.Init(); err != nil { - panic(err) - } + config.Init() - config.Upload(defaultConfigAdmiral) + config.Upload(defaultConfig) name := "project_for_test_get_sev_low" id, err := config.GlobalProjectMgr.Create(&models.Project{ diff --git a/src/core/promgr/pmsdriver/admiral/admiral.go b/src/core/promgr/pmsdriver/admiral/admiral.go deleted file mode 100644 index bb3c65c79..000000000 --- a/src/core/promgr/pmsdriver/admiral/admiral.go +++ /dev/null @@ -1,421 +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 admiral - -import ( - "bytes" - "encoding/json" - "errors" - "fmt" - "io" - "io/ioutil" - "net/http" - "regexp" - "strconv" - "strings" - - commonhttp "github.com/goharbor/harbor/src/common/http" - "github.com/goharbor/harbor/src/common/models" - "github.com/goharbor/harbor/src/common/utils" - er "github.com/goharbor/harbor/src/common/utils/error" - "github.com/goharbor/harbor/src/common/utils/log" - "github.com/goharbor/harbor/src/core/promgr/pmsdriver" -) - -const dupProjectPattern = `Project name '\w+' is already used` - -type driver struct { - client *http.Client - endpoint string - tokenReader TokenReader -} - -type user struct { - Email string `json:"email"` -} - -type project struct { - ID string `json:"id"` - Name string `json:"name"` - Public bool `json:"isPublic"` - OwnerID string `json:"documentOwner"` - CustomProperties map[string]string `json:"customProperties"` - Administrators []*user `json:"administrators"` - Developers []*user `json:"members"` - Guests []*user `json:"viewers"` -} - -// NewDriver returns an instance of driver -func NewDriver(client *http.Client, endpoint string, - tokenReader TokenReader) pmsdriver.PMSDriver { - return &driver{ - client: client, - endpoint: strings.TrimRight(endpoint, "/"), - tokenReader: tokenReader, - } -} - -// Get ... -func (d *driver) Get(projectIDOrName interface{}) (*models.Project, error) { - project, err := d.get(projectIDOrName) - if err != nil { - return nil, err - } - return convert(project) -} - -// get Admiral project with Harbor project ID or name -func (d *driver) get(projectIDOrName interface{}) (*project, error) { - // if token is provided, search project from my projects list first - if len(d.getToken()) != 0 { - project, err := d.getFromMy(projectIDOrName) - if err != nil { - return nil, err - } - if project != nil { - return project, nil - } - } - - // try to get project from public projects list - return d.getFromPublic(projectIDOrName) -} - -// call GET /projects?$filter=xxx eq xxx, the API can only filter projects -// which the user is a member of -func (d *driver) getFromMy(projectIDOrName interface{}) (*project, error) { - return d.getAdmiralProject(projectIDOrName, false) -} - -// call GET /projects?public=true&$filter=xxx eq xxx -func (d *driver) getFromPublic(projectIDOrName interface{}) (*project, error) { - project, err := d.getAdmiralProject(projectIDOrName, true) - if project != nil { - // the projects returned by GET /projects?public=true&xxx have no - // "public" property, populate it here - project.Public = true - } - return project, err -} - -func (d *driver) getAdmiralProject(projectIDOrName interface{}, public bool) (*project, error) { - m := map[string]string{} - - id, name, err := utils.ParseProjectIDOrName(projectIDOrName) - if err != nil { - return nil, err - } - if id > 0 { - m["customProperties.__projectIndex"] = strconv.FormatInt(id, 10) - } else { - m["name"] = name - } - if public { - m["public"] = "true" - } - - projects, err := d.filter(m) - if err != nil { - return nil, err - } - - if len(projects) == 0 { - return nil, nil - } - - if len(projects) != 1 { - for _, project := range projects { - fmt.Printf("%v", project) - } - return nil, fmt.Errorf("unexpected size of project list: %d != 1", len(projects)) - } - - return projects[0], nil -} - -func (d *driver) filter(m map[string]string) ([]*project, error) { - query := "" - for k, v := range m { - if len(query) == 0 { - query += "?" - } else { - query += "&" - } - if k == "public" { - query += fmt.Sprintf("%s=%s", k, v) - } else { - query += fmt.Sprintf("$filter=%s eq '%s'", k, v) - } - } - - if len(query) == 0 { - query = "?expand=true" - } - - path := "/projects" + query - data, err := d.send(http.MethodGet, path, nil) - if err != nil { - return nil, err - } - - return parse(data) -} - -// parse the response of GET /projects?xxx to project list -func parse(b []byte) ([]*project, error) { - documents := &struct { - // DocumentCount int64 `json:"documentCount"` - Projects map[string]*project `json:"documents"` - }{} - if err := json.Unmarshal(b, documents); err != nil { - return nil, err - } - - projects := []*project{} - for link, project := range documents.Projects { - project.ID = strings.TrimPrefix(link, "/projects/") - projects = append(projects, project) - } - - return projects, nil -} - -func convert(p *project) (*models.Project, error) { - if p == nil { - return nil, nil - } - - project := &models.Project{ - Name: p.Name, - } - if p.Public { - project.SetMetadata(models.ProMetaPublic, "true") - } - - value := p.CustomProperties["__projectIndex"] - if len(value) == 0 { - return nil, fmt.Errorf("property __projectIndex is null") - } - - id, err := strconv.ParseInt(value, 10, 64) - if err != nil { - return nil, fmt.Errorf("failed to parse __projectIndex %s to int64: %v", value, err) - } - project.ProjectID = id - - value = p.CustomProperties["__enableContentTrust"] - if len(value) != 0 { - enable, err := strconv.ParseBool(value) - if err != nil { - return nil, fmt.Errorf("failed to parse __enableContentTrust %s to bool: %v", value, err) - } - project.SetMetadata(models.ProMetaEnableContentTrust, strconv.FormatBool(enable)) - } - - value = p.CustomProperties["__preventVulnerableImagesFromRunning"] - if len(value) != 0 { - prevent, err := strconv.ParseBool(value) - if err != nil { - return nil, fmt.Errorf("failed to parse __preventVulnerableImagesFromRunning %s to bool: %v", value, err) - } - project.SetMetadata(models.ProMetaPreventVul, strconv.FormatBool(prevent)) - } - - value = p.CustomProperties["__preventVulnerableImagesFromRunningSeverity"] - if len(value) != 0 { - project.SetMetadata(models.ProMetaSeverity, value) - } - - value = p.CustomProperties["__automaticallyScanImagesOnPush"] - if len(value) != 0 { - scan, err := strconv.ParseBool(value) - if err != nil { - return nil, fmt.Errorf("failed to parse __automaticallyScanImagesOnPush %s to bool: %v", value, err) - } - project.SetMetadata(models.ProMetaAutoScan, strconv.FormatBool(scan)) - } - - return project, nil -} - -func (d *driver) getIDbyHarborIDOrName(projectIDOrName interface{}) (string, error) { - pro, err := d.get(projectIDOrName) - if err != nil { - return "", err - } - - if pro == nil { - return "", fmt.Errorf("project %v not found", projectIDOrName) - } - - return pro.ID, nil -} - -// Create ... -func (d *driver) Create(pro *models.Project) (int64, error) { - proj := &project{ - CustomProperties: make(map[string]string), - } - proj.Name = pro.Name - proj.Public = pro.IsPublic() - proj.CustomProperties["__enableContentTrust"] = strconv.FormatBool(pro.ContentTrustEnabled()) - proj.CustomProperties["__preventVulnerableImagesFromRunning"] = strconv.FormatBool(pro.VulPrevented()) - proj.CustomProperties["__preventVulnerableImagesFromRunningSeverity"] = pro.Severity() - proj.CustomProperties["__automaticallyScanImagesOnPush"] = strconv.FormatBool(pro.AutoScan()) - - data, err := json.Marshal(proj) - if err != nil { - return 0, err - } - - b, err := d.send(http.MethodPost, "/projects", bytes.NewBuffer(data)) - if err != nil { - // when creating a project with a duplicate name in Admiral, a 500 error - // with a specific message will be returned for now. - // Maybe a 409 error will be returned if Admiral team finds the way to - // return a specific code in Xenon. - // The following codes convert both those two errors to DupProjectErr - httpErr, ok := err.(*commonhttp.Error) - if !ok { - return 0, err - } - - if httpErr.Code == http.StatusConflict { - return 0, er.ErrDupProject - } - - if httpErr.Code != http.StatusInternalServerError { - return 0, err - } - - match, e := regexp.MatchString(dupProjectPattern, httpErr.Message) - if e != nil { - log.Errorf("failed to match duplicate project mattern: %v", e) - } - - if match { - err = er.ErrDupProject - } - - return 0, err - } - - proj = &project{} - if err = json.Unmarshal(b, proj); err != nil { - return 0, err - } - - pp, err := convert(proj) - if err != nil { - return 0, err - } - - return pp.ProjectID, err -} - -// Delete ... -func (d *driver) Delete(projectIDOrName interface{}) error { - id, err := d.getIDbyHarborIDOrName(projectIDOrName) - if err != nil { - return err - } - - _, err = d.send(http.MethodDelete, fmt.Sprintf("/projects/%s", id), nil) - return err -} - -// Update ... -func (d *driver) Update(projectIDOrName interface{}, project *models.Project) error { - return errors.New("project update is unsupported") -} - -// List ... -func (d *driver) List(query *models.ProjectQueryParam) (*models.ProjectQueryResult, error) { - m := map[string]string{} - if query != nil { - if len(query.Name) > 0 { - m["name"] = query.Name - } - if query.Public != nil { - m["public"] = strconv.FormatBool(*query.Public) - } - } - - projects, err := d.filter(m) - if err != nil { - return nil, err - } - - list := []*models.Project{} - for _, p := range projects { - project, err := convert(p) - if err != nil { - return nil, err - } - list = append(list, project) - } - - return &models.ProjectQueryResult{ - Total: int64(len(list)), - Projects: list, - }, nil -} - -func (d *driver) send(method, path string, body io.Reader) ([]byte, error) { - req, err := http.NewRequest(method, d.endpoint+path, body) - if err != nil { - return nil, err - } - - req.Header.Add("x-xenon-auth-token", d.getToken()) - - url := req.URL.String() - - req.URL.RawQuery = req.URL.Query().Encode() - resp, err := d.client.Do(req) - if err != nil { - log.Debugf("\"%s %s\" failed", req.Method, url) - return nil, err - } - defer resp.Body.Close() - log.Debugf("\"%s %s\" %d", req.Method, url, resp.StatusCode) - - b, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, err - } - - if resp.StatusCode != http.StatusOK { - return nil, &commonhttp.Error{ - Code: resp.StatusCode, - Message: string(b), - } - } - - return b, nil -} - -func (d *driver) getToken() string { - if d.tokenReader == nil { - return "" - } - - token, err := d.tokenReader.ReadToken() - if err != nil { - token = "" - log.Errorf("failed to read token: %v", err) - } - return token -} diff --git a/src/core/promgr/pmsdriver/admiral/admiral_test.go b/src/core/promgr/pmsdriver/admiral/admiral_test.go deleted file mode 100644 index bcc1bb325..000000000 --- a/src/core/promgr/pmsdriver/admiral/admiral_test.go +++ /dev/null @@ -1,354 +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 admiral - -import ( - "net/http" - "sort" - "testing" - - "github.com/goharbor/harbor/src/common/models" - errutil "github.com/goharbor/harbor/src/common/utils/error" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -var ( - client = http.DefaultClient - endpoint = "http://127.0.0.1:8282" - tokenReader = &RawTokenReader{ - Token: "token", - } -) - -func TestConvert(t *testing.T) { - // nil project - pro, err := convert(nil) - assert.Nil(t, err) - assert.Nil(t, pro) - - // project without property __projectIndex - p := &project{} - pro, err = convert(p) - assert.NotNil(t, err) - assert.Nil(t, pro) - - // project with invalid __projectIndex - p = &project{ - CustomProperties: map[string]string{ - "__projectIndex": "invalid_value", - }, - } - pro, err = convert(p) - assert.NotNil(t, err) - assert.Nil(t, pro) - - // project with invalid __enableContentTrust - p = &project{ - CustomProperties: map[string]string{ - "__enableContentTrust": "invalid_value", - }, - } - pro, err = convert(p) - assert.NotNil(t, err) - assert.Nil(t, pro) - - // project with invalid __preventVulnerableImagesFromRunning - p = &project{ - CustomProperties: map[string]string{ - "__preventVulnerableImagesFromRunning": "invalid_value", - }, - } - pro, err = convert(p) - assert.NotNil(t, err) - assert.Nil(t, pro) - - // project with invalid __automaticallyScanImagesOnPush - p = &project{ - CustomProperties: map[string]string{ - "__automaticallyScanImagesOnPush": "invalid_value", - }, - } - pro, err = convert(p) - assert.NotNil(t, err) - assert.Nil(t, pro) - - // valid project - p = &project{ - Name: "test", - Public: true, - CustomProperties: map[string]string{ - "__projectIndex": "1", - "__enableContentTrust": "true", - "__preventVulnerableImagesFromRunning": "true", - "__preventVulnerableImagesFromRunningSeverity": "medium", - "__automaticallyScanImagesOnPush": "true", - }, - } - pro, err = convert(p) - assert.Nil(t, err) - assert.NotNil(t, pro) - assert.Equal(t, "test", pro.Name) - assert.True(t, pro.IsPublic()) - assert.Equal(t, int64(1), pro.ProjectID) - assert.True(t, pro.ContentTrustEnabled()) - assert.True(t, pro.VulPrevented()) - assert.Equal(t, "medium", pro.Severity()) - assert.True(t, pro.AutoScan()) -} - -func TestParse(t *testing.T) { - data := `{ - "totalCount": 2, - "documentLinks": [ - "/projects/default-project", - "/projects/fc6c6c7ddd430875551449a65e7c8" - ], - "documents": { - "/projects/fc6c6c7ddd430875551449a65e7c8": { - "isPublic": false, - "description": "This is a test project.", - "id": "41427587-70e9-4671-9a9e-b9def0a07bb7", - "name": "project02", - "customProperties": { - "__projectIndex": "2", - "__enableContentTrust": "true", - "__preventVulnerableImagesFromRunning": "true", - "__preventVulnerableImagesFromRunningSeverity": "medium", - "__automaticallyScanImagesOnPush": "false" - }, - "documentVersion": 0, - "documentEpoch": 0, - "documentKind": "com:vmware:admiral:auth:project:ProjectService:ProjectState", - "documentSelfLink": "/projects/fc6c6c7ddd430875551449a65e7c8", - "documentUpdateTimeMicros": 1496729973549001, - "documentUpdateAction": "POST", - "documentExpirationTimeMicros": 0, - "documentOwner": "f65900c4-2b6a-4671-8cf7-c17340dd3d39" - }, - "/projects/default-project": { - "isPublic": false, - "administratorsUserGroupLink": "/core/authz/user-groups/fc6c6c7ddd43087555143835bcaf8", - "membersUserGroupLink": "/core/authz/user-groups/fc6c6c7ddd43087555143835bde80", - "id": "default-project", - "name": "default-project", - "customProperties": { - "__projectIndex": "2", - "__enableContentTrust": "true", - "__preventVulnerableImagesFromRunning": "true", - "__preventVulnerableImagesFromRunningSeverity": "medium", - "__automaticallyScanImagesOnPush": "false" - }, - "documentVersion": 0, - "documentEpoch": 0, - "documentKind": "com:vmware:admiral:auth:project:ProjectService:ProjectState", - "documentSelfLink": "/projects/default-project", - "documentUpdateTimeMicros": 1496725292012001, - "documentUpdateAction": "POST", - "documentExpirationTimeMicros": 0, - "documentOwner": "f65900c4-2b6a-4671-8cf7-c17340dd3d39", - "documentAuthPrincipalLink": "/core/authz/system-user" - } - }, - "documentCount": 2, - "queryTimeMicros": 1, - "documentVersion": 0, - "documentUpdateTimeMicros": 0, - "documentExpirationTimeMicros": 0, - "documentOwner": "f65900c4-2b6a-4671-8cf7-c17340dd3d39" -}` - - projects, err := parse([]byte(data)) - assert.Nil(t, err) - assert.Equal(t, 2, len(projects)) - - ids := []string{projects[0].ID, projects[1].ID} - sort.Strings(ids) - - assert.Equal(t, "default-project", ids[0]) - assert.Equal(t, "fc6c6c7ddd430875551449a65e7c8", ids[1]) -} - -func TestGet(t *testing.T) { - d := NewDriver(client, endpoint, tokenReader) - name := "project_for_test_get" - id, err := d.Create(&models.Project{ - Name: name, - }) - require.Nil(t, err) - defer deleteProject(t, id) - - // get by invalid input type - _, err = d.Get([]string{}) - assert.NotNil(t, err) - - // get by invalid ID - project, err := d.Get(int64(0)) - assert.Nil(t, err) - assert.Nil(t, project) - - // get by invalid name - project, err = d.Get("invalid_name") - assert.Nil(t, err) - assert.Nil(t, project) - - // get by valid ID - project, err = d.Get(id) - assert.Nil(t, err) - assert.Equal(t, id, project.ProjectID) - - // get by valid name - project, err = d.Get(name) - assert.Nil(t, err) - assert.Equal(t, id, project.ProjectID) -} - -func TestCreate(t *testing.T) { - d := NewDriver(client, endpoint, tokenReader) - - name := "project_for_test_create" - id, err := d.Create(&models.Project{ - Name: name, - Metadata: map[string]string{ - models.ProMetaPublic: "true", - models.ProMetaEnableContentTrust: "true", - models.ProMetaPreventVul: "true", - models.ProMetaSeverity: "medium", - models.ProMetaAutoScan: "true", - }, - }) - require.Nil(t, err) - defer deleteProject(t, id) - - project, err := d.Get(id) - assert.Nil(t, err) - assert.Equal(t, name, project.Name) - assert.True(t, project.IsPublic()) - assert.True(t, project.ContentTrustEnabled()) - assert.True(t, project.VulPrevented()) - assert.Equal(t, "medium", project.Severity()) - assert.True(t, project.AutoScan()) - - // duplicate project name - _, err = d.Create(&models.Project{ - Name: name, - }) - assert.Equal(t, errutil.ErrDupProject, err) -} - -func TestDelete(t *testing.T) { - d := NewDriver(client, endpoint, tokenReader) - - // non-exist project - err := d.Delete(int64(0)) - assert.NotNil(t, err) - - // delete by ID - name := "project_for_pm_based_on_pms_id" - id, err := d.Create(&models.Project{ - Name: name, - }) - require.Nil(t, err) - err = d.Delete(id) - assert.Nil(t, err) - - // delete by name - name = "project_for_pm_based_on_pms_name" - id, err = d.Create(&models.Project{ - Name: name, - }) - require.Nil(t, err) - err = d.Delete(name) - assert.Nil(t, err) -} - -func TestUpdate(t *testing.T) { - d := NewDriver(client, endpoint, tokenReader) - err := d.Update(nil, nil) - assert.NotNil(t, err) -} - -func TestList(t *testing.T) { - d := NewDriver(client, endpoint, tokenReader) - - name1 := "project_for_test_get_all_01" - id1, err := d.Create(&models.Project{ - Name: name1, - }) - require.Nil(t, err) - defer deleteProject(t, id1) - - name2 := "project_for_test_get_all_02" - id2, err := d.Create(&models.Project{ - Name: name2, - Metadata: map[string]string{ - models.ProMetaPublic: "true", - }, - }) - require.Nil(t, err) - defer deleteProject(t, id2) - - // no filter - result, err := d.List(nil) - require.Nil(t, err) - found1 := false - found2 := false - for _, project := range result.Projects { - if project.ProjectID == id1 { - found1 = true - } - if project.ProjectID == id2 { - found2 = true - } - } - assert.True(t, found1) - assert.True(t, found2) - - // filter by name - result, err = d.List(&models.ProjectQueryParam{ - Name: name1, - }) - require.Nil(t, err) - found1 = false - for _, project := range result.Projects { - if project.ProjectID == id1 { - found1 = true - break - } - } - assert.True(t, found1) - - // filter by public - value := true - result, err = d.List(&models.ProjectQueryParam{ - Public: &value, - }) - require.Nil(t, err) - found2 = false - for _, project := range result.Projects { - if project.ProjectID == id2 { - found2 = true - break - } - } - assert.True(t, found2) -} - -func deleteProject(t *testing.T, id int64) { - d := NewDriver(client, endpoint, tokenReader) - if err := d.Delete(id); err != nil { - t.Logf("failed to delete project %d: %v", id, err) - } -} diff --git a/src/core/promgr/pmsdriver/admiral/token.go b/src/core/promgr/pmsdriver/admiral/token.go deleted file mode 100644 index 94ad05ef0..000000000 --- a/src/core/promgr/pmsdriver/admiral/token.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 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 admiral - -import ( - "io/ioutil" - "strings" -) - -const ( - key = "access_token" -) - -// TokenReader is an interface used to wrap the way how to get token -type TokenReader interface { - // ReadToken reads token - ReadToken() (string, error) -} - -// RawTokenReader just returns the token contained by field Token -type RawTokenReader struct { - Token string -} - -// ReadToken ... -func (r *RawTokenReader) ReadToken() (string, error) { - return r.Token, nil -} - -// FileTokenReader reads token from file -type FileTokenReader struct { - Path string -} - -// ReadToken ... -func (f *FileTokenReader) ReadToken() (string, error) { - data, err := ioutil.ReadFile(f.Path) - if err != nil { - return "", err - } - return strings.TrimRight(string(data), "\n"), nil -} diff --git a/src/core/promgr/pmsdriver/admiral/token_test.go b/src/core/promgr/pmsdriver/admiral/token_test.go deleted file mode 100644 index cb0f5136d..000000000 --- a/src/core/promgr/pmsdriver/admiral/token_test.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 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 admiral - -import ( - "io/ioutil" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "os" -) - -func TestRawTokenReader(t *testing.T) { - raw := "token" - reader := &RawTokenReader{ - Token: raw, - } - - token, err := reader.ReadToken() - require.Nil(t, err) - assert.Equal(t, raw, token) -} - -func TestFileTokenReader(t *testing.T) { - // file not exist - path := "/tmp/not_exist_file" - reader := &FileTokenReader{ - Path: path, - } - - _, err := reader.ReadToken() - assert.NotNil(t, err) - - // file exist - path = "/tmp/exist_file" - err = ioutil.WriteFile(path, []byte("token"), 0x0766) - require.Nil(t, err) - defer os.Remove(path) - - reader = &FileTokenReader{ - Path: path, - } - - token, err := reader.ReadToken() - require.Nil(t, err) - assert.Equal(t, "token", token) -} diff --git a/src/core/router.go b/src/core/router.go index 97e2186a8..372172c55 100755 --- a/src/core/router.go +++ b/src/core/router.go @@ -28,40 +28,33 @@ import ( ) func initRouters() { + // Controller API: + beego.Router("/c/login", &controllers.CommonController{}, "post:Login") + beego.Router("/c/log_out", &controllers.CommonController{}, "get:LogOut") + beego.Router("/c/reset", &controllers.CommonController{}, "post:ResetPassword") + beego.Router("/c/userExists", &controllers.CommonController{}, "post:UserExists") + beego.Router("/c/sendEmail", &controllers.CommonController{}, "get:SendResetEmail") + beego.Router(common.OIDCLoginPath, &controllers.OIDCController{}, "get:RedirectLogin") + beego.Router("/c/oidc/onboard", &controllers.OIDCController{}, "post:Onboard") + beego.Router(common.OIDCCallbackPath, &controllers.OIDCController{}, "get:Callback") - // standalone - if !config.WithAdmiral() { - // Controller API: - beego.Router("/c/login", &controllers.CommonController{}, "post:Login") - beego.Router("/c/log_out", &controllers.CommonController{}, "get:LogOut") - beego.Router("/c/reset", &controllers.CommonController{}, "post:ResetPassword") - beego.Router("/c/userExists", &controllers.CommonController{}, "post:UserExists") - beego.Router("/c/sendEmail", &controllers.CommonController{}, "get:SendResetEmail") - beego.Router(common.OIDCLoginPath, &controllers.OIDCController{}, "get:RedirectLogin") - beego.Router("/c/oidc/onboard", &controllers.OIDCController{}, "post:Onboard") - beego.Router(common.OIDCCallbackPath, &controllers.OIDCController{}, "get:Callback") - - // API: - beego.Router("/api/projects/:pid([0-9]+)/members/?:pmid([0-9]+)", &api.ProjectMemberAPI{}) - beego.Router("/api/projects/", &api.ProjectAPI{}, "head:Head") - beego.Router("/api/projects/:id([0-9]+)", &api.ProjectAPI{}) - - beego.Router("/api/users/:id", &api.UserAPI{}, "get:Get;delete:Delete;put:Put") - beego.Router("/api/users", &api.UserAPI{}, "get:List;post:Post") - beego.Router("/api/users/search", &api.UserAPI{}, "get:Search") - beego.Router("/api/users/:id([0-9]+)/password", &api.UserAPI{}, "put:ChangePassword") - beego.Router("/api/users/:id/permissions", &api.UserAPI{}, "get:ListUserPermissions") - beego.Router("/api/users/:id/sysadmin", &api.UserAPI{}, "put:ToggleUserAdminRole") - beego.Router("/api/users/:id/cli_secret", &api.UserAPI{}, "put:SetCLISecret") - beego.Router("/api/usergroups/?:ugid([0-9]+)", &api.UserGroupAPI{}) - beego.Router("/api/ldap/ping", &api.LdapAPI{}, "post:Ping") - beego.Router("/api/ldap/users/search", &api.LdapAPI{}, "get:Search") - beego.Router("/api/ldap/groups/search", &api.LdapAPI{}, "get:SearchGroup") - beego.Router("/api/ldap/users/import", &api.LdapAPI{}, "post:ImportUser") - beego.Router("/api/email/ping", &api.EmailAPI{}, "post:Ping") - } - - // API + // API: + beego.Router("/api/projects/:pid([0-9]+)/members/?:pmid([0-9]+)", &api.ProjectMemberAPI{}) + beego.Router("/api/projects/", &api.ProjectAPI{}, "head:Head") + beego.Router("/api/projects/:id([0-9]+)", &api.ProjectAPI{}) + beego.Router("/api/users/:id", &api.UserAPI{}, "get:Get;delete:Delete;put:Put") + beego.Router("/api/users", &api.UserAPI{}, "get:List;post:Post") + beego.Router("/api/users/search", &api.UserAPI{}, "get:Search") + beego.Router("/api/users/:id([0-9]+)/password", &api.UserAPI{}, "put:ChangePassword") + beego.Router("/api/users/:id/permissions", &api.UserAPI{}, "get:ListUserPermissions") + beego.Router("/api/users/:id/sysadmin", &api.UserAPI{}, "put:ToggleUserAdminRole") + beego.Router("/api/users/:id/cli_secret", &api.UserAPI{}, "put:SetCLISecret") + beego.Router("/api/usergroups/?:ugid([0-9]+)", &api.UserGroupAPI{}) + beego.Router("/api/ldap/ping", &api.LdapAPI{}, "post:Ping") + beego.Router("/api/ldap/users/search", &api.LdapAPI{}, "get:Search") + beego.Router("/api/ldap/groups/search", &api.LdapAPI{}, "get:SearchGroup") + beego.Router("/api/ldap/users/import", &api.LdapAPI{}, "post:ImportUser") + beego.Router("/api/email/ping", &api.EmailAPI{}, "post:Ping") beego.Router("/api/health", &api.HealthAPI{}, "get:CheckHealth") beego.Router("/api/ping", &api.SystemInfoAPI{}, "get:Ping") beego.Router("/api/search", &api.SearchAPI{}) @@ -71,8 +64,6 @@ func initRouters() { beego.Router("/api/projects/:id([0-9]+)/_deletable", &api.ProjectAPI{}, "get:Deletable") beego.Router("/api/projects/:id([0-9]+)/metadatas/?:name", &api.MetadataAPI{}, "get:Get") beego.Router("/api/projects/:id([0-9]+)/metadatas/", &api.MetadataAPI{}, "post:Post") - beego.Router("/api/projects/:id([0-9]+)/metadatas/:name", &api.MetadataAPI{}, "put:Put;delete:Delete") - beego.Router("/api/projects/:pid([0-9]+)/robots", &api.RobotAPI{}, "post:Post;get:List") beego.Router("/api/projects/:pid([0-9]+)/robots/:id([0-9]+)", &api.RobotAPI{}, "get:Get;put:Put;delete:Delete") diff --git a/src/core/service/token/token_test.go b/src/core/service/token/token_test.go index 4a8435c2c..236dec04f 100644 --- a/src/core/service/token/token_test.go +++ b/src/core/service/token/token_test.go @@ -14,7 +14,7 @@ package token import ( - "github.com/dgrijalva/jwt-go" + jwt "github.com/dgrijalva/jwt-go" "github.com/docker/distribution/registry/auth/token" "github.com/stretchr/testify/assert" @@ -35,9 +35,7 @@ import ( ) func TestMain(m *testing.M) { - if err := config.Init(); err != nil { - panic(err) - } + config.Init() InitCreators() result := m.Run() if result != 0 { diff --git a/src/core/utils/utils_test.go b/src/core/utils/utils_test.go index 4988722f7..ce9f50484 100644 --- a/src/core/utils/utils_test.go +++ b/src/core/utils/utils_test.go @@ -21,10 +21,7 @@ import ( ) func TestMain(m *testing.M) { - err := config.Init() - if err != nil { - panic(err) - } + config.Init() rc := m.Run() os.Exit(rc) diff --git a/src/pkg/token/token_test.go b/src/pkg/token/token_test.go index eab75a474..b1666a519 100644 --- a/src/pkg/token/token_test.go +++ b/src/pkg/token/token_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - "github.com/dgrijalva/jwt-go" + jwt "github.com/dgrijalva/jwt-go" "github.com/goharbor/harbor/src/common/rbac" "github.com/goharbor/harbor/src/core/config" robot_claim "github.com/goharbor/harbor/src/pkg/token/claims/robot" @@ -13,9 +13,7 @@ import ( ) func TestMain(m *testing.M) { - if err := config.Init(); err != nil { - panic(err) - } + config.Init() result := m.Run() if result != 0 { diff --git a/tests/admiral.sh b/tests/admiral.sh deleted file mode 100755 index ee2cca658..000000000 --- a/tests/admiral.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -# run admiral for unit test -name=admiral -port=8282 -docker rm -f $name 2>/dev/null -docker run -d -p $port:8282 --name $name vmware/admiral:v1.2.1 - -# solution user token file for test -mkdir -p /etc/core/token/ -echo "token" > /etc/core/token/tokens.properties diff --git a/tests/resources/Admiral-Util.robot b/tests/resources/Admiral-Util.robot deleted file mode 100644 index e9d9b82cf..000000000 --- a/tests/resources/Admiral-Util.robot +++ /dev/null @@ -1,105 +0,0 @@ -# Copyright 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 - -*** Settings *** -Documentation This resource contains all keywords related to creating, deleting, maintaining an instance of Admiral -Library Selenium2Library 5 5 -Library OperatingSystem - -*** Keywords *** -Install Admiral - ${rc} ${output}= Run And Return Rc And Output docker %{VCH-PARAMS} run -d -p 8282:8282 --name admiral vmware/admiral:vic_v1.1.0 - Should Be Equal As Integers 0 ${rc} - Set Environment Variable ADMIRAL_IP %{VCH-IP}:8282 - :FOR ${idx} IN RANGE 0 10 - \ ${out}= Run curl %{ADMIRAL_IP} - \ ${status}= Run Keyword And Return Status Should Contain ${out} - \ Return From Keyword If ${status} - \ Sleep 5 - Fail Install Admiral failed: Admiral endpoint failed to respond to curl - -Cleanup Admiral - ${rc} ${output}= Run And Return Rc And Output docker %{VCH-PARAMS} rm -f admiral - Should Be Equal As Integers 0 ${rc} - -Login To Admiral - [Arguments] ${url}=localhost:8282 ${browser}=chrome - Open Browser ${url} ${browser} - Maximize Browser Window - Wait Until Page Contains Welcome! - Wait Until Page Contains This is the place for you to create, provision, manage and monitor containerized applications. - Wait Until Element Is Visible css=button.btn.btn-primary.enter-btn - Wait Until Element Is Enabled css=button.btn.btn-primary.enter-btn - Click Button css=button.btn.btn-primary.enter-btn - Wait Until Element Is Visible css=div.query-search-input-controls.form-control - Wait Until Element Is Enabled css=div.query-search-input-controls.form-control - Wait Until Element Is Visible css=a.btn.btn-primary.addHost-btn - Wait Until Element Is Enabled css=a.btn.btn-primary.addHost-btn - -Add Host To Admiral - [Arguments] ${address} ${credentials}=${EMPTY} - Wait Until Element Is Visible css=a[data-cmd='navigation-hosts'] - Wait Until Element Is Enabled css=a[data-cmd='navigation-hosts'] - Click Element css=a[data-cmd='navigation-hosts'] - - Wait Until Element Is Visible css=div.query-search-input-controls.form-control - Wait Until Element Is Enabled css=div.query-search-input-controls.form-control - Wait Until Element Is Visible css=a.btn.btn-primary.addHost-btn - Wait Until Element Is Enabled css=a.btn.btn-primary.addHost-btn - Click Element css=a.btn.btn-primary.addHost-btn - - Wait Until Page Contains Add Host - Wait Until Element Is Visible address - Wait Until Element Is Enabled address - Wait Until Element Is Visible credential - Wait Until Element Is Enabled credential - - Input Text css=#address > input.form-control ${address} - - Select From List css=#hostType > div.select > select VCH - - Run Keyword If '${credentials}' != '${EMPTY}' Click Element css=#credential > div.form-control > div.dropdown > button.dropdown-toggle - Run Keyword If '${credentials}' != '${EMPTY}' Click Element css=a[data-name=${credentials}] - - Wait Until Element Is Visible css=a.btn.verifyHost - Wait Until Element Is Enabled css=a.btn.verifyHost - Click Element css=a.btn.verifyHost - - Wait Until Page Contains Verified successfully! - Wait Until Element Is Visible css=button.btn.btn-primary.saveHost - Wait Until Element Is Enabled css=button.btn.btn-primary.saveHost - Click Button css=button.btn.btn-primary.saveHost - - Wait Until Element Is Visible css=div.status.ON - Wait Until Element Is Enabled css=div.status.ON - - -Add Project to Admiral - [Arguments] ${name} - Wait Until Element Is Visible css=a[data-cmd='navigation-placements'] - Wait Until Element Is Enabled css=a[data-cmd='navigation-placements'] - Click Element css=a[data-cmd='navigation-placements'] - - Wait Until Element Is Visible css=div.right-context-panel > div.toolbar > div:nth-child(2) > a - Wait Until Element Is Enabled css=div.right-context-panel > div.toolbar > div:nth-child(2) > a - Click Element css=div.right-context-panel > div.toolbar > div:nth-child(2) > a - - Wait Until Page Contains Project - Wait Until Element Is Visible css=div.right-context-panel > div.content > div > div.list-holder > div.inline-editable-list-holder > div.inline-editable-list > div.toolbar > a.new-item - Wait Until Element Is Enabled css=div.right-context-panel > div.content > div > div.list-holder > div.inline-editable-list-holder > div.inline-editable-list > div.toolbar > a.new-item - Click Element css=div.right-context-panel > div.content > div > div.list-holder > div.inline-editable-list-holder > div.inline-editable-list > div.toolbar > a.new-item - Input Text css=input.name-input ${name} - Click Element css=button.btn.btn-primary.inline-edit-save - - Table Should Contain css=div.right-context-panel > div.content > div > div > div > div > table ${name} diff --git a/tests/resources/Util.robot b/tests/resources/Util.robot index a373197ca..95ba6c70f 100644 --- a/tests/resources/Util.robot +++ b/tests/resources/Util.robot @@ -66,7 +66,6 @@ Resource Harbor-Pages/OIDC_Auth_Elements.robot Resource Harbor-Pages/Verify.robot Resource Docker-Util.robot Resource Helm-Util.robot -Resource Admiral-Util.robot Resource OVA-Util.robot Resource Cert-Util.robot Resource SeleniumUtil.robot diff --git a/tests/travis/ut_install.sh b/tests/travis/ut_install.sh index 78627df86..e7951b0d7 100644 --- a/tests/travis/ut_install.sh +++ b/tests/travis/ut_install.sh @@ -26,7 +26,7 @@ sudo mkdir -p /etc/core/ca/ && sudo mv ./tests/ca.crt /etc/core/ca/ sudo mkdir -p /harbor && sudo mv ./VERSION /harbor/UIVERSION sudo ./tests/testprepare.sh -cd tests && sudo ./ldapprepare.sh && sudo ./admiral.sh && cd .. +cd tests && sudo ./ldapprepare.sh && cd .. sudo sed -i 's/__reg_version__/${REG_VERSION}-dev/g' ./make/docker-compose.test.yml sudo sed -i 's/__version__/dev/g' ./make/docker-compose.test.yml sudo mkdir -p ./make/common/config/registry/ && sudo mv ./tests/reg_config.yml ./make/common/config/registry/config.yml