From 86983305521425c732751a45e1e1be4332dbeacc Mon Sep 17 00:00:00 2001 From: Matthias Bertschy Date: Mon, 27 Mar 2023 14:08:00 +0200 Subject: [PATCH] implement scan registry Signed-off-by: Matthias Bertschy --- api/v1/testdata/scan-registry.yaml | 28 ++++++++ cmd/http/main.go | 5 +- cmd/http/main_test.go | 42 ++++++++--- controllers/http.go | 82 +++++++++++++++++++--- core/domain/scan.go | 24 +++++-- core/ports/services.go | 2 + core/services/mockscan.go | 14 ++++ core/services/scan.go | 84 ++++++++++++++++++++-- core/services/scan_test.go | 107 ++++++++++++++++++++++++++++- go.mod | 10 +-- go.sum | 8 +-- 11 files changed, 368 insertions(+), 38 deletions(-) create mode 100644 api/v1/testdata/scan-registry.yaml diff --git a/api/v1/testdata/scan-registry.yaml b/api/v1/testdata/scan-registry.yaml new file mode 100644 index 0000000..80c6621 --- /dev/null +++ b/api/v1/testdata/scan-registry.yaml @@ -0,0 +1,28 @@ +{ + "session": { + "jobIDs": [ + "80fc5ba7-e6df-4d8f-ae94-475242cd7345", + "b56211c7-716a-4f9f-b27f-b4942195fa5e" + ], + "timestamp": "2023-02-02T13:18:50.316451657+02:00", + "rootJobID": "80fc5ba7-e6df-4d8f-ae94-475242cd7345", + "action": "vulnerability-scan" + }, + "imageTag": "k8s.gcr.io/kube-proxy:v1.24.3", + "wlid": "wlid://cluster-minikube/namespace-kube-system/daemonset-kube-proxy", + "isScanned": false, + "containerName": "kube-proxy", + "jobID": "b56211c7-716a-4f9f-b27f-b4942195fa5e", + "parentJobID": "80fc5ba7-e6df-4d8f-ae94-475242cd7345", + "actionIDN": 3, + "credentials": { + "username": "oauth2accesstoken", + "password": "very secret" + }, + "credentialsList": [ + { + "username": "oauth2accesstoken", + "password": "very secret" + } + ] +} diff --git a/cmd/http/main.go b/cmd/http/main.go index c407f75..daf7766 100644 --- a/cmd/http/main.go +++ b/cmd/http/main.go @@ -63,11 +63,12 @@ func main() { router.GET("/v1/liveness", controller.Alive) router.GET("/v1/readiness", controller.Ready) - group := router.Group(apis.WebsocketScanCommandVersion) + group := router.Group(apis.VulnerabilityScanCommandVersion) { group.Use(otelgin.Middleware("kubevuln-svc")) group.POST("/"+apis.SBOMCalculationCommandPath, controller.GenerateSBOM) - group.POST("/"+apis.WebsocketScanCommandPath, controller.ScanCVE) + group.POST("/"+apis.ContainerScanCommandPath, controller.ScanCVE) + group.POST("/"+apis.RegistryScanCommandPath, controller.ScanRegistry) } srv := &http.Server{ diff --git a/cmd/http/main_test.go b/cmd/http/main_test.go index af981bb..bbf42f7 100644 --- a/cmd/http/main_test.go +++ b/cmd/http/main_test.go @@ -20,13 +20,31 @@ func TestScan(t *testing.T) { tests := []struct { name string yamlFile string + url string expectedCode int expectedBody string storage bool }{ + { + "generate SBOM no storage", + "../../api/v1/testdata/scan.yaml", + "/v1/generateSBOM", + 200, + "{\"detail\":\"ImageHash=k8s.gcr.io/kube-proxy@sha256:c1b135231b5b1a6799346cd701da4b59e5b7ef8e694ec7b04fb23b8dbe144137\",\"status\":200,\"title\":\"OK\"}", + false, + }, + { + "generate SBOM storage", + "../../api/v1/testdata/scan.yaml", + "/v1/generateSBOM", + 200, + "{\"detail\":\"ImageHash=k8s.gcr.io/kube-proxy@sha256:c1b135231b5b1a6799346cd701da4b59e5b7ef8e694ec7b04fb23b8dbe144137\",\"status\":200,\"title\":\"OK\"}", + true, + }, { "phase 1: valid scan command succeeds and reports CVE", "../../api/v1/testdata/scan.yaml", + "/v1/scanImage", 200, "{\"detail\":\"Wlid=wlid://cluster-minikube/namespace-kube-system/daemonset-kube-proxy, ImageHash=k8s.gcr.io/kube-proxy@sha256:c1b135231b5b1a6799346cd701da4b59e5b7ef8e694ec7b04fb23b8dbe144137\",\"status\":200,\"title\":\"OK\"}", false, @@ -34,6 +52,7 @@ func TestScan(t *testing.T) { { "phase 1: missing fields", "../../api/v1/testdata/scan-incomplete.yaml", + "/v1/scanImage", 500, "{\"detail\":\"Wlid=wlid://cluster-bez-longrun3/namespace-kube-system/deployment-coredns, ImageHash=\",\"status\":500,\"title\":\"Internal Server Error\"}", false, @@ -41,6 +60,7 @@ func TestScan(t *testing.T) { { "phase 1: invalid yaml", "../../api/v1/testdata/scan-invalid.yaml", + "/v1/scanImage", 400, "{\"status\":400,\"title\":\"Bad Request\"}", false, @@ -48,10 +68,19 @@ func TestScan(t *testing.T) { { "phase 2: valid scan command succeeds and reports CVE", "../../api/v1/testdata/scan.yaml", + "/v1/scanImage", 200, "{\"detail\":\"Wlid=wlid://cluster-minikube/namespace-kube-system/daemonset-kube-proxy, ImageHash=k8s.gcr.io/kube-proxy@sha256:c1b135231b5b1a6799346cd701da4b59e5b7ef8e694ec7b04fb23b8dbe144137\",\"status\":200,\"title\":\"OK\"}", true, }, + { + "registry scan: valid scan command succeeds and reports CVE", + "../../api/v1/testdata/scan-registry.yaml", + "/v1/scanRegistryImage", + 200, + "{\"detail\":\"ImageTag=k8s.gcr.io/kube-proxy:v1.24.3\",\"status\":200,\"title\":\"OK\"}", + false, + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { @@ -67,10 +96,11 @@ func TestScan(t *testing.T) { router.GET("/v1/liveness", controller.Alive) router.GET("/v1/readiness", controller.Ready) - group := router.Group(apis.WebsocketScanCommandVersion) + group := router.Group(apis.VulnerabilityScanCommandVersion) { group.POST("/"+apis.SBOMCalculationCommandPath, controller.GenerateSBOM) - group.POST("/"+apis.WebsocketScanCommandPath, controller.ScanCVE) + group.POST("/"+apis.ContainerScanCommandPath, controller.ScanCVE) + group.POST("/"+apis.RegistryScanCommandPath, controller.ScanRegistry) } req, _ := http.NewRequest("GET", "/v1/liveness", nil) @@ -83,13 +113,7 @@ func TestScan(t *testing.T) { file, err := os.Open(test.yamlFile) tools.EnsureSetup(t, err == nil) - req, _ = http.NewRequest("POST", "/v1/generateSBOM", file) - w = httptest.NewRecorder() - router.ServeHTTP(w, req) - - file, err = os.Open(test.yamlFile) - tools.EnsureSetup(t, err == nil) - req, _ = http.NewRequest("POST", "/v1/scanImage", file) + req, _ = http.NewRequest("POST", test.url, file) w = httptest.NewRecorder() router.ServeHTTP(w, req) diff --git a/controllers/http.go b/controllers/http.go index ba249e6..6e27b2f 100644 --- a/controllers/http.go +++ b/controllers/http.go @@ -33,18 +33,19 @@ func NewHTTPController(scanService ports.ScanService, concurrency int) *HTTPCont func (h HTTPController) GenerateSBOM(c *gin.Context) { ctx := c.Request.Context() - var newScan wssc.WebsocketScanCommand - err := c.ShouldBindJSON(&newScan) + var websocketScanCommand wssc.WebsocketScanCommand + err := c.ShouldBindJSON(&websocketScanCommand) if err != nil { logger.L().Ctx(ctx).Error("handler error", helpers.Error(err)) problem.Of(http.StatusBadRequest).WriteTo(c.Writer) return } - // TODO add proper transformation of wssc.WebsocketScanCommand to domain.ScanCommand + newScan := websocketScanCommandToScanCommand(websocketScanCommand) + details := problem.Detailf("ImageHash=%s", newScan.ImageHash) - ctx, err = h.scanService.ValidateGenerateSBOM(ctx, domain.ScanCommand(newScan)) + 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)) problem.Of(http.StatusInternalServerError).Append(details).WriteTo(c.Writer) @@ -80,18 +81,19 @@ func (h HTTPController) Ready(c *gin.Context) { func (h HTTPController) ScanCVE(c *gin.Context) { ctx := c.Request.Context() - var newScan wssc.WebsocketScanCommand - err := c.ShouldBindJSON(&newScan) + var websocketScanCommand wssc.WebsocketScanCommand + err := c.ShouldBindJSON(&websocketScanCommand) if err != nil { logger.L().Ctx(ctx).Error("handler error", helpers.Error(err)) problem.Of(http.StatusBadRequest).WriteTo(c.Writer) return } - // TODO add proper transformation of wssc.WebsocketScanCommand to domain.ScanCommand + newScan := websocketScanCommandToScanCommand(websocketScanCommand) + details := problem.Detailf("Wlid=%s, ImageHash=%s", newScan.Wlid, newScan.ImageHash) - ctx, err = h.scanService.ValidateScanCVE(ctx, domain.ScanCommand(newScan)) + 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)) problem.Of(http.StatusInternalServerError).Append(details).WriteTo(c.Writer) @@ -108,6 +110,70 @@ func (h HTTPController) ScanCVE(c *gin.Context) { }) } +func websocketScanCommandToScanCommand(c wssc.WebsocketScanCommand) domain.ScanCommand { + command := domain.ScanCommand{ + Credentialslist: c.Credentialslist, + ImageHash: c.ImageHash, + Wlid: c.Wlid, + ImageTag: c.ImageTag, + JobID: c.JobID, + ContainerName: c.ContainerName, + LastAction: c.LastAction, + ParentJobID: c.ParentJobID, + Args: c.Args, + Session: sessionChainToSession(c.Session), + } + if c.InstanceID != nil { + command.InstanceID = *c.InstanceID + } + return command +} + +func sessionChainToSession(s wssc.SessionChain) domain.Session { + return domain.Session{ + JobIDs: s.JobIDs, + } +} + +func (h HTTPController) ScanRegistry(c *gin.Context) { + ctx := c.Request.Context() + + var registryScanCommand wssc.RegistryScanCommand + err := c.ShouldBindJSON(®istryScanCommand) + if err != nil { + logger.L().Ctx(ctx).Error("handler error", helpers.Error(err)) + problem.Of(http.StatusBadRequest).WriteTo(c.Writer) + return + } + + newScan := registryScanCommandToScanCommand(registryScanCommand) + + details := problem.Detailf("ImageTag=%s", newScan.ImageTag) + + 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)) + problem.Of(http.StatusInternalServerError).Append(details).WriteTo(c.Writer) + return + } + + problem.Of(http.StatusOK).Append(details).WriteTo(c.Writer) + + 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)) + } + }) +} + +func registryScanCommandToScanCommand(c wssc.RegistryScanCommand) domain.ScanCommand { + return domain.ScanCommand{ + Credentialslist: c.Credentialslist, + ImageTag: c.ImageTag, + } +} + func (h HTTPController) Shutdown() { logger.L().Info("purging SBOM creation queue", helpers.String("remaining jobs", strconv.Itoa(h.workerPool.WaitingQueueSize()))) h.workerPool.StopWait() diff --git a/core/domain/scan.go b/core/domain/scan.go index b20994c..d15fed3 100644 --- a/core/domain/scan.go +++ b/core/domain/scan.go @@ -1,11 +1,27 @@ package domain -import wssc "github.com/armosec/armoapi-go/apis" +import ( + "github.com/docker/docker/api/types" +) type ScanIDKey struct{} type TimestampKey struct{} type WorkloadKey struct{} -// ScanCommand is a proxy type for wssc.WebsocketScanCommand used to decouple business logic from implementation -// it might evolve into its own struct at a later time -type ScanCommand wssc.WebsocketScanCommand +type ScanCommand struct { + Credentialslist []types.AuthConfig + ImageHash string + InstanceID string + Wlid string + ImageTag string + JobID string + ContainerName string + LastAction int + ParentJobID string + Args map[string]interface{} + Session Session +} + +type Session struct { + JobIDs []string +} diff --git a/core/ports/services.go b/core/ports/services.go index d58e294..d02d7c9 100644 --- a/core/ports/services.go +++ b/core/ports/services.go @@ -11,6 +11,8 @@ type ScanService interface { GenerateSBOM(ctx context.Context) error Ready(ctx context.Context) bool ScanCVE(ctx context.Context) error + ScanRegistry(ctx context.Context) error ValidateGenerateSBOM(ctx context.Context, workload domain.ScanCommand) (context.Context, error) ValidateScanCVE(ctx context.Context, workload domain.ScanCommand) (context.Context, error) + ValidateScanRegistry(ctx context.Context, workload domain.ScanCommand) (context.Context, error) } diff --git a/core/services/mockscan.go b/core/services/mockscan.go index 62d2dc3..99ca694 100644 --- a/core/services/mockscan.go +++ b/core/services/mockscan.go @@ -36,6 +36,13 @@ func (m MockScanService) ScanCVE(context.Context) error { return errors.New("mock error") } +func (m MockScanService) ScanRegistry(context.Context) error { + if m.happy { + return nil + } + return errors.New("mock error") +} + func (m MockScanService) ValidateGenerateSBOM(ctx context.Context, _ domain.ScanCommand) (context.Context, error) { if m.happy { return ctx, nil @@ -49,3 +56,10 @@ func (m MockScanService) ValidateScanCVE(ctx context.Context, _ domain.ScanComma } return ctx, errors.New("mock error") } + +func (m MockScanService) ValidateScanRegistry(ctx context.Context, _ domain.ScanCommand) (context.Context, error) { + if m.happy { + return ctx, nil + } + return ctx, errors.New("mock error") +} diff --git a/core/services/scan.go b/core/services/scan.go index 294c690..e201f79 100644 --- a/core/services/scan.go +++ b/core/services/scan.go @@ -163,10 +163,10 @@ func (s *ScanService) ScanCVE(ctx context.Context) error { // check if SBOM' is already available sbomp := domain.SBOM{} - if s.storage && workload.InstanceID != nil { - sbomp, err = s.sbomRepository.GetSBOMp(ctx, *workload.InstanceID, s.sbomCreator.Version(ctx)) + if s.storage && workload.InstanceID != "" { + sbomp, err = s.sbomRepository.GetSBOMp(ctx, workload.InstanceID, s.sbomCreator.Version(ctx)) 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)) } } @@ -184,7 +184,7 @@ 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)) } } } @@ -209,6 +209,60 @@ func (s *ScanService) ScanCVE(ctx context.Context) error { return nil } +func (s *ScanService) ScanRegistry(ctx context.Context) error { + ctx, span := otel.Tracer("").Start(ctx, "ScanService.ScanRegistry") + defer span.End() + + // retrieve workload from context + workload, ok := ctx.Value(domain.WorkloadKey{}).(domain.ScanCommand) + if !ok { + return errors.New("no workload found in context") + } + logger.L().Info("registry scan started", helpers.String("imageID", workload.ImageTag), 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)) + } + + // create SBOM + sbom, err := s.sbomCreator.CreateSBOM(ctx, workload.ImageTag, optionsFromWorkload(workload)) + if err != nil { + return err + } + + // do not process timed out SBOM + if sbom.Status == domain.SBOMStatusTimedOut { + return errors.New("SBOM incomplete due to timeout, skipping CVE scan") + } + + // scan for CVE + cve, err := s.cveScanner.ScanSBOM(ctx, sbom) + if err != nil { + return err + } + + // 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)) + } + // submit CVE manifest to platform + err = s.platform.SubmitCVE(ctx, cve, domain.CVEManifest{}) + if err != nil { + return err + } + // 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().Info("registry scan complete", helpers.String("imageID", workload.ImageTag), helpers.String("jobID", workload.JobID)) + return nil +} + func enrichContext(ctx context.Context, workload domain.ScanCommand) context.Context { // record start time ctx = context.WithValue(ctx, domain.TimestampKey{}, time.Now().Unix()) @@ -268,8 +322,8 @@ func (s *ScanService) ValidateScanCVE(ctx context.Context, workload domain.ScanC } // add instanceID and imageID to parent span if parentSpan := trace.SpanFromContext(ctx); parentSpan != nil { - if workload.InstanceID != nil { - parentSpan.SetAttributes(attribute.String("instanceID", *workload.InstanceID)) + if workload.InstanceID != "" { + parentSpan.SetAttributes(attribute.String("instanceID", workload.InstanceID)) } parentSpan.SetAttributes(attribute.String("imageID", workload.ImageHash)) parentSpan.SetAttributes(attribute.String("version", os.Getenv("RELEASE"))) @@ -283,3 +337,21 @@ func (s *ScanService) ValidateScanCVE(ctx context.Context, workload domain.ScanC } return ctx, nil } + +func (s *ScanService) ValidateScanRegistry(ctx context.Context, workload domain.ScanCommand) (context.Context, error) { + _, span := otel.Tracer("").Start(ctx, "ScanService.ValidateScanRegistry") + defer span.End() + + ctx = enrichContext(ctx, workload) + // validate inputs + if workload.ImageTag == "" { + return ctx, errors.New("missing imageID") + } + // add imageID to parent span + if parentSpan := trace.SpanFromContext(ctx); parentSpan != nil { + parentSpan.SetAttributes(attribute.String("imageID", workload.ImageTag)) + parentSpan.SetAttributes(attribute.String("version", os.Getenv("RELEASE"))) + ctx = trace.ContextWithSpan(ctx, parentSpan) + } + return ctx, nil +} diff --git a/core/services/scan_test.go b/core/services/scan_test.go index 4be8322..fe278fb 100644 --- a/core/services/scan_test.go +++ b/core/services/scan_test.go @@ -222,7 +222,7 @@ func TestScanService_ScanCVE(t *testing.T) { Wlid: wlid, } if tt.instanceID != "" { - workload.InstanceID = &tt.instanceID + workload.InstanceID = tt.instanceID } var err error ctx, _ = s.ValidateScanCVE(ctx, workload) @@ -332,3 +332,108 @@ func TestScanService_ValidateScanCVE(t *testing.T) { }) } } + +func TestScanService_ScanRegistry(t *testing.T) { + tests := []struct { + createSBOMError bool + name string + timeout bool + workload bool + wantErr bool + }{ + { + name: "no workload", + workload: false, + wantErr: true, + }, + { + name: "create SBOM error", + createSBOMError: true, + workload: true, + wantErr: true, + }, + { + name: "timeout SBOM", + timeout: true, + workload: true, + wantErr: true, + }, + { + name: "scan", + workload: true, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + sbomAdapter := adapters.NewMockSBOMAdapter(tt.createSBOMError, tt.timeout) + storage := repositories.NewMemoryStorage(false, false) + s := NewScanService(sbomAdapter, + storage, + adapters.NewMockCVEAdapter(), + storage, + adapters.NewMockPlatform(), + false) + ctx := context.TODO() + if tt.workload { + workload := domain.ScanCommand{ + ImageTag: "k8s.gcr.io/kube-proxy:v1.24.3", + } + workload.Credentialslist = []types.AuthConfig{ + { + Username: "test", + Password: "test", + }, + { + RegistryToken: "test", + }, + { + Auth: "test", + }, + } + var err error + ctx, _ = s.ValidateScanRegistry(ctx, workload) + tools.EnsureSetup(t, err == nil) + } + if err := s.ScanRegistry(ctx); (err != nil) != tt.wantErr { + t.Errorf("GenerateSBOM() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestScanService_ValidateScanRegistry(t *testing.T) { + tests := []struct { + name string + workload domain.ScanCommand + wantErr bool + }{ + { + name: "missing imageID", + workload: domain.ScanCommand{}, + wantErr: true, + }, + { + name: "with imageID", + workload: domain.ScanCommand{ + ImageTag: "k8s.gcr.io/kube-proxy:v1.24.3", + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := NewScanService(adapters.NewMockSBOMAdapter(false, false), + repositories.NewMemoryStorage(false, false), + adapters.NewMockCVEAdapter(), + repositories.NewMemoryStorage(false, false), + adapters.NewMockPlatform(), + false) + _, err := s.ValidateScanRegistry(context.TODO(), tt.workload) + if (err != nil) != tt.wantErr { + t.Errorf("ValidateScanCVE() error = %v, wantErr %v", err, tt.wantErr) + return + } + }) + } +} diff --git a/go.mod b/go.mod index 9bc5ab8..563cf14 100644 --- a/go.mod +++ b/go.mod @@ -7,12 +7,13 @@ require ( github.com/anchore/grype v0.59.1 github.com/anchore/stereoscope v0.0.0-20230317134707-7928713c391e github.com/anchore/syft v0.75.0 - github.com/armosec/armoapi-go v0.0.173 + github.com/armosec/armoapi-go v0.0.176 github.com/armosec/cluster-container-scanner-api v0.0.52 github.com/armosec/logger-go v0.0.14 github.com/armosec/utils-go v0.0.14 github.com/armosec/utils-k8s-go v0.0.13 github.com/distribution/distribution v2.8.1+incompatible + github.com/docker/docker v23.0.1+incompatible github.com/eapache/go-resiliency v1.3.0 github.com/gammazero/workerpool v1.1.3 github.com/gin-gonic/gin v1.9.0 @@ -67,7 +68,6 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/docker/cli v23.0.1+incompatible // indirect github.com/docker/distribution v2.8.1+incompatible // indirect - github.com/docker/docker v23.0.1+incompatible // indirect github.com/docker/docker-credential-helpers v0.7.0 // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.5.0 // indirect @@ -115,7 +115,7 @@ require ( github.com/imdario/mergo v0.3.12 // indirect github.com/jinzhu/copier v0.3.5 // indirect github.com/jinzhu/inflection v1.0.0 // indirect - github.com/jinzhu/now v1.1.4 // indirect + github.com/jinzhu/now v1.1.5 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -218,7 +218,7 @@ require ( gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - gorm.io/gorm v1.23.10 // indirect + gorm.io/gorm v1.24.6 // indirect k8s.io/api v0.26.3 // indirect k8s.io/klog/v2 v2.80.1 // indirect k8s.io/kube-openapi v0.0.0-20230123231816-1cb3ae25d79a // indirect @@ -237,3 +237,5 @@ require ( sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) + +replace gorm.io/gorm => gorm.io/gorm v1.23.10 diff --git a/go.sum b/go.sum index fe12d6f..6c86465 100644 --- a/go.sum +++ b/go.sum @@ -254,8 +254,8 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/armosec/armoapi-go v0.0.173 h1:TwNxmTxx9ATJPZBlld/53s/WvSVUfoF4gxgHT6UbFng= -github.com/armosec/armoapi-go v0.0.173/go.mod h1:xlW8dGq0vVzbuk+kDZqMQIkfU9P/iiiiDavoCIboqgI= +github.com/armosec/armoapi-go v0.0.176 h1:C0TWqU1BrKpfJGKT9rhqGVzUZBUxLOvcSOFOoWEkFAA= +github.com/armosec/armoapi-go v0.0.176/go.mod h1:cC43pDRr6tLMIVQGdgH1G/UxBiV5QI2QttxE9pkbqmo= github.com/armosec/cluster-container-scanner-api v0.0.52 h1:u6T4wCTGwyJiPPTIAVrRqsT1sfw30e+/mjVuNmDK4mg= github.com/armosec/cluster-container-scanner-api v0.0.52/go.mod h1:HP1ZdO9/R8x8IMiTwO3dwI+MNH1oBTrIwtqdE40lfuI= github.com/armosec/logger-go v0.0.14 h1:5YpXMlYt/7zIAcmJP4q1BmWNH/7bpkSndfZTyysrtUE= @@ -618,8 +618,9 @@ github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg= github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= -github.com/jinzhu/now v1.1.4 h1:tHnRBy1i5F2Dh8BAFxqFzxKqqvezXrL2OW1TnX+Mlas= github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= @@ -1624,7 +1625,6 @@ gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/gorm v1.23.5/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.23.10 h1:4Ne9ZbzID9GUxRkllxN4WjJKpsHx8YbKvekVdgyWh24= gorm.io/gorm v1.23.10/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=