Skip to content

Commit

Permalink
CLI | Update the Cli Calls to SCA Risk Management Service to use Expo…
Browse files Browse the repository at this point in the history
…rt Service (AST-42958) (#812)

* add functionality to export wrapper

* add functionality to export wrapper

* fix fixlink of packages

* fix dependencyPathArray of packages

* fix linter

* fix linter

* fix linter

* optimize runtime

* refactor addPackageInformation in result.go

* refactor addPackageInformation in result.go

* fix linter

* increase timeout

* refactor

* delete risk-management api from cli

* fix linter

* fix linter

* fix integration test compilation

* refactor unused var

* add comment for better understanding

* refactor

* add log

* try solve trivy vuls

* try solve trivy vuls

* try solve trivy vuls

* try solve trivy vuls

* try solve trivy vuls

* revert trivy changes

* Update ci.yml

* resolve conversation

* refactor

---------

Co-authored-by: AlvoBen <alvo@post.bgu.ac.il>
  • Loading branch information
AlvoBen and BenAlvo1 authored Aug 5, 2024
1 parent 9247095 commit 49240aa
Show file tree
Hide file tree
Showing 15 changed files with 316 additions and 240 deletions.
3 changes: 1 addition & 2 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ func main() {
applications := viper.GetString(params.ApplicationsPathKey)
results := viper.GetString(params.ResultsPathKey)
scanSummary := viper.GetString(params.ScanSummaryPathKey)
scaPackage := viper.GetString(params.ScaPackagePathKey)
risksOverview := viper.GetString(params.RisksOverviewPathKey)
scsScanOverview := viper.GetString(params.ScsScanOverviewPathKey)
uploads := viper.GetString(params.UploadsPathKey)
Expand Down Expand Up @@ -63,7 +62,7 @@ func main() {
applicationsWrapper := wrappers.NewApplicationsHTTPWrapper(applications)
risksOverviewWrapper := wrappers.NewHTTPRisksOverviewWrapper(risksOverview)
scsScanOverviewWrapper := wrappers.NewHTTPScanOverviewWrapper(scsScanOverview)
resultsWrapper := wrappers.NewHTTPResultsWrapper(results, scaPackage, scanSummary)
resultsWrapper := wrappers.NewHTTPResultsWrapper(results, scanSummary)
authWrapper := wrappers.NewAuthHTTPWrapper()
resultsPredicatesWrapper := wrappers.NewResultsPredicatesHTTPWrapper()
codeBashingWrapper := wrappers.NewCodeBashingHTTPWrapper(codebashing)
Expand Down
2 changes: 1 addition & 1 deletion internal/commands/.scripts/up.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ wget https://sca-downloads.s3.amazonaws.com/cli/latest/ScaResolver-linux64.tar.g
tar -xzvf ScaResolver-linux64.tar.gz -C /tmp
rm -rf ScaResolver-linux64.tar.gz
# ignore mock and wrappers packages, as they checked by integration tests
go test $(go list ./... | grep -v "mock" | grep -v "wrappers" | grep -v "bitbucketserver" | grep -v "logger") -timeout 940.000s -coverprofile cover.out
go test $(go list ./... | grep -v "mock" | grep -v "wrappers" | grep -v "bitbucketserver" | grep -v "logger") -timeout 20m -coverprofile cover.out
209 changes: 148 additions & 61 deletions internal/commands/result.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ const (
fixLabel = "fix"
redundantLabel = "redundant"
delayValueForReport = 10
fixLinkPrefix = "https://devhub.checkmarx.com/cve-details/"
)

var summaryFormats = []string{
Expand Down Expand Up @@ -1056,7 +1057,7 @@ func CreateScanReport(
return err
}
if !scanPending {
results, err = ReadResults(resultsWrapper, scan, params)
results, err = ReadResults(resultsWrapper, exportWrapper, scan, params)
if err != nil {
return err
}
Expand Down Expand Up @@ -1291,6 +1292,7 @@ func createDirectory(targetPath string) error {

func ReadResults(
resultsWrapper wrappers.ResultsWrapper,
exportWrapper wrappers.ExportWrapper,
scan *wrappers.ScanResponseModel,
params map[string]string,
) (results *wrappers.ScanResultsCollection, err error) {
Expand All @@ -1314,7 +1316,7 @@ func ReadResults(
// Compute SAST results redundancy
resultsModel = ComputeRedundantSastResults(resultsModel)
}
resultsModel, err = enrichScaResults(resultsWrapper, scan, params, resultsModel)
resultsModel, err = enrichScaResults(exportWrapper, scan, resultsModel)
if err != nil {
return nil, err
}
Expand All @@ -1326,33 +1328,17 @@ func ReadResults(
}

func enrichScaResults(
resultsWrapper wrappers.ResultsWrapper,
exportWrapper wrappers.ExportWrapper,
scan *wrappers.ScanResponseModel,
params map[string]string,
resultsModel *wrappers.ScanResultsCollection,
) (*wrappers.ScanResultsCollection, error) {
if slices.Contains(scan.Engines, commonParams.ScaType) {
// Get additional information to enrich sca results
scaPackageModel, errorModel, err := resultsWrapper.GetAllResultsPackageByScanID(params)
if errorModel != nil {
logger.PrintfIfVerbose("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message)
return resultsModel, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message)
}
if err != nil {
logger.PrintfIfVerbose("%s", failedListingResults)
return resultsModel, errors.Wrapf(err, "%s", failedListingResults)
}
// Get additional information to add the type information to the sca results
scaTypeModel, errorModel, err := resultsWrapper.GetAllResultsTypeByScanID(params)
if errorModel != nil {
logger.PrintfIfVerbose("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message)
return resultsModel, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message)
}
scaExportDetails, err := services.GetExportPackage(exportWrapper, scan.ID)
if err != nil {
logger.PrintfIfVerbose("%s", failedListingResults)
return resultsModel, errors.Wrapf(err, "%s", failedListingResults)
return nil, errors.Wrapf(err, "%s", failedListingResults)
}
// Enrich sca results
scaPackageModel := parseScaExportPackage(scaExportDetails.Packages)
scaTypeModel := parseExportScaVulnerability(scaExportDetails.ScaTypes)
if scaPackageModel != nil {
resultsModel = addPackageInformation(resultsModel, scaPackageModel, scaTypeModel)
}
Expand All @@ -1363,6 +1349,61 @@ func enrichScaResults(
return resultsModel, nil
}

func parseExportScaVulnerability(types []wrappers.ScaType) *[]wrappers.ScaTypeCollection {
var scaTypes []wrappers.ScaTypeCollection
for _, t := range types {
scaTypes = append(scaTypes, wrappers.ScaTypeCollection(t))
}
return &scaTypes
}

func parseScaExportPackage(packages []wrappers.ScaPackage) *[]wrappers.ScaPackageCollection {
var scaPackages []wrappers.ScaPackageCollection
for _, pkg := range packages {
pkg := pkg
scaPackages = append(scaPackages, wrappers.ScaPackageCollection{
ID: pkg.ID,
Locations: pkg.Locations,
DependencyPathArray: parsePackagePathToDependencyPath(&pkg),
Outdated: pkg.Outdated,
IsDirectDependency: pkg.IsDirectDependency,
})
}
return &scaPackages
}

func parsePackagePathToDependencyPath(pkg *wrappers.ScaPackage) [][]wrappers.DependencyPath {
var dependencyPathArray [][]wrappers.DependencyPath
for _, path := range pkg.PackagePathArray {
var dependencyPath []wrappers.DependencyPath
for _, dep := range path {
dependencyPath = append(dependencyPath, wrappers.DependencyPath{
ID: dep.ID,
Name: dep.Name,
Version: dep.Version,
})
}
dependencyPathArray = append(dependencyPathArray, dependencyPath)
}

// We are doing this to maintain the same structure that was in risk-management api response
// in risk-management, if the length of the dependency path array is 1, it will be the main package
// in export service, if there are no dependencies, the package path array will be empty
if len(dependencyPathArray) == 0 {
appendMainPackageToDependencyPath(&dependencyPathArray, pkg)
}
return dependencyPathArray
}

func appendMainPackageToDependencyPath(dependencyPathArray *[][]wrappers.DependencyPath, pkg *wrappers.ScaPackage) {
*dependencyPathArray = append(*dependencyPathArray, []wrappers.DependencyPath{{
ID: pkg.ID,
Locations: pkg.Locations,
Name: pkg.Name,
IsDevelopment: pkg.IsDevelopmentDependency,
}})
}

func removeContainerResults(model *wrappers.ScanResultsCollection) *wrappers.ScanResultsCollection {
var newResults []*wrappers.ScanResult
for _, result := range model.Results {
Expand Down Expand Up @@ -2273,52 +2314,98 @@ func addPackageInformation(
scaPackageModel *[]wrappers.ScaPackageCollection,
scaTypeModel *[]wrappers.ScaTypeCollection,
) *wrappers.ScanResultsCollection {
var currentID string

locationsByID, typesByCVE := buildAuxiliaryScaMaps(resultsModel, scaPackageModel, scaTypeModel)
scaPackageMap := buildScaPackageMap(*scaPackageModel)

for _, result := range resultsModel.Results {
if !(result.Type == commonParams.ScaType) {
continue
} else {
currentID = result.ScanResultData.PackageIdentifier
const precision = 1
var roundedScore = util.RoundFloat(result.VulnerabilityDetails.CvssScore, precision)
result.VulnerabilityDetails.CvssScore = roundedScore
// Add the sca type
result.ScaType = buildScaType(typesByCVE, result)
// Temporary code for client
result.State = buildScaState(typesByCVE, result)
for _, packages := range *scaPackageModel {
currentPackage := packages
if packages.ID == currentID {
for _, dependencyPath := range currentPackage.DependencyPathArray {
head := &dependencyPath[0]
head.Locations = locationsByID[head.ID]
head.SupportsQuickFix = len(dependencyPath) == 1
for _, location := range locationsByID[head.ID] {
head.SupportsQuickFix = head.SupportsQuickFix && util.IsPackageFileSupported(*location)
}
currentPackage.SupportsQuickFix = currentPackage.SupportsQuickFix || head.SupportsQuickFix
if result.ID != "" {
currentPackage.FixLink = "https://devhub.checkmarx.com/cve-details/" + result.ID
} else {
currentPackage.FixLink = ""
}
}
if currentPackage.IsDirectDependency {
currentPackage.TypeOfDependency = directDependencyType
} else {
currentPackage.TypeOfDependency = indirectDependencyType
}
result.ScanResultData.ScaPackageCollection = &currentPackage
break
}
}
if result.Type == commonParams.ScaType {
processResult(result, locationsByID, typesByCVE, scaPackageMap)
}
}

return resultsModel
}

func processResult(
result *wrappers.ScanResult,
locationsByID map[string][]*string,
typesByCVE map[string]wrappers.ScaTypeCollection,
scaPackageMap map[string]wrappers.ScaPackageCollection, // Updated parameter
) {
const precision = 1

currentID := result.ScanResultData.PackageIdentifier
result.VulnerabilityDetails.CvssScore = util.RoundFloat(result.VulnerabilityDetails.CvssScore, precision)
result.ScaType = buildScaType(typesByCVE, result)
result.State = buildScaState(typesByCVE, result)

updatePackages(result, scaPackageMap, locationsByID, currentID)
}

func updatePackages(
result *wrappers.ScanResult,
scaPackageMap map[string]wrappers.ScaPackageCollection,
locationsByID map[string][]*string,
currentID string,
) {
packages, found := scaPackageMap[currentID]
if !found {
return
}

updateDependencyPaths(packages.DependencyPathArray, locationsByID)
if !packages.SupportsQuickFix {
packages.SupportsQuickFix = hasQuickFix(packages.DependencyPathArray)
}

if packages.IsDirectDependency {
packages.TypeOfDependency = directDependencyType
} else {
packages.TypeOfDependency = indirectDependencyType
}

packages.FixLink = buildFixLink(result)
result.ScanResultData.ScaPackageCollection = &packages
}

func hasQuickFix(dependencyPaths [][]wrappers.DependencyPath) bool {
for i := range dependencyPaths {
head := &dependencyPaths[i][0]
if head.SupportsQuickFix {
return true
}
}
return false
}

func buildScaPackageMap(scaPackageModel []wrappers.ScaPackageCollection) map[string]wrappers.ScaPackageCollection {
scaPackageMap := make(map[string]wrappers.ScaPackageCollection)
for i := range scaPackageModel {
scaPackageMap[scaPackageModel[i].ID] = scaPackageModel[i]
}
return scaPackageMap
}

func updateDependencyPaths(dependencyPaths [][]wrappers.DependencyPath, locationsByID map[string][]*string) {
for i := range dependencyPaths {
head := &dependencyPaths[i][0]
head.Locations = locationsByID[head.ID]
head.SupportsQuickFix = len(dependencyPaths[i]) == 1

for _, location := range locationsByID[head.ID] {
head.SupportsQuickFix = head.SupportsQuickFix && util.IsPackageFileSupported(*location)
}
}
}

func buildFixLink(result *wrappers.ScanResult) string {
if result.ID != "" {
return fmt.Sprint(fixLinkPrefix, result.ID)
}
return ""
}

func filterViolatedRules(policyModel wrappers.PolicyResponseModel) *wrappers.PolicyResponseModel {
i := 0
for _, policy := range policyModel.Policies {
Expand Down
9 changes: 5 additions & 4 deletions internal/commands/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -1648,7 +1648,7 @@ func runCreateScanCommand(
return err
}

err = applyThreshold(cmd, resultsWrapper, scanResponseModel, thresholdMap)
err = applyThreshold(cmd, resultsWrapper, exportWrapper, scanResponseModel, thresholdMap)
if err != nil {
return err
}
Expand Down Expand Up @@ -1898,6 +1898,7 @@ func createReportsAfterScan(
func applyThreshold(
cmd *cobra.Command,
resultsWrapper wrappers.ResultsWrapper,
exportWrapper wrappers.ExportWrapper,
scanResponseModel *wrappers.ScanResponseModel,
thresholdMap map[string]int,
) error {
Expand All @@ -1911,7 +1912,7 @@ func applyThreshold(
params[commonParams.SastRedundancyFlag] = ""
}

summaryMap, err := getSummaryThresholdMap(resultsWrapper, scanResponseModel, params)
summaryMap, err := getSummaryThresholdMap(resultsWrapper, exportWrapper, scanResponseModel, params)
if err != nil {
return err
}
Expand Down Expand Up @@ -1994,11 +1995,11 @@ func parseThresholdLimit(limit string) (engineName string, intLimit int, err err
return engineName, intLimit, err
}

func getSummaryThresholdMap(resultsWrapper wrappers.ResultsWrapper, scan *wrappers.ScanResponseModel, params map[string]string) (
func getSummaryThresholdMap(resultsWrapper wrappers.ResultsWrapper, exportWrapper wrappers.ExportWrapper, scan *wrappers.ScanResponseModel, params map[string]string) (
map[string]int,
error,
) {
results, err := ReadResults(resultsWrapper, scan, params)
results, err := ReadResults(resultsWrapper, exportWrapper, scan, params)
if err != nil {
return nil, err
}
Expand Down
1 change: 0 additions & 1 deletion internal/params/binds.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ var EnvVarsBinds = []struct {
{ScanSummaryPathKey, ScanSummaryPathEnv, "api/scan-summary"},
{RisksOverviewPathKey, RisksOverviewPathEnv, "api/apisec/static/api/scan/%s/risks-overview"},
{ScsScanOverviewPathKey, ScsScanOverviewPathEnv, "api/micro-engines/scans/%s/scan-overview"},
{ScaPackagePathKey, ScaPackagePathEnv, "api/sca/risk-management/risk-reports/"},
{SastResultsPathKey, SastResultsPathEnv, "api/sast-results"},
{SastResultsPredicatesPathKey, SastResultsPredicatesPathEnv, "api/sast-results-predicates"},
{KicsResultsPathKey, KicsResultsPathEnv, "api/kics-results"},
Expand Down
1 change: 0 additions & 1 deletion internal/params/envs.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ const (
ApplicationsPathEnv = "CX_APPLICATIONS_PATH"
ResultsPathEnv = "CX_RESULTS_PATH"
ScanSummaryPathEnv = "CX_SCAN_SUMMARY_PATH"
ScaPackagePathEnv = "CX_SCA_PACKAGE_PATH"
RisksOverviewPathEnv = "CX_RISKS_OVERVIEW_PATH"
ScsScanOverviewPathEnv = "CX_SCS_SCAN_OVERVIEW_PATH"
SastResultsPathEnv = "CX_SAST_RESULTS_PATH"
Expand Down
1 change: 0 additions & 1 deletion internal/params/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ var (
LogsEngineLogPathKey = strings.ToLower(LogsEngineLogPathEnv)
SastResultsPredicatesPathKey = strings.ToLower(SastResultsPredicatesPathEnv)
KicsResultsPredicatesPathKey = strings.ToLower(KicsResultsPredicatesPathEnv)
ScaPackagePathKey = strings.ToLower(ScaPackagePathEnv)
DescriptionsPathKey = strings.ToLower(DescriptionsPathEnv)
TenantConfigurationPathKey = strings.ToLower(TenantConfigurationPathEnv)
ResultsPdfReportPathKey = strings.ToLower(ResultsPdfReportPathEnv)
Expand Down
Loading

0 comments on commit 49240aa

Please sign in to comment.