mirror of
https://github.com/goharbor/harbor
synced 2025-04-21 19:49:49 +00:00
fix: validate the existence of project for export cve api (#17437)
Validate the existence of the project for export CVE API handler, return not found error if the project is not exist. Closes: #17430 Signed-off-by: chlins <chenyuzh@vmware.com>
This commit is contained in:
parent
5d7a549620
commit
31a3c6d18c
@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/go-openapi/strfmt"
|
"github.com/go-openapi/strfmt"
|
||||||
|
|
||||||
"github.com/goharbor/harbor/src/common/rbac"
|
"github.com/goharbor/harbor/src/common/rbac"
|
||||||
|
"github.com/goharbor/harbor/src/controller/project"
|
||||||
"github.com/goharbor/harbor/src/controller/scandataexport"
|
"github.com/goharbor/harbor/src/controller/scandataexport"
|
||||||
"github.com/goharbor/harbor/src/jobservice/job"
|
"github.com/goharbor/harbor/src/jobservice/job"
|
||||||
"github.com/goharbor/harbor/src/lib/log"
|
"github.com/goharbor/harbor/src/lib/log"
|
||||||
@ -29,6 +30,7 @@ import (
|
|||||||
func newScanDataExportAPI() *scanDataExportAPI {
|
func newScanDataExportAPI() *scanDataExportAPI {
|
||||||
return &scanDataExportAPI{
|
return &scanDataExportAPI{
|
||||||
scanDataExportCtl: scandataexport.Ctl,
|
scanDataExportCtl: scandataexport.Ctl,
|
||||||
|
proCtl: project.Ctl,
|
||||||
sysArtifactMgr: systemartifact.Mgr,
|
sysArtifactMgr: systemartifact.Mgr,
|
||||||
userMgr: user.Mgr,
|
userMgr: user.Mgr,
|
||||||
}
|
}
|
||||||
@ -37,6 +39,7 @@ func newScanDataExportAPI() *scanDataExportAPI {
|
|||||||
type scanDataExportAPI struct {
|
type scanDataExportAPI struct {
|
||||||
BaseAPI
|
BaseAPI
|
||||||
scanDataExportCtl scandataexport.Controller
|
scanDataExportCtl scandataexport.Controller
|
||||||
|
proCtl project.Controller
|
||||||
sysArtifactMgr systemartifact.Manager
|
sysArtifactMgr systemartifact.Manager
|
||||||
userMgr user.Manager
|
userMgr user.Manager
|
||||||
}
|
}
|
||||||
@ -47,7 +50,7 @@ func (se *scanDataExportAPI) Prepare(ctx context.Context, operation string, para
|
|||||||
|
|
||||||
func (se *scanDataExportAPI) ExportScanData(ctx context.Context, params operation.ExportScanDataParams) middleware.Responder {
|
func (se *scanDataExportAPI) ExportScanData(ctx context.Context, params operation.ExportScanDataParams) middleware.Responder {
|
||||||
// validate the request params
|
// validate the request params
|
||||||
if err := validateScanExportParams(params); err != nil {
|
if err := se.validateScanExportParams(ctx, params); err != nil {
|
||||||
return se.SendError(ctx, err)
|
return se.SendError(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,13 +58,6 @@ func (se *scanDataExportAPI) ExportScanData(ctx context.Context, params operatio
|
|||||||
return se.SendError(ctx, err)
|
return se.SendError(ctx, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the MIME type for the export is the Generic vulnerability data
|
|
||||||
if params.XScanDataType != v1.MimeTypeGenericVulnerabilityReport {
|
|
||||||
error := &models.Error{Message: fmt.Sprintf("Unsupported MIME type : %s", params.XScanDataType)}
|
|
||||||
errors := &models.Errors{Errors: []*models.Error{error}}
|
|
||||||
return operation.NewExportScanDataBadRequest().WithPayload(errors)
|
|
||||||
}
|
|
||||||
|
|
||||||
scanDataExportJob := new(models.ScanDataExportJob)
|
scanDataExportJob := new(models.ScanDataExportJob)
|
||||||
|
|
||||||
secContext, err := se.GetSecurityContext(ctx)
|
secContext, err := se.GetSecurityContext(ctx)
|
||||||
@ -309,10 +305,17 @@ func (se *scanDataExportAPI) requireProjectsAccess(ctx context.Context, pids []i
|
|||||||
// validateScanExportParams validates scan data export request parameters by
|
// validateScanExportParams validates scan data export request parameters by
|
||||||
// following policies.
|
// following policies.
|
||||||
// rules:
|
// rules:
|
||||||
// 1. the criteria should not be empty
|
// 1. check the scan data type
|
||||||
// 2. currently only the export of single project is open
|
// 2. the criteria should not be empty
|
||||||
// 3. do not allow to input space in the repo/tag/cve_id (space will lead to misjudge for doublestar filter)
|
// 3. currently only the export of single project is open
|
||||||
func validateScanExportParams(params operation.ExportScanDataParams) error {
|
// 4. check the existence of project
|
||||||
|
// 5. do not allow to input space in the repo/tag/cve_id (space will lead to misjudge for doublestar filter)
|
||||||
|
func (se *scanDataExportAPI) validateScanExportParams(ctx context.Context, params operation.ExportScanDataParams) error {
|
||||||
|
// check if the MIME type for the export is the Generic vulnerability data
|
||||||
|
if params.XScanDataType != v1.MimeTypeGenericVulnerabilityReport {
|
||||||
|
return errors.BadRequestError(errors.Errorf("Unsupported MIME type : %s", params.XScanDataType))
|
||||||
|
}
|
||||||
|
|
||||||
criteria := params.Criteria
|
criteria := params.Criteria
|
||||||
if criteria == nil {
|
if criteria == nil {
|
||||||
return errors.BadRequestError(errors.Errorf("criteria is invalid: %v", criteria))
|
return errors.BadRequestError(errors.Errorf("criteria is invalid: %v", criteria))
|
||||||
@ -323,6 +326,16 @@ func validateScanExportParams(params operation.ExportScanDataParams) error {
|
|||||||
return errors.BadRequestError(errors.Errorf("only support export single project, invalid value: %v", criteria.Projects))
|
return errors.BadRequestError(errors.Errorf("only support export single project, invalid value: %v", criteria.Projects))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check whether the project exists
|
||||||
|
exist, err := se.proCtl.Exists(ctx, criteria.Projects[0])
|
||||||
|
if err != nil {
|
||||||
|
return errors.UnknownError(errors.Errorf("check the existence of project error: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
if !exist {
|
||||||
|
return errors.NotFoundError(errors.Errorf("project %d not found", criteria.Projects[0]))
|
||||||
|
}
|
||||||
|
|
||||||
// check spaces
|
// check spaces
|
||||||
space := " "
|
space := " "
|
||||||
inspectList := []string{criteria.Repositories, criteria.Tags, criteria.CVEIds}
|
inspectList := []string{criteria.Repositories, criteria.Tags, criteria.CVEIds}
|
||||||
|
@ -2,6 +2,7 @@ package handler
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -22,6 +23,7 @@ import (
|
|||||||
"github.com/goharbor/harbor/src/server/v2.0/models"
|
"github.com/goharbor/harbor/src/server/v2.0/models"
|
||||||
"github.com/goharbor/harbor/src/server/v2.0/restapi"
|
"github.com/goharbor/harbor/src/server/v2.0/restapi"
|
||||||
operation "github.com/goharbor/harbor/src/server/v2.0/restapi/operations/scan_data_export"
|
operation "github.com/goharbor/harbor/src/server/v2.0/restapi/operations/scan_data_export"
|
||||||
|
"github.com/goharbor/harbor/src/testing/controller/project"
|
||||||
"github.com/goharbor/harbor/src/testing/controller/scandataexport"
|
"github.com/goharbor/harbor/src/testing/controller/scandataexport"
|
||||||
"github.com/goharbor/harbor/src/testing/mock"
|
"github.com/goharbor/harbor/src/testing/mock"
|
||||||
systemartifacttesting "github.com/goharbor/harbor/src/testing/pkg/systemartifact"
|
systemartifacttesting "github.com/goharbor/harbor/src/testing/pkg/systemartifact"
|
||||||
@ -32,6 +34,7 @@ import (
|
|||||||
type ScanExportTestSuite struct {
|
type ScanExportTestSuite struct {
|
||||||
htesting.Suite
|
htesting.Suite
|
||||||
scanExportCtl *scandataexport.Controller
|
scanExportCtl *scandataexport.Controller
|
||||||
|
proCtl *project.Controller
|
||||||
sysArtifactMgr *systemartifacttesting.Manager
|
sysArtifactMgr *systemartifacttesting.Manager
|
||||||
userMgr *user.Manager
|
userMgr *user.Manager
|
||||||
}
|
}
|
||||||
@ -43,15 +46,18 @@ func (suite *ScanExportTestSuite) SetupSuite() {
|
|||||||
func (suite *ScanExportTestSuite) SetupTest() {
|
func (suite *ScanExportTestSuite) SetupTest() {
|
||||||
|
|
||||||
suite.scanExportCtl = &scandataexport.Controller{}
|
suite.scanExportCtl = &scandataexport.Controller{}
|
||||||
|
suite.proCtl = &project.Controller{}
|
||||||
suite.sysArtifactMgr = &systemartifacttesting.Manager{}
|
suite.sysArtifactMgr = &systemartifacttesting.Manager{}
|
||||||
suite.userMgr = &user.Manager{}
|
suite.userMgr = &user.Manager{}
|
||||||
suite.Config = &restapi.Config{
|
suite.Config = &restapi.Config{
|
||||||
ScanDataExportAPI: &scanDataExportAPI{
|
ScanDataExportAPI: &scanDataExportAPI{
|
||||||
scanDataExportCtl: suite.scanExportCtl,
|
scanDataExportCtl: suite.scanExportCtl,
|
||||||
|
proCtl: suite.proCtl,
|
||||||
sysArtifactMgr: suite.sysArtifactMgr,
|
sysArtifactMgr: suite.sysArtifactMgr,
|
||||||
userMgr: suite.userMgr,
|
userMgr: suite.userMgr,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
mock.OnAnything(suite.proCtl, "Exists").Return(true, nil)
|
||||||
suite.Suite.SetupSuite()
|
suite.Suite.SetupSuite()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,8 +101,17 @@ func (suite *ScanExportTestSuite) TestAuthorization() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *ScanExportTestSuite) TestValidateScanExportParams() {
|
func (suite *ScanExportTestSuite) TestValidateScanExportParams() {
|
||||||
// empty criteria should return error
|
api := newScanDataExportAPI()
|
||||||
err := validateScanExportParams(operation.ExportScanDataParams{})
|
api.proCtl = suite.proCtl
|
||||||
|
ctx := context.TODO()
|
||||||
|
// no scan data type should return error
|
||||||
|
err := api.validateScanExportParams(ctx, operation.ExportScanDataParams{})
|
||||||
|
suite.Error(err)
|
||||||
|
suite.True(errors.IsErr(err, errors.BadRequestCode))
|
||||||
|
|
||||||
|
xScanDataType := v1.MimeTypeGenericVulnerabilityReport
|
||||||
|
// empty params should return error
|
||||||
|
err = api.validateScanExportParams(ctx, operation.ExportScanDataParams{XScanDataType: xScanDataType})
|
||||||
suite.Error(err)
|
suite.Error(err)
|
||||||
suite.True(errors.IsErr(err, errors.BadRequestCode))
|
suite.True(errors.IsErr(err, errors.BadRequestCode))
|
||||||
|
|
||||||
@ -104,7 +119,7 @@ func (suite *ScanExportTestSuite) TestValidateScanExportParams() {
|
|||||||
criteria := models.ScanDataExportRequest{
|
criteria := models.ScanDataExportRequest{
|
||||||
Projects: []int64{200, 300},
|
Projects: []int64{200, 300},
|
||||||
}
|
}
|
||||||
err = validateScanExportParams(operation.ExportScanDataParams{Criteria: &criteria})
|
err = api.validateScanExportParams(ctx, operation.ExportScanDataParams{XScanDataType: xScanDataType, Criteria: &criteria})
|
||||||
suite.Error(err)
|
suite.Error(err)
|
||||||
suite.True(errors.IsErr(err, errors.BadRequestCode))
|
suite.True(errors.IsErr(err, errors.BadRequestCode))
|
||||||
|
|
||||||
@ -116,7 +131,7 @@ func (suite *ScanExportTestSuite) TestValidateScanExportParams() {
|
|||||||
Repositories: "test-repo1, test-repo2",
|
Repositories: "test-repo1, test-repo2",
|
||||||
Tags: "{test-tag1, test-tag2}",
|
Tags: "{test-tag1, test-tag2}",
|
||||||
}
|
}
|
||||||
err = validateScanExportParams(operation.ExportScanDataParams{Criteria: &criteria})
|
err = api.validateScanExportParams(ctx, operation.ExportScanDataParams{XScanDataType: xScanDataType, Criteria: &criteria})
|
||||||
suite.Error(err)
|
suite.Error(err)
|
||||||
suite.True(errors.IsErr(err, errors.BadRequestCode))
|
suite.True(errors.IsErr(err, errors.BadRequestCode))
|
||||||
|
|
||||||
@ -128,8 +143,22 @@ func (suite *ScanExportTestSuite) TestValidateScanExportParams() {
|
|||||||
Repositories: "test-repo1,test-repo2",
|
Repositories: "test-repo1,test-repo2",
|
||||||
Tags: "{test-tag1,test-tag2}",
|
Tags: "{test-tag1,test-tag2}",
|
||||||
}
|
}
|
||||||
err = validateScanExportParams(operation.ExportScanDataParams{Criteria: &criteria})
|
err = api.validateScanExportParams(ctx, operation.ExportScanDataParams{XScanDataType: xScanDataType, Criteria: &criteria})
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
|
|
||||||
|
// none exist project should return error
|
||||||
|
api.proCtl = &project.Controller{}
|
||||||
|
mock.OnAnything(api.proCtl, "Exists").Return(false, nil)
|
||||||
|
criteria = models.ScanDataExportRequest{
|
||||||
|
CVEIds: "CVE-123,CVE-456",
|
||||||
|
Labels: []int64{100},
|
||||||
|
Projects: []int64{200},
|
||||||
|
Repositories: "test-repo1,test-repo2",
|
||||||
|
Tags: "{test-tag1,test-tag2}",
|
||||||
|
}
|
||||||
|
err = api.validateScanExportParams(ctx, operation.ExportScanDataParams{XScanDataType: xScanDataType, Criteria: &criteria})
|
||||||
|
suite.Error(err)
|
||||||
|
suite.True(errors.IsErr(err, errors.NotFoundCode))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *ScanExportTestSuite) TestExportScanData() {
|
func (suite *ScanExportTestSuite) TestExportScanData() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user