mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-22 18:25:56 +01:00
fix 16224 (#16307)
fixes #16224, deny the request to scan an accessory. Signed-off-by: Wang Yan <wangyan@vmware.com>
This commit is contained in:
parent
cda127c27e
commit
93c0e572a0
@ -34,6 +34,7 @@ import (
|
||||
"github.com/goharbor/harbor/src/lib/orm"
|
||||
"github.com/goharbor/harbor/src/lib/q"
|
||||
"github.com/goharbor/harbor/src/lib/retry"
|
||||
"github.com/goharbor/harbor/src/pkg/accessory"
|
||||
allowlist "github.com/goharbor/harbor/src/pkg/allowlist/models"
|
||||
"github.com/goharbor/harbor/src/pkg/permission/types"
|
||||
"github.com/goharbor/harbor/src/pkg/robot/model"
|
||||
@ -94,6 +95,8 @@ type basicController struct {
|
||||
manager report.Manager
|
||||
// Artifact controller
|
||||
ar ar.Controller
|
||||
// Accessory manager
|
||||
acc accessory.Manager
|
||||
// Scanner controller
|
||||
sc sc.Controller
|
||||
// Robot account controller
|
||||
@ -121,6 +124,8 @@ func NewController() Controller {
|
||||
manager: report.NewManager(),
|
||||
// Refer to the default artifact controller
|
||||
ar: ar.Ctl,
|
||||
// Refer to the default accessory manager
|
||||
acc: accessory.Mgr,
|
||||
// Refer to the default scanner controller
|
||||
sc: sc.DefaultController,
|
||||
// Refer to the default robot account controller
|
||||
@ -171,6 +176,14 @@ func (bc *basicController) collectScanningArtifacts(ctx context.Context, r *scan
|
||||
)
|
||||
|
||||
walkFn := func(a *ar.Artifact) error {
|
||||
ok, err := bc.isAccessory(ctx, a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
supported := hasCapability(r, a)
|
||||
|
||||
if !supported && a.IsImageIndex() {
|
||||
@ -1049,6 +1062,17 @@ func (bc *basicController) getLatestTagOfArtifact(ctx context.Context, artifactI
|
||||
return tags[0].Name, nil
|
||||
}
|
||||
|
||||
func (bc *basicController) isAccessory(ctx context.Context, art *ar.Artifact) (bool, error) {
|
||||
ac, err := bc.acc.List(ctx, q.New(q.KeyWords{"ArtifactID": art.Artifact.ID, "digest": art.Artifact.Digest}))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if len(ac) > 0 {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func getArtifactID(extraAttrs map[string]interface{}) int64 {
|
||||
var artifactID float64
|
||||
if extraAttrs != nil {
|
||||
|
@ -19,6 +19,8 @@ import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
accessoryModel "github.com/goharbor/harbor/src/pkg/accessory/model"
|
||||
accessorytesting "github.com/goharbor/harbor/src/testing/pkg/accessory"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@ -58,6 +60,7 @@ type ControllerTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
artifactCtl *artifacttesting.Controller
|
||||
accessoryMgr *accessorytesting.Manager
|
||||
originalArtifactCtl artifact.Controller
|
||||
|
||||
tagCtl *tagtesting.FakeController
|
||||
@ -257,6 +260,7 @@ func (suite *ControllerTestSuite) SetupSuite() {
|
||||
params[sca.JobParameterRobot] = robotJSON
|
||||
|
||||
suite.ar = &artifacttesting.Controller{}
|
||||
suite.accessoryMgr = &accessorytesting.Manager{}
|
||||
|
||||
suite.tagCtl = &tagtesting.FakeController{}
|
||||
suite.tagCtl.On("List", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil)
|
||||
@ -270,6 +274,7 @@ func (suite *ControllerTestSuite) SetupSuite() {
|
||||
ar: suite.ar,
|
||||
sc: sc,
|
||||
rc: rc,
|
||||
acc: suite.accessoryMgr,
|
||||
tagCtl: suite.tagCtl,
|
||||
uuid: func() (string, error) {
|
||||
return "the-uuid-123", nil
|
||||
@ -307,6 +312,7 @@ func (suite *ControllerTestSuite) TestScanControllerScan() {
|
||||
}
|
||||
|
||||
{
|
||||
mock.OnAnything(suite.accessoryMgr, "List").Return([]accessoryModel.Accessory{}, nil).Once()
|
||||
// success
|
||||
mock.OnAnything(suite.ar, "Walk").Return(nil).Run(func(args mock.Arguments) {
|
||||
walkFn := args.Get(2).(func(*artifact.Artifact) error)
|
||||
@ -328,6 +334,7 @@ func (suite *ControllerTestSuite) TestScanControllerScan() {
|
||||
}
|
||||
|
||||
{
|
||||
mock.OnAnything(suite.accessoryMgr, "List").Return([]accessoryModel.Accessory{}, nil).Once()
|
||||
// delete old report failed
|
||||
mock.OnAnything(suite.ar, "Walk").Return(nil).Run(func(args mock.Arguments) {
|
||||
walkFn := args.Get(2).(func(*artifact.Artifact) error)
|
||||
@ -344,6 +351,7 @@ func (suite *ControllerTestSuite) TestScanControllerScan() {
|
||||
}
|
||||
|
||||
{
|
||||
mock.OnAnything(suite.accessoryMgr, "List").Return([]accessoryModel.Accessory{}, nil).Once()
|
||||
// a previous scan process is ongoing
|
||||
mock.OnAnything(suite.ar, "Walk").Return(nil).Run(func(args mock.Arguments) {
|
||||
walkFn := args.Get(2).(func(*artifact.Artifact) error)
|
||||
@ -415,6 +423,7 @@ func (suite *ControllerTestSuite) TestScanControllerGetReport() {
|
||||
|
||||
// TestScanControllerGetSummary ...
|
||||
func (suite *ControllerTestSuite) TestScanControllerGetSummary() {
|
||||
mock.OnAnything(suite.accessoryMgr, "List").Return([]accessoryModel.Accessory{}, nil).Once()
|
||||
mock.OnAnything(suite.ar, "Walk").Return(nil).Run(func(args mock.Arguments) {
|
||||
walkFn := args.Get(2).(func(*artifact.Artifact) error)
|
||||
walkFn(suite.artifact)
|
||||
@ -514,6 +523,8 @@ func (suite *ControllerTestSuite) TestScanAll() {
|
||||
"Create", ctx, "SCAN_ALL", int64(0), "SCHEDULE",
|
||||
).Return(executionID, nil).Once()
|
||||
|
||||
mock.OnAnything(suite.accessoryMgr, "List").Return([]accessoryModel.Accessory{}, nil).Once()
|
||||
|
||||
mock.OnAnything(suite.artifactCtl, "List").Return([]*artifact.Artifact{}, nil).Once()
|
||||
|
||||
suite.taskMgr.On("Count", ctx, q.New(q.KeyWords{"execution_id": executionID})).Return(int64(0), nil).Once()
|
||||
@ -536,6 +547,8 @@ func (suite *ControllerTestSuite) TestScanAll() {
|
||||
"Create", ctx, "SCAN_ALL", int64(0), "SCHEDULE",
|
||||
).Return(executionID, nil).Once()
|
||||
|
||||
mock.OnAnything(suite.accessoryMgr, "List").Return([]accessoryModel.Accessory{}, nil).Once()
|
||||
|
||||
mock.OnAnything(suite.artifactCtl, "List").Return([]*artifact.Artifact{suite.artifact}, nil).Once()
|
||||
mock.OnAnything(suite.ar, "Walk").Return(nil).Run(func(args mock.Arguments) {
|
||||
walkFn := args.Get(2).(func(*artifact.Artifact) error)
|
||||
|
@ -16,10 +16,11 @@ package scan
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/goharbor/harbor/src/controller/artifact"
|
||||
"github.com/goharbor/harbor/src/controller/artifact/processor/image"
|
||||
"github.com/goharbor/harbor/src/controller/scanner"
|
||||
"github.com/goharbor/harbor/src/lib/q"
|
||||
"github.com/goharbor/harbor/src/pkg/accessory"
|
||||
models "github.com/goharbor/harbor/src/pkg/scan/dao/scanner"
|
||||
)
|
||||
|
||||
@ -33,6 +34,7 @@ type Checker interface {
|
||||
func NewChecker() Checker {
|
||||
return &checker{
|
||||
artifactCtl: artifact.Ctl,
|
||||
accMgr: accessory.Mgr,
|
||||
scannerCtl: scanner.DefaultController,
|
||||
registrations: map[int64]*models.Registration{},
|
||||
}
|
||||
@ -40,6 +42,7 @@ func NewChecker() Checker {
|
||||
|
||||
type checker struct {
|
||||
artifactCtl artifact.Controller
|
||||
accMgr accessory.Manager
|
||||
scannerCtl scanner.Controller
|
||||
registrations map[int64]*models.Registration
|
||||
}
|
||||
@ -69,6 +72,14 @@ func (c *checker) IsScannable(ctx context.Context, art *artifact.Artifact) (bool
|
||||
var scannable bool
|
||||
|
||||
walkFn := func(a *artifact.Artifact) error {
|
||||
ok, err := c.isAccessory(ctx, a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
if hasCapability(r, a) {
|
||||
scannable = true
|
||||
return artifact.ErrBreak
|
||||
@ -84,6 +95,17 @@ func (c *checker) IsScannable(ctx context.Context, art *artifact.Artifact) (bool
|
||||
return scannable, nil
|
||||
}
|
||||
|
||||
func (c *checker) isAccessory(ctx context.Context, art *artifact.Artifact) (bool, error) {
|
||||
ac, err := c.accMgr.List(ctx, q.New(q.KeyWords{"ArtifactID": art.Artifact.ID, "digest": art.Artifact.Digest}))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if len(ac) > 0 {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// hasCapability returns true when scanner has capability for the artifact
|
||||
// See https://github.com/goharbor/pluggable-scanner-spec/issues/2 to get more info
|
||||
func hasCapability(r *models.Registration, a *artifact.Artifact) bool {
|
||||
|
@ -16,6 +16,8 @@ package scan
|
||||
|
||||
import (
|
||||
"context"
|
||||
accessoryModel "github.com/goharbor/harbor/src/pkg/accessory/model"
|
||||
accessorytesting "github.com/goharbor/harbor/src/testing/pkg/accessory"
|
||||
"testing"
|
||||
|
||||
"github.com/goharbor/harbor/src/controller/artifact"
|
||||
@ -34,10 +36,12 @@ type CheckerTestSuite struct {
|
||||
func (suite *CheckerTestSuite) new() *checker {
|
||||
artifactCtl := &artifacttesting.Controller{}
|
||||
scannerCtl := &scannertesting.Controller{}
|
||||
accessoryMgr := &accessorytesting.Manager{}
|
||||
|
||||
return &checker{
|
||||
artifactCtl: artifactCtl,
|
||||
scannerCtl: scannerCtl,
|
||||
accMgr: accessoryMgr,
|
||||
registrations: map[int64]*scanner.Registration{},
|
||||
}
|
||||
}
|
||||
@ -68,8 +72,10 @@ func (suite *CheckerTestSuite) TestIsScannable() {
|
||||
}, nil)
|
||||
|
||||
{
|
||||
|
||||
art := &artifact.Artifact{}
|
||||
|
||||
mock.OnAnything(c.accMgr, "List").Return([]accessoryModel.Accessory{}, nil).Once()
|
||||
mock.OnAnything(c.artifactCtl, "Walk").Return(nil).Once().Run(func(args mock.Arguments) {
|
||||
walkFn := args.Get(2).(func(*artifact.Artifact) error)
|
||||
walkFn(art)
|
||||
@ -85,6 +91,7 @@ func (suite *CheckerTestSuite) TestIsScannable() {
|
||||
art.Type = "IMAGE"
|
||||
art.ManifestMediaType = supportMimeType
|
||||
|
||||
mock.OnAnything(c.accMgr, "List").Return([]accessoryModel.Accessory{}, nil).Once()
|
||||
mock.OnAnything(c.artifactCtl, "Walk").Return(nil).Once().Run(func(args mock.Arguments) {
|
||||
walkFn := args.Get(2).(func(*artifact.Artifact) error)
|
||||
walkFn(art)
|
||||
|
@ -17,7 +17,6 @@ package handler
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/go-openapi/runtime/middleware"
|
||||
"github.com/goharbor/harbor/src/common/rbac"
|
||||
"github.com/goharbor/harbor/src/controller/artifact"
|
||||
|
Loading…
Reference in New Issue
Block a user