Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use node-agent generated SBOM #249

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions controllers/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func (h HTTPController) GenerateSBOM(c *gin.Context) {
if err != nil {
logger.L().Ctx(ctx).Error("validation error", helpers.Error(err),
helpers.String("imageSlug", newScan.ImageSlug),
helpers.String("imageTag", newScan.ImageTag),
helpers.String("imageTagNormalized", newScan.ImageTagNormalized),
helpers.String("imageHash", newScan.ImageHash))
_, _ = problem.Of(http.StatusInternalServerError).Append(details).WriteTo(c.Writer)
return
Expand All @@ -64,7 +64,7 @@ func (h HTTPController) GenerateSBOM(c *gin.Context) {
if err != nil {
logger.L().Ctx(ctx).Error("service error - GenerateSBOM", helpers.Error(err),
helpers.String("imageSlug", newScan.ImageSlug),
helpers.String("imageTag", newScan.ImageTag),
helpers.String("imageTagNormalized", newScan.ImageTagNormalized),
helpers.String("imageHash", newScan.ImageHash))
}
})
Expand Down Expand Up @@ -105,7 +105,7 @@ func (h HTTPController) ScanCVE(c *gin.Context) {
if err != nil {
logger.L().Ctx(ctx).Error("validation error", helpers.Error(err),
helpers.String("imageSlug", newScan.ImageSlug),
helpers.String("imageTag", newScan.ImageTag),
helpers.String("imageTagNormalized", newScan.ImageTagNormalized),
helpers.String("imageHash", newScan.ImageHash))
_, _ = problem.Of(http.StatusInternalServerError).Append(details).WriteTo(c.Writer)
return
Expand All @@ -119,27 +119,28 @@ func (h HTTPController) ScanCVE(c *gin.Context) {
logger.L().Ctx(ctx).Error("service error - ScanCVE", helpers.Error(err),
helpers.String("wlid", newScan.Wlid),
helpers.String("imageSlug", newScan.ImageSlug),
helpers.String("imageTag", newScan.ImageTag),
helpers.String("imageTagNormalized", newScan.ImageTagNormalized),
helpers.String("imageHash", newScan.ImageHash))
}
})
}

func websocketScanCommandToScanCommand(c wssc.WebsocketScanCommand) domain.ScanCommand {
imageTagNormalized := tools.NormalizeReference(c.ImageTag)
command := domain.ScanCommand{
CredentialsList: c.Credentialslist,
ImageHash: c.ImageHash,
Wlid: c.Wlid,
ImageTag: c.ImageTag,
ImageTagNormalized: tools.NormalizeReference(c.ImageTag),
ImageTagNormalized: imageTagNormalized,
JobID: c.JobID,
ContainerName: c.ContainerName,
LastAction: c.LastAction,
ParentJobID: c.ParentJobID,
Args: c.Args,
Session: sessionChainToSession(c.Session),
}
if slug, err := names.ImageInfoToSlug(c.ImageTag, c.ImageHash); err == nil {
if slug, err := names.ImageInfoToSlug(imageTagNormalized, c.ImageHash); err == nil {
command.ImageSlug = slug
}
if c.InstanceID != nil {
Expand Down Expand Up @@ -173,7 +174,7 @@ func (h HTTPController) ScanRegistry(c *gin.Context) {
if err != nil {
logger.L().Ctx(ctx).Error("validation error", helpers.Error(err),
helpers.String("imageSlug", newScan.ImageSlug),
helpers.String("imageTag", newScan.ImageTag),
helpers.String("imageTagNormalized", newScan.ImageTagNormalized),
helpers.String("imageHash", newScan.ImageHash))
_, _ = problem.Of(http.StatusInternalServerError).Append(details).WriteTo(c.Writer)
return
Expand All @@ -186,7 +187,7 @@ func (h HTTPController) ScanRegistry(c *gin.Context) {
if err != nil {
logger.L().Ctx(ctx).Error("service error - ScanRegistry", helpers.Error(err),
helpers.String("imageSlug", newScan.ImageSlug),
helpers.String("imageTag", newScan.ImageTag),
helpers.String("imageTagNormalized", newScan.ImageTagNormalized),
helpers.String("imageHash", newScan.ImageHash))
}
})
Expand Down
18 changes: 10 additions & 8 deletions core/domain/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ var (
ErrSBOMWithPartialArtifacts = errors.New("SBOM having partial artifacts")
ErrInvalidScanID = errors.New("invalid scanID")
ErrMissingImageInfo = errors.New("missing image information")
ErrMissingSBOM = errors.New("missing SBOM")
ErrMissingScanID = errors.New("missing scanID")
ErrMissingTimestamp = errors.New("missing timestamp")
ErrCastingWorkload = errors.New("casting workload")
Expand All @@ -37,14 +38,15 @@ type ScanCommand struct {
ImageSlug string
InstanceID string
Wlid string
ImageTag string
JobID string
ContainerName string
ParentJobID string
ImageHash string
CredentialsList []registry.AuthConfig
Session Session
LastAction int
// deprecated
ImageTag string
JobID string
ContainerName string
ParentJobID string
ImageHash string
CredentialsList []registry.AuthConfig
Session Session
LastAction int
}

type Session struct {
Expand Down
34 changes: 12 additions & 22 deletions core/services/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ func (s *ScanService) checkCreateSBOM(err error, key string) {
}

// GenerateSBOM implements the "Generate SBOM flow"
// FIXME check if we still use this method
func (s *ScanService) GenerateSBOM(ctx context.Context) error {
ctx, span := otel.Tracer("").Start(ctx, "ScanService.GenerateSBOM")
defer span.End()
Expand All @@ -97,7 +98,7 @@ func (s *ScanService) GenerateSBOM(ctx context.Context) error {
// if SBOM is not available, create it
if sbom.Content == nil {
// create SBOM
sbom, err = s.sbomCreator.CreateSBOM(ctx, workload.ImageSlug, workload.ImageHash, workload.ImageTag, optionsFromWorkload(workload))
sbom, err = s.sbomCreator.CreateSBOM(ctx, workload.ImageSlug, workload.ImageHash, workload.ImageTagNormalized, optionsFromWorkload(workload))
s.checkCreateSBOM(err, workload.ImageHash)
if err != nil {
return err
Expand Down Expand Up @@ -167,20 +168,9 @@ func (s *ScanService) ScanCVE(ctx context.Context) error {

// if SBOM is not available, create it
if sbom.Content == nil {
// create SBOM
sbom, err = s.sbomCreator.CreateSBOM(ctx, workload.ImageSlug, workload.ImageHash, workload.ImageTag, optionsFromWorkload(workload))
s.checkCreateSBOM(err, workload.ImageHash)
if err != nil {
return fmt.Errorf("error creating SBOM: %w", err)
}
// store SBOM
if s.storage {
err = s.sbomRepository.StoreSBOM(ctx, sbom)
if err != nil {
logger.L().Ctx(ctx).Warning("error storing SBOM", helpers.Error(err),
helpers.String("imageSlug", workload.ImageSlug))
}
}
logger.L().Ctx(ctx).Warning("missing SBOM",
helpers.String("imageSlug", workload.ImageSlug))
return domain.ErrMissingSBOM
}

// do not process timed out SBOM
Expand Down Expand Up @@ -325,8 +315,8 @@ func (s *ScanService) ScanRegistry(ctx context.Context) error {
}

// create SBOM
sbom, err := s.sbomCreator.CreateSBOM(ctx, workload.ImageSlug, workload.ImageHash, workload.ImageTag, optionsFromWorkload(workload))
s.checkCreateSBOM(err, workload.ImageTag)
sbom, err := s.sbomCreator.CreateSBOM(ctx, workload.ImageSlug, workload.ImageHash, workload.ImageTagNormalized, optionsFromWorkload(workload))
s.checkCreateSBOM(err, workload.ImageTagNormalized)
if err != nil {
repErr := s.platform.ReportError(ctx, err)
if repErr != nil {
Expand Down Expand Up @@ -400,8 +390,8 @@ func generateScanID(workload domain.ScanCommand, scannerVersion string) string {
return fmt.Sprintf("%s-%s", workload.InstanceID, scannerVersion)
}

if workload.ImageTag != "" && workload.ImageHash != "" {
sum := sha256.Sum256([]byte(workload.ImageTag + workload.ImageHash + scannerVersion))
if workload.ImageTagNormalized != "" && workload.ImageHash != "" {
sum := sha256.Sum256([]byte(workload.ImageTagNormalized + workload.ImageHash + scannerVersion))
if scanID := fmt.Sprintf("%x", sum); armotypes.ValidateContainerScanID(scanID) {
return scanID
}
Expand All @@ -421,7 +411,7 @@ func optionsFromWorkload(workload domain.ScanCommand) domain.RegistryOptions {
}

logger.L().Debug("created registryOptions from workload",
helpers.String("imageTag", workload.ImageTag),
helpers.String("imageTagNormalized", workload.ImageTagNormalized),
helpers.String("credentials", credentialsLog(options.Credentials)))
return options
}
Expand Down Expand Up @@ -533,7 +523,7 @@ func (s *ScanService) ValidateScanRegistry(ctx context.Context, workload domain.

ctx = enrichContext(ctx, workload, s.sbomCreator.Version())
// validate inputs
if workload.ImageTag == "" || workload.ImageSlug == "" {
if workload.ImageTagNormalized == "" || workload.ImageSlug == "" {
return ctx, domain.ErrMissingImageInfo
}
// add imageSlug to parent span
Expand All @@ -543,7 +533,7 @@ func (s *ScanService) ValidateScanRegistry(ctx context.Context, workload domain.
ctx = trace.ContextWithSpan(ctx, parentSpan)
}
// check if previous image pull resulted in TOOMANYREQUESTS error
if _, ok := s.tooManyRequests.Get(workload.ImageTag); ok {
if _, ok := s.tooManyRequests.Get(workload.ImageTagNormalized); ok {
return ctx, domain.ErrTooManyRequests
}
return ctx, nil
Expand Down
64 changes: 16 additions & 48 deletions core/services/scan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,19 +128,15 @@ func TestScanService_GenerateSBOM(t *testing.T) {

func TestScanService_ScanCVE(t *testing.T) {
tests := []struct {
createSBOMError bool
name string
instanceID string
emptyWlid bool
cveManifest bool
sbom bool
storage bool
getErrorCVE bool
getErrorSBOM bool
storeErrorCVE bool
storeErrorSBOM bool
timeout bool
toomanyrequests bool
workload bool
wantCvep bool
wantEmptyReport bool
Expand All @@ -154,19 +150,7 @@ func TestScanService_ScanCVE(t *testing.T) {
{
name: "no storage",
workload: true,
wantErr: false,
},
{
name: "create SBOM error",
createSBOMError: true,
workload: true,
wantErr: true,
},
{
name: "create SBOM too many requests",
toomanyrequests: true,
workload: true,
wantErr: true,
wantErr: true,
},
{
name: "empty wlid",
Expand All @@ -185,7 +169,6 @@ func TestScanService_ScanCVE(t *testing.T) {
name: "second scan",
storage: true,
cveManifest: true,
sbom: true,
workload: true,
wantEmptyReport: false,
wantErr: false,
Expand All @@ -195,14 +178,7 @@ func TestScanService_ScanCVE(t *testing.T) {
getErrorSBOM: true,
storage: true,
workload: true,
wantErr: false,
},
{
name: "store SBOM failed",
storeErrorSBOM: true,
storage: true,
workload: true,
wantErr: false,
wantErr: true,
},
{
name: "get CVE failed",
Expand All @@ -220,15 +196,13 @@ func TestScanService_ScanCVE(t *testing.T) {
},
{
name: "timeout SBOM",
sbom: true,
storage: true,
timeout: true,
workload: true,
wantErr: true,
},
{
name: "with SBOMp",
sbom: true,
instanceID: "ee9bdd0adec9ce004572faf3492f583aa82042a8b3a9d5c7d9179dc03c531eef",
storage: true,
workload: true,
Expand All @@ -243,9 +217,9 @@ func TestScanService_ScanCVE(t *testing.T) {
if tt.emptyWlid {
wlid = ""
}
sbomAdapter := adapters.NewMockSBOMAdapter(tt.createSBOMError, tt.timeout, tt.toomanyrequests)
sbomAdapter := adapters.NewMockSBOMAdapter(false, tt.timeout, false)
cveAdapter := adapters.NewMockCVEAdapter()
storageSBOM := repositories.NewMemoryStorage(tt.getErrorSBOM, tt.storeErrorSBOM)
storageSBOM := repositories.NewMemoryStorage(tt.getErrorSBOM, false)
storageCVE := repositories.NewMemoryStorage(tt.getErrorCVE, tt.storeErrorCVE)
s := NewScanService(sbomAdapter,
storageSBOM,
Expand All @@ -270,15 +244,13 @@ func TestScanService_ScanCVE(t *testing.T) {
ctx, err = s.ValidateScanCVE(ctx, workload)
require.NoError(t, err)
}
if tt.sbom {
sbom, err := sbomAdapter.CreateSBOM(ctx, "imageSlug", imageHash, "", domain.RegistryOptions{})
sbom, err := sbomAdapter.CreateSBOM(ctx, "imageSlug", imageHash, "", domain.RegistryOptions{})
require.NoError(t, err)
_ = storageSBOM.StoreSBOM(ctx, sbom)
if tt.cveManifest {
cve, err := cveAdapter.ScanSBOM(ctx, sbom)
require.NoError(t, err)
_ = storageSBOM.StoreSBOM(ctx, sbom)
if tt.cveManifest {
cve, err := cveAdapter.ScanSBOM(ctx, sbom)
require.NoError(t, err)
_ = storageCVE.StoreCVE(ctx, cve, false)
}
_ = storageCVE.StoreCVE(ctx, cve, false)
}
var sbomp domain.SBOM
if tt.instanceID != "" {
Expand All @@ -291,10 +263,6 @@ func TestScanService_ScanCVE(t *testing.T) {
if err := s.ScanCVE(ctx); (err != nil) != tt.wantErr {
t.Errorf("ScanCVE() error = %v, wantErr %v", err, tt.wantErr)
}
if tt.toomanyrequests {
_, err := s.ValidateScanCVE(ctx, workload)
assert.Equal(t, domain.ErrTooManyRequests, err)
}
if tt.wantCvep {
cvep, err := storageCVE.GetCVE(ctx, sbomp.Name, sbomAdapter.Version(), cveAdapter.Version(ctx), cveAdapter.DBVersion(ctx))
require.NoError(t, err)
Expand Down Expand Up @@ -492,8 +460,8 @@ func TestScanService_ScanRegistry(t *testing.T) {
false, false)
ctx := context.TODO()
workload := domain.ScanCommand{
ImageSlug: "imageSlug",
ImageTag: "k8s.gcr.io/kube-proxy:v1.24.3",
ImageSlug: "imageSlug",
ImageTagNormalized: "k8s.gcr.io/kube-proxy:v1.24.3",
}
workload.CredentialsList = []registry.AuthConfig{
{
Expand Down Expand Up @@ -537,8 +505,8 @@ func TestScanService_ValidateScanRegistry(t *testing.T) {
{
name: "with imageID",
workload: domain.ScanCommand{
ImageSlug: "imageSlug",
ImageTag: "k8s.gcr.io/kube-proxy:v1.24.3",
ImageSlug: "imageSlug",
ImageTagNormalized: "k8s.gcr.io/kube-proxy:v1.24.3",
},
wantErr: false,
},
Expand Down Expand Up @@ -574,8 +542,8 @@ func Test_generateScanID(t *testing.T) {
name: "generate scanID with imageHash",
args: args{
workload: domain.ScanCommand{
ImageTag: "k8s.gcr.io/kube-proxy:v1.24.3",
ImageHash: "sha256:6f9c1c5b5b1b2b3b4b5b6b7b8b9b0b1b2b3b4b5b6b7b8b9b0b1b2b3b4b5b6b7b",
ImageTagNormalized: "k8s.gcr.io/kube-proxy:v1.24.3",
ImageHash: "sha256:6f9c1c5b5b1b2b3b4b5b6b7b8b9b0b1b2b3b4b5b6b7b8b9b0b1b2b3b4b5b6b7b",
},
},
want: "2d0ee020566e8ff66542c5cd9e324111731c6a49d237fea3bd880448dac1a37f",
Expand Down
2 changes: 1 addition & 1 deletion internal/tools/tools.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,5 +106,5 @@ func NormalizeReference(ref string) string {
if err != nil {
return ref
}
return n.String()
return reference.TagNameOnly(n).String()
}
7 changes: 7 additions & 0 deletions internal/tools/tools_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ func TestNormalizeReference(t *testing.T) {
args args
want string
}{
{
name: "image tag only - assuming latest",
args: args{
ref: "nginx",
},
want: "docker.io/library/nginx:latest",
},
{
name: "image tag",
args: args{
Expand Down
Loading
Loading