From 942f0a4c3faad7220f5c71c1d0ecf5ee6825911f Mon Sep 17 00:00:00 2001 From: Gireesh Naidu Date: Fri, 2 Aug 2024 15:50:13 +0530 Subject: [PATCH 1/9] feat: add support for app and env sorting in scan list api and add medium, high and unknown severity support --- api/restHandler/ImageScanRestHandler.go | 23 +- api/restHandler/PolicyRestHandler.go | 20 +- cmd/external-app/wire_gen.go | 2 +- .../repository/security/CvePolicyControle.go | 134 +++-------- .../repository/security/CveStoreRepository.go | 14 +- .../security/ImageScanDeployInfoRepository.go | 101 ++++---- internal/sql/repository/security/bean/bean.go | 71 ++++++ pkg/security/ImageScanService.go | 224 ++++++++---------- pkg/security/bean/bean.go | 119 ++++++++++ pkg/security/policyService.go | 112 ++++----- wire_gen.go | 2 +- 11 files changed, 456 insertions(+), 366 deletions(-) create mode 100644 internal/sql/repository/security/bean/bean.go create mode 100644 pkg/security/bean/bean.go diff --git a/api/restHandler/ImageScanRestHandler.go b/api/restHandler/ImageScanRestHandler.go index 90b68a8898..eded4a3de4 100644 --- a/api/restHandler/ImageScanRestHandler.go +++ b/api/restHandler/ImageScanRestHandler.go @@ -19,6 +19,7 @@ package restHandler import ( "encoding/json" "fmt" + securityBean "github.com/devtron-labs/devtron/pkg/security/bean" "net/http" "strconv" @@ -70,7 +71,7 @@ func (impl ImageScanRestHandlerImpl) ScanExecutionList(w http.ResponseWriter, r } decoder := json.NewDecoder(r.Body) - var request *security.ImageScanRequest + var request *securityBean.ImageScanRequest err = decoder.Decode(&request) if err != nil { impl.logger.Errorw("request err, ScanExecutionList", "err", err, "payload", request) @@ -82,8 +83,8 @@ func (impl ImageScanRestHandlerImpl) ScanExecutionList(w http.ResponseWriter, r if err != nil { impl.logger.Errorw("service err, ScanExecutionList", "err", err, "payload", request) if util.IsErrNoRows(err) { - responseList := make([]*security.ImageScanHistoryResponse, 0) - common.WriteJsonResp(w, nil, &security.ImageScanHistoryListingResponse{ImageScanHistoryResponse: responseList}, http.StatusOK) + responseList := make([]*securityBean.ImageScanHistoryResponse, 0) + common.WriteJsonResp(w, nil, &securityBean.ImageScanHistoryListingResponse{ImageScanHistoryResponse: responseList}, http.StatusOK) } else { common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) } @@ -126,8 +127,8 @@ func (impl ImageScanRestHandlerImpl) ScanExecutionList(w http.ResponseWriter, r if err != nil { impl.logger.Errorw("service err, ScanExecutionList", "err", err, "payload", request) if util.IsErrNoRows(err) { - responseList := make([]*security.ImageScanHistoryResponse, 0) - common.WriteJsonResp(w, nil, &security.ImageScanHistoryListingResponse{ImageScanHistoryResponse: responseList}, http.StatusOK) + responseList := make([]*securityBean.ImageScanHistoryResponse, 0) + common.WriteJsonResp(w, nil, &securityBean.ImageScanHistoryListingResponse{ImageScanHistoryResponse: responseList}, http.StatusOK) } else { common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) } @@ -177,7 +178,7 @@ func (impl ImageScanRestHandlerImpl) FetchExecutionDetail(w http.ResponseWriter, } } image := v.Get("image") - request := &security.ImageScanRequest{ + request := &securityBean.ImageScanRequest{ ImageScanDeployInfoId: imageScanDeployInfoId, Image: image, ArtifactId: artifactId, @@ -189,7 +190,7 @@ func (impl ImageScanRestHandlerImpl) FetchExecutionDetail(w http.ResponseWriter, if err != nil { impl.logger.Errorw("service err, FetchExecutionDetail", "err", err, "payload", request) if util.IsErrNoRows(err) { - common.WriteJsonResp(w, nil, &security.ImageScanExecutionDetail{}, http.StatusOK) + common.WriteJsonResp(w, nil, &securityBean.ImageScanExecutionDetail{}, http.StatusOK) } else { common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) } @@ -221,7 +222,7 @@ func (impl ImageScanRestHandlerImpl) FetchExecutionDetail(w http.ResponseWriter, } //RBAC } else { - common.WriteJsonResp(w, err, &security.ImageScanExecutionDetail{}, http.StatusOK) + common.WriteJsonResp(w, err, &securityBean.ImageScanExecutionDetail{}, http.StatusOK) } common.WriteJsonResp(w, err, executionDetail, http.StatusOK) @@ -230,7 +231,7 @@ func (impl ImageScanRestHandlerImpl) FetchExecutionDetail(w http.ResponseWriter, func (impl ImageScanRestHandlerImpl) FetchMinScanResultByAppIdAndEnvId(w http.ResponseWriter, r *http.Request) { v := r.URL.Query() var appId, envId int - request := &security.ImageScanRequest{} + request := &securityBean.ImageScanRequest{} appIds := v.Get("appId") if len(appIds) > 0 { appId, err := strconv.Atoi(appIds) @@ -299,8 +300,8 @@ func (impl ImageScanRestHandlerImpl) VulnerabilityExposure(w http.ResponseWriter if err != nil { impl.logger.Errorw("service err, VulnerabilityExposure", "err", err, "payload", request) if util.IsErrNoRows(err) { - responseList := make([]*security.ImageScanHistoryResponse, 0) - common.WriteJsonResp(w, nil, &security.ImageScanHistoryListingResponse{ImageScanHistoryResponse: responseList}, http.StatusOK) + responseList := make([]*securityBean.ImageScanHistoryResponse, 0) + common.WriteJsonResp(w, nil, &securityBean.ImageScanHistoryListingResponse{ImageScanHistoryResponse: responseList}, http.StatusOK) } else { common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) } diff --git a/api/restHandler/PolicyRestHandler.go b/api/restHandler/PolicyRestHandler.go index fdbc7e9982..6dce4c3037 100644 --- a/api/restHandler/PolicyRestHandler.go +++ b/api/restHandler/PolicyRestHandler.go @@ -20,12 +20,12 @@ import ( "encoding/json" "errors" "fmt" + securityBean "github.com/devtron-labs/devtron/internal/sql/repository/security/bean" "net/http" "strconv" "github.com/devtron-labs/devtron/api/bean" "github.com/devtron-labs/devtron/api/restHandler/common" - security2 "github.com/devtron-labs/devtron/internal/sql/repository/security" "github.com/devtron-labs/devtron/pkg/auth/authorisation/casbin" user2 "github.com/devtron-labs/devtron/pkg/auth/user" "github.com/devtron-labs/devtron/pkg/cluster" @@ -221,18 +221,18 @@ func (impl PolicyRestHandlerImpl) GetPolicy(w http.ResponseWriter, r *http.Reque req.Id = ids } var clusterId, environmentId, appId int - var policyLevel security2.PolicyLevel - if level == security2.Global.String() { - policyLevel = security2.Global - } else if level == security2.Cluster.String() { + var policyLevel securityBean.PolicyLevel + if level == securityBean.Global.String() { + policyLevel = securityBean.Global + } else if level == securityBean.Cluster.String() { clusterId = req.Id - policyLevel = security2.Cluster - } else if level == security2.Environment.String() { + policyLevel = securityBean.Cluster + } else if level == securityBean.Environment.String() { environmentId = req.Id - policyLevel = security2.Environment - } else if level == security2.Application.String() { + policyLevel = securityBean.Environment + } else if level == securityBean.Application.String() { appId = req.Id - policyLevel = security2.Application + policyLevel = securityBean.Application } token := r.Header.Get("token") diff --git a/cmd/external-app/wire_gen.go b/cmd/external-app/wire_gen.go index 917252738d..7cada24e76 100644 --- a/cmd/external-app/wire_gen.go +++ b/cmd/external-app/wire_gen.go @@ -1,6 +1,6 @@ // Code generated by Wire. DO NOT EDIT. -//go:generate go run -mod=mod github.com/google/wire/cmd/wire +//go:generate go run github.com/google/wire/cmd/wire //go:build !wireinject // +build !wireinject diff --git a/internal/sql/repository/security/CvePolicyControle.go b/internal/sql/repository/security/CvePolicyControle.go index 45728ca1b6..aac9c0f5ed 100644 --- a/internal/sql/repository/security/CvePolicyControle.go +++ b/internal/sql/repository/security/CvePolicyControle.go @@ -18,6 +18,7 @@ package security import ( "fmt" + securityBean "github.com/devtron-labs/devtron/internal/sql/repository/security/bean" "github.com/devtron-labs/devtron/pkg/sql" "github.com/go-pg/pg" "github.com/go-pg/pg/orm" @@ -25,92 +26,29 @@ import ( ) type CvePolicy struct { - tableName struct{} `sql:"cve_policy_control" pg:",discard_unknown_columns"` - Id int `sql:"id,pk"` - Global bool `sql:"global,notnull"` - ClusterId int `sql:"cluster_id"` - EnvironmentId int `sql:"env_id"` - AppId int `sql:"app_id"` - CVEStoreId string `sql:"cve_store_id"` - Action PolicyAction `sql:"action, notnull"` - Severity *Severity `sql:"severity, notnull "` - Deleted bool `sql:"deleted, notnull"` + tableName struct{} `sql:"cve_policy_control" pg:",discard_unknown_columns"` + Id int `sql:"id,pk"` + Global bool `sql:"global,notnull"` + ClusterId int `sql:"cluster_id"` + EnvironmentId int `sql:"env_id"` + AppId int `sql:"app_id"` + CVEStoreId string `sql:"cve_store_id"` + Action securityBean.PolicyAction `sql:"action, notnull"` + Severity *securityBean.Severity `sql:"severity, notnull "` + Deleted bool `sql:"deleted, notnull"` sql.AuditLog CveStore *CveStore } -type PolicyAction int - -const ( - Inherit PolicyAction = iota - Allow - Block - Blockiffixed -) - -func (d PolicyAction) String() string { - return [...]string{"inherit", "allow", "block", "blockiffixed"}[d] -} - -// ------------------ -type Severity int - -const ( - Low Severity = iota - Medium - Critical - High - Safe -) -const ( - HIGH string = "high" - CRITICAL string = "critical" - SAFE string = "safe" - LOW string = "low" - MEDIUM string = "medium" - MODERATE string = "moderate" -) - -// Handling for future use -func (d Severity) ValuesOf(severity string) Severity { - if severity == CRITICAL || severity == HIGH { - return Critical - } else if severity == MODERATE || severity == MEDIUM { - return Medium - } else if severity == LOW || severity == SAFE { - return Low - } - return Low -} - -// Updating it for future use(not in use for standard severity) -func (d Severity) String() string { - return [...]string{"low", "moderate", "critical", "high", "safe"}[d] -} - -// ---------------- -type PolicyLevel int - -const ( - Global PolicyLevel = iota - Cluster - Environment - Application -) - -func (d PolicyLevel) String() string { - return [...]string{"global", "cluster", "environment", "application"}[d] -} - -func (policy *CvePolicy) PolicyLevel() PolicyLevel { +func (policy *CvePolicy) PolicyLevel() securityBean.PolicyLevel { if policy.ClusterId != 0 { - return Cluster + return securityBean.Cluster } else if policy.AppId != 0 { - return Application + return securityBean.Application } else if policy.EnvironmentId != 0 { - return Environment + return securityBean.Environment } else { - return Global + return securityBean.Global } } @@ -250,19 +188,19 @@ func (impl *CvePolicyRepositoryImpl) GetBlockedCVEList(cves []*CveStore, cluster return blockedCve, nil } -func EnforceCvePolicy(cves []*CveStore, cvePolicy map[string]*CvePolicy, severityPolicy map[Severity]*CvePolicy) (blockedCVE []*CveStore) { +func EnforceCvePolicy(cves []*CveStore, cvePolicy map[string]*CvePolicy, severityPolicy map[securityBean.Severity]*CvePolicy) (blockedCVE []*CveStore) { for _, cve := range cves { if policy, ok := cvePolicy[cve.Name]; ok { - if policy.Action == Allow { + if policy.Action == securityBean.Allow { continue - } else if (policy.Action == Block) || (policy.Action == Blockiffixed && cve.FixedVersion != "") { + } else if (policy.Action == securityBean.Block) || (policy.Action == securityBean.Blockiffixed && cve.FixedVersion != "") { blockedCVE = append(blockedCVE, cve) } } else { - if severityPolicy[cve.Severity] != nil && severityPolicy[cve.Severity].Action == Allow { + if severityPolicy[cve.StandardSeverity] != nil && severityPolicy[cve.StandardSeverity].Action == securityBean.Allow { continue - } else if severityPolicy[cve.Severity] != nil && (severityPolicy[cve.Severity].Action == Block || (severityPolicy[cve.Severity].Action == Blockiffixed && cve.FixedVersion != "")) { + } else if severityPolicy[cve.StandardSeverity] != nil && (severityPolicy[cve.StandardSeverity].Action == securityBean.Block || (severityPolicy[cve.StandardSeverity].Action == securityBean.Blockiffixed && cve.FixedVersion != "")) { blockedCVE = append(blockedCVE, cve) } } @@ -270,17 +208,17 @@ func EnforceCvePolicy(cves []*CveStore, cvePolicy map[string]*CvePolicy, severit return blockedCVE } -func (impl *CvePolicyRepositoryImpl) getApplicablePolicy(clusterId, envId, appId int, isAppstore bool) (map[string]*CvePolicy, map[Severity]*CvePolicy, error) { +func (impl *CvePolicyRepositoryImpl) getApplicablePolicy(clusterId, envId, appId int, isAppstore bool) (map[string]*CvePolicy, map[securityBean.Severity]*CvePolicy, error) { - var policyLevel PolicyLevel + var policyLevel securityBean.PolicyLevel if isAppstore && appId > 0 && envId > 0 && clusterId > 0 { - policyLevel = Environment + policyLevel = securityBean.Environment } else if appId > 0 && envId > 0 && clusterId > 0 { - policyLevel = Application + policyLevel = securityBean.Application } else if envId > 0 && clusterId > 0 { - policyLevel = Environment + policyLevel = securityBean.Environment } else if clusterId > 0 { - policyLevel = Cluster + policyLevel = securityBean.Cluster } else { //error in case of global or other policy return nil, nil, fmt.Errorf("policy not identified") @@ -290,16 +228,16 @@ func (impl *CvePolicyRepositoryImpl) getApplicablePolicy(clusterId, envId, appId return cvePolicy, severityPolicy, err } -func (impl *CvePolicyRepositoryImpl) getPolicies(policyLevel PolicyLevel, clusterId, environmentId, appId int) (map[string]*CvePolicy, map[Severity]*CvePolicy, error) { +func (impl *CvePolicyRepositoryImpl) getPolicies(policyLevel securityBean.PolicyLevel, clusterId, environmentId, appId int) (map[string]*CvePolicy, map[securityBean.Severity]*CvePolicy, error) { var policies []*CvePolicy var err error - if policyLevel == Global { + if policyLevel == securityBean.Global { policies, err = impl.GetGlobalPolicies() - } else if policyLevel == Cluster { + } else if policyLevel == securityBean.Cluster { policies, err = impl.GetClusterPolicies(clusterId) - } else if policyLevel == Environment { + } else if policyLevel == securityBean.Environment { policies, err = impl.GetEnvPolicies(clusterId, environmentId) - } else if policyLevel == Application { + } else if policyLevel == securityBean.Application { policies, err = impl.GetAppEnvPolicies(clusterId, environmentId, appId) } else { return nil, nil, fmt.Errorf("unsupported policy level: %s", policyLevel) @@ -314,9 +252,9 @@ func (impl *CvePolicyRepositoryImpl) getPolicies(policyLevel PolicyLevel, cluste return cvePolicy, severityPolicy, nil } -func (impl *CvePolicyRepositoryImpl) getApplicablePolicies(policies []*CvePolicy) (map[string]*CvePolicy, map[Severity]*CvePolicy) { +func (impl *CvePolicyRepositoryImpl) getApplicablePolicies(policies []*CvePolicy) (map[string]*CvePolicy, map[securityBean.Severity]*CvePolicy) { cvePolicy := make(map[string][]*CvePolicy) - severityPolicy := make(map[Severity][]*CvePolicy) + severityPolicy := make(map[securityBean.Severity][]*CvePolicy) for _, policy := range policies { if policy.CVEStoreId != "" { cvePolicy[policy.CveStore.Name] = append(cvePolicy[policy.CveStore.Name], policy) @@ -347,8 +285,8 @@ func (impl *CvePolicyRepositoryImpl) getHighestPolicy(allPolicies map[string][]* return applicablePolicies } -func (impl *CvePolicyRepositoryImpl) getHighestPolicyS(allPolicies map[Severity][]*CvePolicy) map[Severity]*CvePolicy { - applicablePolicies := make(map[Severity]*CvePolicy) +func (impl *CvePolicyRepositoryImpl) getHighestPolicyS(allPolicies map[securityBean.Severity][]*CvePolicy) map[securityBean.Severity]*CvePolicy { + applicablePolicies := make(map[securityBean.Severity]*CvePolicy) for key, policies := range allPolicies { var applicablePolicy *CvePolicy for _, policy := range policies { diff --git a/internal/sql/repository/security/CveStoreRepository.go b/internal/sql/repository/security/CveStoreRepository.go index 64342d20f5..1fca124966 100644 --- a/internal/sql/repository/security/CveStoreRepository.go +++ b/internal/sql/repository/security/CveStoreRepository.go @@ -19,6 +19,7 @@ package security import ( "fmt" "github.com/devtron-labs/devtron/internal/sql/repository/helper" + securityBean "github.com/devtron-labs/devtron/internal/sql/repository/security/bean" "github.com/devtron-labs/devtron/pkg/sql" "github.com/go-pg/pg" "go.uber.org/zap" @@ -27,12 +28,13 @@ import ( ) type CveStore struct { - tableName struct{} `sql:"cve_store" pg:",discard_unknown_columns"` - Name string `sql:"name,pk"` - Severity Severity `sql:"severity,notnull"` - Package string `sql:"package,notnull"` // deprecated - Version string `sql:"version,notnull"` - FixedVersion string `sql:"fixed_version,notnull"` + tableName struct{} `sql:"cve_store" pg:",discard_unknown_columns"` + Name string `sql:"name,pk"` + //Severity securityBean.Severity `sql:"severity,notnull"` + Package string `sql:"package,notnull"` // deprecated + Version string `sql:"version,notnull"` + FixedVersion string `sql:"fixed_version,notnull"` + StandardSeverity securityBean.Severity `sql:"standard_severity,notnull"` sql.AuditLog } diff --git a/internal/sql/repository/security/ImageScanDeployInfoRepository.go b/internal/sql/repository/security/ImageScanDeployInfoRepository.go index ab4d386472..02e2b5eecd 100644 --- a/internal/sql/repository/security/ImageScanDeployInfoRepository.go +++ b/internal/sql/repository/security/ImageScanDeployInfoRepository.go @@ -18,6 +18,7 @@ package security import ( "fmt" + securityBean "github.com/devtron-labs/devtron/pkg/security/bean" "github.com/devtron-labs/devtron/pkg/sql" "strconv" "strings" @@ -49,25 +50,6 @@ const ( ScanObjectType_POD string = "pod" ) -type SortBy string -type SortOrder string - -const ( - Asc SortOrder = "ASC" - Desc SortOrder = "DESC" -) - -type ImageScanFilter struct { - Offset int `json:"offset"` - Size int `json:"size"` - CVEName string `json:"cveName"` - AppName string `json:"appName"` - ObjectName string `json:"objectName"` - EnvironmentIds []int `json:"envIds"` - ClusterIds []int `json:"clusterIds"` - Severity []int `json:"severity"` -} - type ImageScanListingResponse struct { Id int `json:"id"` ScanObjectMetaId int `json:"scanObjectMetaId"` @@ -76,6 +58,7 @@ type ImageScanListingResponse struct { SecurityScan string `json:"securityScan"` EnvironmentName string `json:"environmentName"` LastChecked time.Time `json:"lastChecked"` + TotalCount int `json:"totalCount"` } type ImageScanDeployInfoRepository interface { @@ -87,7 +70,7 @@ type ImageScanDeployInfoRepository interface { FetchListingGroupByObject(size int, offset int) ([]*ImageScanDeployInfo, error) FetchByAppIdAndEnvId(appId int, envId int, objectType []string) (*ImageScanDeployInfo, error) FindByTypeMetaAndTypeId(scanObjectMetaId int, objectType string) (*ImageScanDeployInfo, error) - ScanListingWithFilter(request *ImageScanFilter, size int, offset int, deployInfoIds []int) ([]*ImageScanListingResponse, error) + ScanListingWithFilter(request *securityBean.ImageScanFilter, size int, offset int, deployInfoIds []int) ([]*ImageScanListingResponse, error) } type ImageScanDeployInfoRepositoryImpl struct { @@ -162,7 +145,7 @@ func (impl ImageScanDeployInfoRepositoryImpl) FindByTypeMetaAndTypeId(scanObject return &model, err } -func (impl ImageScanDeployInfoRepositoryImpl) ScanListingWithFilter(request *ImageScanFilter, size int, offset int, deployInfoIds []int) ([]*ImageScanListingResponse, error) { +func (impl ImageScanDeployInfoRepositoryImpl) ScanListingWithFilter(request *securityBean.ImageScanFilter, size int, offset int, deployInfoIds []int) ([]*ImageScanListingResponse, error) { var models []*ImageScanListingResponse query := impl.scanListingQueryBuilder(request, size, offset, deployInfoIds) _, err := impl.dbConnection.Query(&models, query, size, offset) @@ -173,9 +156,9 @@ func (impl ImageScanDeployInfoRepositoryImpl) ScanListingWithFilter(request *Ima return models, err } -func (impl ImageScanDeployInfoRepositoryImpl) scanListQueryWithoutObject(request *ImageScanFilter, size int, offset int, deployInfoIds []int) string { +func (impl ImageScanDeployInfoRepositoryImpl) scanListQueryWithoutObject(request *securityBean.ImageScanFilter, size int, offset int, deployInfoIds []int) string { query := "" - query = query + "select info.scan_object_meta_id, info.object_type, env.environment_name, max(info.id) as id" + query = query + "select info.scan_object_meta_id, info.object_type, env.environment_name, max(info.id) as id, COUNT(*) OVER() AS total_count" query = query + " from image_scan_deploy_info info" if len(request.CVEName) > 0 || len(request.Severity) > 0 { query = query + " INNER JOIN image_scan_execution_history his on his.id = any (info.image_scan_execution_history_id)" @@ -185,17 +168,17 @@ func (impl ImageScanDeployInfoRepositoryImpl) scanListQueryWithoutObject(request query = query + " INNER JOIN environment env on env.id=info.env_id" query = query + " INNER JOIN cluster clus on clus.id=env.cluster_id" query = query + " LEFT JOIN app ap on ap.id = info.scan_object_meta_id and info.object_type='app' WHERE ap.active=true" - query = query + " AND info.scan_object_meta_id > 0 and env.active=true and info.image_scan_execution_history_id[1] != -1 " + query = query + " AND info.scan_object_meta_id > 0 and env.active=true and info.image_scan_execution_history_id[1] != -1" if len(deployInfoIds) > 0 { ids := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(deployInfoIds)), ","), "[]") query = query + " AND info.id IN (" + ids + ")" } if len(request.CVEName) > 0 { - query = query + " AND res.cve_store_name like '" + request.CVEName + "'" + query = query + " AND res.cve_store_name ILIKE '%" + request.CVEName + "%'" } if len(request.Severity) > 0 { severities := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(request.Severity)), ","), "[]") - query = query + " AND cs.severity IN (" + severities + ")" + query = query + " AND cs.standard_severity IN (" + severities + ")" } if len(request.EnvironmentIds) > 0 { envIds := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(request.EnvironmentIds)), ","), "[]") @@ -205,46 +188,59 @@ func (impl ImageScanDeployInfoRepositoryImpl) scanListQueryWithoutObject(request clusterIds := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(request.ClusterIds)), ","), "[]") query = query + " AND clus.id IN (" + clusterIds + ")" } - query = query + " group by info.scan_object_meta_id, info.object_type, env.environment_name" - query = query + " order by id desc" + query = query + " GROUP BY info.scan_object_meta_id, info.object_type, env.environment_name" + //query = query + " order by id desc" + query += getOrderByQueryPart(request.SortBy, request.SortOrder) if size > 0 { - query = query + " limit " + strconv.Itoa(size) + " offset " + strconv.Itoa(offset) + "" + query = query + " LIMIT " + strconv.Itoa(size) + " OFFSET " + strconv.Itoa(offset) + "" } query = query + " ;" return query } -func (impl ImageScanDeployInfoRepositoryImpl) scanListQueryWithObject(request *ImageScanFilter, size int, offset int, deployInfoIds []int) string { - query := "" - if len(request.AppName) > 0 { - query = query + " select info.scan_object_meta_id, a.app_name as object_name, info.object_type, env.environment_name, max(info.id) as id" - query = query + " from image_scan_deploy_info info" - query = query + " INNER JOIN app a on a.id=info.scan_object_meta_id" - } else if len(request.ObjectName) > 0 { - query = query + " select info.scan_object_meta_id, om.name as object_name,info.object_type, env.environment_name, max(info.id) as id" - query = query + " from image_scan_deploy_info info" - query = query + " INNER JOIN image_scan_object_meta om on om.id=info.scan_object_meta_id" +func getOrderByQueryPart(sortBy securityBean.SortBy, sortOrder securityBean.SortOrder) string { + var sort, order string + if sortBy == "appName" { + sort = "object_name" + } else if sortBy == "envName" { + sort = "environment_name" + } else { + // id is to sort by time. + // id with desc fetches latest scans + sort = "id" } + + if sortOrder != securityBean.Desc { + sortOrder = "" + } + return fmt.Sprintf(" ORDER BY %s %s ", sort, order) +} + +func (impl ImageScanDeployInfoRepositoryImpl) scanListQueryWithObject(request *securityBean.ImageScanFilter, size int, offset int, deployInfoIds []int) string { + + query := " select info.scan_object_meta_id, a.app_name as object_name, info.object_type, env.environment_name, max(info.id) as id, COUNT(*) OVER() AS total_count" + query = query + " from image_scan_deploy_info info" + query = query + " INNER JOIN app a on a.id=info.scan_object_meta_id" + if len(request.Severity) > 0 { query = query + " INNER JOIN image_scan_execution_history his on his.id = any (info.image_scan_execution_history_id)" query = query + " INNER JOIN image_scan_execution_result res on res.image_scan_execution_history_id=his.id" query = query + " INNER JOIN cve_store cs on cs.name= res.cve_store_name" } + query = query + " INNER JOIN environment env on env.id=info.env_id" query = query + " INNER JOIN cluster c on c.id=env.cluster_id" query = query + " WHERE info.scan_object_meta_id > 0 and env.active=true and info.image_scan_execution_history_id[1] != -1" + query = query + " AND a.app_name like '%" + request.AppName + "%'" + if len(deployInfoIds) > 0 { ids := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(deployInfoIds)), ","), "[]") query = query + " AND info.id IN (" + ids + ")" } - if len(request.AppName) > 0 { - query = query + " AND a.app_name like '%" + request.AppName + "%'" - } else if len(request.ObjectName) > 0 { - query = query + " AND om.name like '%" + request.ObjectName + "%'" - } + if len(request.Severity) > 0 { severities := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(request.Severity)), ","), "[]") - query = query + " AND cs.severity IN (" + severities + ")" + query = query + " AND cs.standard_severity IN (" + severities + ")" } if len(request.EnvironmentIds) > 0 { envIds := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(request.EnvironmentIds)), ","), "[]") @@ -255,26 +251,23 @@ func (impl ImageScanDeployInfoRepositoryImpl) scanListQueryWithObject(request *I query = query + " AND c.id IN (" + clusterIds + ")" } - if len(request.AppName) > 0 { - query = query + " group by info.scan_object_meta_id, a.app_name, info.object_type, env.environment_name" - } else if len(request.ObjectName) > 0 { - query = query + " group by info.scan_object_meta_id, om.name, info.object_type, env.environment_name" - } - query = query + " order by id desc" + query = query + " GROUP BY info.scan_object_meta_id, a.app_name, info.object_type, env.environment_name" + + query += getOrderByQueryPart(request.SortBy, request.SortOrder) if size > 0 { - query = query + " limit " + strconv.Itoa(size) + " offset " + strconv.Itoa(offset) + "" + query = query + " LIMIT " + strconv.Itoa(size) + " OFFSET " + strconv.Itoa(offset) + "" } query = query + " ;" return query } -func (impl ImageScanDeployInfoRepositoryImpl) scanListingQueryBuilder(request *ImageScanFilter, size int, offset int, deployInfoIds []int) string { +func (impl ImageScanDeployInfoRepositoryImpl) scanListingQueryBuilder(request *securityBean.ImageScanFilter, size int, offset int, deployInfoIds []int) string { query := "" if request.AppName == "" && request.CVEName == "" && request.ObjectName == "" { query = impl.scanListQueryWithoutObject(request, size, offset, deployInfoIds) } else if len(request.CVEName) > 0 { query = impl.scanListQueryWithoutObject(request, size, offset, deployInfoIds) - } else if len(request.AppName) > 0 || len(request.ObjectName) > 0 { + } else if len(request.AppName) > 0 { query = impl.scanListQueryWithObject(request, size, offset, deployInfoIds) } diff --git a/internal/sql/repository/security/bean/bean.go b/internal/sql/repository/security/bean/bean.go new file mode 100644 index 0000000000..851d7d0254 --- /dev/null +++ b/internal/sql/repository/security/bean/bean.go @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2024. Devtron Inc. + */ + +package bean + +const ( + HIGH string = "high" + CRITICAL string = "critical" + SAFE string = "safe" + LOW string = "low" + MEDIUM string = "medium" + MODERATE string = "moderate" + UNKNOWN string = "unknown" +) + +type PolicyAction int + +const ( + Inherit PolicyAction = iota + Allow + Block + Blockiffixed +) + +func (d PolicyAction) String() string { + return [...]string{"inherit", "allow", "block", "blockiffixed"}[d] +} + +// ------------------ +type Severity int + +const ( + Low Severity = iota + Medium + Critical + High + Safe + Unknown +) + +//// Handling for future use +//func (d Severity) ValuesOf(severity string) Severity { +// if severity == CRITICAL || severity == HIGH { +// return Critical +// } else if severity == MODERATE || severity == MEDIUM { +// return Medium +// } else if severity == LOW || severity == SAFE { +// return Low +// } +// return Low +//} + +// Updating it for future use(not in use for standard severity) +func (d Severity) String() string { + return [...]string{LOW, MEDIUM, CRITICAL, HIGH, SAFE, UNKNOWN}[d] +} + +// ---------------- +type PolicyLevel int + +const ( + Global PolicyLevel = iota + Cluster + Environment + Application +) + +func (d PolicyLevel) String() string { + return [...]string{"global", "cluster", "environment", "application"}[d] +} diff --git a/pkg/security/ImageScanService.go b/pkg/security/ImageScanService.go index 99ec726779..2244d9c74d 100644 --- a/pkg/security/ImageScanService.go +++ b/pkg/security/ImageScanService.go @@ -18,8 +18,10 @@ package security import ( "context" + securityBean "github.com/devtron-labs/devtron/internal/sql/repository/security/bean" "github.com/devtron-labs/devtron/pkg/cluster/repository/bean" bean2 "github.com/devtron-labs/devtron/pkg/deployment/trigger/devtronApps/bean" + bean3 "github.com/devtron-labs/devtron/pkg/security/bean" "go.opentelemetry.io/otel" "time" @@ -37,10 +39,10 @@ import ( ) type ImageScanService interface { - FetchAllDeployInfo(request *ImageScanRequest) ([]*security.ImageScanDeployInfo, error) - FetchScanExecutionListing(request *ImageScanRequest, ids []int) (*ImageScanHistoryListingResponse, error) - FetchExecutionDetailResult(request *ImageScanRequest) (*ImageScanExecutionDetail, error) - FetchMinScanResultByAppIdAndEnvId(request *ImageScanRequest) (*ImageScanExecutionDetail, error) + FetchAllDeployInfo(request *bean3.ImageScanRequest) ([]*security.ImageScanDeployInfo, error) + FetchScanExecutionListing(request *bean3.ImageScanRequest, ids []int) (*bean3.ImageScanHistoryListingResponse, error) + FetchExecutionDetailResult(request *bean3.ImageScanRequest) (*bean3.ImageScanExecutionDetail, error) + FetchMinScanResultByAppIdAndEnvId(request *bean3.ImageScanRequest) (*bean3.ImageScanExecutionDetail, error) VulnerabilityExposure(request *security.VulnerabilityRequest) (*security.VulnerabilityExposureListingResponse, error) GetArtifactVulnerabilityStatus(ctx context.Context, request *bean2.VulnerabilityCheckRequest) (bool, error) } @@ -65,70 +67,6 @@ type ImageScanServiceImpl struct { cvePolicyRepository security.CvePolicyRepository } -type ImageScanRequest struct { - ScanExecutionId int `json:"ScanExecutionId"` - ImageScanDeployInfoId int `json:"imageScanDeployInfo"` - AppId int `json:"appId"` - EnvId int `json:"envId"` - ObjectId int `json:"objectId"` - ArtifactId int `json:"artifactId"` - Image string `json:"image"` - security.ImageScanFilter -} - -type ImageScanHistoryListingResponse struct { - Offset int `json:"offset"` - Size int `json:"size"` - Total int `json:"total"` - ImageScanHistoryResponse []*ImageScanHistoryResponse `json:"scanList"` -} - -type ImageScanHistoryResponse struct { - ImageScanDeployInfoId int `json:"imageScanDeployInfoId"` - AppId int `json:"appId"` - EnvId int `json:"envId"` - Name string `json:"name"` - Type string `json:"type"` - Environment string `json:"environment"` - LastChecked *time.Time `json:"lastChecked"` - Image string `json:"image,omitempty"` - SeverityCount *SeverityCount `json:"severityCount,omitempty"` -} - -type ImageScanExecutionDetail struct { - ImageScanDeployInfoId int `json:"imageScanDeployInfoId"` - AppId int `json:"appId,omitempty"` - EnvId int `json:"envId,omitempty"` - AppName string `json:"appName,omitempty"` - EnvName string `json:"envName,omitempty"` - ArtifactId int `json:"artifactId,omitempty"` - Image string `json:"image,omitempty"` - PodName string `json:"podName,omitempty"` - ReplicaSet string `json:"replicaSet,omitempty"` - Vulnerabilities []*Vulnerabilities `json:"vulnerabilities,omitempty"` - SeverityCount *SeverityCount `json:"severityCount,omitempty"` - ExecutionTime time.Time `json:"executionTime,omitempty"` - ScanEnabled bool `json:"scanEnabled,notnull"` - Scanned bool `json:"scanned,notnull"` - ObjectType string `json:"objectType,notnull"` - ScanToolId int `json:"scanToolId,omitempty""` -} - -type Vulnerabilities struct { - CVEName string `json:"cveName"` - Severity string `json:"severity"` - Package string `json:"package,omitempty"` - CVersion string `json:"currentVersion"` - FVersion string `json:"fixedVersion"` - Permission string `json:"permission"` -} - -type SeverityCount struct { - High int `json:"high"` - Moderate int `json:"moderate"` - Low int `json:"low"` -} - func NewImageScanServiceImpl(Logger *zap.SugaredLogger, scanHistoryRepository security.ImageScanHistoryRepository, scanResultRepository security.ImageScanResultRepository, scanObjectMetaRepository security.ImageScanObjectMetaRepository, cveStoreRepository security.CveStoreRepository, imageScanDeployInfoRepository security.ImageScanDeployInfoRepository, @@ -154,7 +92,7 @@ func NewImageScanServiceImpl(Logger *zap.SugaredLogger, scanHistoryRepository se } } -func (impl ImageScanServiceImpl) FetchAllDeployInfo(request *ImageScanRequest) ([]*security.ImageScanDeployInfo, error) { +func (impl ImageScanServiceImpl) FetchAllDeployInfo(request *bean3.ImageScanRequest) ([]*security.ImageScanDeployInfo, error) { deployedList, err := impl.imageScanDeployInfoRepository.FindAll() if err != nil { impl.Logger.Errorw("error while fetching scan execution result", "err", err) @@ -163,28 +101,30 @@ func (impl ImageScanServiceImpl) FetchAllDeployInfo(request *ImageScanRequest) ( return deployedList, nil } -func (impl ImageScanServiceImpl) FetchScanExecutionListing(request *ImageScanRequest, deployInfoIds []int) (*ImageScanHistoryListingResponse, error) { - size := request.Size - request.Size = 0 - groupByListCount, err := impl.imageScanDeployInfoRepository.ScanListingWithFilter(&request.ImageScanFilter, request.Size, request.Offset, deployInfoIds) - if err != nil { - impl.Logger.Errorw("error while fetching scan execution result", "err", err) - return nil, err - } - request.Size = size +func (impl ImageScanServiceImpl) FetchScanExecutionListing(request *bean3.ImageScanRequest, deployInfoIds []int) (*bean3.ImageScanHistoryListingResponse, error) { + //size := request.Size + //request.Size = 0 + //groupByListCount, err := impl.imageScanDeployInfoRepository.ScanListingWithFilter(&request.ImageScanFilter, request.Size, request.Offset, deployInfoIds) + //if err != nil { + // impl.Logger.Errorw("error while fetching scan execution result", "err", err) + // return nil, err + //} + //request.Size = size groupByList, err := impl.imageScanDeployInfoRepository.ScanListingWithFilter(&request.ImageScanFilter, request.Size, request.Offset, deployInfoIds) if err != nil { impl.Logger.Errorw("error while fetching scan execution result", "err", err) return nil, err } var ids []int + totalCount := 0 for _, item := range groupByList { + totalCount = item.TotalCount ids = append(ids, item.Id) } if len(ids) == 0 { impl.Logger.Debugw("no image scan deploy info exists", "err", err) - responseList := make([]*ImageScanHistoryResponse, 0) - return &ImageScanHistoryListingResponse{ImageScanHistoryResponse: responseList}, nil + responseList := make([]*bean3.ImageScanHistoryResponse, 0) + return &bean3.ImageScanHistoryListingResponse{ImageScanHistoryResponse: responseList}, nil } deployedList, err := impl.imageScanDeployInfoRepository.FindByIds(ids) if err != nil { @@ -206,14 +146,15 @@ func (impl ImageScanServiceImpl) FetchScanExecutionListing(request *ImageScanReq impl.Logger.Errorw("error encountered in FetchScanExecutionListing", "err", err) } - var finalResponseList []*ImageScanHistoryResponse + var finalResponseList []*bean3.ImageScanHistoryResponse for _, item := range groupByList { - imageScanHistoryResponse := &ImageScanHistoryResponse{} + imageScanHistoryResponse := &bean3.ImageScanHistoryResponse{} var lastChecked time.Time + criticalCount := 0 highCount := 0 moderateCount := 0 - lowCount := 0 + lowCount, unkownCount := 0, 0 imageScanDeployInfo := groupByListMap[item.Id] if imageScanDeployInfo != nil { scanResultList, err := impl.scanResultRepository.FetchByScanExecutionIds(imageScanDeployInfo.ImageScanExecutionHistoryId) @@ -228,13 +169,7 @@ func (impl ImageScanServiceImpl) FetchScanExecutionListing(request *ImageScanReq for _, item := range scanResultList { lastChecked = item.ImageScanExecutionHistory.ExecutionTime - if item.CveStore.Severity == security.Critical { - highCount = highCount + 1 - } else if item.CveStore.Severity == security.Medium { - moderateCount = moderateCount + 1 - } else if item.CveStore.Severity == security.Low { - lowCount = lowCount + 1 - } + criticalCount, highCount, moderateCount, lowCount, unkownCount = impl.updateCount(item.CveStore.StandardSeverity, criticalCount, highCount, moderateCount, lowCount, unkownCount) } // updating in case when no vul are found (no results) if lastChecked.IsZero() && len(imageScanDeployInfo.ImageScanExecutionHistoryId) > 0 && mapOfExecutionHistoryIdVsLastExecTime != nil { @@ -245,10 +180,12 @@ func (impl ImageScanServiceImpl) FetchScanExecutionListing(request *ImageScanReq } } } - severityCount := &SeverityCount{ + severityCount := &bean3.SeverityCount{ + Critical: criticalCount, High: highCount, - Moderate: moderateCount, + Medium: moderateCount, Low: lowCount, + Unknown: unkownCount, } imageScanHistoryResponse.ImageScanDeployInfoId = item.Id if imageScanDeployInfo != nil { @@ -292,11 +229,11 @@ func (impl ImageScanServiceImpl) FetchScanExecutionListing(request *ImageScanReq finalResponseList = append(finalResponseList, imageScanHistoryResponse) } - finalResponse := &ImageScanHistoryListingResponse{ + finalResponse := &bean3.ImageScanHistoryListingResponse{ Offset: request.Offset, Size: request.Size, ImageScanHistoryResponse: finalResponseList, - Total: len(groupByListCount), + Total: totalCount, } /* @@ -323,11 +260,11 @@ func (impl ImageScanServiceImpl) fetchImageExecutionHistoryMapByIds(historyIds [ return mapOfExecutionHistoryIdVsExecutionTime, nil } -func (impl ImageScanServiceImpl) FetchExecutionDetailResult(request *ImageScanRequest) (*ImageScanExecutionDetail, error) { +func (impl ImageScanServiceImpl) FetchExecutionDetailResult(request *bean3.ImageScanRequest) (*bean3.ImageScanExecutionDetail, error) { //var scanExecution *security.ImageScanExecutionHistory var scanExecutionIds []int var executionTime time.Time - imageScanResponse := &ImageScanExecutionDetail{} + imageScanResponse := &bean3.ImageScanExecutionDetail{} isRegularApp := false if request.ImageScanDeployInfoId > 0 { // scan detail for deployed images @@ -383,8 +320,8 @@ func (impl ImageScanServiceImpl) FetchExecutionDetailResult(request *ImageScanRe imageScanResponse.ObjectType = security.ScanObjectType_APP } - var vulnerabilities []*Vulnerabilities - var highCount, moderateCount, lowCount int + var vulnerabilities []*bean3.Vulnerabilities + var criticalCount, highCount, moderateCount, lowCount, unkownCount int var cveStores []*security.CveStore imageDigests := make(map[string]string) if len(scanExecutionIds) > 0 { @@ -396,12 +333,12 @@ func (impl ImageScanServiceImpl) FetchExecutionDetailResult(request *ImageScanRe } for _, item := range imageScanResult { - vulnerability := &Vulnerabilities{ + vulnerability := &bean3.Vulnerabilities{ CVEName: item.CveStore.Name, CVersion: item.CveStore.Version, FVersion: item.FixedVersion, Package: item.CveStore.Package, - Severity: item.CveStore.Severity.String(), + Severity: item.CveStore.StandardSeverity.String(), //Permission: "BLOCK", TODO } // data already migrated hence get package, version and fixedVersion from image_scan_execution_result @@ -412,13 +349,7 @@ func (impl ImageScanServiceImpl) FetchExecutionDetailResult(request *ImageScanRe if len(item.Version) > 0 { vulnerability.CVersion = item.Version } - if item.CveStore.Severity == security.Critical { - highCount = highCount + 1 - } else if item.CveStore.Severity == security.Medium { - moderateCount = moderateCount + 1 - } else if item.CveStore.Severity == security.Low { - lowCount = lowCount + 1 - } + criticalCount, highCount, moderateCount, lowCount, unkownCount = impl.updateCount(item.CveStore.StandardSeverity, criticalCount, highCount, moderateCount, lowCount, unkownCount) vulnerabilities = append(vulnerabilities, vulnerability) cveStores = append(cveStores, &item.CveStore) if _, ok := imageDigests[item.ImageScanExecutionHistory.ImageHash]; !ok { @@ -439,14 +370,15 @@ func (impl ImageScanServiceImpl) FetchExecutionDetailResult(request *ImageScanRe } } } - severityCount := &SeverityCount{ + severityCount := &bean3.SeverityCount{ + Critical: criticalCount, High: highCount, - Moderate: moderateCount, + Medium: moderateCount, Low: lowCount, } imageScanResponse.ImageScanDeployInfoId = request.ImageScanDeployInfoId if len(vulnerabilities) == 0 { - vulnerabilities = make([]*Vulnerabilities, 0) + vulnerabilities = make([]*bean3.Vulnerabilities, 0) } imageScanResponse.Vulnerabilities = vulnerabilities imageScanResponse.SeverityCount = severityCount @@ -490,31 +422,31 @@ func (impl ImageScanServiceImpl) FetchExecutionDetailResult(request *ImageScanRe if blockCveList != nil { vulnerabilityPermissionMap := make(map[string]string) for _, cve := range blockCveList { - vulnerabilityPermissionMap[cve.Name] = "BLOCK" + vulnerabilityPermissionMap[cve.Name] = bean3.BLOCK } - var updatedVulnerabilities []*Vulnerabilities + var updatedVulnerabilities []*bean3.Vulnerabilities for _, vulnerability := range imageScanResponse.Vulnerabilities { if _, ok := vulnerabilityPermissionMap[vulnerability.CVEName]; ok { - vulnerability.Permission = "BLOCK" + vulnerability.Permission = bean3.BLOCK } else { - vulnerability.Permission = "WHITELISTED" + vulnerability.Permission = bean3.WHITELISTED } updatedVulnerabilities = append(updatedVulnerabilities, vulnerability) } if len(updatedVulnerabilities) == 0 { - updatedVulnerabilities = make([]*Vulnerabilities, 0) + updatedVulnerabilities = make([]*bean3.Vulnerabilities, 0) } imageScanResponse.Vulnerabilities = updatedVulnerabilities } else { for _, vulnerability := range imageScanResponse.Vulnerabilities { - vulnerability.Permission = "WHITELISTED" + vulnerability.Permission = bean3.WHITELISTED } } } return imageScanResponse, nil } -func (impl ImageScanServiceImpl) FetchMinScanResultByAppIdAndEnvId(request *ImageScanRequest) (*ImageScanExecutionDetail, error) { +func (impl *ImageScanServiceImpl) FetchMinScanResultByAppIdAndEnvId(request *bean3.ImageScanRequest) (*bean3.ImageScanExecutionDetail, error) { //var scanExecution *security.ImageScanExecutionHistory var scanExecutionIds []int var executionTime time.Time @@ -531,7 +463,7 @@ func (impl ImageScanServiceImpl) FetchMinScanResultByAppIdAndEnvId(request *Imag } scanExecutionIds = append(scanExecutionIds, scanDeployInfo.ImageScanExecutionHistoryId...) - var highCount, moderateCount, lowCount, scantoolId int + var criticalCount, highCount, moderateCount, lowCount, unkownCount, scantoolId int if len(scanExecutionIds) > 0 { imageScanResult, err := impl.scanResultRepository.FetchByScanExecutionIds(scanExecutionIds) if err != nil { @@ -540,13 +472,7 @@ func (impl ImageScanServiceImpl) FetchMinScanResultByAppIdAndEnvId(request *Imag } for _, item := range imageScanResult { executionTime = item.ImageScanExecutionHistory.ExecutionTime - if item.CveStore.Severity == security.Critical { - highCount = highCount + 1 - } else if item.CveStore.Severity == security.Medium { - moderateCount = moderateCount + 1 - } else if item.CveStore.Severity == security.Low { - lowCount = lowCount + 1 - } + criticalCount, highCount, moderateCount, lowCount, unkownCount = impl.updateCount(item.CveStore.StandardSeverity, criticalCount, highCount, moderateCount, lowCount, unkownCount) } if len(imageScanResult) > 0 { scantoolId = imageScanResult[0].ScanToolId @@ -559,12 +485,14 @@ func (impl ImageScanServiceImpl) FetchMinScanResultByAppIdAndEnvId(request *Imag scantoolId = toolIdFromExecutionHistory } } - severityCount := &SeverityCount{ + severityCount := &bean3.SeverityCount{ + Critical: criticalCount, High: highCount, - Moderate: moderateCount, + Medium: moderateCount, Low: lowCount, + Unknown: unkownCount, } - imageScanResponse := &ImageScanExecutionDetail{ + imageScanResponse := &bean3.ImageScanExecutionDetail{ ImageScanDeployInfoId: scanDeployInfo.Id, SeverityCount: severityCount, ExecutionTime: executionTime, @@ -575,7 +503,8 @@ func (impl ImageScanServiceImpl) FetchMinScanResultByAppIdAndEnvId(request *Imag } return imageScanResponse, nil } -func (impl ImageScanServiceImpl) getScanToolIdFromExecutionHistory(scanExecutionIds []int) (int, error) { + +func (impl *ImageScanServiceImpl) getScanToolIdFromExecutionHistory(scanExecutionIds []int) (int, error) { scanToolHistoryMappings, err := impl.scanToolExecutionHistoryMappingRepository.GetAllScanHistoriesByExecutionHistoryIds(scanExecutionIds) if err != nil { if err == pg.ErrNoRows { @@ -591,7 +520,7 @@ func (impl ImageScanServiceImpl) getScanToolIdFromExecutionHistory(scanExecution return -1, err } -func (impl ImageScanServiceImpl) VulnerabilityExposure(request *security.VulnerabilityRequest) (*security.VulnerabilityExposureListingResponse, error) { +func (impl *ImageScanServiceImpl) VulnerabilityExposure(request *security.VulnerabilityRequest) (*security.VulnerabilityExposureListingResponse, error) { vulnerabilityExposureListingResponse := &security.VulnerabilityExposureListingResponse{ Offset: request.Offset, Size: request.Size, @@ -654,7 +583,25 @@ func (impl ImageScanServiceImpl) VulnerabilityExposure(request *security.Vulnera return vulnerabilityExposureListingResponse, nil } -func (impl ImageScanServiceImpl) GetArtifactVulnerabilityStatus(ctx context.Context, request *bean2.VulnerabilityCheckRequest) (bool, error) { +func (impl *ImageScanServiceImpl) CalculateSeverityCountInfo(vulnerabilities []*bean3.Vulnerabilities) *bean3.SeverityCount { + diff := bean3.SeverityCount{} + for _, vulnerability := range vulnerabilities { + if vulnerability.IsCritical() { + diff.Critical += 1 + } else if vulnerability.IsHigh() { + diff.High += 1 + } else if vulnerability.IsMedium() { + diff.Medium += 1 + } else if vulnerability.IsLow() { + diff.Low += 1 + } else if vulnerability.IsUnknown() { + diff.Unknown += 1 + } + } + return &diff +} + +func (impl *ImageScanServiceImpl) GetArtifactVulnerabilityStatus(ctx context.Context, request *bean2.VulnerabilityCheckRequest) (bool, error) { isVulnerable := false if len(request.ImageDigest) > 0 { var cveStores []*security.CveStore @@ -689,3 +636,18 @@ func (impl ImageScanServiceImpl) GetArtifactVulnerabilityStatus(ctx context.Cont } return isVulnerable, nil } + +func (impl ImageScanServiceImpl) updateCount(severity securityBean.Severity, criticalCount int, highCount int, moderateCount int, lowCount int, unkownCount int) (int, int, int, int, int) { + if severity == securityBean.Critical { + criticalCount += 1 + } else if severity == securityBean.High { + highCount = highCount + 1 + } else if severity == securityBean.Medium { + moderateCount = moderateCount + 1 + } else if severity == securityBean.Low { + lowCount = lowCount + 1 + } else if severity == securityBean.Unknown { + unkownCount += 1 + } + return criticalCount, highCount, moderateCount, lowCount, unkownCount +} diff --git a/pkg/security/bean/bean.go b/pkg/security/bean/bean.go new file mode 100644 index 0000000000..1659966527 --- /dev/null +++ b/pkg/security/bean/bean.go @@ -0,0 +1,119 @@ +package bean + +import ( + "github.com/devtron-labs/devtron/internal/sql/repository/security/bean" + "time" +) + +type SortBy string +type SortOrder string + +const ( + Asc SortOrder = "ASC" + Desc SortOrder = "DESC" +) + +const ( + BLOCK string = "BLOCK" + WHITELISTED = "WHITELISTED" +) + +type Vulnerabilities struct { + CVEName string `json:"cveName"` + Severity string `json:"severity"` + Package string `json:"package,omitempty"` + CVersion string `json:"currentVersion"` + FVersion string `json:"fixedVersion"` + Permission string `json:"permission"` +} + +func (vul *Vulnerabilities) IsCritical() bool { + return vul.Severity == bean.CRITICAL +} + +func (vul *Vulnerabilities) IsHigh() bool { + return vul.Severity == bean.HIGH +} + +func (vul *Vulnerabilities) IsMedium() bool { + return vul.Severity == bean.MODERATE || vul.Severity == bean.MEDIUM +} + +func (vul *Vulnerabilities) IsLow() bool { + return vul.Severity == bean.LOW +} + +func (vul *Vulnerabilities) IsUnknown() bool { + return vul.Severity == bean.UNKNOWN +} + +type SeverityCount struct { + Critical int `json:"critical"` + High int `json:"high"` + Medium int `json:"medium"` + Low int `json:"low"` + Unknown int `json:"unknown"` +} + +type ImageScanFilter struct { + Offset int `json:"offset"` + Size int `json:"size"` + CVEName string `json:"cveName"` + AppName string `json:"appName"` + // ObjectName deprecated + ObjectName string `json:"objectName"` + EnvironmentIds []int `json:"envIds"` + ClusterIds []int `json:"clusterIds"` + Severity []int `json:"severity"` + SortOrder SortOrder `json:"sortOrder"` + SortBy SortBy `json:"sortBy"` // sort by objectName,envName,lastChecked +} + +type ImageScanRequest struct { + ScanExecutionId int `json:"ScanExecutionId"` + ImageScanDeployInfoId int `json:"imageScanDeployInfo"` + AppId int `json:"appId"` + EnvId int `json:"envId"` + ObjectId int `json:"objectId"` + ArtifactId int `json:"artifactId"` + Image string `json:"image"` + ImageScanFilter +} + +type ImageScanHistoryListingResponse struct { + Offset int `json:"offset"` + Size int `json:"size"` + Total int `json:"total"` + ImageScanHistoryResponse []*ImageScanHistoryResponse `json:"scanList"` +} + +type ImageScanHistoryResponse struct { + ImageScanDeployInfoId int `json:"imageScanDeployInfoId"` + AppId int `json:"appId"` + EnvId int `json:"envId"` + Name string `json:"name"` + Type string `json:"type"` + Environment string `json:"environment"` + LastChecked *time.Time `json:"lastChecked"` + Image string `json:"image,omitempty"` + SeverityCount *SeverityCount `json:"severityCount,omitempty"` +} + +type ImageScanExecutionDetail struct { + ImageScanDeployInfoId int `json:"imageScanDeployInfoId"` + AppId int `json:"appId,omitempty"` + EnvId int `json:"envId,omitempty"` + AppName string `json:"appName,omitempty"` + EnvName string `json:"envName,omitempty"` + ArtifactId int `json:"artifactId,omitempty"` + Image string `json:"image,omitempty"` + PodName string `json:"podName,omitempty"` + ReplicaSet string `json:"replicaSet,omitempty"` + Vulnerabilities []*Vulnerabilities `json:"vulnerabilities,omitempty"` + SeverityCount *SeverityCount `json:"severityCount,omitempty"` + ExecutionTime time.Time `json:"executionTime,omitempty"` + ScanEnabled bool `json:"scanEnabled,notnull"` + Scanned bool `json:"scanned,notnull"` + ObjectType string `json:"objectType,notnull"` + ScanToolId int `json:"scanToolId,omitempty""` +} diff --git a/pkg/security/policyService.go b/pkg/security/policyService.go index 0a99fda54d..f4acc96f52 100644 --- a/pkg/security/policyService.go +++ b/pkg/security/policyService.go @@ -22,6 +22,7 @@ import ( "fmt" repository1 "github.com/devtron-labs/devtron/internal/sql/repository/app" "github.com/devtron-labs/devtron/internal/sql/repository/helper" + securityBean "github.com/devtron-labs/devtron/internal/sql/repository/security/bean" "github.com/devtron-labs/devtron/pkg/pipeline/types" "github.com/devtron-labs/devtron/pkg/sql" "net/http" @@ -42,12 +43,12 @@ type PolicyService interface { SavePolicy(request bean.CreateVulnerabilityPolicyRequest, userId int32) (*bean.IdVulnerabilityPolicyResult, error) UpdatePolicy(updatePolicyParams bean.UpdatePolicyParams, userId int32) (*bean.IdVulnerabilityPolicyResult, error) DeletePolicy(id int, userId int32) (*bean.IdVulnerabilityPolicyResult, error) - GetPolicies(policyLevel security.PolicyLevel, clusterId, environmentId, appId int) (*bean.GetVulnerabilityPolicyResult, error) + GetPolicies(policyLevel securityBean.PolicyLevel, clusterId, environmentId, appId int) (*bean.GetVulnerabilityPolicyResult, error) GetBlockedCVEList(cves []*security.CveStore, clusterId, envId, appId int, isAppstore bool) ([]*security.CveStore, error) VerifyImage(verifyImageRequest *VerifyImageRequest) (map[string][]*VerifyImageResponse, error) GetCvePolicy(id int, userId int32) (*security.CvePolicy, error) - GetApplicablePolicy(clusterId, envId, appId int, isAppstore bool) (map[string]*security.CvePolicy, map[security.Severity]*security.CvePolicy, error) - HasBlockedCVE(cves []*security.CveStore, cvePolicy map[string]*security.CvePolicy, severityPolicy map[security.Severity]*security.CvePolicy) bool + GetApplicablePolicy(clusterId, envId, appId int, isAppstore bool) (map[string]*security.CvePolicy, map[securityBean.Severity]*security.CvePolicy, error) + HasBlockedCVE(cves []*security.CveStore, cvePolicy map[string]*security.CvePolicy, severityPolicy map[securityBean.Severity]*security.CvePolicy) bool } type PolicyServiceImpl struct { environmentService cluster.EnvironmentService @@ -161,6 +162,7 @@ func (impl *PolicyServiceImpl) SendEventToClairUtility(event *ScanEvent) error { impl.logger.Errorw("error while UpdateJiraTransition request ", "err", err) return err } + resp.Body.Close() impl.logger.Debugw("response from test suit create api", "status code", resp.StatusCode) return err } @@ -192,7 +194,7 @@ func (impl *PolicyServiceImpl) VerifyImage(verifyImageRequest *VerifyImageReques appId = app.Id isAppStore = app.AppType == helper.ChartStoreApp } else { - //np app do nothing + // np app do nothing } cvePolicy, severityPolicy, err := impl.GetApplicablePolicy(clusterId, envId, appId, isAppStore) @@ -215,7 +217,7 @@ func (impl *PolicyServiceImpl) VerifyImage(verifyImageRequest *VerifyImageReques scanResultsIdMap := make(map[int]int) for _, image := range verifyImageRequest.Images { - //TODO - scan only if ci scan enabled + // TODO - scan only if ci scan enabled scanHistory, err := impl.scanHistoryRepository.FindByImage(image) if err != nil && err != pg.ErrNoRows { @@ -256,7 +258,7 @@ func (impl *PolicyServiceImpl) VerifyImage(verifyImageRequest *VerifyImageReques for _, cve := range blockedCves { vr := &VerifyImageResponse{ Name: cve.Name, - Severity: cve.Severity.String(), + Severity: cve.StandardSeverity.String(), Package: cve.Package, Version: cve.Version, FixedVersion: cve.FixedVersion, @@ -273,7 +275,7 @@ func (impl *PolicyServiceImpl) VerifyImage(verifyImageRequest *VerifyImageReques } if objectType == security.ScanObjectType_POD { - //TODO create entry + // TODO create entry imageScanObjectMeta := &security.ImageScanObjectMeta{ Name: verifyImageRequest.PodName, Image: strings.Join(verifyImageRequest.Images, ","), @@ -308,7 +310,7 @@ func (impl *PolicyServiceImpl) VerifyImage(verifyImageRequest *VerifyImageReques } if len(scanResultsId) > 0 { - ot, err := impl.imageScanDeployInfoRepository.FindByTypeMetaAndTypeId(typeId, objectType) //todo insure this touple unique in db + ot, err := impl.imageScanDeployInfoRepository.FindByTypeMetaAndTypeId(typeId, objectType) // todo insure this touple unique in db if err != nil && err != pg.ErrNoRows { return nil, err } else if err == pg.ErrNoRows { @@ -336,28 +338,28 @@ func (impl *PolicyServiceImpl) VerifyImage(verifyImageRequest *VerifyImageReques return imageBlockedCves, nil } -func (impl *PolicyServiceImpl) GetApplicablePolicy(clusterId, envId, appId int, isAppstore bool) (map[string]*security.CvePolicy, map[security.Severity]*security.CvePolicy, error) { +func (impl *PolicyServiceImpl) GetApplicablePolicy(clusterId, envId, appId int, isAppstore bool) (map[string]*security.CvePolicy, map[securityBean.Severity]*security.CvePolicy, error) { - var policyLevel security.PolicyLevel + var policyLevel securityBean.PolicyLevel if isAppstore && appId > 0 && envId > 0 && clusterId > 0 { - policyLevel = security.Environment + policyLevel = securityBean.Environment } else if appId > 0 && envId > 0 && clusterId > 0 { - policyLevel = security.Application + policyLevel = securityBean.Application } else if envId > 0 && clusterId > 0 { - policyLevel = security.Environment + policyLevel = securityBean.Environment } else if clusterId > 0 { - policyLevel = security.Cluster + policyLevel = securityBean.Cluster } else { - //error in case of global or other policy + // error in case of global or other policy return nil, nil, fmt.Errorf("policy not identified") } cvePolicy, severityPolicy, err := impl.getPolicies(policyLevel, clusterId, envId, appId) return cvePolicy, severityPolicy, err } -func (impl *PolicyServiceImpl) getApplicablePolicies(policies []*security.CvePolicy) (map[string]*security.CvePolicy, map[security.Severity]*security.CvePolicy) { +func (impl *PolicyServiceImpl) getApplicablePolicies(policies []*security.CvePolicy) (map[string]*security.CvePolicy, map[securityBean.Severity]*security.CvePolicy) { cvePolicy := make(map[string][]*security.CvePolicy) - severityPolicy := make(map[security.Severity][]*security.CvePolicy) + severityPolicy := make(map[securityBean.Severity][]*security.CvePolicy) for _, policy := range policies { if policy.CVEStoreId != "" { cvePolicy[policy.CveStore.Name] = append(cvePolicy[policy.CveStore.Name], policy) @@ -387,8 +389,8 @@ func (impl *PolicyServiceImpl) getHighestPolicy(allPolicies map[string][]*securi } return applicablePolicies } -func (impl *PolicyServiceImpl) getHighestPolicyS(allPolicies map[security.Severity][]*security.CvePolicy) map[security.Severity]*security.CvePolicy { - applicablePolicies := make(map[security.Severity]*security.CvePolicy) +func (impl *PolicyServiceImpl) getHighestPolicyS(allPolicies map[securityBean.Severity][]*security.CvePolicy) map[securityBean.Severity]*security.CvePolicy { + applicablePolicies := make(map[securityBean.Severity]*security.CvePolicy) for key, policies := range allPolicies { var applicablePolicy *security.CvePolicy for _, policy := range policies { @@ -405,7 +407,7 @@ func (impl *PolicyServiceImpl) getHighestPolicyS(allPolicies map[security.Severi return applicablePolicies } -//-----------crud api---- +// -----------crud api---- /* Severity/cveId -- @@ -420,18 +422,18 @@ action res: id, */ -func (impl *PolicyServiceImpl) parsePolicyAction(action string) (security.PolicyAction, error) { - var policyAction security.PolicyAction +func (impl *PolicyServiceImpl) parsePolicyAction(action string) (securityBean.PolicyAction, error) { + var policyAction securityBean.PolicyAction if action == "allow" { - policyAction = security.Allow + policyAction = securityBean.Allow } else if action == "block" { - policyAction = security.Block + policyAction = securityBean.Block } else if action == "inherit" { - policyAction = security.Inherit + policyAction = securityBean.Inherit } else if action == "blockiffixed" { - policyAction = security.Blockiffixed + policyAction = securityBean.Blockiffixed } else { - return security.Inherit, fmt.Errorf("unsupported action %s", action) + return securityBean.Inherit, fmt.Errorf("unsupported action %s", action) } return policyAction, nil } @@ -445,14 +447,16 @@ func (impl *PolicyServiceImpl) SavePolicy(request bean.CreateVulnerabilityPolicy if err != nil { return nil, err } - var severity security.Severity + var severity securityBean.Severity if len(request.Severity) > 0 { - if request.Severity == "critical" { - severity = security.Critical - } else if request.Severity == "moderate" { - severity = security.Medium - } else if request.Severity == "low" { - severity = security.Low + if request.Severity == securityBean.CRITICAL { + severity = securityBean.Critical + } else if request.Severity == securityBean.HIGH { + severity = securityBean.High + } else if request.Severity == securityBean.MODERATE || request.Severity == securityBean.MEDIUM { + severity = securityBean.Medium + } else if request.Severity == securityBean.LOW { + severity = securityBean.Low } else { return nil, fmt.Errorf("unsupported Severity %s", request.Severity) } @@ -461,7 +465,7 @@ func (impl *PolicyServiceImpl) SavePolicy(request bean.CreateVulnerabilityPolicy if err != nil { return nil, err } - severity = cveStore.Severity + severity = cveStore.StandardSeverity } policy := &security.CvePolicy{ Global: isGlobal, @@ -495,7 +499,7 @@ func (impl *PolicyServiceImpl) UpdatePolicy(updatePolicyParams bean.UpdatePolicy if err != nil { return nil, err } - if policyAction == security.Inherit { + if policyAction == securityBean.Inherit { return impl.DeletePolicy(updatePolicyParams.Id, userId) } else { policy, err := impl.cvePolicyRepository.GetById(updatePolicyParams.Id) @@ -547,23 +551,23 @@ func (impl *PolicyServiceImpl) DeletePolicy(id int, userId int32) (*bean.IdVulne res: */ -func (impl *PolicyServiceImpl) GetPolicies(policyLevel security.PolicyLevel, clusterId, environmentId, appId int) (*bean.GetVulnerabilityPolicyResult, error) { +func (impl *PolicyServiceImpl) GetPolicies(policyLevel securityBean.PolicyLevel, clusterId, environmentId, appId int) (*bean.GetVulnerabilityPolicyResult, error) { vulnerabilityPolicyResult := &bean.GetVulnerabilityPolicyResult{ Level: bean.ResourceLevel(policyLevel.String()), } - if policyLevel == security.Global { + if policyLevel == securityBean.Global { cvePolicy, severityPolicy, err := impl.getPolicies(policyLevel, clusterId, environmentId, appId) if err != nil { return nil, err } vulnerabilityPolicy := impl.vulnerabilityPolicyBuilder(policyLevel, cvePolicy, severityPolicy) vulnerabilityPolicyResult.Policies = append(vulnerabilityPolicyResult.Policies, vulnerabilityPolicy) - } else if policyLevel == security.Cluster { + } else if policyLevel == securityBean.Cluster { if clusterId == 0 { return nil, fmt.Errorf("cluster id is missing") } - //get cluster name + // get cluster name cluster, err := impl.clusterService.FindById(clusterId) if err != nil { impl.logger.Errorw("error in fetching cluster details", "id", clusterId, "err", err) @@ -578,7 +582,7 @@ func (impl *PolicyServiceImpl) GetPolicies(policyLevel security.PolicyLevel, clu vulnerabilityPolicy.Name = cluster.ClusterName vulnerabilityPolicy.ClusterId = clusterId vulnerabilityPolicyResult.Policies = append(vulnerabilityPolicyResult.Policies, vulnerabilityPolicy) - } else if policyLevel == security.Environment { + } else if policyLevel == securityBean.Environment { if environmentId == 0 { return nil, fmt.Errorf("environmentId is missing") } @@ -596,7 +600,7 @@ func (impl *PolicyServiceImpl) GetPolicies(policyLevel security.PolicyLevel, clu vulnerabilityPolicy.Name = env.Environment vulnerabilityPolicy.EnvId = env.Id vulnerabilityPolicyResult.Policies = append(vulnerabilityPolicyResult.Policies, vulnerabilityPolicy) - } else if policyLevel == security.Application { + } else if policyLevel == securityBean.Application { if appId == 0 { return nil, fmt.Errorf("appId is missing") } @@ -630,7 +634,7 @@ func (impl *PolicyServiceImpl) GetPolicies(policyLevel security.PolicyLevel, clu return vulnerabilityPolicyResult, nil } -func (impl *PolicyServiceImpl) vulnerabilityPolicyBuilder(policyLevel security.PolicyLevel, cvePolicy map[string]*security.CvePolicy, severityPolicy map[security.Severity]*security.CvePolicy) *bean.VulnerabilityPolicy { +func (impl *PolicyServiceImpl) vulnerabilityPolicyBuilder(policyLevel securityBean.PolicyLevel, cvePolicy map[string]*security.CvePolicy, severityPolicy map[securityBean.Severity]*security.CvePolicy) *bean.VulnerabilityPolicy { vulnerabilityPolicy := &bean.VulnerabilityPolicy{} for _, v := range severityPolicy { @@ -665,16 +669,16 @@ func (impl *PolicyServiceImpl) vulnerabilityPolicyBuilder(policyLevel security.P return vulnerabilityPolicy } -func (impl *PolicyServiceImpl) getPolicies(policyLevel security.PolicyLevel, clusterId, environmentId, appId int) (map[string]*security.CvePolicy, map[security.Severity]*security.CvePolicy, error) { +func (impl *PolicyServiceImpl) getPolicies(policyLevel securityBean.PolicyLevel, clusterId, environmentId, appId int) (map[string]*security.CvePolicy, map[securityBean.Severity]*security.CvePolicy, error) { var policies []*security.CvePolicy var err error - if policyLevel == security.Global { + if policyLevel == securityBean.Global { policies, err = impl.cvePolicyRepository.GetGlobalPolicies() - } else if policyLevel == security.Cluster { + } else if policyLevel == securityBean.Cluster { policies, err = impl.cvePolicyRepository.GetClusterPolicies(clusterId) - } else if policyLevel == security.Environment { + } else if policyLevel == securityBean.Environment { policies, err = impl.cvePolicyRepository.GetEnvPolicies(clusterId, environmentId) - } else if policyLevel == security.Application { + } else if policyLevel == securityBean.Application { policies, err = impl.cvePolicyRepository.GetAppEnvPolicies(clusterId, environmentId, appId) } else { return nil, nil, fmt.Errorf("unsupported policy level: %s", policyLevel) @@ -685,7 +689,7 @@ func (impl *PolicyServiceImpl) getPolicies(policyLevel security.PolicyLevel, clu } cvePolicy, severityPolicy := impl.getApplicablePolicies(policies) impl.logger.Debugw("policy identified ", "policyLevel", policyLevel) - //transform and return + // transform and return return cvePolicy, severityPolicy, nil } @@ -699,18 +703,18 @@ func (impl *PolicyServiceImpl) GetBlockedCVEList(cves []*security.CveStore, clus return blockedCve, nil } -func (impl *PolicyServiceImpl) HasBlockedCVE(cves []*security.CveStore, cvePolicy map[string]*security.CvePolicy, severityPolicy map[security.Severity]*security.CvePolicy) bool { +func (impl *PolicyServiceImpl) HasBlockedCVE(cves []*security.CveStore, cvePolicy map[string]*security.CvePolicy, severityPolicy map[securityBean.Severity]*security.CvePolicy) bool { for _, cve := range cves { if policy, ok := cvePolicy[cve.Name]; ok { - if policy.Action == security.Allow { + if policy.Action == securityBean.Allow { continue - } else if (policy.Action == security.Block) || (policy.Action == security.Blockiffixed && cve.FixedVersion != "") { + } else if (policy.Action == securityBean.Block) || (policy.Action == securityBean.Blockiffixed && cve.FixedVersion != "") { return true } } else { - if severityPolicy[cve.Severity] != nil && severityPolicy[cve.Severity].Action == security.Allow { + if severityPolicy[cve.StandardSeverity] != nil && severityPolicy[cve.StandardSeverity].Action == securityBean.Allow { continue - } else if severityPolicy[cve.Severity] != nil && (severityPolicy[cve.Severity].Action == security.Block || (severityPolicy[cve.Severity].Action == security.Blockiffixed && cve.FixedVersion != "")) { + } else if severityPolicy[cve.StandardSeverity] != nil && (severityPolicy[cve.StandardSeverity].Action == securityBean.Block || (severityPolicy[cve.StandardSeverity].Action == securityBean.Blockiffixed && cve.FixedVersion != "")) { return true } } diff --git a/wire_gen.go b/wire_gen.go index 29bf98bbdb..e0c79db411 100644 --- a/wire_gen.go +++ b/wire_gen.go @@ -1,6 +1,6 @@ // Code generated by Wire. DO NOT EDIT. -//go:generate go run -mod=mod github.com/google/wire/cmd/wire +//go:generate go run github.com/google/wire/cmd/wire //go:build !wireinject // +build !wireinject From 0a991b64aca14c09897835ffa57936f2aeaf2870 Mon Sep 17 00:00:00 2001 From: Gireesh Naidu Date: Fri, 2 Aug 2024 21:18:43 +0530 Subject: [PATCH 2/9] fix: query fix for appName sort or envName sort --- .../repository/security/ImageScanDeployInfoRepository.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/sql/repository/security/ImageScanDeployInfoRepository.go b/internal/sql/repository/security/ImageScanDeployInfoRepository.go index 02e2b5eecd..03e687b566 100644 --- a/internal/sql/repository/security/ImageScanDeployInfoRepository.go +++ b/internal/sql/repository/security/ImageScanDeployInfoRepository.go @@ -158,7 +158,7 @@ func (impl ImageScanDeployInfoRepositoryImpl) ScanListingWithFilter(request *sec func (impl ImageScanDeployInfoRepositoryImpl) scanListQueryWithoutObject(request *securityBean.ImageScanFilter, size int, offset int, deployInfoIds []int) string { query := "" - query = query + "select info.scan_object_meta_id, info.object_type, env.environment_name, max(info.id) as id, COUNT(*) OVER() AS total_count" + query = query + "select info.scan_object_meta_id,a.app_name as object_name, info.object_type, env.environment_name, max(info.id) as id, COUNT(*) OVER() AS total_count" query = query + " from image_scan_deploy_info info" if len(request.CVEName) > 0 || len(request.Severity) > 0 { query = query + " INNER JOIN image_scan_execution_history his on his.id = any (info.image_scan_execution_history_id)" @@ -167,7 +167,7 @@ func (impl ImageScanDeployInfoRepositoryImpl) scanListQueryWithoutObject(request } query = query + " INNER JOIN environment env on env.id=info.env_id" query = query + " INNER JOIN cluster clus on clus.id=env.cluster_id" - query = query + " LEFT JOIN app ap on ap.id = info.scan_object_meta_id and info.object_type='app' WHERE ap.active=true" + query = query + " LEFT JOIN app a on a.id = info.scan_object_meta_id and info.object_type='app' WHERE a.active=true" query = query + " AND info.scan_object_meta_id > 0 and env.active=true and info.image_scan_execution_history_id[1] != -1" if len(deployInfoIds) > 0 { ids := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(deployInfoIds)), ","), "[]") @@ -188,7 +188,7 @@ func (impl ImageScanDeployInfoRepositoryImpl) scanListQueryWithoutObject(request clusterIds := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(request.ClusterIds)), ","), "[]") query = query + " AND clus.id IN (" + clusterIds + ")" } - query = query + " GROUP BY info.scan_object_meta_id, info.object_type, env.environment_name" + query = query + " GROUP BY info.scan_object_meta_id, a.app_name, info.object_type, env.environment_name" //query = query + " order by id desc" query += getOrderByQueryPart(request.SortBy, request.SortOrder) if size > 0 { @@ -201,7 +201,7 @@ func (impl ImageScanDeployInfoRepositoryImpl) scanListQueryWithoutObject(request func getOrderByQueryPart(sortBy securityBean.SortBy, sortOrder securityBean.SortOrder) string { var sort, order string if sortBy == "appName" { - sort = "object_name" + sort = "a.app_name" } else if sortBy == "envName" { sort = "environment_name" } else { From b928140098e69e0a0c53f58d23749ff0cbc77abb Mon Sep 17 00:00:00 2001 From: Gireesh Naidu Date: Mon, 5 Aug 2024 19:27:39 +0530 Subject: [PATCH 3/9] fix: sql script number change --- scripts/sql/273_scan_policies.down.sql | 3 +++ scripts/sql/273_scan_policies.up.sql | 3 +++ 2 files changed, 6 insertions(+) create mode 100644 scripts/sql/273_scan_policies.down.sql create mode 100644 scripts/sql/273_scan_policies.up.sql diff --git a/scripts/sql/273_scan_policies.down.sql b/scripts/sql/273_scan_policies.down.sql new file mode 100644 index 0000000000..dbe1502309 --- /dev/null +++ b/scripts/sql/273_scan_policies.down.sql @@ -0,0 +1,3 @@ +UPDATE cve_policy_control +SET deleted = true, updated_on = 'now()', updated_by = '1' +WHERE severity = '3' OR severity = '5'; \ No newline at end of file diff --git a/scripts/sql/273_scan_policies.up.sql b/scripts/sql/273_scan_policies.up.sql new file mode 100644 index 0000000000..72ac002f08 --- /dev/null +++ b/scripts/sql/273_scan_policies.up.sql @@ -0,0 +1,3 @@ +INSERT INTO "public"."cve_policy_control" ("global", "cluster_id", "env_id", "app_id", "cve_store_id", "action", "severity", "deleted", "created_on", "created_by", "updated_on", "updated_by") VALUES + ('t', NULL, NULL, NULL, NULL, '1', '3', 'f', 'now()', '1', 'now()', '1'), + ('t', NULL, NULL, NULL, NULL, '1', '5', 'f', 'now()', '1', 'now()', '1'); \ No newline at end of file From 0279d8a19036f7240c1ce5b59d5da5490da814aa Mon Sep 17 00:00:00 2001 From: Gireesh Naidu Date: Tue, 6 Aug 2024 13:10:25 +0530 Subject: [PATCH 4/9] fix: minor changes --- pkg/security/policyService.go | 2 ++ scripts/sql/273_scan_policies.up.sql | 10 ++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/pkg/security/policyService.go b/pkg/security/policyService.go index f4acc96f52..920128600a 100644 --- a/pkg/security/policyService.go +++ b/pkg/security/policyService.go @@ -457,6 +457,8 @@ func (impl *PolicyServiceImpl) SavePolicy(request bean.CreateVulnerabilityPolicy severity = securityBean.Medium } else if request.Severity == securityBean.LOW { severity = securityBean.Low + } else if request.Severity == securityBean.UNKNOWN { + severity = securityBean.Unknown } else { return nil, fmt.Errorf("unsupported Severity %s", request.Severity) } diff --git a/scripts/sql/273_scan_policies.up.sql b/scripts/sql/273_scan_policies.up.sql index 72ac002f08..dfa2877e8b 100644 --- a/scripts/sql/273_scan_policies.up.sql +++ b/scripts/sql/273_scan_policies.up.sql @@ -1,3 +1,9 @@ + +-- severity 3 is for high and 5 is for unknown INSERT INTO "public"."cve_policy_control" ("global", "cluster_id", "env_id", "app_id", "cve_store_id", "action", "severity", "deleted", "created_on", "created_by", "updated_on", "updated_by") VALUES - ('t', NULL, NULL, NULL, NULL, '1', '3', 'f', 'now()', '1', 'now()', '1'), - ('t', NULL, NULL, NULL, NULL, '1', '5', 'f', 'now()', '1', 'now()', '1'); \ No newline at end of file + ('t', NULL, NULL, NULL, NULL, '1', '3', 'f', 'now()', '1', 'now()', '1'), + ('t', NULL, NULL, NULL, NULL, '1', '5', 'f', 'now()', '1', 'now()', '1'); + +-- UPDATE THE NULL VALUES IN THE STANDARD_SEVERITY COLUMN WITH THE SEVERITY COLUMN +-- standard_severity column was introduced in 148_trivy_image_scanning.up.sql. all the scans happened before that will contains null values in standard_severity column. +UPDATE "public"."cve_store" SET standard_severity = severity WHERE standard_severity IS NULL; \ No newline at end of file From 8f03c8f1142ea4262efb353bc8ead6ff744379d6 Mon Sep 17 00:00:00 2001 From: Gireesh Naidu Date: Tue, 6 Aug 2024 17:58:08 +0530 Subject: [PATCH 5/9] fix: review fix --- .../sql/repository/security/ImageScanDeployInfoRepository.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/sql/repository/security/ImageScanDeployInfoRepository.go b/internal/sql/repository/security/ImageScanDeployInfoRepository.go index 03e687b566..7de6f1e3f1 100644 --- a/internal/sql/repository/security/ImageScanDeployInfoRepository.go +++ b/internal/sql/repository/security/ImageScanDeployInfoRepository.go @@ -199,7 +199,7 @@ func (impl ImageScanDeployInfoRepositoryImpl) scanListQueryWithoutObject(request } func getOrderByQueryPart(sortBy securityBean.SortBy, sortOrder securityBean.SortOrder) string { - var sort, order string + var sort string if sortBy == "appName" { sort = "a.app_name" } else if sortBy == "envName" { @@ -213,7 +213,7 @@ func getOrderByQueryPart(sortBy securityBean.SortBy, sortOrder securityBean.Sort if sortOrder != securityBean.Desc { sortOrder = "" } - return fmt.Sprintf(" ORDER BY %s %s ", sort, order) + return fmt.Sprintf(" ORDER BY %s %s ", sort, sortOrder) } func (impl ImageScanDeployInfoRepositoryImpl) scanListQueryWithObject(request *securityBean.ImageScanFilter, size int, offset int, deployInfoIds []int) string { From 05246c3683b9352964868a853a61bd4b1da5a2d7 Mon Sep 17 00:00:00 2001 From: Gireesh Naidu Date: Thu, 8 Aug 2024 18:01:27 +0530 Subject: [PATCH 6/9] fix: remove dml on cve_store and handle it in code handling this versioning --- .../repository/security/CvePolicyControle.go | 4 +-- .../repository/security/CveStoreRepository.go | 35 ++++++++++++++++--- .../security/ImageScanDeployInfoRepository.go | 4 +-- pkg/security/ImageScanService.go | 6 ++-- pkg/security/policyService.go | 6 ++-- scripts/sql/273_scan_policies.up.sql | 7 ++-- 6 files changed, 42 insertions(+), 20 deletions(-) diff --git a/internal/sql/repository/security/CvePolicyControle.go b/internal/sql/repository/security/CvePolicyControle.go index aac9c0f5ed..262e863a7c 100644 --- a/internal/sql/repository/security/CvePolicyControle.go +++ b/internal/sql/repository/security/CvePolicyControle.go @@ -198,9 +198,9 @@ func EnforceCvePolicy(cves []*CveStore, cvePolicy map[string]*CvePolicy, severit blockedCVE = append(blockedCVE, cve) } } else { - if severityPolicy[cve.StandardSeverity] != nil && severityPolicy[cve.StandardSeverity].Action == securityBean.Allow { + if severityPolicy[cve.GetSeverity()] != nil && severityPolicy[cve.GetSeverity()].Action == securityBean.Allow { continue - } else if severityPolicy[cve.StandardSeverity] != nil && (severityPolicy[cve.StandardSeverity].Action == securityBean.Block || (severityPolicy[cve.StandardSeverity].Action == securityBean.Blockiffixed && cve.FixedVersion != "")) { + } else if severityPolicy[cve.GetSeverity()] != nil && (severityPolicy[cve.GetSeverity()].Action == securityBean.Block || (severityPolicy[cve.GetSeverity()].Action == securityBean.Blockiffixed && cve.FixedVersion != "")) { blockedCVE = append(blockedCVE, cve) } } diff --git a/internal/sql/repository/security/CveStoreRepository.go b/internal/sql/repository/security/CveStoreRepository.go index 1fca124966..424a7061bc 100644 --- a/internal/sql/repository/security/CveStoreRepository.go +++ b/internal/sql/repository/security/CveStoreRepository.go @@ -30,14 +30,39 @@ import ( type CveStore struct { tableName struct{} `sql:"cve_store" pg:",discard_unknown_columns"` Name string `sql:"name,pk"` - //Severity securityBean.Severity `sql:"severity,notnull"` - Package string `sql:"package,notnull"` // deprecated - Version string `sql:"version,notnull"` - FixedVersion string `sql:"fixed_version,notnull"` - StandardSeverity securityBean.Severity `sql:"standard_severity,notnull"` + + // Deprecated: Severity, use StandardSeverity for all read purposes + Severity securityBean.Severity `sql:"severity,notnull"` + // Deprecated: Package + Package string `sql:"package,notnull"` // deprecated, storing package data in image_scan_execution_result table + // Deprecated: Version + Version string `sql:"version,notnull"` + // Deprecated: FixedVersion + FixedVersion string `sql:"fixed_version,notnull"` + + // StandardSeverity is the actual severity. use GetSeverity method to get severity of the vulnerability + // earlier severity is maintained in Severity column by merging HIGH and CRITICAL severities. + // later we introduced new column StandardSeverity to store raw severity, but didn't migrate the existing Severity data to StandardSeverity. + // currently, we deprecated Severity. + StandardSeverity *securityBean.Severity `sql:"standard_severity"` sql.AuditLog } +// GetSeverity returns the actual severity of the vulnerability. +func (cve *CveStore) GetSeverity() securityBean.Severity { + if cve.StandardSeverity == nil { + // we need this as there was a time when StandardSeverity didn't exist. + // and migration of Severity data to StandardSeverity is not done. + return cve.Severity + } + return *cve.StandardSeverity +} + +func (cve *CveStore) SetStandardSeverity(severity securityBean.Severity) { + cve.Severity = severity + cve.StandardSeverity = &severity +} + type VulnerabilityRequest struct { AppName string `json:"appName"` CveName string `json:"cveName"` diff --git a/internal/sql/repository/security/ImageScanDeployInfoRepository.go b/internal/sql/repository/security/ImageScanDeployInfoRepository.go index 7de6f1e3f1..c705d2a18c 100644 --- a/internal/sql/repository/security/ImageScanDeployInfoRepository.go +++ b/internal/sql/repository/security/ImageScanDeployInfoRepository.go @@ -178,7 +178,7 @@ func (impl ImageScanDeployInfoRepositoryImpl) scanListQueryWithoutObject(request } if len(request.Severity) > 0 { severities := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(request.Severity)), ","), "[]") - query = query + " AND cs.standard_severity IN (" + severities + ")" + query = query + fmt.Sprintf(" AND (cs.standard_severity IN (%s) OR (cs.standard_severity IN (%s) AND cs.standard_severity IS NULL))", severities, severities) } if len(request.EnvironmentIds) > 0 { envIds := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(request.EnvironmentIds)), ","), "[]") @@ -240,7 +240,7 @@ func (impl ImageScanDeployInfoRepositoryImpl) scanListQueryWithObject(request *s if len(request.Severity) > 0 { severities := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(request.Severity)), ","), "[]") - query = query + " AND cs.standard_severity IN (" + severities + ")" + query = query + fmt.Sprintf(" AND (cs.standard_severity IN (%s) OR (cs.standard_severity IN (%s) AND cs.standard_severity IS NULL))", severities, severities) } if len(request.EnvironmentIds) > 0 { envIds := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(request.EnvironmentIds)), ","), "[]") diff --git a/pkg/security/ImageScanService.go b/pkg/security/ImageScanService.go index 2244d9c74d..f64a5a4747 100644 --- a/pkg/security/ImageScanService.go +++ b/pkg/security/ImageScanService.go @@ -169,7 +169,7 @@ func (impl ImageScanServiceImpl) FetchScanExecutionListing(request *bean3.ImageS for _, item := range scanResultList { lastChecked = item.ImageScanExecutionHistory.ExecutionTime - criticalCount, highCount, moderateCount, lowCount, unkownCount = impl.updateCount(item.CveStore.StandardSeverity, criticalCount, highCount, moderateCount, lowCount, unkownCount) + criticalCount, highCount, moderateCount, lowCount, unkownCount = impl.updateCount(item.CveStore.GetSeverity(), criticalCount, highCount, moderateCount, lowCount, unkownCount) } // updating in case when no vul are found (no results) if lastChecked.IsZero() && len(imageScanDeployInfo.ImageScanExecutionHistoryId) > 0 && mapOfExecutionHistoryIdVsLastExecTime != nil { @@ -349,7 +349,7 @@ func (impl ImageScanServiceImpl) FetchExecutionDetailResult(request *bean3.Image if len(item.Version) > 0 { vulnerability.CVersion = item.Version } - criticalCount, highCount, moderateCount, lowCount, unkownCount = impl.updateCount(item.CveStore.StandardSeverity, criticalCount, highCount, moderateCount, lowCount, unkownCount) + criticalCount, highCount, moderateCount, lowCount, unkownCount = impl.updateCount(item.CveStore.GetSeverity(), criticalCount, highCount, moderateCount, lowCount, unkownCount) vulnerabilities = append(vulnerabilities, vulnerability) cveStores = append(cveStores, &item.CveStore) if _, ok := imageDigests[item.ImageScanExecutionHistory.ImageHash]; !ok { @@ -472,7 +472,7 @@ func (impl *ImageScanServiceImpl) FetchMinScanResultByAppIdAndEnvId(request *bea } for _, item := range imageScanResult { executionTime = item.ImageScanExecutionHistory.ExecutionTime - criticalCount, highCount, moderateCount, lowCount, unkownCount = impl.updateCount(item.CveStore.StandardSeverity, criticalCount, highCount, moderateCount, lowCount, unkownCount) + criticalCount, highCount, moderateCount, lowCount, unkownCount = impl.updateCount(item.CveStore.GetSeverity(), criticalCount, highCount, moderateCount, lowCount, unkownCount) } if len(imageScanResult) > 0 { scantoolId = imageScanResult[0].ScanToolId diff --git a/pkg/security/policyService.go b/pkg/security/policyService.go index 920128600a..8de1d07bbb 100644 --- a/pkg/security/policyService.go +++ b/pkg/security/policyService.go @@ -467,7 +467,7 @@ func (impl *PolicyServiceImpl) SavePolicy(request bean.CreateVulnerabilityPolicy if err != nil { return nil, err } - severity = cveStore.StandardSeverity + severity = cveStore.GetSeverity() } policy := &security.CvePolicy{ Global: isGlobal, @@ -714,9 +714,9 @@ func (impl *PolicyServiceImpl) HasBlockedCVE(cves []*security.CveStore, cvePolic return true } } else { - if severityPolicy[cve.StandardSeverity] != nil && severityPolicy[cve.StandardSeverity].Action == securityBean.Allow { + if severityPolicy[cve.GetSeverity()] != nil && severityPolicy[cve.GetSeverity()].Action == securityBean.Allow { continue - } else if severityPolicy[cve.StandardSeverity] != nil && (severityPolicy[cve.StandardSeverity].Action == securityBean.Block || (severityPolicy[cve.StandardSeverity].Action == securityBean.Blockiffixed && cve.FixedVersion != "")) { + } else if severityPolicy[cve.GetSeverity()] != nil && (severityPolicy[cve.GetSeverity()].Action == securityBean.Block || (severityPolicy[cve.GetSeverity()].Action == securityBean.Blockiffixed && cve.FixedVersion != "")) { return true } } diff --git a/scripts/sql/273_scan_policies.up.sql b/scripts/sql/273_scan_policies.up.sql index dfa2877e8b..64ad44b17a 100644 --- a/scripts/sql/273_scan_policies.up.sql +++ b/scripts/sql/273_scan_policies.up.sql @@ -1,9 +1,6 @@ -- severity 3 is for high and 5 is for unknown INSERT INTO "public"."cve_policy_control" ("global", "cluster_id", "env_id", "app_id", "cve_store_id", "action", "severity", "deleted", "created_on", "created_by", "updated_on", "updated_by") VALUES - ('t', NULL, NULL, NULL, NULL, '1', '3', 'f', 'now()', '1', 'now()', '1'), - ('t', NULL, NULL, NULL, NULL, '1', '5', 'f', 'now()', '1', 'now()', '1'); + ('t', NULL, NULL, NULL, NULL, '1', '3', 'f', 'now()', '1', 'now()', '1'), + ('t', NULL, NULL, NULL, NULL, '1', '5', 'f', 'now()', '1', 'now()', '1'); --- UPDATE THE NULL VALUES IN THE STANDARD_SEVERITY COLUMN WITH THE SEVERITY COLUMN --- standard_severity column was introduced in 148_trivy_image_scanning.up.sql. all the scans happened before that will contains null values in standard_severity column. -UPDATE "public"."cve_store" SET standard_severity = severity WHERE standard_severity IS NULL; \ No newline at end of file From 7d7bde7adc23d169047d142c24719ea21fa54339 Mon Sep 17 00:00:00 2001 From: Gireesh Naidu Date: Thu, 8 Aug 2024 22:02:57 +0530 Subject: [PATCH 7/9] fix: review comments --- .../security/ImageScanDeployInfoRepository.go | 4 ++-- pkg/security/ImageScanService.go | 10 +--------- pkg/security/policyService.go | 2 +- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/internal/sql/repository/security/ImageScanDeployInfoRepository.go b/internal/sql/repository/security/ImageScanDeployInfoRepository.go index c705d2a18c..b3146dd6d8 100644 --- a/internal/sql/repository/security/ImageScanDeployInfoRepository.go +++ b/internal/sql/repository/security/ImageScanDeployInfoRepository.go @@ -178,7 +178,7 @@ func (impl ImageScanDeployInfoRepositoryImpl) scanListQueryWithoutObject(request } if len(request.Severity) > 0 { severities := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(request.Severity)), ","), "[]") - query = query + fmt.Sprintf(" AND (cs.standard_severity IN (%s) OR (cs.standard_severity IN (%s) AND cs.standard_severity IS NULL))", severities, severities) + query = query + fmt.Sprintf(" AND (cs.standard_severity IN (%s) OR (cs.severity IN (%s) AND cs.standard_severity IS NULL))", severities, severities) } if len(request.EnvironmentIds) > 0 { envIds := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(request.EnvironmentIds)), ","), "[]") @@ -240,7 +240,7 @@ func (impl ImageScanDeployInfoRepositoryImpl) scanListQueryWithObject(request *s if len(request.Severity) > 0 { severities := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(request.Severity)), ","), "[]") - query = query + fmt.Sprintf(" AND (cs.standard_severity IN (%s) OR (cs.standard_severity IN (%s) AND cs.standard_severity IS NULL))", severities, severities) + query = query + fmt.Sprintf(" AND (cs.standard_severity IN (%s) OR (cs.severity IN (%s) AND cs.standard_severity IS NULL))", severities, severities) } if len(request.EnvironmentIds) > 0 { envIds := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(request.EnvironmentIds)), ","), "[]") diff --git a/pkg/security/ImageScanService.go b/pkg/security/ImageScanService.go index f64a5a4747..66db644b3c 100644 --- a/pkg/security/ImageScanService.go +++ b/pkg/security/ImageScanService.go @@ -102,14 +102,6 @@ func (impl ImageScanServiceImpl) FetchAllDeployInfo(request *bean3.ImageScanRequ } func (impl ImageScanServiceImpl) FetchScanExecutionListing(request *bean3.ImageScanRequest, deployInfoIds []int) (*bean3.ImageScanHistoryListingResponse, error) { - //size := request.Size - //request.Size = 0 - //groupByListCount, err := impl.imageScanDeployInfoRepository.ScanListingWithFilter(&request.ImageScanFilter, request.Size, request.Offset, deployInfoIds) - //if err != nil { - // impl.Logger.Errorw("error while fetching scan execution result", "err", err) - // return nil, err - //} - //request.Size = size groupByList, err := impl.imageScanDeployInfoRepository.ScanListingWithFilter(&request.ImageScanFilter, request.Size, request.Offset, deployInfoIds) if err != nil { impl.Logger.Errorw("error while fetching scan execution result", "err", err) @@ -338,7 +330,7 @@ func (impl ImageScanServiceImpl) FetchExecutionDetailResult(request *bean3.Image CVersion: item.CveStore.Version, FVersion: item.FixedVersion, Package: item.CveStore.Package, - Severity: item.CveStore.StandardSeverity.String(), + Severity: item.CveStore.GetSeverity().String(), //Permission: "BLOCK", TODO } // data already migrated hence get package, version and fixedVersion from image_scan_execution_result diff --git a/pkg/security/policyService.go b/pkg/security/policyService.go index 8de1d07bbb..e00fa0eacf 100644 --- a/pkg/security/policyService.go +++ b/pkg/security/policyService.go @@ -258,7 +258,7 @@ func (impl *PolicyServiceImpl) VerifyImage(verifyImageRequest *VerifyImageReques for _, cve := range blockedCves { vr := &VerifyImageResponse{ Name: cve.Name, - Severity: cve.StandardSeverity.String(), + Severity: cve.GetSeverity().String(), Package: cve.Package, Version: cve.Version, FixedVersion: cve.FixedVersion, From 7d39ab35585107373dea63608985dc3fd4e0acdd Mon Sep 17 00:00:00 2001 From: Gireesh Naidu Date: Tue, 13 Aug 2024 15:36:59 +0530 Subject: [PATCH 8/9] fix: update script numbers --- .../{275_scan_policies.down.sql => 276_scan_policies.down.sql} | 0 .../sql/{275_scan_policies.up.sql => 276_scan_policies.up.sql} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename scripts/sql/{275_scan_policies.down.sql => 276_scan_policies.down.sql} (100%) rename scripts/sql/{275_scan_policies.up.sql => 276_scan_policies.up.sql} (100%) diff --git a/scripts/sql/275_scan_policies.down.sql b/scripts/sql/276_scan_policies.down.sql similarity index 100% rename from scripts/sql/275_scan_policies.down.sql rename to scripts/sql/276_scan_policies.down.sql diff --git a/scripts/sql/275_scan_policies.up.sql b/scripts/sql/276_scan_policies.up.sql similarity index 100% rename from scripts/sql/275_scan_policies.up.sql rename to scripts/sql/276_scan_policies.up.sql From d068f5c04b2a1f1598e92189b4c5aee2069e7e0d Mon Sep 17 00:00:00 2001 From: Gireesh Naidu Date: Tue, 20 Aug 2024 12:44:42 +0530 Subject: [PATCH 9/9] fix: minor fix --- .../sql/repository/security/ImageScanDeployInfoRepository.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/sql/repository/security/ImageScanDeployInfoRepository.go b/internal/sql/repository/security/ImageScanDeployInfoRepository.go index b3146dd6d8..f6cb1cf3ad 100644 --- a/internal/sql/repository/security/ImageScanDeployInfoRepository.go +++ b/internal/sql/repository/security/ImageScanDeployInfoRepository.go @@ -177,7 +177,7 @@ func (impl ImageScanDeployInfoRepositoryImpl) scanListQueryWithoutObject(request query = query + " AND res.cve_store_name ILIKE '%" + request.CVEName + "%'" } if len(request.Severity) > 0 { - severities := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(request.Severity)), ","), "[]") + severities := strings.Trim(strings.Join(strings.Fields(fmt.Sprintf("%d", request.Severity)), ","), "[]") query = query + fmt.Sprintf(" AND (cs.standard_severity IN (%s) OR (cs.severity IN (%s) AND cs.standard_severity IS NULL))", severities, severities) } if len(request.EnvironmentIds) > 0 { @@ -239,7 +239,7 @@ func (impl ImageScanDeployInfoRepositoryImpl) scanListQueryWithObject(request *s } if len(request.Severity) > 0 { - severities := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(request.Severity)), ","), "[]") + severities := strings.Trim(strings.Join(strings.Fields(fmt.Sprintf("%d", request.Severity)), ","), "[]") query = query + fmt.Sprintf(" AND (cs.standard_severity IN (%s) OR (cs.severity IN (%s) AND cs.standard_severity IS NULL))", severities, severities) } if len(request.EnvironmentIds) > 0 {