fixes #16224, deny the request to scan an accessory.

Signed-off-by: Wang Yan <wangyan@vmware.com>
This commit is contained in:
Wang Yan 2022-01-30 03:03:39 +08:00 committed by GitHub
parent cda127c27e
commit 93c0e572a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 67 additions and 2 deletions

View File

@ -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 {

View File

@ -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)

View File

@ -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 {

View File

@ -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)

View File

@ -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"