Display status in sbom_overview for image index (#20425)

fixes #20418

Signed-off-by: stonezdj <stone.zhang@broadcom.com>
This commit is contained in:
stonezdj(Daojun Zhang) 2024-05-15 19:52:39 +08:00 committed by GitHub
parent bb6c7242a4
commit df5b3618c7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 72 additions and 11 deletions

View File

@ -20,8 +20,10 @@ import (
"github.com/goharbor/harbor/src/controller/scan" "github.com/goharbor/harbor/src/controller/scan"
"github.com/goharbor/harbor/src/lib" "github.com/goharbor/harbor/src/lib"
"github.com/goharbor/harbor/src/lib/log" "github.com/goharbor/harbor/src/lib/log"
"github.com/goharbor/harbor/src/lib/q"
v1 "github.com/goharbor/harbor/src/pkg/scan/rest/v1" v1 "github.com/goharbor/harbor/src/pkg/scan/rest/v1"
sbomModel "github.com/goharbor/harbor/src/pkg/scan/sbom/model" sbomModel "github.com/goharbor/harbor/src/pkg/scan/sbom/model"
"github.com/goharbor/harbor/src/pkg/task"
"github.com/goharbor/harbor/src/server/v2.0/handler/model" "github.com/goharbor/harbor/src/server/v2.0/handler/model"
) )
@ -36,6 +38,7 @@ func NewScanReportAssembler(option *model.OverviewOptions, mimeTypes []string) *
scanChecker: scan.NewChecker(), scanChecker: scan.NewChecker(),
scanCtl: scan.DefaultController, scanCtl: scan.DefaultController,
mimeTypes: mimeTypes, mimeTypes: mimeTypes,
executionMgr: task.ExecMgr,
} }
} }
@ -43,6 +46,7 @@ func NewScanReportAssembler(option *model.OverviewOptions, mimeTypes []string) *
type ScanReportAssembler struct { type ScanReportAssembler struct {
scanChecker scan.Checker scanChecker scan.Checker
scanCtl scan.Controller scanCtl scan.Controller
executionMgr task.ExecutionManager
artifacts []*model.Artifact artifacts []*model.Artifact
mimeTypes []string mimeTypes []string
@ -89,7 +93,29 @@ func (assembler *ScanReportAssembler) Assemble(ctx context.Context) error {
if err != nil { if err != nil {
log.Warningf("get scan summary of artifact %s@%s for %s failed, error:%v", artifact.RepositoryName, artifact.Digest, v1.MimeTypeSBOMReport, err) log.Warningf("get scan summary of artifact %s@%s for %s failed, error:%v", artifact.RepositoryName, artifact.Digest, v1.MimeTypeSBOMReport, err)
} }
if len(overview) > 0 { if len(overview) == 0 {
log.Warningf("overview is empty, retrieve sbom status from execution")
query := q.New(q.KeyWords{"extra_attrs.artifact.digest": artifact.Digest, "extra_attrs.enabled_capabilities.type": "sbom"})
// sort by ID desc to get the latest execution
query.Sorts = []*q.Sort{q.NewSort("ID", true)}
execs, err := assembler.executionMgr.List(ctx, query)
if err != nil {
log.Warningf("get scan summary of artifact %s@%s for %s failed, error:%v", artifact.RepositoryName, artifact.Digest, v1.MimeTypeSBOMReport, err)
continue
}
// if no execs, means this artifact is not scanned, leave the sbom_overview empty
if len(execs) == 0 {
continue
}
artifact.SBOMOverView = map[string]interface{}{
sbomModel.ScanStatus: execs[0].Status,
sbomModel.StartTime: execs[0].StartTime,
sbomModel.EndTime: execs[0].EndTime,
sbomModel.Duration: int64(execs[0].EndTime.Sub(execs[0].StartTime).Seconds()),
}
continue
}
artifact.SBOMOverView = map[string]interface{}{ artifact.SBOMOverView = map[string]interface{}{
sbomModel.StartTime: overview[sbomModel.StartTime], sbomModel.StartTime: overview[sbomModel.StartTime],
sbomModel.EndTime: overview[sbomModel.EndTime], sbomModel.EndTime: overview[sbomModel.EndTime],
@ -101,6 +127,5 @@ func (assembler *ScanReportAssembler) Assemble(ctx context.Context) error {
} }
} }
} }
}
return nil return nil
} }

View File

@ -21,9 +21,11 @@ import (
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
v1sq "github.com/goharbor/harbor/src/pkg/scan/rest/v1" v1sq "github.com/goharbor/harbor/src/pkg/scan/rest/v1"
"github.com/goharbor/harbor/src/pkg/task"
"github.com/goharbor/harbor/src/server/v2.0/handler/model" "github.com/goharbor/harbor/src/server/v2.0/handler/model"
"github.com/goharbor/harbor/src/testing/controller/scan" "github.com/goharbor/harbor/src/testing/controller/scan"
"github.com/goharbor/harbor/src/testing/mock" "github.com/goharbor/harbor/src/testing/mock"
mockTask "github.com/goharbor/harbor/src/testing/pkg/task"
) )
type VulAssemblerTestSuite struct { type VulAssemblerTestSuite struct {
@ -101,6 +103,40 @@ func (suite *VulAssemblerTestSuite) TestAssembleSBOMOverview() {
} }
func (suite *VulAssemblerTestSuite) TestAssembleSBOMOverviewImageIndex() {
checker := &scan.Checker{}
scanCtl := &scan.Controller{}
exeMgr := &mockTask.ExecutionManager{}
assembler := ScanReportAssembler{
scanChecker: checker,
scanCtl: scanCtl,
executionMgr: exeMgr,
overviewOption: model.NewOverviewOptions(model.WithSBOM(true)),
mimeTypes: []string{v1sq.MimeTypeSBOMReport},
}
mock.OnAnything(checker, "IsScannable").Return(true, nil)
overview := map[string]interface{}{}
mock.OnAnything(scanCtl, "GetSummary").Return(overview, nil)
execs := []*task.Execution{
{ID: 1, Status: "Error"},
{ID: 2, Status: "Success"},
}
mock.OnAnything(exeMgr, "List").Return(execs, nil).Once()
var artifact model.Artifact
err := assembler.WithArtifacts(&artifact).Assemble(context.TODO())
suite.Nil(err)
suite.Equal(artifact.SBOMOverView["scan_status"], "Error")
mock.OnAnything(exeMgr, "List").Return(nil, nil).Once()
var artifact2 model.Artifact
err2 := assembler.WithArtifacts(&artifact2).Assemble(context.TODO())
suite.Nil(err2)
suite.Nil(artifact2.SBOMOverView, "sbom overview should be nil")
}
func TestVulAssemblerTestSuite(t *testing.T) { func TestVulAssemblerTestSuite(t *testing.T) {
suite.Run(t, &VulAssemblerTestSuite{}) suite.Run(t, &VulAssemblerTestSuite{})
} }