From 50e3ed1595ed3d7fb22dc246ebaa26fcc9b0fcd7 Mon Sep 17 00:00:00 2001 From: Matthias Bertschy Date: Tue, 30 May 2023 11:01:44 +0200 Subject: [PATCH 1/2] rename crd Signed-off-by: Matthias Bertschy --- adapters/mocksbom.go | 4 +- adapters/mocksbom_test.go | 6 +-- adapters/v1/syft.go | 4 +- adapters/v1/syft_test.go | 2 +- controllers/http.go | 38 ++++++++++++++++--- core/domain/scan.go | 3 +- core/ports/providers.go | 2 +- core/services/scan.go | 60 ++++++++++++++--------------- core/services/scan_test.go | 14 +++++-- go.mod | 2 +- go.sum | 6 ++- repositories/apiserver.go | 69 +++------------------------------- repositories/apiserver_test.go | 48 ----------------------- 13 files changed, 94 insertions(+), 164 deletions(-) diff --git a/adapters/mocksbom.go b/adapters/mocksbom.go index 2e46998..c60c88c 100644 --- a/adapters/mocksbom.go +++ b/adapters/mocksbom.go @@ -35,7 +35,7 @@ func NewMockSBOMAdapter(error, timeout, toomanyrequests bool) *MockSBOMAdapter { } // CreateSBOM returns a dummy SBOM for the given imageID -func (m MockSBOMAdapter) CreateSBOM(_ context.Context, imageID string, _ domain.RegistryOptions) (domain.SBOM, error) { +func (m MockSBOMAdapter) CreateSBOM(_ context.Context, name, imageID string, _ domain.RegistryOptions) (domain.SBOM, error) { logger.L().Info("CreateSBOM") if m.error { return domain.SBOM{}, domain.ErrMockError @@ -48,7 +48,7 @@ func (m MockSBOMAdapter) CreateSBOM(_ context.Context, imageID string, _ domain. ) } sbom := domain.SBOM{ - ID: imageID, + ID: name, SBOMCreatorVersion: m.Version(), Annotations: map[string]string{ instanceidhandler.ImageIDMetadataKey: imageID, diff --git a/adapters/mocksbom_test.go b/adapters/mocksbom_test.go index 503552e..54df912 100644 --- a/adapters/mocksbom_test.go +++ b/adapters/mocksbom_test.go @@ -11,19 +11,19 @@ import ( func TestMockSBOMAdapter_CreateSBOM(t *testing.T) { m := NewMockSBOMAdapter(false, false, false) - sbom, _ := m.CreateSBOM(context.TODO(), "image", domain.RegistryOptions{}) + sbom, _ := m.CreateSBOM(context.TODO(), "name", "image", domain.RegistryOptions{}) assert.NotNil(t, sbom.Content) } func TestMockSBOMAdapter_CreateSBOM_Error(t *testing.T) { m := NewMockSBOMAdapter(true, false, false) - _, err := m.CreateSBOM(context.TODO(), "image", domain.RegistryOptions{}) + _, err := m.CreateSBOM(context.TODO(), "name", "image", domain.RegistryOptions{}) assert.Error(t, err) } func TestMockSBOMAdapter_CreateSBOM_Timeout(t *testing.T) { m := NewMockSBOMAdapter(false, true, false) - sbom, _ := m.CreateSBOM(context.TODO(), "image", domain.RegistryOptions{}) + sbom, _ := m.CreateSBOM(context.TODO(), "name", "image", domain.RegistryOptions{}) assert.Equal(t, sbom.Status, instanceidhandler.Incomplete) } diff --git a/adapters/v1/syft.go b/adapters/v1/syft.go index 25fbd8c..751ca13 100644 --- a/adapters/v1/syft.go +++ b/adapters/v1/syft.go @@ -54,12 +54,12 @@ func NewSyftAdapter(scanTimeout time.Duration, maxImageSize int64) *SyftAdapter // CreateSBOM creates an SBOM for a given imageID, restrict parallelism to prevent disk space issues, // a timeout prevents the process from hanging for too long. // Format is SPDX JSON and the resulting SBOM is tagged with the Syft version. -func (s *SyftAdapter) CreateSBOM(ctx context.Context, imageID string, options domain.RegistryOptions) (domain.SBOM, error) { +func (s *SyftAdapter) CreateSBOM(ctx context.Context, name, imageID string, options domain.RegistryOptions) (domain.SBOM, error) { ctx, span := otel.Tracer("").Start(ctx, "SyftAdapter.CreateSBOM") defer span.End() // prepare an SBOM and fill it progressively domainSBOM := domain.SBOM{ - ID: imageID, + ID: name, SBOMCreatorVersion: s.Version(), Annotations: map[string]string{ instanceidhandler.ImageIDMetadataKey: imageID, diff --git a/adapters/v1/syft_test.go b/adapters/v1/syft_test.go index 43a8060..3212615 100644 --- a/adapters/v1/syft_test.go +++ b/adapters/v1/syft_test.go @@ -75,7 +75,7 @@ func Test_syftAdapter_CreateSBOM(t *testing.T) { maxImageSize = tt.maxImageSize } s := NewSyftAdapter(5*time.Minute, maxImageSize) - got, err := s.CreateSBOM(context.TODO(), tt.imageID, tt.options) + got, err := s.CreateSBOM(context.TODO(), "name", tt.imageID, tt.options) if (err != nil) != tt.wantErr { t.Errorf("CreateSBOM() error = %v, wantErr %v", err, tt.wantErr) return diff --git a/controllers/http.go b/controllers/http.go index 496bbab..e9282b9 100644 --- a/controllers/http.go +++ b/controllers/http.go @@ -9,6 +9,7 @@ import ( "github.com/gin-gonic/gin" "github.com/kubescape/go-logger" "github.com/kubescape/go-logger/helpers" + "github.com/kubescape/k8s-interface/names" "github.com/kubescape/kubevuln/core/domain" "github.com/kubescape/kubevuln/core/ports" "schneider.vip/problem" @@ -47,7 +48,10 @@ func (h HTTPController) GenerateSBOM(c *gin.Context) { ctx, err = h.scanService.ValidateGenerateSBOM(ctx, newScan) if err != nil { - logger.L().Ctx(ctx).Error("validation error", helpers.Error(err), helpers.String("imageID", newScan.ImageHash)) + logger.L().Ctx(ctx).Error("validation error", helpers.Error(err), + helpers.String("imageID", newScan.ImageID), + helpers.String("imageTag", newScan.ImageTag), + helpers.String("imageHash", newScan.ImageHash)) _, _ = problem.Of(http.StatusInternalServerError).Append(details).WriteTo(c.Writer) return } @@ -57,7 +61,10 @@ func (h HTTPController) GenerateSBOM(c *gin.Context) { h.workerPool.Submit(func() { err = h.scanService.GenerateSBOM(ctx) if err != nil { - logger.L().Ctx(ctx).Error("service error", helpers.Error(err), helpers.String("imageID", newScan.ImageHash)) + logger.L().Ctx(ctx).Error("service error", helpers.Error(err), + helpers.String("imageID", newScan.ImageID), + helpers.String("imageTag", newScan.ImageTag), + helpers.String("imageHash", newScan.ImageHash)) } }) } @@ -95,7 +102,10 @@ func (h HTTPController) ScanCVE(c *gin.Context) { ctx, err = h.scanService.ValidateScanCVE(ctx, newScan) if err != nil { - logger.L().Ctx(ctx).Error("validation error", helpers.Error(err), helpers.String("wlid", newScan.Wlid), helpers.String("imageID", newScan.ImageHash)) + logger.L().Ctx(ctx).Error("validation error", helpers.Error(err), + helpers.String("imageID", newScan.ImageID), + helpers.String("imageTag", newScan.ImageTag), + helpers.String("imageHash", newScan.ImageHash)) _, _ = problem.Of(http.StatusInternalServerError).Append(details).WriteTo(c.Writer) return } @@ -105,7 +115,11 @@ func (h HTTPController) ScanCVE(c *gin.Context) { h.workerPool.Submit(func() { err = h.scanService.ScanCVE(ctx) if err != nil { - logger.L().Ctx(ctx).Error("service error", helpers.Error(err), helpers.String("wlid", newScan.Wlid), helpers.String("imageID", newScan.ImageHash)) + logger.L().Ctx(ctx).Error("service error", helpers.Error(err), + helpers.String("wlid", newScan.Wlid), + helpers.String("imageID", newScan.ImageID), + helpers.String("imageTag", newScan.ImageTag), + helpers.String("imageHash", newScan.ImageHash)) } }) } @@ -123,6 +137,9 @@ func websocketScanCommandToScanCommand(c wssc.WebsocketScanCommand) domain.ScanC Args: c.Args, Session: sessionChainToSession(c.Session), } + if slug, err := names.ImageInfoToSlug(c.ImageTag, c.ImageHash); err == nil { + command.ImageID = slug + } if c.InstanceID != nil { command.InstanceID = *c.InstanceID } @@ -152,7 +169,10 @@ func (h HTTPController) ScanRegistry(c *gin.Context) { ctx, err = h.scanService.ValidateScanRegistry(ctx, newScan) if err != nil { - logger.L().Ctx(ctx).Error("validation error", helpers.Error(err), helpers.String("imageID", newScan.ImageTag)) + logger.L().Ctx(ctx).Error("validation error", helpers.Error(err), + helpers.String("imageID", newScan.ImageID), + helpers.String("imageTag", newScan.ImageTag), + helpers.String("imageHash", newScan.ImageHash)) _, _ = problem.Of(http.StatusInternalServerError).Append(details).WriteTo(c.Writer) return } @@ -162,7 +182,10 @@ func (h HTTPController) ScanRegistry(c *gin.Context) { h.workerPool.Submit(func() { err = h.scanService.ScanRegistry(ctx) if err != nil { - logger.L().Ctx(ctx).Error("service error", helpers.Error(err), helpers.String("imageID", newScan.ImageTag)) + logger.L().Ctx(ctx).Error("service error", helpers.Error(err), + helpers.String("imageID", newScan.ImageID), + helpers.String("imageTag", newScan.ImageTag), + helpers.String("imageHash", newScan.ImageHash)) } }) } @@ -176,6 +199,9 @@ func registryScanCommandToScanCommand(c wssc.RegistryScanCommand) domain.ScanCom Args: c.Args, Session: sessionChainToSession(c.Session), } + if slug, err := names.ImageInfoToSlug(c.ImageTag, "nohash"); err == nil { + command.ImageID = slug + } return command } diff --git a/core/domain/scan.go b/core/domain/scan.go index a9a01ab..17bf05d 100644 --- a/core/domain/scan.go +++ b/core/domain/scan.go @@ -16,7 +16,7 @@ var ( ErrExpectedError = errors.New("expected error") ErrInitVulnDB = errors.New("vulnerability DB is not initialized, run readiness probe") ErrIncompleteSBOM = errors.New("incomplete SBOM, skipping CVE scan") - ErrMissingImageID = errors.New("missing imageID") + ErrMissingImageInfo = errors.New("missing image information") ErrMissingScanID = errors.New("missing scanID") ErrMissingTimestamp = errors.New("missing timestamp") ErrMissingWorkload = errors.New("missing workload") @@ -31,6 +31,7 @@ type WorkloadKey struct{} type ScanCommand struct { Credentialslist []types.AuthConfig ImageHash string + ImageID string InstanceID string Wlid string ImageTag string diff --git a/core/ports/providers.go b/core/ports/providers.go index 3584691..00172a9 100644 --- a/core/ports/providers.go +++ b/core/ports/providers.go @@ -16,7 +16,7 @@ type CVEScanner interface { // SBOMCreator is the port implemented by adapters to be used in ScanService to generate SBOM type SBOMCreator interface { - CreateSBOM(ctx context.Context, imageID string, options domain.RegistryOptions) (domain.SBOM, error) + CreateSBOM(ctx context.Context, name, imageID string, options domain.RegistryOptions) (domain.SBOM, error) Version() string } diff --git a/core/services/scan.go b/core/services/scan.go index 78feeca..86b8816 100644 --- a/core/services/scan.go +++ b/core/services/scan.go @@ -80,16 +80,16 @@ func (s *ScanService) GenerateSBOM(ctx context.Context) error { sbom := domain.SBOM{} var err error if s.storage { - sbom, err = s.sbomRepository.GetSBOM(ctx, workload.ImageHash, s.sbomCreator.Version()) + sbom, err = s.sbomRepository.GetSBOM(ctx, workload.ImageID, s.sbomCreator.Version()) if err != nil { - logger.L().Ctx(ctx).Warning("error getting SBOM", helpers.Error(err), helpers.String("imageID", workload.ImageHash)) + logger.L().Ctx(ctx).Warning("error getting SBOM", helpers.Error(err), helpers.String("imageID", workload.ImageID)) } } // if SBOM is not available, create it if sbom.Content == nil { // create SBOM - sbom, err = s.sbomCreator.CreateSBOM(ctx, workload.ImageHash, optionsFromWorkload(workload)) + sbom, err = s.sbomCreator.CreateSBOM(ctx, workload.ImageID, workload.ImageHash, optionsFromWorkload(workload)) s.checkCreateSBOM(err, workload.ImageHash) if err != nil { return err @@ -124,20 +124,20 @@ func (s *ScanService) ScanCVE(ctx context.Context) error { if !ok { return domain.ErrMissingWorkload } - logger.L().Info("scan started", helpers.String("imageID", workload.ImageHash), helpers.String("jobID", workload.JobID)) + logger.L().Info("scan started", helpers.String("imageID", workload.ImageID), helpers.String("jobID", workload.JobID)) // report to platform err := s.platform.SendStatus(ctx, domain.Started) if err != nil { - logger.L().Ctx(ctx).Warning("telemetry error", helpers.Error(err), helpers.String("imageID", workload.ImageHash)) + logger.L().Ctx(ctx).Warning("telemetry error", helpers.Error(err), helpers.String("imageID", workload.ImageID)) } // check if CVE manifest is already available cve := domain.CVEManifest{} if s.storage { - cve, err = s.cveRepository.GetCVE(ctx, workload.ImageHash, s.sbomCreator.Version(), s.cveScanner.Version(ctx), s.cveScanner.DBVersion(ctx)) + cve, err = s.cveRepository.GetCVE(ctx, workload.ImageID, s.sbomCreator.Version(), s.cveScanner.Version(ctx), s.cveScanner.DBVersion(ctx)) if err != nil { - logger.L().Ctx(ctx).Warning("error getting CVE", helpers.Error(err), helpers.String("imageID", workload.ImageHash)) + logger.L().Ctx(ctx).Warning("error getting CVE", helpers.Error(err), helpers.String("imageID", workload.ImageID)) } } @@ -146,16 +146,16 @@ func (s *ScanService) ScanCVE(ctx context.Context) error { // check if SBOM is already available sbom := domain.SBOM{} if s.storage { - sbom, err = s.sbomRepository.GetSBOM(ctx, workload.ImageHash, s.sbomCreator.Version()) + sbom, err = s.sbomRepository.GetSBOM(ctx, workload.ImageID, s.sbomCreator.Version()) if err != nil { - logger.L().Ctx(ctx).Warning("error getting SBOM", helpers.Error(err), helpers.String("imageID", workload.ImageHash)) + logger.L().Ctx(ctx).Warning("error getting SBOM", helpers.Error(err), helpers.String("imageID", workload.ImageID)) } } // if SBOM is not available, create it if sbom.Content == nil { // create SBOM - sbom, err = s.sbomCreator.CreateSBOM(ctx, workload.ImageHash, optionsFromWorkload(workload)) + sbom, err = s.sbomCreator.CreateSBOM(ctx, workload.ImageID, workload.ImageHash, optionsFromWorkload(workload)) s.checkCreateSBOM(err, workload.ImageHash) if err != nil { return err @@ -164,7 +164,7 @@ func (s *ScanService) ScanCVE(ctx context.Context) error { 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("imageID", workload.ImageHash)) + logger.L().Ctx(ctx).Warning("error storing SBOM", helpers.Error(err), helpers.String("imageID", workload.ImageID)) } } } @@ -184,7 +184,7 @@ func (s *ScanService) ScanCVE(ctx context.Context) error { if s.storage { err = s.cveRepository.StoreCVE(ctx, cve, false) if err != nil { - logger.L().Ctx(ctx).Warning("error storing CVE", helpers.Error(err), helpers.String("imageID", workload.ImageHash)) + logger.L().Ctx(ctx).Warning("error storing CVE", helpers.Error(err), helpers.String("imageID", workload.ImageID)) } } } @@ -219,7 +219,7 @@ func (s *ScanService) ScanCVE(ctx context.Context) error { // report scan success to platform err = s.platform.SendStatus(ctx, domain.Success) if err != nil { - logger.L().Ctx(ctx).Warning("telemetry error", helpers.Error(err), helpers.String("imageID", workload.ImageHash)) + logger.L().Ctx(ctx).Warning("telemetry error", helpers.Error(err), helpers.String("imageID", workload.ImageID)) } // submit CVE manifest to platform err = s.platform.SubmitCVE(ctx, cve, cvep) @@ -229,10 +229,10 @@ func (s *ScanService) ScanCVE(ctx context.Context) error { // report submit success to platform err = s.platform.SendStatus(ctx, domain.Done) if err != nil { - logger.L().Ctx(ctx).Warning("telemetry error", helpers.Error(err), helpers.String("imageID", workload.ImageHash)) + logger.L().Ctx(ctx).Warning("telemetry error", helpers.Error(err), helpers.String("imageID", workload.ImageID)) } - logger.L().Info("scan complete", helpers.String("imageID", workload.ImageHash), helpers.String("jobID", workload.JobID)) + logger.L().Info("scan complete", helpers.String("imageID", workload.ImageID), helpers.String("jobID", workload.JobID)) return nil } @@ -247,16 +247,16 @@ func (s *ScanService) ScanRegistry(ctx context.Context) error { if !ok { return domain.ErrMissingWorkload } - logger.L().Info("registry scan started", helpers.String("imageID", workload.ImageTag), helpers.String("jobID", workload.JobID)) + logger.L().Info("registry scan started", helpers.String("imageID", workload.ImageID), helpers.String("jobID", workload.JobID)) // report to platform err := s.platform.SendStatus(ctx, domain.Started) if err != nil { - logger.L().Ctx(ctx).Warning("telemetry error", helpers.Error(err), helpers.String("imageID", workload.ImageTag)) + logger.L().Ctx(ctx).Warning("telemetry error", helpers.Error(err), helpers.String("imageID", workload.ImageID)) } // create SBOM - sbom, err := s.sbomCreator.CreateSBOM(ctx, workload.ImageTag, optionsFromWorkload(workload)) + sbom, err := s.sbomCreator.CreateSBOM(ctx, workload.ImageID, workload.ImageTag, optionsFromWorkload(workload)) s.checkCreateSBOM(err, workload.ImageTag) if err != nil { return err @@ -276,7 +276,7 @@ func (s *ScanService) ScanRegistry(ctx context.Context) error { // report scan success to platform err = s.platform.SendStatus(ctx, domain.Success) if err != nil { - logger.L().Ctx(ctx).Warning("telemetry error", helpers.Error(err), helpers.String("imageID", workload.ImageTag)) + logger.L().Ctx(ctx).Warning("telemetry error", helpers.Error(err), helpers.String("imageID", workload.ImageID)) } // submit CVE manifest to platform err = s.platform.SubmitCVE(ctx, cve, domain.CVEManifest{}) @@ -286,10 +286,10 @@ func (s *ScanService) ScanRegistry(ctx context.Context) error { // report submit success to platform err = s.platform.SendStatus(ctx, domain.Done) if err != nil { - logger.L().Ctx(ctx).Warning("telemetry error", helpers.Error(err), helpers.String("imageID", workload.ImageTag)) + logger.L().Ctx(ctx).Warning("telemetry error", helpers.Error(err), helpers.String("imageID", workload.ImageID)) } - logger.L().Info("registry scan complete", helpers.String("imageID", workload.ImageTag), helpers.String("jobID", workload.JobID)) + logger.L().Info("registry scan complete", helpers.String("imageID", workload.ImageID), helpers.String("jobID", workload.JobID)) return nil } @@ -345,12 +345,12 @@ func (s *ScanService) ValidateGenerateSBOM(ctx context.Context, workload domain. ctx = enrichContext(ctx, workload) // validate inputs - if workload.ImageHash == "" { - return ctx, domain.ErrMissingImageID + if workload.ImageHash == "" || workload.ImageID == "" { + return ctx, domain.ErrMissingImageInfo } // add imageID to parent span if parentSpan := trace.SpanFromContext(ctx); parentSpan != nil { - parentSpan.SetAttributes(attribute.String("imageID", workload.ImageHash)) + parentSpan.SetAttributes(attribute.String("imageID", workload.ImageID)) parentSpan.SetAttributes(attribute.String("version", os.Getenv("RELEASE"))) ctx = trace.ContextWithSpan(ctx, parentSpan) } @@ -367,15 +367,15 @@ func (s *ScanService) ValidateScanCVE(ctx context.Context, workload domain.ScanC ctx = enrichContext(ctx, workload) // validate inputs - if workload.ImageHash == "" { - return ctx, domain.ErrMissingImageID + if workload.ImageHash == "" || workload.ImageID == "" { + return ctx, domain.ErrMissingImageInfo } // add instanceID and imageID to parent span if parentSpan := trace.SpanFromContext(ctx); parentSpan != nil { if workload.InstanceID != "" { parentSpan.SetAttributes(attribute.String("instanceID", workload.InstanceID)) } - parentSpan.SetAttributes(attribute.String("imageID", workload.ImageHash)) + parentSpan.SetAttributes(attribute.String("imageID", workload.ImageID)) parentSpan.SetAttributes(attribute.String("version", os.Getenv("RELEASE"))) parentSpan.SetAttributes(attribute.String("wlid", workload.Wlid)) ctx = trace.ContextWithSpan(ctx, parentSpan) @@ -398,12 +398,12 @@ func (s *ScanService) ValidateScanRegistry(ctx context.Context, workload domain. ctx = enrichContext(ctx, workload) // validate inputs - if workload.ImageTag == "" { - return ctx, domain.ErrMissingImageID + if workload.ImageTag == "" || workload.ImageID == "" { + return ctx, domain.ErrMissingImageInfo } // add imageID to parent span if parentSpan := trace.SpanFromContext(ctx); parentSpan != nil { - parentSpan.SetAttributes(attribute.String("imageID", workload.ImageTag)) + parentSpan.SetAttributes(attribute.String("imageID", workload.ImageID)) parentSpan.SetAttributes(attribute.String("version", os.Getenv("RELEASE"))) ctx = trace.ContextWithSpan(ctx, parentSpan) } diff --git a/core/services/scan_test.go b/core/services/scan_test.go index f44b992..be2fa54 100644 --- a/core/services/scan_test.go +++ b/core/services/scan_test.go @@ -92,6 +92,7 @@ func TestScanService_GenerateSBOM(t *testing.T) { ctx := context.TODO() workload := domain.ScanCommand{ + ImageID: "imageID", ImageHash: "k8s.gcr.io/kube-proxy@sha256:c1b135231b5b1a6799346cd701da4b59e5b7ef8e694ec7b04fb23b8dbe144137", } workload.Credentialslist = []types.AuthConfig{ @@ -244,6 +245,7 @@ func TestScanService_ScanCVE(t *testing.T) { s.Ready(ctx) workload := domain.ScanCommand{ + ImageID: "imageID", ImageHash: imageHash, Wlid: wlid, } @@ -256,14 +258,14 @@ func TestScanService_ScanCVE(t *testing.T) { tools.EnsureSetup(t, err == nil) } if tt.sbom { - sbom, err := sbomAdapter.CreateSBOM(ctx, imageHash, domain.RegistryOptions{}) + sbom, err := sbomAdapter.CreateSBOM(ctx, "sbom", imageHash, domain.RegistryOptions{}) tools.EnsureSetup(t, err == nil) _ = storageSBOM.StoreSBOM(ctx, sbom) } var sbomp domain.SBOM if tt.instanceID != "" { var err error - sbomp, err = sbomAdapter.CreateSBOM(ctx, tt.instanceID, domain.RegistryOptions{}) + sbomp, err = sbomAdapter.CreateSBOM(ctx, tt.instanceID, tt.instanceID, domain.RegistryOptions{}) tools.EnsureSetup(t, err == nil) sbomp.Labels = map[string]string{"foo": "bar"} _ = storageSBOM.StoreSBOM(ctx, sbomp) @@ -297,6 +299,7 @@ func fileToSBOM(path string) *v1beta1.Document { func TestScanService_NginxTest(t *testing.T) { imageHash := "docker.io/library/nginx@sha256:32fdf92b4e986e109e4db0865758020cb0c3b70d6ba80d02fe87bad5cc3dc228" + imageID := "name" instanceID := "1c83b589d90ba26957627525e08124b1a24732755a330924f7987e9d9e3952c1" ctx := context.TODO() sbomAdapter := adapters.NewMockSBOMAdapter(false, false, false) @@ -312,13 +315,14 @@ func TestScanService_NginxTest(t *testing.T) { workload := domain.ScanCommand{ ContainerName: "nginx", ImageHash: imageHash, + ImageID: imageID, ImageTag: "docker.io/library/nginx:1.14.1", InstanceID: instanceID, Wlid: "wlid://cluster-minikube/namespace-default/deployment-nginx", } ctx, _ = s.ValidateScanCVE(ctx, workload) sbom := domain.SBOM{ - ID: imageHash, + ID: imageID, Content: fileToSBOM("../../adapters/v1/testdata/nginx-sbom.json"), SBOMCreatorVersion: sbomAdapter.Version(), } @@ -352,6 +356,7 @@ func TestScanService_ValidateGenerateSBOM(t *testing.T) { { name: "with imageID", workload: domain.ScanCommand{ + ImageID: "imageID", ImageHash: "k8s.gcr.io/kube-proxy@sha256:c1b135231b5b1a6799346cd701da4b59e5b7ef8e694ec7b04fb23b8dbe144137", }, wantErr: false, @@ -395,6 +400,7 @@ func TestScanService_ValidateScanCVE(t *testing.T) { { name: "with Wlid and ImageHash", workload: domain.ScanCommand{ + ImageID: "imageID", ImageHash: "k8s.gcr.io/kube-proxy@sha256:c1b135231b5b1a6799346cd701da4b59e5b7ef8e694ec7b04fb23b8dbe144137", Wlid: "wlid://cluster-minikube/namespace-kube-system/daemonset-kube-proxy", }, @@ -468,6 +474,7 @@ func TestScanService_ScanRegistry(t *testing.T) { false) ctx := context.TODO() workload := domain.ScanCommand{ + ImageID: "imageID", ImageTag: "k8s.gcr.io/kube-proxy:v1.24.3", } workload.Credentialslist = []types.AuthConfig{ @@ -512,6 +519,7 @@ func TestScanService_ValidateScanRegistry(t *testing.T) { { name: "with imageID", workload: domain.ScanCommand{ + ImageID: "imageID", ImageTag: "k8s.gcr.io/kube-proxy:v1.24.3", }, wantErr: false, diff --git a/go.mod b/go.mod index a175153..04e8234 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/hashicorp/go-multierror v1.1.1 github.com/kinbiko/jsonassert v1.1.1 github.com/kubescape/go-logger v0.0.11 - github.com/kubescape/k8s-interface v0.0.123 + github.com/kubescape/k8s-interface v0.0.127 github.com/kubescape/storage v0.2.0 github.com/spdx/tools-golang v0.5.0-rc1 github.com/spf13/viper v1.15.0 diff --git a/go.sum b/go.sum index 46460ce..c7c4f88 100644 --- a/go.sum +++ b/go.sum @@ -680,8 +680,10 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kubescape/go-logger v0.0.11 h1:oucpq2S7+DT7O+UclG5IrmHado/tj6+IkYf9czVk/aY= github.com/kubescape/go-logger v0.0.11/go.mod h1:yGiKBJ2lhq/kxzY/MVYDREL9fLV3RGD6gv+UFjslaew= -github.com/kubescape/k8s-interface v0.0.123 h1:7KjQ1bHoaggzAPcufdT6NZeffyL4t0WWZBoaJ1tCgmY= -github.com/kubescape/k8s-interface v0.0.123/go.mod h1:ENpA9SkkS6E3PIT+AaMu/JGkuyE04aUamY+a7WLqsJQ= +github.com/kubescape/k8s-interface v0.0.126 h1:W4XijGLV94OQeuWQP9WjmIl2sMIZc3eMvDDt7i9CJCM= +github.com/kubescape/k8s-interface v0.0.126/go.mod h1:ENpA9SkkS6E3PIT+AaMu/JGkuyE04aUamY+a7WLqsJQ= +github.com/kubescape/k8s-interface v0.0.127 h1:9H4TxbUliliQe4eY+jsZDOaYRWMEK/jriMBj4cMX73A= +github.com/kubescape/k8s-interface v0.0.127/go.mod h1:ENpA9SkkS6E3PIT+AaMu/JGkuyE04aUamY+a7WLqsJQ= github.com/kubescape/storage v0.2.0 h1:WZXy4Dyjf5ltEMtk0SOD9RFL1haS9ffFPGfs1gUV1aM= github.com/kubescape/storage v0.2.0/go.mod h1:sPE749pFNoxoskBn6JTpNQyguF2rv/u2kYqzRd3MvXw= github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= diff --git a/repositories/apiserver.go b/repositories/apiserver.go index 4291cb0..c73c82c 100644 --- a/repositories/apiserver.go +++ b/repositories/apiserver.go @@ -2,13 +2,9 @@ package repositories import ( "context" - "fmt" - "regexp" "strconv" - "strings" "time" - "github.com/distribution/distribution/reference" "github.com/kubescape/go-logger" "github.com/kubescape/go-logger/helpers" "github.com/kubescape/k8s-interface/instanceidhandler/v1" @@ -36,10 +32,6 @@ var _ ports.CVERepository = (*APIServerStore)(nil) var _ ports.SBOMRepository = (*APIServerStore)(nil) -var re = regexp.MustCompile(`([a-f0-9]{64})`) - -const ImageHashLength = 64 - // NewAPIServerStorage initializes the APIServerStore struct func NewAPIServerStorage(namespace string) (*APIServerStore, error) { config, err := rest.InClusterConfig() @@ -63,37 +55,6 @@ func NewFakeAPIServerStorage(namespace string) *APIServerStore { } } -func newImageHashError(imageID string) error { - return fmt.Errorf("failed to get image hash from imageID: %s", imageID) -} -func getImageHash(imageID string) (string, error) { - if match := re.FindStringSubmatch(imageID); len(match) > 1 { - return match[1], nil - } - return "", newImageHashError(imageID) -} - -func hashFromImageID(imageID string) (string, error) { - // Check if the imageID is a plain SHA256 hash - if len(imageID) == ImageHashLength && re.MatchString(imageID) { - return imageID, nil - } - - match := reference.ReferenceRegexp.FindStringSubmatch(imageID) - - if len(match) < 3 || match[3] == "" { - // Fall back to getImageHash if not enough submatches or if the third submatch is empty - return getImageHash(imageID) - } - - if s := strings.Split(match[3], ":"); len(s) > 1 { - // If there's a ":" in the third submatch, return the part after it - return s[1], nil - } - - return "", newImageHashError(imageID) -} - func (a *APIServerStore) GetCVE(ctx context.Context, imageID, SBOMCreatorVersion, CVEScannerVersion, CVEDBVersion string) (cve domain.CVEManifest, err error) { _, span := otel.Tracer("").Start(ctx, "APIServerStore.GetCVE") defer span.End() @@ -101,12 +62,7 @@ func (a *APIServerStore) GetCVE(ctx context.Context, imageID, SBOMCreatorVersion logger.L().Debug("empty image ID provided, skipping CVE retrieval") return domain.CVEManifest{}, nil } - imageHash, err := hashFromImageID(imageID) - if err != nil { - logger.L().Ctx(ctx).Warning("failed to get CVE manifest from apiserver", helpers.Error(err), helpers.String("ID", imageID)) - return domain.CVEManifest{}, nil - } - manifest, err := a.StorageClient.VulnerabilityManifests(a.Namespace).Get(context.Background(), imageHash, metav1.GetOptions{}) + manifest, err := a.StorageClient.VulnerabilityManifests(a.Namespace).Get(context.Background(), imageID, metav1.GetOptions{}) switch { case errors.IsNotFound(err): logger.L().Debug("CVE manifest not found in storage", helpers.String("ID", imageID)) @@ -148,14 +104,9 @@ func (a *APIServerStore) StoreCVE(ctx context.Context, cve domain.CVEManifest, w cve.Labels[v1.ContextMetadataKey] = v1.ContextMetadataKeyNonFiltered } - name, e := hashFromImageID(cve.ID) - if e != nil { - logger.L().Debug("skipping storing CVE manifest with unsupported ID", helpers.Error(e)) - return nil - } manifest := v1beta1.VulnerabilityManifest{ ObjectMeta: metav1.ObjectMeta{ - Name: name, + Name: cve.ID, Annotations: cve.Annotations, Labels: cve.Labels, }, @@ -179,7 +130,7 @@ func (a *APIServerStore) StoreCVE(ctx context.Context, cve domain.CVEManifest, w retryErr := retry.RetryOnConflict(retry.DefaultRetry, func() error { // retrieve the latest version before attempting update // RetryOnConflict uses exponential backoff to avoid exhausting the apiserver - result, getErr := a.StorageClient.VulnerabilityManifests(a.Namespace).Get(context.Background(), name, metav1.GetOptions{}) + result, getErr := a.StorageClient.VulnerabilityManifests(a.Namespace).Get(context.Background(), cve.ID, metav1.GetOptions{}) if getErr != nil { return getErr } @@ -211,12 +162,7 @@ func (a *APIServerStore) GetSBOM(ctx context.Context, imageID, SBOMCreatorVersio logger.L().Debug("empty image ID provided, skipping SBOM retrieval") return domain.SBOM{}, nil } - imageHash, err := hashFromImageID(imageID) - if err != nil { - logger.L().Debug("unsupported image ID provided, skipping SBOM retrieval") - return domain.SBOM{}, nil - } - manifest, err := a.StorageClient.SBOMSPDXv2p3s(a.Namespace).Get(context.Background(), imageHash, metav1.GetOptions{}) + manifest, err := a.StorageClient.SBOMSPDXv2p3s(a.Namespace).Get(context.Background(), imageID, metav1.GetOptions{}) switch { case errors.IsNotFound(err): logger.L().Debug("SBOM manifest not found in storage", helpers.String("ID", imageID)) @@ -290,14 +236,9 @@ func (a *APIServerStore) StoreSBOM(ctx context.Context, sbom domain.SBOM) error logger.L().Debug("skipping storing SBOM with empty ID") return nil } - imageHash, e := hashFromImageID(sbom.ID) - if e != nil { - logger.L().Debug("skipping storing SBOM with unknown SBOM ID", helpers.String("ID", sbom.ID), helpers.Error(e)) - return nil - } manifest := v1beta1.SBOMSPDXv2p3{ ObjectMeta: metav1.ObjectMeta{ - Name: imageHash, + Name: sbom.ID, Annotations: sbom.Annotations, Labels: sbom.Labels, }, diff --git a/repositories/apiserver_test.go b/repositories/apiserver_test.go index 6e34194..967938c 100644 --- a/repositories/apiserver_test.go +++ b/repositories/apiserver_test.go @@ -351,51 +351,3 @@ func TestAPIServerStore_GetSBOMp(t *testing.T) { }) } } - -func Test_extractHashFromImageID(t *testing.T) { - tests := []struct { - name string - imageID string - want string - err bool - }{ - { - name: "no tag", - imageID: "k8s.gcr.io/kube-proxy@sha256:c1b135231b5b1a6799346cd701da4b59e5b7ef8e694ec7b04fb23b8dbe144137", - want: "c1b135231b5b1a6799346cd701da4b59e5b7ef8e694ec7b04fb23b8dbe144137", - }, - { - name: "with tag", - imageID: "library/nginx:v1.21.0@sha256:c1b135231b5b1a6799346cd701da4b59e5b7ef8e694ec7b04fb23b8dbe144137", - want: "c1b135231b5b1a6799346cd701da4b59e5b7ef8e694ec7b04fb23b8dbe144137", - }, - { - name: "only hash", - imageID: "c1b135231b5b1a6799346cd701da4b59e5b7ef8e694ec7b04fb23b8dbe144137", - want: "c1b135231b5b1a6799346cd701da4b59e5b7ef8e694ec7b04fb23b8dbe144137", - }, - { - name: "sha256 hash", - imageID: "sha256:c1b135231b5b1a6799346cd701da4b59e5b7ef8e694ec7b04fb23b8dbe144137", - want: "c1b135231b5b1a6799346cd701da4b59e5b7ef8e694ec7b04fb23b8dbe144137", - }, - { - name: "docker imageID", - imageID: "docker://sha256:c1b135231b5b1a6799346cd701da4b59e5b7ef8e694ec7b04fb23b8dbe144137", - want: "c1b135231b5b1a6799346cd701da4b59e5b7ef8e694ec7b04fb23b8dbe144137", - }, - { - name: "empty imageID", - imageID: "", - want: "", - err: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got, e := hashFromImageID(tt.imageID); got != tt.want || (e != nil) != tt.err { - t.Errorf("hashFromImageID() = %v, want %v", got, tt.want) - } - }) - } -} From bfd668b7a649008838568af155fa4016c38a9378 Mon Sep 17 00:00:00 2001 From: Matthias Bertschy Date: Wed, 7 Jun 2023 11:53:50 +0200 Subject: [PATCH 2/2] renamed variables for clarity Signed-off-by: Matthias Bertschy --- adapters/mockcve.go | 2 +- adapters/mocksbom.go | 2 +- adapters/v1/armo_utils.go | 14 +++-- adapters/v1/grype.go | 23 ++++--- adapters/v1/grype_test.go | 4 +- adapters/v1/syft.go | 30 ++++++--- controllers/http.go | 19 +++--- core/domain/cve.go | 2 +- core/domain/sbom.go | 2 +- core/domain/scan.go | 2 +- core/ports/repositories.go | 6 +- core/services/scan.go | 85 +++++++++++++++---------- core/services/scan_test.go | 32 +++++----- repositories/apiserver.go | 112 +++++++++++++++++++++------------ repositories/apiserver_test.go | 97 ++++++++++++++-------------- repositories/memory.go | 12 ++-- repositories/memory_test.go | 16 ++--- 17 files changed, 267 insertions(+), 193 deletions(-) diff --git a/adapters/mockcve.go b/adapters/mockcve.go index 35b97a3..232d9e9 100644 --- a/adapters/mockcve.go +++ b/adapters/mockcve.go @@ -37,7 +37,7 @@ func (m MockCVEAdapter) Ready(context.Context) bool { func (m MockCVEAdapter) ScanSBOM(ctx context.Context, sbom domain.SBOM) (domain.CVEManifest, error) { logger.L().Info("ScanSBOM") return domain.CVEManifest{ - ID: sbom.ID, + Name: sbom.Name, SBOMCreatorVersion: sbom.SBOMCreatorVersion, CVEScannerVersion: m.Version(ctx), CVEDBVersion: m.DBVersion(ctx), diff --git a/adapters/mocksbom.go b/adapters/mocksbom.go index c60c88c..d453bee 100644 --- a/adapters/mocksbom.go +++ b/adapters/mocksbom.go @@ -48,7 +48,7 @@ func (m MockSBOMAdapter) CreateSBOM(_ context.Context, name, imageID string, _ d ) } sbom := domain.SBOM{ - ID: name, + Name: name, SBOMCreatorVersion: m.Version(), Annotations: map[string]string{ instanceidhandler.ImageIDMetadataKey: imageID, diff --git a/adapters/v1/armo_utils.go b/adapters/v1/armo_utils.go index 3ef6643..5fc5fa9 100644 --- a/adapters/v1/armo_utils.go +++ b/adapters/v1/armo_utils.go @@ -64,14 +64,17 @@ func (a *ArmoAdapter) postResultsAsGoroutine(ctx context.Context, report *v1.Sca func (a *ArmoAdapter) postResults(ctx context.Context, report *v1.ScanResultReport, eventReceiverURL, imagetag, wlid string, errorChan chan<- error) { payload, err := json.Marshal(report) if err != nil { - logger.L().Ctx(ctx).Error("failed to convert to json", helpers.Error(err), helpers.String("wlid", wlid)) + logger.L().Ctx(ctx).Error("failed to convert to json", helpers.Error(err), + helpers.String("wlid", wlid)) errorChan <- err return } urlBase, err := url.Parse(eventReceiverURL) if err != nil { - logger.L().Ctx(ctx).Error("failed parsing eventReceiverURL", helpers.Error(err), helpers.String("url", eventReceiverURL), helpers.String("wlid", wlid)) + logger.L().Ctx(ctx).Error("failed parsing eventReceiverURL", helpers.Error(err), + helpers.String("url", eventReceiverURL), + helpers.String("wlid", wlid)) err = fmt.Errorf("fail parsing URL, %s, err: %s", eventReceiverURL, err.Error()) errorChan <- err return @@ -84,14 +87,17 @@ func (a *ArmoAdapter) postResults(ctx context.Context, report *v1.ScanResultRepo resp, err := a.httpPostFunc(http.DefaultClient, urlBase.String(), map[string]string{"Content-Type": "application/json"}, payload) if err != nil { - logger.L().Ctx(ctx).Error("failed posting to event", helpers.String("image", imagetag), helpers.String("wlid", wlid), helpers.Error(err)) + logger.L().Ctx(ctx).Error("failed posting to event", helpers.Error(err), + helpers.String("image", imagetag), + helpers.String("wlid", wlid)) errorChan <- err return } defer resp.Body.Close() body, err := httputils.HttpRespToString(resp) if err != nil { - logger.L().Ctx(ctx).Error("Vulnerabilities post to event receiver failed", helpers.Error(err), helpers.String("body", body)) + logger.L().Ctx(ctx).Error("Vulnerabilities post to event receiver failed", helpers.Error(err), + helpers.String("body", body)) errorChan <- err return } diff --git a/adapters/v1/grype.go b/adapters/v1/grype.go index 5f567f4..879c2f9 100644 --- a/adapters/v1/grype.go +++ b/adapters/v1/grype.go @@ -84,7 +84,8 @@ func (g *GrypeAdapter) Ready(ctx context.Context) bool { defer g.mu.Unlock() ctx, span := otel.Tracer("").Start(ctx, "GrypeAdapter.UpdateDB") defer span.End() - logger.L().Info("updating grype DB", helpers.String("listingURL", g.dbConfig.ListingURL)) + logger.L().Info("updating grype DB", + helpers.String("listingURL", g.dbConfig.ListingURL)) var err error g.store, g.dbStatus, g.dbCloser, err = grype.LoadVulnerabilityDB(g.dbConfig, true) if err != nil { @@ -113,13 +114,15 @@ func (g *GrypeAdapter) ScanSBOM(ctx context.Context, sbom domain.SBOM) (domain.C return domain.CVEManifest{}, domain.ErrInitVulnDB } - logger.L().Debug("decoding SBOM", helpers.String("imageID", sbom.ID)) + logger.L().Debug("decoding SBOM", + helpers.String("name", sbom.Name)) s, err := domainToSyft(*sbom.Content) if err != nil { return domain.CVEManifest{}, err } - logger.L().Debug("reading packages from SBOM", helpers.String("imageID", sbom.ID)) + logger.L().Debug("reading packages from SBOM", + helpers.String("name", sbom.Name)) packages := pkg.FromCatalog(s.Artifacts.PackageCatalog, pkg.SynthesisConfig{}) if err != nil { return domain.CVEManifest{}, err @@ -133,27 +136,31 @@ func (g *GrypeAdapter) ScanSBOM(ctx context.Context, sbom domain.SBOM) (domain.C Matchers: getMatchers(), } - logger.L().Debug("finding vulnerabilities", helpers.String("imageID", sbom.ID)) + logger.L().Debug("finding vulnerabilities", + helpers.String("name", sbom.Name)) remainingMatches, ignoredMatches, err := vulnMatcher.FindMatches(packages, pkgContext) if err != nil { return domain.CVEManifest{}, err } - logger.L().Debug("compiling results", helpers.String("imageID", sbom.ID)) + logger.L().Debug("compiling results", + helpers.String("name", sbom.Name)) doc, err := models.NewDocument(packages, pkgContext, *remainingMatches, ignoredMatches, g.store, nil, g.dbStatus) if err != nil { return domain.CVEManifest{}, err } - logger.L().Debug("converting results to common format", helpers.String("imageID", sbom.ID)) + logger.L().Debug("converting results to common format", + helpers.String("name", sbom.Name)) vulnerabilityResults, err := grypeToDomain(doc) if err != nil { return domain.CVEManifest{}, err } - logger.L().Debug("returning CVE manifest", helpers.String("imageID", sbom.ID)) + logger.L().Debug("returning CVE manifest", + helpers.String("name", sbom.Name)) return domain.CVEManifest{ - ID: sbom.ID, + Name: sbom.Name, SBOMCreatorVersion: sbom.SBOMCreatorVersion, CVEScannerVersion: g.Version(ctx), CVEDBVersion: g.DBVersion(ctx), diff --git a/adapters/v1/grype_test.go b/adapters/v1/grype_test.go index 66f79b6..8deac94 100644 --- a/adapters/v1/grype_test.go +++ b/adapters/v1/grype_test.go @@ -42,7 +42,7 @@ func Test_grypeAdapter_ScanSBOM(t *testing.T) { { name: "valid SBOM produces well-formed vulnerability list", sbom: domain.SBOM{ - ID: "library/alpine@sha256:e2e16842c9b54d985bf1ef9242a313f36b856181f188de21313820e177002501", + Name: "library/alpine@sha256:e2e16842c9b54d985bf1ef9242a313f36b856181f188de21313820e177002501", SBOMCreatorVersion: "TODO", Content: fileToSBOM("testdata/alpine-sbom.json"), }, @@ -51,7 +51,7 @@ func Test_grypeAdapter_ScanSBOM(t *testing.T) { { name: "filtered SBOM", sbom: domain.SBOM{ - ID: "927669769708707a6ec583b2f4f93eeb4d5b59e27d793a6e99134e505dac6c3c", + Name: "927669769708707a6ec583b2f4f93eeb4d5b59e27d793a6e99134e505dac6c3c", SBOMCreatorVersion: "TODO", Content: fileToSBOM("testdata/nginx-filtered-sbom.json"), }, diff --git a/adapters/v1/syft.go b/adapters/v1/syft.go index 751ca13..ae1c28a 100644 --- a/adapters/v1/syft.go +++ b/adapters/v1/syft.go @@ -59,7 +59,7 @@ func (s *SyftAdapter) CreateSBOM(ctx context.Context, name, imageID string, opti defer span.End() // prepare an SBOM and fill it progressively domainSBOM := domain.SBOM{ - ID: name, + Name: name, SBOMCreatorVersion: s.Version(), Annotations: map[string]string{ instanceidhandler.ImageIDMetadataKey: imageID, @@ -94,22 +94,27 @@ func (s *SyftAdapter) CreateSBOM(ctx context.Context, name, imageID string, opti defer func(t *file.TempDirGenerator) { err := t.Cleanup() if err != nil { - logger.L().Ctx(ctx).Warning("failed to cleanup temp dir", helpers.String("imageID", imageID), helpers.Error(err)) + logger.L().Ctx(ctx).Warning("failed to cleanup temp dir", helpers.Error(err), + helpers.String("imageID", imageID)) } }(t) // download image - logger.L().Debug("downloading image", helpers.String("imageID", imageID)) + logger.L().Debug("downloading image", + helpers.String("imageID", imageID)) src, err := newFromRegistry(t, sourceInput, registryOptions, s.maxImageSize) // check for 401 error and retry without credentials var transportError *transport.Error if errors.As(err, &transportError) && transportError.StatusCode == http.StatusUnauthorized { - logger.L().Debug("got 401, retrying without credentials", helpers.String("imageID", imageID)) + logger.L().Debug("got 401, retrying without credentials", + helpers.String("imageID", imageID)) registryOptions.Credentials = nil src, err = newFromRegistry(t, sourceInput, registryOptions, s.maxImageSize) } switch { case errors.Is(err, ErrImageTooLarge): - logger.L().Ctx(ctx).Warning("Image exceeds size limit", helpers.Int("maxImageSize", int(s.maxImageSize)), helpers.String("imageID", imageID)) + logger.L().Ctx(ctx).Warning("Image exceeds size limit", + helpers.Int("maxImageSize", int(s.maxImageSize)), + helpers.String("imageID", imageID)) domainSBOM.Status = instanceidhandler.Incomplete return domainSBOM, nil case err != nil: @@ -123,7 +128,8 @@ func (s *SyftAdapter) CreateSBOM(ctx context.Context, name, imageID string, opti var actualDistro *linux.Release dl := deadline.New(s.scanTimeout) err = dl.Run(func(stopper <-chan struct{}) error { - logger.L().Debug("extracting packages", helpers.String("imageID", imageID)) + logger.L().Debug("extracting packages", + helpers.String("imageID", imageID)) catalogOptions := cataloger.Config{ Search: cataloger.DefaultSearchConfig(), Parallelism: 4, // TODO assess this value @@ -133,7 +139,8 @@ func (s *SyftAdapter) CreateSBOM(ctx context.Context, name, imageID string, opti }) switch err { case deadline.ErrTimedOut: - logger.L().Ctx(ctx).Warning("Syft timed out", helpers.String("imageID", imageID)) + logger.L().Ctx(ctx).Warning("Syft timed out", + helpers.String("imageID", imageID)) domainSBOM.Status = instanceidhandler.Incomplete return domainSBOM, nil case nil: @@ -144,7 +151,8 @@ func (s *SyftAdapter) CreateSBOM(ctx context.Context, name, imageID string, opti return domainSBOM, err } // generate SBOM - logger.L().Debug("generating SBOM", helpers.String("imageID", imageID)) + logger.L().Debug("generating SBOM", + helpers.String("imageID", imageID)) syftSBOM := sbom.SBOM{ Source: src.Metadata, Relationships: relationships, @@ -154,10 +162,12 @@ func (s *SyftAdapter) CreateSBOM(ctx context.Context, name, imageID string, opti }, } // convert SBOM - logger.L().Debug("converting SBOM", helpers.String("imageID", imageID)) + logger.L().Debug("converting SBOM", + helpers.String("imageID", imageID)) domainSBOM.Content, err = s.syftToDomain(syftSBOM) // return SBOM - logger.L().Debug("returning SBOM", helpers.String("imageID", imageID)) + logger.L().Debug("returning SBOM", + helpers.String("imageID", imageID)) return domainSBOM, err } diff --git a/controllers/http.go b/controllers/http.go index e9282b9..20d61b6 100644 --- a/controllers/http.go +++ b/controllers/http.go @@ -49,7 +49,7 @@ func (h HTTPController) GenerateSBOM(c *gin.Context) { ctx, err = h.scanService.ValidateGenerateSBOM(ctx, newScan) if err != nil { logger.L().Ctx(ctx).Error("validation error", helpers.Error(err), - helpers.String("imageID", newScan.ImageID), + helpers.String("imageSlug", newScan.ImageSlug), helpers.String("imageTag", newScan.ImageTag), helpers.String("imageHash", newScan.ImageHash)) _, _ = problem.Of(http.StatusInternalServerError).Append(details).WriteTo(c.Writer) @@ -62,7 +62,7 @@ func (h HTTPController) GenerateSBOM(c *gin.Context) { err = h.scanService.GenerateSBOM(ctx) if err != nil { logger.L().Ctx(ctx).Error("service error", helpers.Error(err), - helpers.String("imageID", newScan.ImageID), + helpers.String("imageSlug", newScan.ImageSlug), helpers.String("imageTag", newScan.ImageTag), helpers.String("imageHash", newScan.ImageHash)) } @@ -103,7 +103,7 @@ func (h HTTPController) ScanCVE(c *gin.Context) { ctx, err = h.scanService.ValidateScanCVE(ctx, newScan) if err != nil { logger.L().Ctx(ctx).Error("validation error", helpers.Error(err), - helpers.String("imageID", newScan.ImageID), + helpers.String("imageSlug", newScan.ImageSlug), helpers.String("imageTag", newScan.ImageTag), helpers.String("imageHash", newScan.ImageHash)) _, _ = problem.Of(http.StatusInternalServerError).Append(details).WriteTo(c.Writer) @@ -117,7 +117,7 @@ func (h HTTPController) ScanCVE(c *gin.Context) { if err != nil { logger.L().Ctx(ctx).Error("service error", helpers.Error(err), helpers.String("wlid", newScan.Wlid), - helpers.String("imageID", newScan.ImageID), + helpers.String("imageSlug", newScan.ImageSlug), helpers.String("imageTag", newScan.ImageTag), helpers.String("imageHash", newScan.ImageHash)) } @@ -138,7 +138,7 @@ func websocketScanCommandToScanCommand(c wssc.WebsocketScanCommand) domain.ScanC Session: sessionChainToSession(c.Session), } if slug, err := names.ImageInfoToSlug(c.ImageTag, c.ImageHash); err == nil { - command.ImageID = slug + command.ImageSlug = slug } if c.InstanceID != nil { command.InstanceID = *c.InstanceID @@ -170,7 +170,7 @@ func (h HTTPController) ScanRegistry(c *gin.Context) { ctx, err = h.scanService.ValidateScanRegistry(ctx, newScan) if err != nil { logger.L().Ctx(ctx).Error("validation error", helpers.Error(err), - helpers.String("imageID", newScan.ImageID), + helpers.String("imageSlug", newScan.ImageSlug), helpers.String("imageTag", newScan.ImageTag), helpers.String("imageHash", newScan.ImageHash)) _, _ = problem.Of(http.StatusInternalServerError).Append(details).WriteTo(c.Writer) @@ -183,7 +183,7 @@ func (h HTTPController) ScanRegistry(c *gin.Context) { err = h.scanService.ScanRegistry(ctx) if err != nil { logger.L().Ctx(ctx).Error("service error", helpers.Error(err), - helpers.String("imageID", newScan.ImageID), + helpers.String("imageSlug", newScan.ImageSlug), helpers.String("imageTag", newScan.ImageTag), helpers.String("imageHash", newScan.ImageHash)) } @@ -200,12 +200,13 @@ func registryScanCommandToScanCommand(c wssc.RegistryScanCommand) domain.ScanCom Session: sessionChainToSession(c.Session), } if slug, err := names.ImageInfoToSlug(c.ImageTag, "nohash"); err == nil { - command.ImageID = slug + command.ImageSlug = slug } return command } func (h HTTPController) Shutdown() { - logger.L().Info("purging SBOM creation queue", helpers.String("remaining jobs", strconv.Itoa(h.workerPool.WaitingQueueSize()))) + logger.L().Info("purging SBOM creation queue", + helpers.String("remaining jobs", strconv.Itoa(h.workerPool.WaitingQueueSize()))) h.workerPool.StopWait() } diff --git a/core/domain/cve.go b/core/domain/cve.go index faa08c8..0b3837a 100644 --- a/core/domain/cve.go +++ b/core/domain/cve.go @@ -9,7 +9,7 @@ type CVEExceptions []armotypes.VulnerabilityExceptionPolicy // CVEManifest contains a JSON CVE report manifest with some metadata type CVEManifest struct { - ID string + Name string Wlid string SBOMCreatorName string SBOMCreatorVersion string diff --git a/core/domain/sbom.go b/core/domain/sbom.go index 02ed1b1..f794f19 100644 --- a/core/domain/sbom.go +++ b/core/domain/sbom.go @@ -6,7 +6,7 @@ import ( // SBOM contains an SPDX SBOM in JSON format with some metadata type SBOM struct { - ID string + Name string SBOMCreatorName string SBOMCreatorVersion string Status string diff --git a/core/domain/scan.go b/core/domain/scan.go index 17bf05d..287533b 100644 --- a/core/domain/scan.go +++ b/core/domain/scan.go @@ -31,7 +31,7 @@ type WorkloadKey struct{} type ScanCommand struct { Credentialslist []types.AuthConfig ImageHash string - ImageID string + ImageSlug string InstanceID string Wlid string ImageTag string diff --git a/core/ports/repositories.go b/core/ports/repositories.go index 813740e..958286e 100644 --- a/core/ports/repositories.go +++ b/core/ports/repositories.go @@ -8,13 +8,13 @@ import ( // CVERepository is the port implemented by adapters to be used in ScanService to store CVE manifests type CVERepository interface { - GetCVE(ctx context.Context, imageID, SBOMCreatorVersion, CVEScannerVersion, CVEDBVersion string) (cve domain.CVEManifest, err error) + GetCVE(ctx context.Context, name, SBOMCreatorVersion, CVEScannerVersion, CVEDBVersion string) (cve domain.CVEManifest, err error) StoreCVE(ctx context.Context, cve domain.CVEManifest, withRelevancy bool) error } // SBOMRepository is the port implemented by adapters to be used in ScanService to store SBOMs type SBOMRepository interface { - GetSBOM(ctx context.Context, imageID, SBOMCreatorVersion string) (sbom domain.SBOM, err error) - GetSBOMp(ctx context.Context, instanceID, SBOMCreatorVersion string) (sbom domain.SBOM, err error) + GetSBOM(ctx context.Context, name, SBOMCreatorVersion string) (sbom domain.SBOM, err error) + GetSBOMp(ctx context.Context, name, SBOMCreatorVersion string) (sbom domain.SBOM, err error) StoreSBOM(ctx context.Context, sbom domain.SBOM) error } diff --git a/core/services/scan.go b/core/services/scan.go index 86b8816..50fb167 100644 --- a/core/services/scan.go +++ b/core/services/scan.go @@ -80,16 +80,17 @@ func (s *ScanService) GenerateSBOM(ctx context.Context) error { sbom := domain.SBOM{} var err error if s.storage { - sbom, err = s.sbomRepository.GetSBOM(ctx, workload.ImageID, s.sbomCreator.Version()) + sbom, err = s.sbomRepository.GetSBOM(ctx, workload.ImageSlug, s.sbomCreator.Version()) if err != nil { - logger.L().Ctx(ctx).Warning("error getting SBOM", helpers.Error(err), helpers.String("imageID", workload.ImageID)) + logger.L().Ctx(ctx).Warning("error getting SBOM", helpers.Error(err), + helpers.String("imageSlug", workload.ImageSlug)) } } // if SBOM is not available, create it if sbom.Content == nil { // create SBOM - sbom, err = s.sbomCreator.CreateSBOM(ctx, workload.ImageID, workload.ImageHash, optionsFromWorkload(workload)) + sbom, err = s.sbomCreator.CreateSBOM(ctx, workload.ImageSlug, workload.ImageHash, optionsFromWorkload(workload)) s.checkCreateSBOM(err, workload.ImageHash) if err != nil { return err @@ -124,20 +125,24 @@ func (s *ScanService) ScanCVE(ctx context.Context) error { if !ok { return domain.ErrMissingWorkload } - logger.L().Info("scan started", helpers.String("imageID", workload.ImageID), helpers.String("jobID", workload.JobID)) + logger.L().Info("scan started", + helpers.String("imageSlug", workload.ImageSlug), + helpers.String("jobID", workload.JobID)) // report to platform err := s.platform.SendStatus(ctx, domain.Started) if err != nil { - logger.L().Ctx(ctx).Warning("telemetry error", helpers.Error(err), helpers.String("imageID", workload.ImageID)) + logger.L().Ctx(ctx).Warning("telemetry error", helpers.Error(err), + helpers.String("imageSlug", workload.ImageSlug)) } // check if CVE manifest is already available cve := domain.CVEManifest{} if s.storage { - cve, err = s.cveRepository.GetCVE(ctx, workload.ImageID, s.sbomCreator.Version(), s.cveScanner.Version(ctx), s.cveScanner.DBVersion(ctx)) + cve, err = s.cveRepository.GetCVE(ctx, workload.ImageSlug, s.sbomCreator.Version(), s.cveScanner.Version(ctx), s.cveScanner.DBVersion(ctx)) if err != nil { - logger.L().Ctx(ctx).Warning("error getting CVE", helpers.Error(err), helpers.String("imageID", workload.ImageID)) + logger.L().Ctx(ctx).Warning("error getting CVE", helpers.Error(err), + helpers.String("imageSlug", workload.ImageSlug)) } } @@ -146,16 +151,17 @@ func (s *ScanService) ScanCVE(ctx context.Context) error { // check if SBOM is already available sbom := domain.SBOM{} if s.storage { - sbom, err = s.sbomRepository.GetSBOM(ctx, workload.ImageID, s.sbomCreator.Version()) + sbom, err = s.sbomRepository.GetSBOM(ctx, workload.ImageSlug, s.sbomCreator.Version()) if err != nil { - logger.L().Ctx(ctx).Warning("error getting SBOM", helpers.Error(err), helpers.String("imageID", workload.ImageID)) + logger.L().Ctx(ctx).Warning("error getting SBOM", helpers.Error(err), + helpers.String("imageSlug", workload.ImageSlug)) } } // if SBOM is not available, create it if sbom.Content == nil { // create SBOM - sbom, err = s.sbomCreator.CreateSBOM(ctx, workload.ImageID, workload.ImageHash, optionsFromWorkload(workload)) + sbom, err = s.sbomCreator.CreateSBOM(ctx, workload.ImageSlug, workload.ImageHash, optionsFromWorkload(workload)) s.checkCreateSBOM(err, workload.ImageHash) if err != nil { return err @@ -164,7 +170,8 @@ func (s *ScanService) ScanCVE(ctx context.Context) error { 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("imageID", workload.ImageID)) + logger.L().Ctx(ctx).Warning("error storing SBOM", helpers.Error(err), + helpers.String("imageSlug", workload.ImageSlug)) } } } @@ -184,7 +191,8 @@ func (s *ScanService) ScanCVE(ctx context.Context) error { if s.storage { err = s.cveRepository.StoreCVE(ctx, cve, false) if err != nil { - logger.L().Ctx(ctx).Warning("error storing CVE", helpers.Error(err), helpers.String("imageID", workload.ImageID)) + logger.L().Ctx(ctx).Warning("error storing CVE", helpers.Error(err), + helpers.String("imageSlug", workload.ImageSlug)) } } } @@ -194,7 +202,8 @@ func (s *ScanService) ScanCVE(ctx context.Context) error { if s.storage && workload.InstanceID != "" { sbomp, err = s.sbomRepository.GetSBOMp(ctx, workload.InstanceID, s.sbomCreator.Version()) if err != nil { - logger.L().Ctx(ctx).Warning("error getting relevant SBOM", helpers.Error(err), helpers.String("instanceID", workload.InstanceID)) + logger.L().Ctx(ctx).Warning("error getting relevant SBOM", helpers.Error(err), + helpers.String("instanceID", workload.InstanceID)) } } @@ -211,7 +220,8 @@ func (s *ScanService) ScanCVE(ctx context.Context) error { cvep.Wlid = workload.Wlid err = s.cveRepository.StoreCVE(ctx, cvep, true) if err != nil { - logger.L().Ctx(ctx).Warning("error storing CVEp", helpers.Error(err), helpers.String("instanceID", workload.InstanceID)) + logger.L().Ctx(ctx).Warning("error storing CVEp", helpers.Error(err), + helpers.String("instanceID", workload.InstanceID)) } } } @@ -219,7 +229,8 @@ func (s *ScanService) ScanCVE(ctx context.Context) error { // report scan success to platform err = s.platform.SendStatus(ctx, domain.Success) if err != nil { - logger.L().Ctx(ctx).Warning("telemetry error", helpers.Error(err), helpers.String("imageID", workload.ImageID)) + logger.L().Ctx(ctx).Warning("telemetry error", helpers.Error(err), + helpers.String("imageSlug", workload.ImageSlug)) } // submit CVE manifest to platform err = s.platform.SubmitCVE(ctx, cve, cvep) @@ -229,10 +240,13 @@ func (s *ScanService) ScanCVE(ctx context.Context) error { // report submit success to platform err = s.platform.SendStatus(ctx, domain.Done) if err != nil { - logger.L().Ctx(ctx).Warning("telemetry error", helpers.Error(err), helpers.String("imageID", workload.ImageID)) + logger.L().Ctx(ctx).Warning("telemetry error", helpers.Error(err), + helpers.String("imageSlug", workload.ImageSlug)) } - logger.L().Info("scan complete", helpers.String("imageID", workload.ImageID), helpers.String("jobID", workload.JobID)) + logger.L().Info("scan complete", + helpers.String("imageSlug", workload.ImageSlug), + helpers.String("jobID", workload.JobID)) return nil } @@ -247,16 +261,19 @@ func (s *ScanService) ScanRegistry(ctx context.Context) error { if !ok { return domain.ErrMissingWorkload } - logger.L().Info("registry scan started", helpers.String("imageID", workload.ImageID), helpers.String("jobID", workload.JobID)) + logger.L().Info("registry scan started", + helpers.String("imageSlug", workload.ImageSlug), + helpers.String("jobID", workload.JobID)) // report to platform err := s.platform.SendStatus(ctx, domain.Started) if err != nil { - logger.L().Ctx(ctx).Warning("telemetry error", helpers.Error(err), helpers.String("imageID", workload.ImageID)) + logger.L().Ctx(ctx).Warning("telemetry error", helpers.Error(err), + helpers.String("imageSlug", workload.ImageSlug)) } // create SBOM - sbom, err := s.sbomCreator.CreateSBOM(ctx, workload.ImageID, workload.ImageTag, optionsFromWorkload(workload)) + sbom, err := s.sbomCreator.CreateSBOM(ctx, workload.ImageSlug, workload.ImageTag, optionsFromWorkload(workload)) s.checkCreateSBOM(err, workload.ImageTag) if err != nil { return err @@ -276,7 +293,8 @@ func (s *ScanService) ScanRegistry(ctx context.Context) error { // report scan success to platform err = s.platform.SendStatus(ctx, domain.Success) if err != nil { - logger.L().Ctx(ctx).Warning("telemetry error", helpers.Error(err), helpers.String("imageID", workload.ImageID)) + logger.L().Ctx(ctx).Warning("telemetry error", helpers.Error(err), + helpers.String("imageSlug", workload.ImageSlug)) } // submit CVE manifest to platform err = s.platform.SubmitCVE(ctx, cve, domain.CVEManifest{}) @@ -286,10 +304,13 @@ func (s *ScanService) ScanRegistry(ctx context.Context) error { // report submit success to platform err = s.platform.SendStatus(ctx, domain.Done) if err != nil { - logger.L().Ctx(ctx).Warning("telemetry error", helpers.Error(err), helpers.String("imageID", workload.ImageID)) + logger.L().Ctx(ctx).Warning("telemetry error", helpers.Error(err), + helpers.String("imageID", workload.ImageSlug)) } - logger.L().Info("registry scan complete", helpers.String("imageID", workload.ImageID), helpers.String("jobID", workload.JobID)) + logger.L().Info("registry scan complete", + helpers.String("imageSlug", workload.ImageSlug), + helpers.String("jobID", workload.JobID)) return nil } @@ -345,12 +366,12 @@ func (s *ScanService) ValidateGenerateSBOM(ctx context.Context, workload domain. ctx = enrichContext(ctx, workload) // validate inputs - if workload.ImageHash == "" || workload.ImageID == "" { + if workload.ImageHash == "" || workload.ImageSlug == "" { return ctx, domain.ErrMissingImageInfo } - // add imageID to parent span + // add imageSlug to parent span if parentSpan := trace.SpanFromContext(ctx); parentSpan != nil { - parentSpan.SetAttributes(attribute.String("imageID", workload.ImageID)) + parentSpan.SetAttributes(attribute.String("imageSlug", workload.ImageSlug)) parentSpan.SetAttributes(attribute.String("version", os.Getenv("RELEASE"))) ctx = trace.ContextWithSpan(ctx, parentSpan) } @@ -367,15 +388,15 @@ func (s *ScanService) ValidateScanCVE(ctx context.Context, workload domain.ScanC ctx = enrichContext(ctx, workload) // validate inputs - if workload.ImageHash == "" || workload.ImageID == "" { + if workload.ImageHash == "" || workload.ImageSlug == "" { return ctx, domain.ErrMissingImageInfo } - // add instanceID and imageID to parent span + // add instanceID and imageSlug to parent span if parentSpan := trace.SpanFromContext(ctx); parentSpan != nil { if workload.InstanceID != "" { parentSpan.SetAttributes(attribute.String("instanceID", workload.InstanceID)) } - parentSpan.SetAttributes(attribute.String("imageID", workload.ImageID)) + parentSpan.SetAttributes(attribute.String("imageSlug", workload.ImageSlug)) parentSpan.SetAttributes(attribute.String("version", os.Getenv("RELEASE"))) parentSpan.SetAttributes(attribute.String("wlid", workload.Wlid)) ctx = trace.ContextWithSpan(ctx, parentSpan) @@ -398,12 +419,12 @@ func (s *ScanService) ValidateScanRegistry(ctx context.Context, workload domain. ctx = enrichContext(ctx, workload) // validate inputs - if workload.ImageTag == "" || workload.ImageID == "" { + if workload.ImageTag == "" || workload.ImageSlug == "" { return ctx, domain.ErrMissingImageInfo } - // add imageID to parent span + // add imageSlug to parent span if parentSpan := trace.SpanFromContext(ctx); parentSpan != nil { - parentSpan.SetAttributes(attribute.String("imageID", workload.ImageID)) + parentSpan.SetAttributes(attribute.String("imageSlug", workload.ImageSlug)) parentSpan.SetAttributes(attribute.String("version", os.Getenv("RELEASE"))) ctx = trace.ContextWithSpan(ctx, parentSpan) } diff --git a/core/services/scan_test.go b/core/services/scan_test.go index be2fa54..a6d10b1 100644 --- a/core/services/scan_test.go +++ b/core/services/scan_test.go @@ -92,7 +92,7 @@ func TestScanService_GenerateSBOM(t *testing.T) { ctx := context.TODO() workload := domain.ScanCommand{ - ImageID: "imageID", + ImageSlug: "imageSlug", ImageHash: "k8s.gcr.io/kube-proxy@sha256:c1b135231b5b1a6799346cd701da4b59e5b7ef8e694ec7b04fb23b8dbe144137", } workload.Credentialslist = []types.AuthConfig{ @@ -245,7 +245,7 @@ func TestScanService_ScanCVE(t *testing.T) { s.Ready(ctx) workload := domain.ScanCommand{ - ImageID: "imageID", + ImageSlug: "imageSlug", ImageHash: imageHash, Wlid: wlid, } @@ -278,7 +278,7 @@ func TestScanService_ScanCVE(t *testing.T) { assert.Equal(t, domain.ErrTooManyRequests, err) } if tt.wantCvep { - cvep, err := storageCVE.GetCVE(ctx, sbomp.ID, sbomAdapter.Version(), cveAdapter.Version(ctx), cveAdapter.DBVersion(ctx)) + cvep, err := storageCVE.GetCVE(ctx, sbomp.Name, sbomAdapter.Version(), cveAdapter.Version(ctx), cveAdapter.DBVersion(ctx)) tools.EnsureSetup(t, err == nil) assert.NotNil(t, cvep.Labels) } @@ -299,7 +299,7 @@ func fileToSBOM(path string) *v1beta1.Document { func TestScanService_NginxTest(t *testing.T) { imageHash := "docker.io/library/nginx@sha256:32fdf92b4e986e109e4db0865758020cb0c3b70d6ba80d02fe87bad5cc3dc228" - imageID := "name" + imageSlug := "name" instanceID := "1c83b589d90ba26957627525e08124b1a24732755a330924f7987e9d9e3952c1" ctx := context.TODO() sbomAdapter := adapters.NewMockSBOMAdapter(false, false, false) @@ -315,21 +315,21 @@ func TestScanService_NginxTest(t *testing.T) { workload := domain.ScanCommand{ ContainerName: "nginx", ImageHash: imageHash, - ImageID: imageID, + ImageSlug: imageSlug, ImageTag: "docker.io/library/nginx:1.14.1", InstanceID: instanceID, Wlid: "wlid://cluster-minikube/namespace-default/deployment-nginx", } ctx, _ = s.ValidateScanCVE(ctx, workload) sbom := domain.SBOM{ - ID: imageID, + Name: imageSlug, Content: fileToSBOM("../../adapters/v1/testdata/nginx-sbom.json"), SBOMCreatorVersion: sbomAdapter.Version(), } err := storageSBOM.StoreSBOM(ctx, sbom) tools.EnsureSetup(t, err == nil) sbomp := domain.SBOM{ - ID: instanceID, + Name: instanceID, Content: fileToSBOM("../../adapters/v1/testdata/nginx-filtered-sbom.json"), SBOMCreatorVersion: sbomAdapter.Version(), } @@ -337,7 +337,7 @@ func TestScanService_NginxTest(t *testing.T) { tools.EnsureSetup(t, err == nil) err = s.ScanCVE(ctx) tools.EnsureSetup(t, err == nil) - cvep, err := storageCVE.GetCVE(ctx, sbomp.ID, sbomAdapter.Version(), cveAdapter.Version(ctx), cveAdapter.DBVersion(ctx)) + cvep, err := storageCVE.GetCVE(ctx, sbomp.Name, sbomAdapter.Version(), cveAdapter.Version(ctx), cveAdapter.DBVersion(ctx)) tools.EnsureSetup(t, err == nil) assert.NotNil(t, cvep.Content) } @@ -349,14 +349,14 @@ func TestScanService_ValidateGenerateSBOM(t *testing.T) { wantErr bool }{ { - name: "missing imageID", + name: "missing imageSlug", workload: domain.ScanCommand{}, wantErr: true, }, { - name: "with imageID", + name: "with imageSlug", workload: domain.ScanCommand{ - ImageID: "imageID", + ImageSlug: "imageSlug", ImageHash: "k8s.gcr.io/kube-proxy@sha256:c1b135231b5b1a6799346cd701da4b59e5b7ef8e694ec7b04fb23b8dbe144137", }, wantErr: false, @@ -400,7 +400,7 @@ func TestScanService_ValidateScanCVE(t *testing.T) { { name: "with Wlid and ImageHash", workload: domain.ScanCommand{ - ImageID: "imageID", + ImageSlug: "imageSlug", ImageHash: "k8s.gcr.io/kube-proxy@sha256:c1b135231b5b1a6799346cd701da4b59e5b7ef8e694ec7b04fb23b8dbe144137", Wlid: "wlid://cluster-minikube/namespace-kube-system/daemonset-kube-proxy", }, @@ -474,8 +474,8 @@ func TestScanService_ScanRegistry(t *testing.T) { false) ctx := context.TODO() workload := domain.ScanCommand{ - ImageID: "imageID", - ImageTag: "k8s.gcr.io/kube-proxy:v1.24.3", + ImageSlug: "imageSlug", + ImageTag: "k8s.gcr.io/kube-proxy:v1.24.3", } workload.Credentialslist = []types.AuthConfig{ { @@ -519,8 +519,8 @@ func TestScanService_ValidateScanRegistry(t *testing.T) { { name: "with imageID", workload: domain.ScanCommand{ - ImageID: "imageID", - ImageTag: "k8s.gcr.io/kube-proxy:v1.24.3", + ImageSlug: "imageSlug", + ImageTag: "k8s.gcr.io/kube-proxy:v1.24.3", }, wantErr: false, }, diff --git a/repositories/apiserver.go b/repositories/apiserver.go index c73c82c..711232d 100644 --- a/repositories/apiserver.go +++ b/repositories/apiserver.go @@ -55,31 +55,39 @@ func NewFakeAPIServerStorage(namespace string) *APIServerStore { } } -func (a *APIServerStore) GetCVE(ctx context.Context, imageID, SBOMCreatorVersion, CVEScannerVersion, CVEDBVersion string) (cve domain.CVEManifest, err error) { +func (a *APIServerStore) GetCVE(ctx context.Context, name, SBOMCreatorVersion, CVEScannerVersion, CVEDBVersion string) (cve domain.CVEManifest, err error) { _, span := otel.Tracer("").Start(ctx, "APIServerStore.GetCVE") defer span.End() - if imageID == "" { - logger.L().Debug("empty image ID provided, skipping CVE retrieval") + if name == "" { + logger.L().Debug("empty name provided, skipping CVE retrieval") return domain.CVEManifest{}, nil } - manifest, err := a.StorageClient.VulnerabilityManifests(a.Namespace).Get(context.Background(), imageID, metav1.GetOptions{}) + manifest, err := a.StorageClient.VulnerabilityManifests(a.Namespace).Get(context.Background(), name, metav1.GetOptions{}) switch { case errors.IsNotFound(err): - logger.L().Debug("CVE manifest not found in storage", helpers.String("ID", imageID)) + logger.L().Debug("CVE manifest not found in storage", + helpers.String("name", name)) return domain.CVEManifest{}, nil case err != nil: - logger.L().Ctx(ctx).Warning("failed to get CVE manifest from apiserver", helpers.Error(err), helpers.String("ID", imageID)) + logger.L().Ctx(ctx).Warning("failed to get CVE manifest from apiserver", helpers.Error(err), + helpers.String("name", name)) return domain.CVEManifest{}, nil } // discard the manifest if it was created by an older version of the scanner // TODO: also check SBOMCreatorVersion ? if manifest.Spec.Metadata.Tool.Version != CVEScannerVersion || manifest.Spec.Metadata.Tool.DatabaseVersion != CVEDBVersion { - logger.L().Debug("discarding CVE manifest with outdated scanner version", helpers.String("ID", imageID), helpers.String("manifest scanner version", manifest.Spec.Metadata.Tool.Version), helpers.String("manifest DB version", manifest.Spec.Metadata.Tool.DatabaseVersion), helpers.String("wanted scanner version", CVEScannerVersion), helpers.String("wanted DB version", CVEDBVersion)) + logger.L().Debug("discarding CVE manifest with outdated scanner version", + helpers.String("name", name), + helpers.String("manifest scanner version", manifest.Spec.Metadata.Tool.Version), + helpers.String("manifest DB version", manifest.Spec.Metadata.Tool.DatabaseVersion), + helpers.String("wanted scanner version", CVEScannerVersion), + helpers.String("wanted DB version", CVEDBVersion)) return domain.CVEManifest{}, nil } - logger.L().Debug("got CVE manifest from storage", helpers.String("ID", imageID)) + logger.L().Debug("got CVE manifest from storage", + helpers.String("name", name)) return domain.CVEManifest{ - ID: imageID, + Name: name, SBOMCreatorVersion: SBOMCreatorVersion, CVEScannerVersion: CVEScannerVersion, CVEDBVersion: CVEDBVersion, @@ -90,8 +98,9 @@ func (a *APIServerStore) GetCVE(ctx context.Context, imageID, SBOMCreatorVersion func (a *APIServerStore) StoreCVE(ctx context.Context, cve domain.CVEManifest, withRelevancy bool) error { _, span := otel.Tracer("").Start(ctx, "APIServerStore.StoreCVE") defer span.End() - if cve.ID == "" { - logger.L().Debug("skipping storing CVE manifest with empty ID", helpers.String("relevant", strconv.FormatBool(withRelevancy))) + if cve.Name == "" { + logger.L().Debug("skipping storing CVE manifest with empty name", + helpers.String("relevant", strconv.FormatBool(withRelevancy))) return nil } if cve.Labels == nil { @@ -106,7 +115,7 @@ func (a *APIServerStore) StoreCVE(ctx context.Context, cve domain.CVEManifest, w manifest := v1beta1.VulnerabilityManifest{ ObjectMeta: metav1.ObjectMeta{ - Name: cve.ID, + Name: cve.Name, Annotations: cve.Annotations, Labels: cve.Labels, }, @@ -130,7 +139,7 @@ func (a *APIServerStore) StoreCVE(ctx context.Context, cve domain.CVEManifest, w retryErr := retry.RetryOnConflict(retry.DefaultRetry, func() error { // retrieve the latest version before attempting update // RetryOnConflict uses exponential backoff to avoid exhausting the apiserver - result, getErr := a.StorageClient.VulnerabilityManifests(a.Namespace).Get(context.Background(), cve.ID, metav1.GetOptions{}) + result, getErr := a.StorageClient.VulnerabilityManifests(a.Namespace).Get(context.Background(), cve.Name, metav1.GetOptions{}) if getErr != nil { return getErr } @@ -143,48 +152,62 @@ func (a *APIServerStore) StoreCVE(ctx context.Context, cve domain.CVEManifest, w return updateErr }) if retryErr != nil { - logger.L().Ctx(ctx).Warning("failed to update CVE manifest in storage", helpers.Error(err), helpers.String("ID", cve.ID), helpers.String("relevant", strconv.FormatBool(withRelevancy))) + logger.L().Ctx(ctx).Warning("failed to update CVE manifest in storage", helpers.Error(err), + helpers.String("name", cve.Name), + helpers.String("relevant", strconv.FormatBool(withRelevancy))) } else { - logger.L().Debug("updated CVE manifest in storage", helpers.String("ID", cve.ID), helpers.String("relevant", strconv.FormatBool(withRelevancy))) + logger.L().Debug("updated CVE manifest in storage", + helpers.String("name", cve.Name), + helpers.String("relevant", strconv.FormatBool(withRelevancy))) } case err != nil: - logger.L().Ctx(ctx).Warning("failed to store CVE manifest in storage", helpers.Error(err), helpers.String("ID", cve.ID), helpers.String("relevant", strconv.FormatBool(withRelevancy))) + logger.L().Ctx(ctx).Warning("failed to store CVE manifest in storage", helpers.Error(err), + helpers.String("name", cve.Name), + helpers.String("relevant", strconv.FormatBool(withRelevancy))) default: - logger.L().Debug("stored CVE manifest in storage", helpers.String("ID", cve.ID), helpers.String("relevant", strconv.FormatBool(withRelevancy))) + logger.L().Debug("stored CVE manifest in storage", + helpers.String("name", cve.Name), + helpers.String("relevant", strconv.FormatBool(withRelevancy))) } return nil } -func (a *APIServerStore) GetSBOM(ctx context.Context, imageID, SBOMCreatorVersion string) (sbom domain.SBOM, err error) { +func (a *APIServerStore) GetSBOM(ctx context.Context, name, SBOMCreatorVersion string) (sbom domain.SBOM, err error) { _, span := otel.Tracer("").Start(ctx, "APIServerStore.GetSBOM") defer span.End() - if imageID == "" { - logger.L().Debug("empty image ID provided, skipping SBOM retrieval") + if name == "" { + logger.L().Debug("empty name provided, skipping SBOM retrieval") return domain.SBOM{}, nil } - manifest, err := a.StorageClient.SBOMSPDXv2p3s(a.Namespace).Get(context.Background(), imageID, metav1.GetOptions{}) + manifest, err := a.StorageClient.SBOMSPDXv2p3s(a.Namespace).Get(context.Background(), name, metav1.GetOptions{}) switch { case errors.IsNotFound(err): - logger.L().Debug("SBOM manifest not found in storage", helpers.String("ID", imageID)) + logger.L().Debug("SBOM manifest not found in storage", + helpers.String("name", name)) return domain.SBOM{}, nil case err != nil: - logger.L().Ctx(ctx).Warning("failed to get SBOM from apiserver", helpers.Error(err), helpers.String("ID", imageID)) + logger.L().Ctx(ctx).Warning("failed to get SBOM from apiserver", helpers.Error(err), + helpers.String("name", name)) return domain.SBOM{}, nil } // discard the manifest if it was created by an older version of the scanner if manifest.Spec.Metadata.Tool.Version != SBOMCreatorVersion { - logger.L().Debug("discarding SBOM with outdated scanner version", helpers.String("ID", imageID), helpers.String("manifest scanner version", manifest.Spec.Metadata.Tool.Version), helpers.String("wanted scanner version", SBOMCreatorVersion)) + logger.L().Debug("discarding SBOM with outdated scanner version", + helpers.String("name", name), + helpers.String("manifest scanner version", manifest.Spec.Metadata.Tool.Version), + helpers.String("wanted scanner version", SBOMCreatorVersion)) return domain.SBOM{}, nil } result := domain.SBOM{ - ID: imageID, + Name: name, SBOMCreatorVersion: SBOMCreatorVersion, Content: &manifest.Spec.SPDX, } if status, ok := manifest.Annotations[instanceidhandler.StatusMetadataKey]; ok { result.Status = status } - logger.L().Debug("got SBOM from storage", helpers.String("ID", imageID)) + logger.L().Debug("got SBOM from storage", + helpers.String("name", name)) return result, nil } @@ -195,29 +218,32 @@ func validateSBOMp(manifest *v1beta1.SBOMSPDXv2p3Filtered) error { return nil } -func (a *APIServerStore) GetSBOMp(ctx context.Context, instanceID, SBOMCreatorVersion string) (sbom domain.SBOM, err error) { +func (a *APIServerStore) GetSBOMp(ctx context.Context, name, SBOMCreatorVersion string) (sbom domain.SBOM, err error) { _, span := otel.Tracer("").Start(ctx, "APIServerStore.GetSBOMp") defer span.End() - if instanceID == "" { - logger.L().Debug("empty instance ID provided, skipping relevant SBOM retrieval") + if name == "" { + logger.L().Debug("empty name provided, skipping relevant SBOM retrieval") return domain.SBOM{}, nil } - manifest, err := a.StorageClient.SBOMSPDXv2p3Filtereds(a.Namespace).Get(context.Background(), instanceID, metav1.GetOptions{}) + manifest, err := a.StorageClient.SBOMSPDXv2p3Filtereds(a.Namespace).Get(context.Background(), name, metav1.GetOptions{}) switch { case errors.IsNotFound(err): - logger.L().Debug("relevant SBOM manifest not found in storage", helpers.String("ID", instanceID)) + logger.L().Debug("relevant SBOM manifest not found in storage", + helpers.String("name", name)) return domain.SBOM{}, nil case err != nil: - logger.L().Ctx(ctx).Warning("failed to get relevant SBOM from apiserver", helpers.Error(err), helpers.String("ID", instanceID)) + logger.L().Ctx(ctx).Warning("failed to get relevant SBOM from apiserver", helpers.Error(err), + helpers.String("name", name)) return domain.SBOM{}, nil } // validate SBOMp manifest if err := validateSBOMp(manifest); err != nil { - logger.L().Debug("discarding relevant SBOM", helpers.Error(err), helpers.String("ID", instanceID)) + logger.L().Debug("discarding relevant SBOM", helpers.Error(err), + helpers.String("name", name)) return domain.SBOM{}, nil } result := domain.SBOM{ - ID: instanceID, + Name: name, SBOMCreatorVersion: SBOMCreatorVersion, Content: &manifest.Spec.SPDX, Labels: manifest.Labels, @@ -225,20 +251,21 @@ func (a *APIServerStore) GetSBOMp(ctx context.Context, instanceID, SBOMCreatorVe if status, ok := manifest.Annotations[instanceidhandler.StatusMetadataKey]; ok { result.Status = status } - logger.L().Debug("got relevant SBOM from storage", helpers.String("ID", instanceID)) + logger.L().Debug("got relevant SBOM from storage", + helpers.String("name", name)) return result, nil } func (a *APIServerStore) StoreSBOM(ctx context.Context, sbom domain.SBOM) error { _, span := otel.Tracer("").Start(ctx, "APIServerStore.StoreSBOM") defer span.End() - if sbom.ID == "" { - logger.L().Debug("skipping storing SBOM with empty ID") + if sbom.Name == "" { + logger.L().Debug("skipping storing SBOM with empty name") return nil } manifest := v1beta1.SBOMSPDXv2p3{ ObjectMeta: metav1.ObjectMeta{ - Name: sbom.ID, + Name: sbom.Name, Annotations: sbom.Annotations, Labels: sbom.Labels, }, @@ -266,11 +293,14 @@ func (a *APIServerStore) StoreSBOM(ctx context.Context, sbom domain.SBOM) error _, err := a.StorageClient.SBOMSPDXv2p3s(a.Namespace).Create(context.Background(), &manifest, metav1.CreateOptions{}) switch { case errors.IsAlreadyExists(err): - logger.L().Debug("SBOM manifest already exists in storage", helpers.String("ID", sbom.ID)) + logger.L().Debug("SBOM manifest already exists in storage", + helpers.String("name", sbom.Name)) case err != nil: - logger.L().Ctx(ctx).Warning("failed to store SBOM into apiserver", helpers.Error(err), helpers.String("ID", sbom.ID)) + logger.L().Ctx(ctx).Warning("failed to store SBOM into apiserver", helpers.Error(err), + helpers.String("name", sbom.Name)) default: - logger.L().Debug("stored SBOM in storage", helpers.String("ID", sbom.ID)) + logger.L().Debug("stored SBOM in storage", + helpers.String("name", sbom.Name)) } return nil } diff --git a/repositories/apiserver_test.go b/repositories/apiserver_test.go index 967938c..6c6c948 100644 --- a/repositories/apiserver_test.go +++ b/repositories/apiserver_test.go @@ -13,13 +13,12 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -const imageID = "k8s.gcr.io/kube-proxy@sha256:c1b135231b5b1a6799346cd701da4b59e5b7ef8e694ec7b04fb23b8dbe144137" -const instanceID = "ee9bdd0adec9ce004572faf3492f583aa82042a8b3a9d5c7d9179dc03c531eef" +const name = "k8s.gcr.io-kube-proxy-sha256-c1b13" func (a *APIServerStore) storeSBOMp(ctx context.Context, sbom domain.SBOM, incomplete bool) error { manifest := v1beta1.SBOMSPDXv2p3Filtered{ ObjectMeta: metav1.ObjectMeta{ - Name: sbom.ID, + Name: sbom.Name, Annotations: map[string]string{ instanceidhandler.StatusMetadataKey: sbom.Status, }, @@ -39,7 +38,7 @@ func (a *APIServerStore) storeSBOMp(ctx context.Context, sbom domain.SBOM, incom func TestAPIServerStore_GetCVE(t *testing.T) { type args struct { ctx context.Context - imageID string + name string SBOMCreatorVersion string CVEScannerVersion string CVEDBVersion string @@ -53,11 +52,11 @@ func TestAPIServerStore_GetCVE(t *testing.T) { { "valid CVE is retrieved", args{ - ctx: context.TODO(), - imageID: imageID, + ctx: context.TODO(), + name: name, }, domain.CVEManifest{ - ID: imageID, + Name: name, Content: &v1beta1.GrypeDocument{}, }, false, @@ -66,11 +65,11 @@ func TestAPIServerStore_GetCVE(t *testing.T) { "CVEScannerVersion mismatch", args{ ctx: context.TODO(), - imageID: imageID, + name: name, CVEScannerVersion: "v1.1.0", }, domain.CVEManifest{ - ID: imageID, + Name: name, CVEScannerVersion: "v1.0.0", Content: &v1beta1.GrypeDocument{}, }, @@ -80,25 +79,25 @@ func TestAPIServerStore_GetCVE(t *testing.T) { "CVEDBVersion mismatch", args{ ctx: context.TODO(), - imageID: imageID, + name: name, CVEDBVersion: "v1.1.0", }, domain.CVEManifest{ - ID: imageID, + Name: name, CVEDBVersion: "v1.0.0", Content: &v1beta1.GrypeDocument{}, }, true, }, { - "empty imageID", + "empty name", args{ ctx: context.TODO(), - imageID: "", + name: "", CVEDBVersion: "v1.1.0", }, domain.CVEManifest{ - ID: "", + Name: "", CVEDBVersion: "v1.0.0", Content: &v1beta1.GrypeDocument{}, }, @@ -108,11 +107,11 @@ func TestAPIServerStore_GetCVE(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { a := NewFakeAPIServerStorage("kubescape") - _, err := a.GetCVE(tt.args.ctx, tt.args.imageID, tt.args.SBOMCreatorVersion, tt.args.CVEScannerVersion, tt.args.CVEDBVersion) + _, err := a.GetCVE(tt.args.ctx, tt.args.name, tt.args.SBOMCreatorVersion, tt.args.CVEScannerVersion, tt.args.CVEDBVersion) tools.EnsureSetup(t, err == nil) err = a.StoreCVE(tt.args.ctx, tt.cve, false) tools.EnsureSetup(t, err == nil) - gotCve, _ := a.GetCVE(tt.args.ctx, tt.args.imageID, tt.args.SBOMCreatorVersion, tt.args.CVEScannerVersion, tt.args.CVEDBVersion) + gotCve, _ := a.GetCVE(tt.args.ctx, tt.args.name, tt.args.SBOMCreatorVersion, tt.args.CVEScannerVersion, tt.args.CVEDBVersion) if (gotCve.Content == nil) != tt.wantEmptyCVE { t.Errorf("GetCVE() gotCve.Content = %v, wantEmptyCVE %v", gotCve.Content, tt.wantEmptyCVE) return @@ -125,7 +124,7 @@ func TestAPIServerStore_UpdateCVE(t *testing.T) { ctx := context.TODO() a := NewFakeAPIServerStorage("kubescape") cvep := domain.CVEManifest{ - ID: instanceID, + Name: name, Content: &v1beta1.GrypeDocument{ Descriptor: v1beta1.Descriptor{ Version: "v1.0.0", @@ -137,7 +136,7 @@ func TestAPIServerStore_UpdateCVE(t *testing.T) { cvep.Content.Descriptor.Version = "v1.1.0" err = a.StoreCVE(ctx, cvep, true) assert.NoError(t, err) - got, err := a.GetCVE(ctx, instanceID, "", "", "") + got, err := a.GetCVE(ctx, name, "", "", "") tools.EnsureSetup(t, err == nil) assert.Equal(t, got.Content.Descriptor.Version, "v1.1.0") } @@ -145,7 +144,7 @@ func TestAPIServerStore_UpdateCVE(t *testing.T) { func TestAPIServerStore_GetSBOM(t *testing.T) { type args struct { ctx context.Context - imageID string + name string SBOMCreatorVersion string } tests := []struct { @@ -157,11 +156,11 @@ func TestAPIServerStore_GetSBOM(t *testing.T) { { "valid SBOM is retrieved", args{ - ctx: context.TODO(), - imageID: imageID, + ctx: context.TODO(), + name: name, }, domain.SBOM{ - ID: imageID, + Name: name, Content: &v1beta1.Document{ CreationInfo: &v1beta1.CreationInfo{ Created: time.Now().Format(time.RFC3339), @@ -173,11 +172,11 @@ func TestAPIServerStore_GetSBOM(t *testing.T) { { "invalid timestamp, SBOM is still retrieved", args{ - ctx: context.TODO(), - imageID: imageID, + ctx: context.TODO(), + name: name, }, domain.SBOM{ - ID: imageID, + Name: name, Content: &v1beta1.Document{ CreationInfo: &v1beta1.CreationInfo{ Created: "invalid timestamp", @@ -190,11 +189,11 @@ func TestAPIServerStore_GetSBOM(t *testing.T) { "SBOMCreatorVersion mismatch", args{ ctx: context.TODO(), - imageID: imageID, + name: name, SBOMCreatorVersion: "v1.1.0", }, domain.SBOM{ - ID: imageID, + Name: name, SBOMCreatorVersion: "v1.0.0", Content: &v1beta1.Document{ CreationInfo: &v1beta1.CreationInfo{ @@ -205,14 +204,14 @@ func TestAPIServerStore_GetSBOM(t *testing.T) { true, }, { - "empty imageID", + "empty name", args{ ctx: context.TODO(), - imageID: "", + name: "", SBOMCreatorVersion: "v1.1.0", }, domain.SBOM{ - ID: "", + Name: "", SBOMCreatorVersion: "v1.0.0", Content: &v1beta1.Document{ CreationInfo: &v1beta1.CreationInfo{ @@ -226,11 +225,11 @@ func TestAPIServerStore_GetSBOM(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { a := NewFakeAPIServerStorage("kubescape") - _, err := a.GetSBOM(tt.args.ctx, tt.args.imageID, tt.args.SBOMCreatorVersion) + _, err := a.GetSBOM(tt.args.ctx, tt.args.name, tt.args.SBOMCreatorVersion) tools.EnsureSetup(t, err == nil) err = a.StoreSBOM(tt.args.ctx, tt.sbom) tools.EnsureSetup(t, err == nil) - gotSbom, _ := a.GetSBOM(tt.args.ctx, tt.args.imageID, tt.args.SBOMCreatorVersion) + gotSbom, _ := a.GetSBOM(tt.args.ctx, tt.args.name, tt.args.SBOMCreatorVersion) if (gotSbom.Content == nil) != tt.wantEmptySBOM { t.Errorf("GetSBOM() gotSbom.Content = %v, wantEmptySBOM %v", gotSbom.Content, tt.wantEmptySBOM) return @@ -242,7 +241,7 @@ func TestAPIServerStore_GetSBOM(t *testing.T) { func TestAPIServerStore_GetSBOMp(t *testing.T) { type args struct { ctx context.Context - instanceID string + name string SBOMCreatorVersion string } tests := []struct { @@ -255,11 +254,11 @@ func TestAPIServerStore_GetSBOMp(t *testing.T) { { name: "valid SBOMp is retrieved", args: args{ - ctx: context.TODO(), - instanceID: instanceID, + ctx: context.TODO(), + name: name, }, sbom: domain.SBOM{ - ID: instanceID, + Name: name, Content: &v1beta1.Document{ CreationInfo: &v1beta1.CreationInfo{ Created: time.Now().Format(time.RFC3339), @@ -270,11 +269,11 @@ func TestAPIServerStore_GetSBOMp(t *testing.T) { { name: "invalid timestamp, SBOMp is still retrieved", args: args{ - ctx: context.TODO(), - instanceID: instanceID, + ctx: context.TODO(), + name: name, }, sbom: domain.SBOM{ - ID: instanceID, + Name: name, Content: &v1beta1.Document{ CreationInfo: &v1beta1.CreationInfo{ Created: "invalid timestamp", @@ -286,11 +285,11 @@ func TestAPIServerStore_GetSBOMp(t *testing.T) { name: "SBOMCreatorVersion mismatch", args: args{ ctx: context.TODO(), - instanceID: instanceID, + name: name, SBOMCreatorVersion: "v1.1.0", }, sbom: domain.SBOM{ - ID: instanceID, + Name: name, SBOMCreatorVersion: "v1.0.0", Content: &v1beta1.Document{ CreationInfo: &v1beta1.CreationInfo{ @@ -301,14 +300,14 @@ func TestAPIServerStore_GetSBOMp(t *testing.T) { wantEmptySBOM: false, // SBOMp is not versioned }, { - name: "empty imageID", + name: "empty name", args: args{ ctx: context.TODO(), - instanceID: "", + name: "", SBOMCreatorVersion: "v1.1.0", }, sbom: domain.SBOM{ - ID: "", + Name: "", SBOMCreatorVersion: "v1.0.0", Content: &v1beta1.Document{ CreationInfo: &v1beta1.CreationInfo{ @@ -321,11 +320,11 @@ func TestAPIServerStore_GetSBOMp(t *testing.T) { { name: "incomplete SBOMp is retrieved", args: args{ - ctx: context.TODO(), - instanceID: instanceID, + ctx: context.TODO(), + name: name, }, sbom: domain.SBOM{ - ID: instanceID, + Name: name, Content: &v1beta1.Document{ CreationInfo: &v1beta1.CreationInfo{ Created: time.Now().Format(time.RFC3339), @@ -339,11 +338,11 @@ func TestAPIServerStore_GetSBOMp(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { a := NewFakeAPIServerStorage("kubescape") - _, err := a.GetSBOMp(tt.args.ctx, tt.args.instanceID, tt.args.SBOMCreatorVersion) + _, err := a.GetSBOMp(tt.args.ctx, tt.args.name, tt.args.SBOMCreatorVersion) tools.EnsureSetup(t, err == nil) err = a.storeSBOMp(tt.args.ctx, tt.sbom, tt.incomplete) tools.EnsureSetup(t, err == nil) - gotSbom, _ := a.GetSBOMp(tt.args.ctx, tt.args.instanceID, tt.args.SBOMCreatorVersion) + gotSbom, _ := a.GetSBOMp(tt.args.ctx, tt.args.name, tt.args.SBOMCreatorVersion) if (gotSbom.Content == nil) != tt.wantEmptySBOM { t.Errorf("GetSBOM() gotSbom.Content = %v, wantEmptySBOM %v", gotSbom.Content, tt.wantEmptySBOM) return diff --git a/repositories/memory.go b/repositories/memory.go index 9edba03..c1e8010 100644 --- a/repositories/memory.go +++ b/repositories/memory.go @@ -43,7 +43,7 @@ func NewMemoryStorage(getError, storeError bool) *MemoryStore { } // GetCVE returns a CVE manifest from an in-memory map -func (m *MemoryStore) GetCVE(ctx context.Context, imageID, SBOMCreatorVersion, CVEScannerVersion, CVEDBVersion string) (cve domain.CVEManifest, err error) { +func (m *MemoryStore) GetCVE(ctx context.Context, name, SBOMCreatorVersion, CVEScannerVersion, CVEDBVersion string) (cve domain.CVEManifest, err error) { _, span := otel.Tracer("").Start(ctx, "MemoryStore.GetCVE") defer span.End() @@ -52,7 +52,7 @@ func (m *MemoryStore) GetCVE(ctx context.Context, imageID, SBOMCreatorVersion, C } id := cveID{ - Name: imageID, + Name: name, SBOMCreatorVersion: SBOMCreatorVersion, CVEScannerVersion: CVEScannerVersion, CVEDBVersion: CVEDBVersion, @@ -73,7 +73,7 @@ func (m *MemoryStore) StoreCVE(ctx context.Context, cve domain.CVEManifest, _ bo } id := cveID{ - Name: cve.ID, + Name: cve.Name, SBOMCreatorVersion: cve.SBOMCreatorVersion, CVEScannerVersion: cve.CVEScannerVersion, CVEDBVersion: cve.CVEDBVersion, @@ -83,7 +83,7 @@ func (m *MemoryStore) StoreCVE(ctx context.Context, cve domain.CVEManifest, _ bo } // GetSBOM returns a SBOM from an in-memory map -func (m *MemoryStore) GetSBOM(ctx context.Context, imageID, SBOMCreatorVersion string) (sbom domain.SBOM, err error) { +func (m *MemoryStore) GetSBOM(ctx context.Context, name, SBOMCreatorVersion string) (sbom domain.SBOM, err error) { _, span := otel.Tracer("").Start(ctx, "MemoryStore.GetSBOM") defer span.End() @@ -92,7 +92,7 @@ func (m *MemoryStore) GetSBOM(ctx context.Context, imageID, SBOMCreatorVersion s } id := sbomID{ - Name: imageID, + Name: name, SBOMCreatorVersion: SBOMCreatorVersion, } if value, ok := m.sboms[id]; ok { @@ -130,7 +130,7 @@ func (m *MemoryStore) StoreSBOM(ctx context.Context, sbom domain.SBOM) error { } id := sbomID{ - Name: sbom.ID, + Name: sbom.Name, SBOMCreatorVersion: sbom.SBOMCreatorVersion, } m.sboms[id] = sbom diff --git a/repositories/memory_test.go b/repositories/memory_test.go index bee1b2d..a6b34b2 100644 --- a/repositories/memory_test.go +++ b/repositories/memory_test.go @@ -12,36 +12,36 @@ import ( func TestMemoryStore_GetCVE(t *testing.T) { m := NewMemoryStorage(false, false) ctx := context.TODO() - got, _ := m.GetCVE(ctx, "imageID", "", "", "") + got, _ := m.GetCVE(ctx, "name", "", "", "") assert.Nil(t, got.Content) cve := domain.CVEManifest{ - ID: "imageID", + Name: "name", SBOMCreatorVersion: "", CVEScannerVersion: "", CVEDBVersion: "", Content: &v1beta1.GrypeDocument{}, } _ = m.StoreCVE(ctx, cve, false) - got, _ = m.GetCVE(ctx, "imageID", "", "", "") + got, _ = m.GetCVE(ctx, "name", "", "", "") assert.NotNil(t, got.Content) } func TestMemoryStore_GetSBOM(t *testing.T) { m := NewMemoryStorage(false, false) ctx := context.TODO() - got, _ := m.GetSBOM(ctx, "imageID", "") + got, _ := m.GetSBOM(ctx, "name", "") assert.Nil(t, got.Content) - got, _ = m.GetSBOMp(ctx, "imageID", "") + got, _ = m.GetSBOMp(ctx, "name", "") assert.Nil(t, got.Content) sbom := domain.SBOM{ - ID: "imageID", + Name: "name", SBOMCreatorVersion: "", Status: "", Content: &v1beta1.Document{}, } _ = m.StoreSBOM(ctx, sbom) - got, _ = m.GetSBOM(ctx, "imageID", "") + got, _ = m.GetSBOM(ctx, "name", "") assert.NotNil(t, got.Content) - got, _ = m.GetSBOMp(ctx, "imageID", "") + got, _ = m.GetSBOMp(ctx, "name", "") assert.NotNil(t, got.Content) }