From af58195a29e9c18660cdb5d8b960ff76b1b8ad6f Mon Sep 17 00:00:00 2001 From: DQ Date: Wed, 17 Jul 2019 15:14:50 +0800 Subject: [PATCH 1/7] Fix: Internal server error with messy code when chartmuseum not work log err when doesn't get data from chart museum Signed-off-by: DQ --- src/chartserver/client.go | 14 +++++++---- src/chartserver/handler_manipulation.go | 8 +++---- src/common/api/base.go | 5 ++-- src/core/api/base.go | 2 +- src/core/api/project.go | 31 ++++++++++++++----------- 5 files changed, 32 insertions(+), 28 deletions(-) diff --git a/src/chartserver/client.go b/src/chartserver/client.go index e7e1fb646..1ab153570 100644 --- a/src/chartserver/client.go +++ b/src/chartserver/client.go @@ -1,16 +1,16 @@ package chartserver import ( - "errors" "fmt" - commonhttp "github.com/goharbor/harbor/src/common/http" - hlog "github.com/goharbor/harbor/src/common/utils/log" "io" "io/ioutil" "net/http" "net/url" "strings" "time" + + commonhttp "github.com/goharbor/harbor/src/common/http" + "github.com/pkg/errors" ) const ( @@ -49,11 +49,13 @@ func NewChartClient(credential *Credential) *ChartClient { // Create http client func (cc *ChartClient) GetContent(addr string) ([]byte, error) { response, err := cc.sendRequest(addr, http.MethodGet, nil) if err != nil { + err = errors.Wrap(err, "get content failed") return nil, err } content, err := ioutil.ReadAll(response.Body) if err != nil { + err = errors.Wrap(err, "Read response body error") return nil, err } defer response.Body.Close() @@ -61,6 +63,7 @@ func (cc *ChartClient) GetContent(addr string) ([]byte, error) { if response.StatusCode != http.StatusOK { text, err := extractError(content) if err != nil { + err = errors.Wrap(err, "Extract content error failed") return nil, err } return nil, &commonhttp.Error{ @@ -106,7 +109,8 @@ func (cc *ChartClient) sendRequest(addr string, method string, body io.Reader) ( fullURI, err := url.Parse(addr) if err != nil { - return nil, fmt.Errorf("invalid url: %s", err.Error()) + err = errors.Wrap(err, "Invalid url") + return nil, err } request, err := http.NewRequest(method, addr, body) @@ -121,7 +125,7 @@ func (cc *ChartClient) sendRequest(addr string, method string, body io.Reader) ( response, err := cc.httpClient.Do(request) if err != nil { - hlog.Errorf("%s '%s' failed with error: %s", method, fullURI.Path, err) + err = errors.Wrap(err, fmt.Sprintf("send request %s %s failed", method, fullURI.Path)) return nil, err } diff --git a/src/chartserver/handler_manipulation.go b/src/chartserver/handler_manipulation.go index 9250f2476..bcec47731 100644 --- a/src/chartserver/handler_manipulation.go +++ b/src/chartserver/handler_manipulation.go @@ -2,19 +2,17 @@ package chartserver import ( "encoding/json" - "errors" "fmt" + "os" "strings" "github.com/ghodss/yaml" + "github.com/goharbor/harbor/src/common/utils/log" "github.com/goharbor/harbor/src/replication" rep_event "github.com/goharbor/harbor/src/replication/event" "github.com/goharbor/harbor/src/replication/model" + "github.com/pkg/errors" helm_repo "k8s.io/helm/pkg/repo" - - "os" - - "github.com/goharbor/harbor/src/common/utils/log" ) // ListCharts gets the chart list under the namespace diff --git a/src/common/api/base.go b/src/common/api/base.go index fba8c3621..928c37e08 100644 --- a/src/common/api/base.go +++ b/src/common/api/base.go @@ -20,12 +20,11 @@ import ( "net/http" "strconv" + "github.com/astaxie/beego" "github.com/astaxie/beego/validation" commonhttp "github.com/goharbor/harbor/src/common/http" "github.com/goharbor/harbor/src/common/utils/log" - - "errors" - "github.com/astaxie/beego" + "github.com/pkg/errors" ) const ( diff --git a/src/core/api/base.go b/src/core/api/base.go index bea127d0b..a3f3de4d3 100644 --- a/src/core/api/base.go +++ b/src/core/api/base.go @@ -15,9 +15,9 @@ package api import ( + "errors" "net/http" - "errors" "github.com/ghodss/yaml" "github.com/goharbor/harbor/src/common/api" "github.com/goharbor/harbor/src/common/security" diff --git a/src/core/api/project.go b/src/core/api/project.go index aaf0f2e02..e1441472d 100644 --- a/src/core/api/project.go +++ b/src/core/api/project.go @@ -18,6 +18,8 @@ import ( "fmt" "net/http" "regexp" + "strconv" + "time" "github.com/goharbor/harbor/src/common" "github.com/goharbor/harbor/src/common/dao" @@ -27,10 +29,7 @@ import ( errutil "github.com/goharbor/harbor/src/common/utils/error" "github.com/goharbor/harbor/src/common/utils/log" "github.com/goharbor/harbor/src/core/config" - - "errors" - "strconv" - "time" + "github.com/pkg/errors" ) type deletableResp struct { @@ -231,7 +230,10 @@ func (p *ProjectAPI) Get() { return } - p.populateProperties(p.project) + err := p.populateProperties(p.project) + if err != nil { + log.Errorf("populate project poroperties failed with : %+v", err) + } p.Data["json"] = p.project p.ServeJSON() @@ -401,15 +403,17 @@ func (p *ProjectAPI) List() { } for _, project := range result.Projects { - p.populateProperties(project) + err = p.populateProperties(project) + if err != nil { + log.Errorf("populate project properties failed %v", err) + } } - p.SetPaginationHeader(result.Total, page, size) p.Data["json"] = result.Projects p.ServeJSON() } -func (p *ProjectAPI) populateProperties(project *models.Project) { +func (p *ProjectAPI) populateProperties(project *models.Project) error { if p.SecurityCtx.IsAuthenticated() { roles := p.SecurityCtx.GetProjectRoles(project.ProjectID) if len(roles) != 0 { @@ -426,9 +430,8 @@ func (p *ProjectAPI) populateProperties(project *models.Project) { ProjectIDs: []int64{project.ProjectID}, }) if err != nil { - log.Errorf("failed to get total of repositories of project %d: %v", project.ProjectID, err) - p.SendInternalServerError(errors.New("")) - return + err = errors.Wrap(err, fmt.Sprintf("get repo count of project %d failed", project.ProjectID)) + return err } project.RepoCount = total @@ -437,13 +440,13 @@ func (p *ProjectAPI) populateProperties(project *models.Project) { if config.WithChartMuseum() { count, err := chartController.GetCountOfCharts([]string{project.Name}) if err != nil { - log.Errorf("Failed to get total of charts under project %s: %v", project.Name, err) - p.SendInternalServerError(errors.New("")) - return + err = errors.Wrap(err, fmt.Sprintf("get chart count of project %d failed", project.ProjectID)) + return err } project.ChartCount = count } + return nil } // Put ... From 9404810a1c14bda4ed9fb9544c19cb16a759cf87 Mon Sep 17 00:00:00 2001 From: AllForNothing Date: Thu, 18 Jul 2019 17:12:26 +0800 Subject: [PATCH 2/7] fix issue : time shown for scheduled scanning is incorrect Signed-off-by: AllForNothing --- .../lib/src/config/system/system-settings.component.html | 1 + .../vulnerability/vulnerability-config.component.html | 6 +++--- .../project-policy-config.component.html | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/portal/lib/src/config/system/system-settings.component.html b/src/portal/lib/src/config/system/system-settings.component.html index 1fcb25051..803348995 100644 --- a/src/portal/lib/src/config/system/system-settings.component.html +++ b/src/portal/lib/src/config/system/system-settings.component.html @@ -99,6 +99,7 @@ class="btn btn-link">{{'CVE_WHITELIST.ADD'|translate}}
+
diff --git a/src/portal/lib/src/config/vulnerability/vulnerability-config.component.html b/src/portal/lib/src/config/vulnerability/vulnerability-config.component.html index 7dc12abf4..c0023b470 100644 --- a/src/portal/lib/src/config/vulnerability/vulnerability-config.component.html +++ b/src/portal/lib/src/config/vulnerability/vulnerability-config.component.html @@ -11,17 +11,17 @@
{{nt.namespace}} - {{ convertToLocalTime(nt.last_update) | date:'MM/dd/y HH:mm:ss'}} AM + {{ convertToLocalTime(nt.last_update) | date:'short'}}
- {{ updatedTimestamp | date:'MM/dd/y HH:mm:ss' }} AM + {{ updatedTimestamp | date:'short' }}
diff --git a/src/portal/lib/src/project-policy-config/project-policy-config.component.html b/src/portal/lib/src/project-policy-config/project-policy-config.component.html index 9dcd87aa1..31912edc3 100644 --- a/src/portal/lib/src/project-policy-config/project-policy-config.component.html +++ b/src/portal/lib/src/project-policy-config/project-policy-config.component.html @@ -109,6 +109,7 @@ class="btn btn-link ml-1">{{'CVE_WHITELIST.ADD_SYSTEM'|translate}}
+
From 13772b859eef46606776ac3c2350e40a9816a12e Mon Sep 17 00:00:00 2001 From: stonezdj Date: Thu, 18 Jul 2019 17:22:21 +0800 Subject: [PATCH 3/7] Fix OnBoardGroup issue Signed-off-by: stonezdj Fix issue when adding a HTTP user group to a project member, returns HTTP 500 error. --- src/common/dao/group/usergroup.go | 15 ++++++++++----- src/common/dao/group/usergroup_test.go | 2 +- src/core/auth/authproxy/auth.go | 9 ++++++--- src/core/auth/authproxy/auth_test.go | 24 ++++++++++++++++++++++++ src/core/auth/ldap/ldap.go | 2 +- 5 files changed, 42 insertions(+), 10 deletions(-) diff --git a/src/common/dao/group/usergroup.go b/src/common/dao/group/usergroup.go index f17be1003..a6eedfec1 100644 --- a/src/common/dao/group/usergroup.go +++ b/src/common/dao/group/usergroup.go @@ -144,11 +144,7 @@ func UpdateUserGroupName(id int, groupName string) error { return err } -// OnBoardUserGroup will check if a usergroup exists in usergroup table, if not insert the usergroup and -// put the id in the pointer of usergroup model, if it does exist, return the usergroup's profile. -// This is used for ldap and uaa authentication, such the usergroup can have an ID in Harbor. -// the keyAttribute and combinedKeyAttribute are key columns used to check duplicate usergroup in harbor -func OnBoardUserGroup(g *models.UserGroup, keyAttribute string, combinedKeyAttributes ...string) error { +func onBoardCommonUserGroup(g *models.UserGroup, keyAttribute string, combinedKeyAttributes ...string) error { g.LdapGroupDN = utils.TrimLower(g.LdapGroupDN) o := dao.GetOrmer() @@ -172,3 +168,12 @@ func OnBoardUserGroup(g *models.UserGroup, keyAttribute string, combinedKeyAttri return nil } + +// OnBoardUserGroup will check if a usergroup exists in usergroup table, if not insert the usergroup and +// put the id in the pointer of usergroup model, if it does exist, return the usergroup's profile. +func OnBoardUserGroup(g *models.UserGroup) error { + if g.GroupType == common.LDAPGroupType { + return onBoardCommonUserGroup(g, "LdapGroupDN", "GroupType") + } + return onBoardCommonUserGroup(g, "GroupName", "GroupType") +} diff --git a/src/common/dao/group/usergroup_test.go b/src/common/dao/group/usergroup_test.go index 1cd8919e1..b4ad3897d 100644 --- a/src/common/dao/group/usergroup_test.go +++ b/src/common/dao/group/usergroup_test.go @@ -256,7 +256,7 @@ func TestOnBoardUserGroup(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := OnBoardUserGroup(tt.args.g, "LdapGroupDN", "GroupType"); (err != nil) != tt.wantErr { + if err := OnBoardUserGroup(tt.args.g); (err != nil) != tt.wantErr { t.Errorf("OnBoardUserGroup() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/src/core/auth/authproxy/auth.go b/src/core/auth/authproxy/auth.go index 9081ad8ea..f3efae49d 100644 --- a/src/core/auth/authproxy/auth.go +++ b/src/core/auth/authproxy/auth.go @@ -17,6 +17,7 @@ package authproxy import ( "crypto/tls" "encoding/json" + "errors" "fmt" "io/ioutil" "net/http" @@ -190,12 +191,14 @@ func (a *Auth) SearchGroup(groupKey string) (*models.UserGroup, error) { // OnBoardGroup create user group entity in Harbor DB, altGroupName is not used. func (a *Auth) OnBoardGroup(u *models.UserGroup, altGroupName string) error { // if group name provided, on board the user group - userGroup := &models.UserGroup{GroupName: u.GroupName, GroupType: common.HTTPGroupType} - err := group.OnBoardUserGroup(u, "GroupName", "GroupType") + if len(u.GroupName) == 0 { + return errors.New("Should provide a group name") + } + u.GroupType = common.HTTPGroupType + err := group.OnBoardUserGroup(u) if err != nil { return err } - u.ID = userGroup.ID return nil } diff --git a/src/core/auth/authproxy/auth_test.go b/src/core/auth/authproxy/auth_test.go index 07c035211..2dbcdf061 100644 --- a/src/core/auth/authproxy/auth_test.go +++ b/src/core/auth/authproxy/auth_test.go @@ -43,6 +43,7 @@ func TestMain(m *testing.M) { } mockSvr = test.NewMockServer(map[string]string{"jt": "pp", "Admin@vsphere.local": "Admin!23"}) defer mockSvr.Close() + defer dao.ExecuteBatchSQL([]string{"delete from user_group where group_name='OnBoardTest'"}) a = &Auth{ Endpoint: mockSvr.URL + "/test/login", TokenReviewEndpoint: mockSvr.URL + "/test/tokenreview", @@ -50,10 +51,17 @@ func TestMain(m *testing.M) { // So it won't require mocking the cfgManager settingTimeStamp: time.Now(), } + cfgMap := cut.GetUnitTestConfig() conf := map[string]interface{}{ common.HTTPAuthProxyEndpoint: a.Endpoint, common.HTTPAuthProxyTokenReviewEndpoint: a.TokenReviewEndpoint, common.HTTPAuthProxyVerifyCert: !a.SkipCertVerify, + common.PostGreSQLSSLMode: cfgMap[common.PostGreSQLSSLMode], + common.PostGreSQLUsername: cfgMap[common.PostGreSQLUsername], + common.PostGreSQLPort: cfgMap[common.PostGreSQLPort], + common.PostGreSQLHOST: cfgMap[common.PostGreSQLHOST], + common.PostGreSQLPassword: cfgMap[common.PostGreSQLPassword], + common.PostGreSQLDatabase: cfgMap[common.PostGreSQLDatabase], } config.InitWithSettings(conf) @@ -174,3 +182,19 @@ func TestAuth_PostAuthenticate(t *testing.T) { } } + +func TestAuth_OnBoardGroup(t *testing.T) { + input := &models.UserGroup{ + GroupName: "OnBoardTest", + GroupType: common.HTTPGroupType, + } + a.OnBoardGroup(input, "") + + assert.True(t, input.ID > 0, "The OnBoardGroup should have a valid group ID") + + emptyGroup := &models.UserGroup{} + err := a.OnBoardGroup(emptyGroup, "") + if err == nil { + t.Fatal("Empty user group should failed to OnBoard") + } +} diff --git a/src/core/auth/ldap/ldap.go b/src/core/auth/ldap/ldap.go index cf1963f7c..15a44da12 100644 --- a/src/core/auth/ldap/ldap.go +++ b/src/core/auth/ldap/ldap.go @@ -214,7 +214,7 @@ func (l *Auth) OnBoardGroup(u *models.UserGroup, altGroupName string) error { if len(userGroupList) > 0 { return auth.ErrDuplicateLDAPGroup } - return group.OnBoardUserGroup(u, "LdapGroupDN", "GroupType") + return group.OnBoardUserGroup(u) } // PostAuthenticate -- If user exist in harbor DB, sync email address, if not exist, call OnBoardUser From 96e2e0b1453b177062c34dc2fe8ae76e2767c9ee Mon Sep 17 00:00:00 2001 From: Daniel Jiang Date: Wed, 17 Jul 2019 16:19:56 +0800 Subject: [PATCH 4/7] Add API to ping OIDC endpoint This commit adds an API to help admin verify the OIDC endpoint is a valid one. Signed-off-by: Daniel Jiang --- docs/swagger.yaml | 33 +++++++++++++ src/common/utils/oidc/helper.go | 16 +++++++ src/common/utils/oidc/helper_test.go | 13 ++++++ src/core/api/harborapi_test.go | 1 + src/core/api/oidc.go | 56 ++++++++++++++++++++++ src/core/api/oidc_test.go | 69 ++++++++++++++++++++++++++++ src/core/router.go | 1 + 7 files changed, 189 insertions(+) create mode 100644 src/core/api/oidc.go create mode 100644 src/core/api/oidc_test.go diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 095e2077d..bb158bd26 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -3478,6 +3478,39 @@ paths: description: The robot account is not found. '500': description: Unexpected internal errors. + '/system/oidc/ping': + post: + summary: Test the OIDC endpoint. + description: Test the OIDC endpoint, the setting of the endpoint is provided in the request. This API can only + be called by system admin. + tags: + - Products + - System + parameters: + - name: endpoint + in: body + description: Request body for OIDC endpoint to be tested. + required: true + schema: + type: object + properties: + url: + type: string + description: The URL of OIDC endpoint to be tested. + verify_cert: + type: boolean + description: Whether the certificate should be verified + responses: + '200': + description: The specified robot account is successfully deleted. + '400': + description: The ping failed + '401': + description: User need to log in first. + '403': + description: User does not have permission to call this API + '500': + description: Unexpected internal errors. '/system/CVEWhitelist': get: summary: Get the system level whitelist of CVE. diff --git a/src/common/utils/oidc/helper.go b/src/common/utils/oidc/helper.go index a970d5942..30f14e209 100644 --- a/src/common/utils/oidc/helper.go +++ b/src/common/utils/oidc/helper.go @@ -206,3 +206,19 @@ func RefreshToken(ctx context.Context, token *Token) (*Token, error) { } return &Token{Token: *t, IDToken: it}, nil } + +// Conn wraps connection info of an OIDC endpoint +type Conn struct { + URL string `json:"url"` + VerifyCert bool `json:"verify_cert"` +} + +// TestEndpoint tests whether the endpoint is a valid OIDC endpoint. +// The nil return value indicates the success of the test +func TestEndpoint(conn Conn) error { + + // gooidc will try to call the discovery api when creating the provider and that's all we need to check + ctx := clientCtx(context.Background(), conn.VerifyCert) + _, err := gooidc.NewProvider(ctx, conn.URL) + return err +} diff --git a/src/common/utils/oidc/helper_test.go b/src/common/utils/oidc/helper_test.go index 8586e6301..d706836b8 100644 --- a/src/common/utils/oidc/helper_test.go +++ b/src/common/utils/oidc/helper_test.go @@ -97,3 +97,16 @@ func TestAuthCodeURL(t *testing.T) { assert.Equal(t, "offline", q.Get("access_type")) assert.False(t, strings.Contains(q.Get("scope"), "offline_access")) } + +func TestTestEndpoint(t *testing.T) { + c1 := Conn{ + URL: googleEndpoint, + VerifyCert: true, + } + c2 := Conn{ + URL: "https://www.baidu.com", + VerifyCert: false, + } + assert.Nil(t, TestEndpoint(c1)) + assert.NotNil(t, TestEndpoint(c2)) +} diff --git a/src/core/api/harborapi_test.go b/src/core/api/harborapi_test.go index eed976dfd..ed51699c8 100644 --- a/src/core/api/harborapi_test.go +++ b/src/core/api/harborapi_test.go @@ -145,6 +145,7 @@ func init() { beego.Router("/api/system/gc/schedule", &GCAPI{}, "get:Get;put:Put;post:Post") beego.Router("/api/system/scanAll/schedule", &ScanAllAPI{}, "get:Get;put:Put;post:Post") beego.Router("/api/system/CVEWhitelist", &SysCVEWhitelistAPI{}, "get:Get;put:Put") + beego.Router("/api/system/oidc/ping", &OIDCAPI{}, "post:Ping") beego.Router("/api/projects/:pid([0-9]+)/robots/", &RobotAPI{}, "post:Post;get:List") beego.Router("/api/projects/:pid([0-9]+)/robots/:id([0-9]+)", &RobotAPI{}, "get:Get;put:Put;delete:Delete") diff --git a/src/core/api/oidc.go b/src/core/api/oidc.go new file mode 100644 index 000000000..ed4688cf8 --- /dev/null +++ b/src/core/api/oidc.go @@ -0,0 +1,56 @@ +// 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 api + +import ( + "errors" + "github.com/goharbor/harbor/src/common/utils/log" + "github.com/goharbor/harbor/src/common/utils/oidc" +) + +// OIDCAPI handles the requests to /api/system/oidc/xxx +type OIDCAPI struct { + BaseController +} + +// Prepare validates the request initially +func (oa *OIDCAPI) Prepare() { + oa.BaseController.Prepare() + if !oa.SecurityCtx.IsAuthenticated() { + oa.SendUnAuthorizedError(errors.New("unauthorized")) + return + } + if !oa.SecurityCtx.IsSysAdmin() { + msg := "only system admin has permission to access this API" + log.Errorf(msg) + oa.SendForbiddenError(errors.New(msg)) + return + } +} + +// Ping will handles the request to test connection to OIDC endpoint +func (oa *OIDCAPI) Ping() { + var c oidc.Conn + if err := oa.DecodeJSONReq(&c); err != nil { + log.Error("Failed to decode JSON request.") + oa.SendBadRequestError(err) + return + } + if err := oidc.TestEndpoint(c); err != nil { + log.Errorf("Failed to verify connection: %+v, err: %v", c, err) + oa.SendBadRequestError(err) + return + } +} diff --git a/src/core/api/oidc_test.go b/src/core/api/oidc_test.go new file mode 100644 index 000000000..ec9ada990 --- /dev/null +++ b/src/core/api/oidc_test.go @@ -0,0 +1,69 @@ +// 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 api + +import ( + "github.com/goharbor/harbor/src/common/utils/oidc" + "net/http" + "testing" +) + +func TestOIDCAPI_Ping(t *testing.T) { + url := "/api/system/oidc/ping" + cases := []*codeCheckingCase{ + { // 401 + request: &testingRequest{ + method: http.MethodPost, + bodyJSON: oidc.Conn{}, + url: url, + }, + code: http.StatusUnauthorized, + }, + { // 403 + request: &testingRequest{ + method: http.MethodPost, + bodyJSON: oidc.Conn{}, + url: url, + credential: nonSysAdmin, + }, + code: http.StatusForbidden, + }, + { // 400 + request: &testingRequest{ + method: http.MethodPost, + bodyJSON: oidc.Conn{ + URL: "https://www.baidu.com", + VerifyCert: true, + }, + url: url, + credential: sysAdmin, + }, + code: http.StatusBadRequest, + }, + { // 200 + request: &testingRequest{ + method: http.MethodPost, + bodyJSON: oidc.Conn{ + URL: "https://accounts.google.com", + VerifyCert: true, + }, + url: url, + credential: sysAdmin, + }, + code: http.StatusOK, + }, + } + runCodeCheckingCases(t, cases...) +} diff --git a/src/core/router.go b/src/core/router.go index 344967c1d..5a857ee6f 100644 --- a/src/core/router.go +++ b/src/core/router.go @@ -97,6 +97,7 @@ func initRouters() { beego.Router("/api/system/gc/schedule", &api.GCAPI{}, "get:Get;put:Put;post:Post") beego.Router("/api/system/scanAll/schedule", &api.ScanAllAPI{}, "get:Get;put:Put;post:Post") beego.Router("/api/system/CVEWhitelist", &api.SysCVEWhitelistAPI{}, "get:Get;put:Put") + beego.Router("/api/system/oidc/ping", &api.OIDCAPI{}, "post:Ping") beego.Router("/api/logs", &api.LogAPI{}) From bd5b19501997d4e7f0b28b2a2832b239d95c6fd5 Mon Sep 17 00:00:00 2001 From: AllForNothing Date: Fri, 19 Jul 2019 14:08:22 +0800 Subject: [PATCH 5/7] UI Modification: When New Robot Signed-off-by: AllForNothing --- .../add-robot/add-robot.component.html | 76 ++++++++++--------- .../add-robot/add-robot.component.scss | 5 +- .../add-robot/add-robot.component.ts | 13 ++-- src/portal/src/i18n/lang/en-us-lang.json | 3 +- src/portal/src/i18n/lang/es-es-lang.json | 3 +- src/portal/src/i18n/lang/fr-fr-lang.json | 3 +- src/portal/src/i18n/lang/pt-br-lang.json | 3 +- src/portal/src/i18n/lang/zh-cn-lang.json | 3 +- 8 files changed, 62 insertions(+), 47 deletions(-) diff --git a/src/portal/src/app/project/robot-account/add-robot/add-robot.component.html b/src/portal/src/app/project/robot-account/add-robot/add-robot.component.html index e9227de9a..248631225 100644 --- a/src/portal/src/app/project/robot-account/add-robot/add-robot.component.html +++ b/src/portal/src/app/project/robot-account/add-robot/add-robot.component.html @@ -44,42 +44,46 @@ {{'ROBOT_ACCOUNT.PERMISSIONS' | translate}}
-
-
- -
- - -
-
- - -
-
-
- -
- - -
-
- - -
-
+
+ + + + + + + + + + + + + + + + +
{{'ROBOT_ACCOUNT.PUSH' | translate}}{{'ROBOT_ACCOUNT.PULL' | translate}}
+ {{'ROBOT_ACCOUNT.PERMISSIONS_IMAGE' | translate}} + + + + {{'ROBOT_ACCOUNT.PULL_IS_MUST' | translate}} + + + + + + +
{{'ROBOT_ACCOUNT.PERMISSIONS_HELMCHART' | translate}} + + + +
diff --git a/src/portal/src/app/project/robot-account/add-robot/add-robot.component.scss b/src/portal/src/app/project/robot-account/add-robot/add-robot.component.scss index 54652aa42..df3f83daa 100644 --- a/src/portal/src/app/project/robot-account/add-robot/add-robot.component.scss +++ b/src/portal/src/app/project/robot-account/add-robot/add-robot.component.scss @@ -42,5 +42,8 @@ } .padding-left-120{ - padding-left: 120px; + padding-left: 126px; +} +.w-90{ + width: 90%; } \ No newline at end of file diff --git a/src/portal/src/app/project/robot-account/add-robot/add-robot.component.ts b/src/portal/src/app/project/robot-account/add-robot/add-robot.component.ts index d88fba5df..805ad4e91 100644 --- a/src/portal/src/app/project/robot-account/add-robot/add-robot.component.ts +++ b/src/portal/src/app/project/robot-account/add-robot/add-robot.component.ts @@ -38,7 +38,8 @@ export class AddRobotComponent implements OnInit, OnDestroy { robotNameChecker: Subject = new Subject(); nameTooltipText = "ROBOT_ACCOUNT.ROBOT_NAME"; robotForm: NgForm; - imagePermission: string = "push-and-pull"; + imagePermissionPush: boolean = true; + imagePermissionPull: boolean = true; @Input() projectId: number; @Input() projectName: string; @Output() create = new EventEmitter(); @@ -99,6 +100,8 @@ export class AddRobotComponent implements OnInit, OnDestroy { this.robot.name = ""; this.robot.description = ""; this.addRobotOpened = true; + this.imagePermissionPush = true; + this.imagePermissionPull = true; this.isRobotNameValid = true; this.robot = new Robot(); this.nameTooltipText = "ROBOT_ACCOUNT.ROBOT_NAME"; @@ -118,12 +121,12 @@ export class AddRobotComponent implements OnInit, OnDestroy { return; } // set value to robot.access.isPullImage and robot.access.isPushOrPullImage when submit - if ( this.imagePermission === 'pull' ) { - this.robot.access.isPullImage = true; - this.robot.access.isPushOrPullImage = false; - } else { + if ( this.imagePermissionPush && this.imagePermissionPull) { this.robot.access.isPullImage = false; this.robot.access.isPushOrPullImage = true; + } else { + this.robot.access.isPullImage = true; + this.robot.access.isPushOrPullImage = false; } this.isSubmitOnGoing = true; this.robotService diff --git a/src/portal/src/i18n/lang/en-us-lang.json b/src/portal/src/i18n/lang/en-us-lang.json index e99464ab8..93bb2c978 100644 --- a/src/portal/src/i18n/lang/en-us-lang.json +++ b/src/portal/src/i18n/lang/en-us-lang.json @@ -322,7 +322,8 @@ "CREATED_SUCCESS": "Created '{{param}}' successfully.", "COPY_SUCCESS": "Copy token successfully of '{{param}}'", "DELETION_TITLE": "Confirm removal of robot accounts", - "DELETION_SUMMARY": "Do you want to delete robot accounts {{param}}?" + "DELETION_SUMMARY": "Do you want to delete robot accounts {{param}}?", + "PULL_IS_MUST" : "Pull permission is checked by default and can not be modified." }, "GROUP": { "GROUP": "Group", diff --git a/src/portal/src/i18n/lang/es-es-lang.json b/src/portal/src/i18n/lang/es-es-lang.json index 5c1d1450c..e3a9c2e62 100644 --- a/src/portal/src/i18n/lang/es-es-lang.json +++ b/src/portal/src/i18n/lang/es-es-lang.json @@ -323,7 +323,8 @@ "CREATED_SUCCESS": "Created '{{param}}' successfully.", "COPY_SUCCESS": "Copy token successfully of '{{param}}'", "DELETION_TITLE": "Confirm removal of robot accounts", - "DELETION_SUMMARY": "Do you want to delete robot accounts {{param}}?" + "DELETION_SUMMARY": "Do you want to delete robot accounts {{param}}?", + "PULL_IS_MUST" : "Pull permission is checked by default and can not be modified." }, "GROUP": { "GROUP": "Group", diff --git a/src/portal/src/i18n/lang/fr-fr-lang.json b/src/portal/src/i18n/lang/fr-fr-lang.json index ebd3bf090..b0e6fc08b 100644 --- a/src/portal/src/i18n/lang/fr-fr-lang.json +++ b/src/portal/src/i18n/lang/fr-fr-lang.json @@ -315,7 +315,8 @@ "CREATED_SUCCESS": "Created '{{param}}' successfully.", "COPY_SUCCESS": "Copy token successfully of '{{param}}'", "DELETION_TITLE": "confirmer l'enlèvement des comptes du robot ", - "DELETION_SUMMARY": "Voulez-vous supprimer la règle {{param}}?" + "DELETION_SUMMARY": "Voulez-vous supprimer la règle {{param}}?", + "PULL_IS_MUST" : "Pull permission is checked by default and can not be modified." }, "GROUP": { "Group": "Group", diff --git a/src/portal/src/i18n/lang/pt-br-lang.json b/src/portal/src/i18n/lang/pt-br-lang.json index 0358f2447..adbb68718 100644 --- a/src/portal/src/i18n/lang/pt-br-lang.json +++ b/src/portal/src/i18n/lang/pt-br-lang.json @@ -320,7 +320,8 @@ "CREATED_SUCCESS": "Created '{{param}}' successfully.", "COPY_SUCCESS": "Copy token successfully of '{{param}}'", "DELETION_TITLE": "Confirmar a remoção do robô Contas", - "DELETION_SUMMARY": "Você quer remover a regra {{param}}?" + "DELETION_SUMMARY": "Você quer remover a regra {{param}}?", + "PULL_IS_MUST" : "Pull permission is checked by default and can not be modified." }, "GROUP": { "GROUP": "Grupo", diff --git a/src/portal/src/i18n/lang/zh-cn-lang.json b/src/portal/src/i18n/lang/zh-cn-lang.json index 14a5a4243..a1940bb8c 100644 --- a/src/portal/src/i18n/lang/zh-cn-lang.json +++ b/src/portal/src/i18n/lang/zh-cn-lang.json @@ -321,7 +321,8 @@ "CREATED_SUCCESS": "创建账户 '{{param}}' 成功。", "COPY_SUCCESS": "成功复制 '{{param}}' 的令牌", "DELETION_TITLE": "删除账户确认", - "DELETION_SUMMARY": "你确认删除机器人账户 {{param}}?" + "DELETION_SUMMARY": "你确认删除机器人账户 {{param}}?", + "PULL_IS_MUST" : "拉取权限默认选中且不可修改。" }, "GROUP": { "GROUP": "组", From 791394a2b1d06f46046c7270432bce6e3b253584 Mon Sep 17 00:00:00 2001 From: Bernardo Pastorelli Date: Fri, 19 Jul 2019 16:26:38 +0200 Subject: [PATCH 6/7] Make jobservice use the proxy env variables (including no_proxy) Signed-off-by: Bernardo Pastorelli --- src/jobservice/hook/hook_client.go | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/src/jobservice/hook/hook_client.go b/src/jobservice/hook/hook_client.go index 075614322..820880f7b 100644 --- a/src/jobservice/hook/hook_client.go +++ b/src/jobservice/hook/hook_client.go @@ -21,18 +21,10 @@ import ( "io/ioutil" "net" "net/http" - "net/url" - "os" "strings" "time" "context" - "github.com/goharbor/harbor/src/jobservice/common/utils" -) - -const ( - proxyEnvHTTP = "http_proxy" - proxyEnvHTTPS = "https_proxy" ) // Client for handling the hook events @@ -60,19 +52,7 @@ func NewClient(ctx context.Context) Client { TLSHandshakeTimeout: 10 * time.Second, ResponseHeaderTimeout: 10 * time.Second, ExpectContinueTimeout: 1 * time.Second, - } - - // Get the http/https proxies - proxyAddr, ok := os.LookupEnv(proxyEnvHTTP) - if !ok { - proxyAddr, ok = os.LookupEnv(proxyEnvHTTPS) - } - - if ok && !utils.IsEmptyStr(proxyAddr) { - proxyURL, err := url.Parse(proxyAddr) - if err == nil { - transport.Proxy = http.ProxyURL(proxyURL) - } + Proxy: http.ProxyFromEnvironment, } client := &http.Client{ From 4f00c0e227b4e1cda30844dacdc988a5e7f2b9ae Mon Sep 17 00:00:00 2001 From: Daniel Jiang Date: Mon, 22 Jul 2019 12:52:28 +0800 Subject: [PATCH 7/7] Fix error in swagger doc for ping OIDC API Signed-off-by: Daniel Jiang --- docs/swagger.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/swagger.yaml b/docs/swagger.yaml index bb158bd26..ce165247a 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -3502,15 +3502,13 @@ paths: description: Whether the certificate should be verified responses: '200': - description: The specified robot account is successfully deleted. + description: Ping succeeded. The OIDC endpoint is valid. '400': description: The ping failed '401': description: User need to log in first. '403': description: User does not have permission to call this API - '500': - description: Unexpected internal errors. '/system/CVEWhitelist': get: summary: Get the system level whitelist of CVE.