mirror of
https://github.com/goharbor/harbor.git
synced 2024-12-22 16:48:30 +01:00
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 <jiangd@vmware.com>
This commit is contained in:
parent
e0e6a1d30b
commit
96e2e0b145
@ -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.
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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")
|
||||
|
56
src/core/api/oidc.go
Normal file
56
src/core/api/oidc.go
Normal file
@ -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
|
||||
}
|
||||
}
|
69
src/core/api/oidc_test.go
Normal file
69
src/core/api/oidc_test.go
Normal file
@ -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...)
|
||||
}
|
@ -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{})
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user