Skip to content

Commit

Permalink
Skip scan in-toto sbom artifact
Browse files Browse the repository at this point in the history
  fixes goharbor#20337

Signed-off-by: stonezdj <stone.zhang@broadcom.com>
  • Loading branch information
stonezdj committed May 11, 2024
1 parent d01dfd4 commit 651e632
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 4 deletions.
21 changes: 21 additions & 0 deletions src/controller/artifact/controller.go
Expand Up @@ -56,6 +56,8 @@ import (
model_tag "github.com/goharbor/harbor/src/pkg/tag/model/tag"
)

const inTotoContentType = "application/vnd.in-toto+json"

var (
// Ctl is a global artifact controller instance
Ctl = NewController()
Expand Down Expand Up @@ -113,6 +115,8 @@ type Controller interface {
RemoveLabel(ctx context.Context, artifactID int64, labelID int64) (err error)
// Walk walks the artifact tree rooted at root, calling walkFn for each artifact in the tree, including root.
Walk(ctx context.Context, root *Artifact, walkFn func(*Artifact) error, option *Option) error
// HasUnscannableLayer check artifact with digest if has unscannable layer
HasUnscannableLayer(ctx context.Context, dgst string) (bool, error)
}

// NewController creates an instance of the default artifact controller
Expand Down Expand Up @@ -759,3 +763,20 @@ func (c *controller) populateAccessories(ctx context.Context, art *Artifact) {
}
art.Accessories = accs
}

// IsInToto check if it is a in-toto sbom, if it contains any blob with a content_type is application/vnd.in-toto+json, then consider as in-toto sbom
func (c *controller) HasUnscannableLayer(ctx context.Context, dgst string) (bool, error) {
if len(dgst) == 0 {
return false, nil
}
blobs, err := c.blobMgr.GetByArt(ctx, dgst)
if err != nil {
return false, err
}
for _, b := range blobs {
if b.ContentType == inTotoContentType {
return true, nil
}
}
return false, nil
}
24 changes: 24 additions & 0 deletions src/controller/artifact/controller_test.go
Expand Up @@ -35,6 +35,7 @@ import (
accessorymodel "github.com/goharbor/harbor/src/pkg/accessory/model"
basemodel "github.com/goharbor/harbor/src/pkg/accessory/model/base"
"github.com/goharbor/harbor/src/pkg/artifact"
"github.com/goharbor/harbor/src/pkg/blob/models"
"github.com/goharbor/harbor/src/pkg/label/model"
repomodel "github.com/goharbor/harbor/src/pkg/repository/model"
model_tag "github.com/goharbor/harbor/src/pkg/tag/model/tag"
Expand Down Expand Up @@ -678,6 +679,29 @@ func (c *controllerTestSuite) TestWalk() {
}
}

func (c *controllerTestSuite) TestIsIntoto() {
blobs := []*models.Blob{
{Digest: "sha256:00000", ContentType: "application/vnd.oci.image.manifest.v1+json"},
{Digest: "sha256:22222", ContentType: "application/vnd.oci.image.config.v1+json"},
{Digest: "sha256:11111", ContentType: inTotoContentType},
}
c.blobMgr.On("GetByArt", mock.Anything, mock.Anything).Return(blobs, nil).Once()
isIntoto, err := c.ctl.HasUnscannableLayer(context.Background(), "sha256: 77777")
c.Nil(err)
c.True(isIntoto)

blobs2 := []*models.Blob{
{Digest: "sha256:00000", ContentType: "application/vnd.oci.image.manifest.v1+json"},
{Digest: "sha256:22222", ContentType: "application/vnd.oci.image.config.v1+json"},
{Digest: "sha256:11111", ContentType: "application/vnd.oci.image.layer.v1.tar+gzip"},
}

c.blobMgr.On("GetByArt", mock.Anything, mock.Anything).Return(blobs2, nil).Once()
isIntoto2, err := c.ctl.HasUnscannableLayer(context.Background(), "sha256: 8888")
c.Nil(err)
c.False(isIntoto2)
}

func TestControllerTestSuite(t *testing.T) {
suite.Run(t, &controllerTestSuite{})
}
14 changes: 11 additions & 3 deletions src/controller/scan/base_controller.go
Expand Up @@ -52,7 +52,6 @@ import (
sbomModel "github.com/goharbor/harbor/src/pkg/scan/sbom/model"
"github.com/goharbor/harbor/src/pkg/scan/vuln"
"github.com/goharbor/harbor/src/pkg/task"
"github.com/goharbor/harbor/src/testing/controller/artifact"
)

var (
Expand Down Expand Up @@ -111,8 +110,6 @@ type basicController struct {
rc robot.Controller
// Tag controller
tagCtl tag.Controller
// Artifact controller
artCtl artifact.Controller
// UUID generator
uuid uuidGenerator
// Configuration getter func
Expand Down Expand Up @@ -199,6 +196,17 @@ func (bc *basicController) collectScanningArtifacts(ctx context.Context, r *scan
return nil
}

// because there are lots of in-toto sbom artifacts in dockerhub and replicated to Harbor, they are considered as image type
// when scanning these type of sbom artifact, they cause many pannic in the harbor-core log
// to avoid pannic, skip scan the in-toto sbom artifact sbom artifact
unscannable, err := bc.ar.HasUnscannableLayer(ctx, a.Digest)
if err != nil {
return err
}
if unscannable {
return nil
}

supported := hasCapability(r, a)

if !supported && a.IsImageIndex() {
Expand Down
11 changes: 11 additions & 0 deletions src/controller/scan/checker.go
Expand Up @@ -86,6 +86,17 @@ func (c *checker) IsScannable(ctx context.Context, art *artifact.Artifact) (bool
return artifact.ErrBreak
}

// because there are lots of in-toto sbom artifacts in dockerhub and replicated to Harbor, they are considered as image type
// when scanning these type of sbom artifact, they cause many pannic in the harbor-core log
// to avoid pannic, skip scan the in-toto sbom artifact sbom artifact
unscannable, err := c.artifactCtl.HasUnscannableLayer(ctx, a.Digest)
if err != nil {
return err
}
if unscannable {
return nil
}

return nil
}

Expand Down
3 changes: 2 additions & 1 deletion src/controller/scan/checker_test.go
Expand Up @@ -81,7 +81,7 @@ func (suite *CheckerTestSuite) TestIsScannable() {
walkFn := args.Get(2).(func(*artifact.Artifact) error)
walkFn(art)
})

mock.OnAnything(c.artifactCtl, "HasUnscannableLayer").Return(false, nil).Once()
isScannable, err := c.IsScannable(context.TODO(), art)
suite.Nil(err)
suite.False(isScannable)
Expand All @@ -97,6 +97,7 @@ func (suite *CheckerTestSuite) TestIsScannable() {
walkFn := args.Get(2).(func(*artifact.Artifact) error)
walkFn(art)
})
mock.OnAnything(c.artifactCtl, "HasUnscannableLayer").Return(false, nil).Once()

isScannable, err := c.IsScannable(context.TODO(), art)
suite.Nil(err)
Expand Down
28 changes: 28 additions & 0 deletions src/testing/controller/artifact/controller.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 651e632

Please sign in to comment.