From 2e7db335b3d082aa184f24203c284e21a4e00734 Mon Sep 17 00:00:00 2001 From: "stonezdj(Daojun Zhang)" Date: Tue, 9 Apr 2024 17:30:53 +0800 Subject: [PATCH] Add auto generate SBOM on push feature (#20250) Signed-off-by: stonezdj Co-authored-by: stonezdj Co-authored-by: Wang Yan --- .../event/handler/internal/artifact.go | 5 ++++ src/controller/event/handler/internal/util.go | 19 ++++++++++++ .../event/handler/internal/util_test.go | 30 +++++++++++++++++++ 3 files changed, 54 insertions(+) diff --git a/src/controller/event/handler/internal/artifact.go b/src/controller/event/handler/internal/artifact.go index fb212ac87..9218db95a 100644 --- a/src/controller/event/handler/internal/artifact.go +++ b/src/controller/event/handler/internal/artifact.go @@ -258,6 +258,11 @@ func (a *ArtifactEventHandler) onPush(ctx context.Context, event *event.Artifact if err := autoScan(ctx, &artifact.Artifact{Artifact: *event.Artifact}, event.Tags...); err != nil { log.Errorf("scan artifact %s@%s failed, error: %v", event.Artifact.RepositoryName, event.Artifact.Digest, err) } + + log.Debugf("auto generate sbom is triggered for artifact event %+v", event) + if err := autoGenSBOM(ctx, &artifact.Artifact{Artifact: *event.Artifact}); err != nil { + log.Errorf("generate sbom for artifact %s@%s failed, error: %v", event.Artifact.RepositoryName, event.Artifact.Digest, err) + } }() return nil diff --git a/src/controller/event/handler/internal/util.go b/src/controller/event/handler/internal/util.go index c7cf51243..cc10e09ca 100644 --- a/src/controller/event/handler/internal/util.go +++ b/src/controller/event/handler/internal/util.go @@ -20,6 +20,7 @@ import ( "github.com/goharbor/harbor/src/controller/artifact" "github.com/goharbor/harbor/src/controller/project" "github.com/goharbor/harbor/src/controller/scan" + "github.com/goharbor/harbor/src/lib/log" "github.com/goharbor/harbor/src/lib/orm" ) @@ -43,3 +44,21 @@ func autoScan(ctx context.Context, a *artifact.Artifact, tags ...string) error { return scan.DefaultController.Scan(ctx, a, options...) })(orm.SetTransactionOpNameToContext(ctx, "tx-auto-scan")) } + +func autoGenSBOM(ctx context.Context, a *artifact.Artifact) error { + proj, err := project.Ctl.Get(ctx, a.ProjectID) + if err != nil { + return err + } + if !proj.AutoSBOMGen() { + return nil + } + // transaction here to work with the image index + return orm.WithTransaction(func(ctx context.Context) error { + options := []scan.Option{} + // TODO: extract the sbom scan type to a constant + options = append(options, scan.WithScanType("sbom")) + log.Debugf("sbom scan controller artifact %+v, options %+v", a, options) + return scan.DefaultController.Scan(ctx, a, options...) + })(orm.SetTransactionOpNameToContext(ctx, "tx-auto-gen-sbom")) +} diff --git a/src/controller/event/handler/internal/util_test.go b/src/controller/event/handler/internal/util_test.go index 615fad9f6..4a48378a4 100644 --- a/src/controller/event/handler/internal/util_test.go +++ b/src/controller/event/handler/internal/util_test.go @@ -95,6 +95,36 @@ func (suite *AutoScanTestSuite) TestAutoScan() { suite.Nil(autoScan(ctx, art)) } +func (suite *AutoScanTestSuite) TestAutoScanSBOM() { + mock.OnAnything(suite.projectController, "Get").Return(&proModels.Project{ + Metadata: map[string]string{ + proModels.ProMetaAutoSBOMGen: "true", + }, + }, nil) + + mock.OnAnything(suite.scanController, "Scan").Return(nil) + + ctx := orm.NewContext(nil, &ormtesting.FakeOrmer{}) + art := &artifact.Artifact{} + + suite.Nil(autoGenSBOM(ctx, art)) +} + +func (suite *AutoScanTestSuite) TestAutoScanSBOMFalse() { + mock.OnAnything(suite.projectController, "Get").Return(&proModels.Project{ + Metadata: map[string]string{ + proModels.ProMetaAutoSBOMGen: "false", + }, + }, nil) + + mock.OnAnything(suite.scanController, "Scan").Return(nil) + + ctx := orm.NewContext(nil, &ormtesting.FakeOrmer{}) + art := &artifact.Artifact{} + + suite.Nil(autoGenSBOM(ctx, art)) +} + func (suite *AutoScanTestSuite) TestAutoScanFailed() { mock.OnAnything(suite.projectController, "Get").Return(&proModels.Project{ Metadata: map[string]string{