diff --git a/cmd/main.go b/cmd/main.go index b15e93fe7..71eeed7d8 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -1,7 +1,7 @@ package main import ( - "log" + "fmt" "os" "github.com/checkmarx/ast-cli/internal/commands" @@ -70,10 +70,10 @@ func exitIfError(err error) { if err != nil { switch e := err.(type) { case *wrappers.AstError: - log.Println(e.Err) + fmt.Println(e.Err) os.Exit(e.Code) default: - log.Println(e) + fmt.Println(e) os.Exit(failureExitCode) } } diff --git a/internal/commands/predicates.go b/internal/commands/predicates.go index ad9f166fc..591c777b6 100644 --- a/internal/commands/predicates.go +++ b/internal/commands/predicates.go @@ -112,14 +112,14 @@ func runTriageShow(resultsPredicatesWrapper wrappers.ResultsPredicatesWrapper) f ) if err != nil { - return errors.Wrapf(err, "%s", "Failed getting the predicate.") + return errors.Wrapf(err, "%s", "Failed showing the predicate") } // Checking the response if errorModel != nil { return errors.Errorf( "%s: CODE: %d, %s", - "Failed getting the predicate.", + "Failed showing the predicate.", errorModel.Code, errorModel.Message, ) @@ -154,7 +154,7 @@ func runTriageUpdate(resultsPredicatesWrapper wrappers.ResultsPredicatesWrapper) _, err := resultsPredicatesWrapper.PredicateSeverityAndState(predicate) if err != nil { - return err + return errors.Wrapf(err, "%s", "Failed updating the predicate") } return nil diff --git a/internal/commands/result.go b/internal/commands/result.go index 853fa30da..b76c2aceb 100644 --- a/internal/commands/result.go +++ b/internal/commands/result.go @@ -31,6 +31,9 @@ const ( lowSonar = "MINOR" mediumSonar = "MAJOR" highSonar = "CRITICAL" + infoLowSarif = "note" + mediumSarif = "warning" + highSarif = "error" vulnerabilitySonar = "VULNERABILITY" infoCx = "INFO" lowCx = "LOW" @@ -705,16 +708,20 @@ func parseSonarTextRange(results *wrappers.ScanResultNode) wrappers.SonarTextRan func findRule(ruleIds map[interface{}]bool, result *wrappers.ScanResult) *wrappers.SarifDriverRule { var sarifRule wrappers.SarifDriverRule - + var sarifDescription wrappers.SarifDescription + sarifDescription.Text = "No description available" if result.ScanResultData.QueryID == nil { - sarifRule.ID = result.ID + sarifRule.ID = fmt.Sprintf("%s (%s)", result.ID, result.Type) } else { - sarifRule.ID = fmt.Sprintf("%v", result.ScanResultData.QueryID) + sarifRule.ID = fmt.Sprintf("%v (%s)", result.ScanResultData.QueryID, result.Type) } + sarifRule.Name = strings.ReplaceAll(result.ScanResultData.QueryName, "_", " ") - if result.ScanResultData.QueryName != "" { - sarifRule.Name = result.ScanResultData.QueryName + sarifDescription.Text = result.Description + if result.Type == commonParams.KicsType { + sarifDescription.Text = result.Description + " Value:" + result.ScanResultData.Value + ". Expected value:" + result.ScanResultData.ExpectedValue } + sarifRule.FullDescription = sarifDescription sarifRule.HelpURI = wrappers.SarifInformationURI @@ -728,25 +735,52 @@ func findRule(ruleIds map[interface{}]bool, result *wrappers.ScanResult) *wrappe func findResult(result *wrappers.ScanResult) *wrappers.SarifScanResult { var scanResult wrappers.SarifScanResult - scanResult.RuleID = fmt.Sprintf("%v", result.ScanResultData.QueryID) - scanResult.Message.Text = result.ScanResultData.QueryName + // Match cx severity with sarif severity + level := map[string]string{ + infoCx: infoLowSarif, + lowCx: infoLowSarif, + mediumCx: mediumSarif, + highCx: highSarif, + } + if result.ScanResultData.QueryID == nil { + scanResult.RuleID = fmt.Sprintf("%v (%s)", result.ID, result.Type) + } else { + scanResult.RuleID = fmt.Sprintf("%v (%s)", result.ScanResultData.QueryID, result.Type) + } + scanResult.Level = level[result.Severity] + scanResult.Message.Text = strings.ReplaceAll(result.ScanResultData.QueryName, "_", " ") scanResult.Locations = []wrappers.SarifLocation{} - for _, node := range result.ScanResultData.Nodes { + if len(result.ScanResultData.Nodes) == 0 { var scanLocation wrappers.SarifLocation - scanLocation.PhysicalLocation.ArtifactLocation.URI = node.FileName[1:] - if node.Line <= 0 { - continue + // to use in kics scan type + if result.Type == commonParams.KicsType { + // Need to remove the first / in kics filename in order to correct in sarif + scanLocation.PhysicalLocation.ArtifactLocation.URI = strings.Replace(result.ScanResultData.Filename, "/", "", 1) + scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} + scanLocation.PhysicalLocation.Region.StartLine = result.ScanResultData.Line + scanLocation.PhysicalLocation.Region.StartColumn = 1 + scanLocation.PhysicalLocation.Region.EndColumn = 2 + scanResult.Locations = append(scanResult.Locations, scanLocation) + } + } else { + for _, node := range result.ScanResultData.Nodes { + var scanLocation wrappers.SarifLocation + scanLocation.PhysicalLocation.ArtifactLocation.URI = node.FileName[1:] + if node.Line <= 0 { + continue + } + scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} + scanLocation.PhysicalLocation.Region.StartLine = node.Line + column := node.Column + length := node.Length + scanLocation.PhysicalLocation.Region.StartColumn = column + scanLocation.PhysicalLocation.Region.EndColumn = column + length + + scanResult.Locations = append(scanResult.Locations, scanLocation) } - scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} - scanLocation.PhysicalLocation.Region.StartLine = node.Line - column := node.Column - length := node.Length - scanLocation.PhysicalLocation.Region.StartColumn = column - scanLocation.PhysicalLocation.Region.EndColumn = column + length - - scanResult.Locations = append(scanResult.Locations, scanLocation) } + if len(scanResult.Locations) > 0 { return &scanResult } diff --git a/internal/wrappers/predicates-http.go b/internal/wrappers/predicates-http.go index 9dc90ddca..a8a220ce2 100644 --- a/internal/wrappers/predicates-http.go +++ b/internal/wrappers/predicates-http.go @@ -83,7 +83,7 @@ func (r ResultsPredicatesHTTPWrapper) PredicateSeverityAndState(predicate *Predi return nil, err } - PrintIfVerbose(fmt.Sprintf("Response : %s", resp.Status)) + PrintIfVerbose(fmt.Sprintf("Response : %s ", resp.Status)) defer func() { _ = resp.Body.Close() @@ -95,6 +95,10 @@ func (r ResultsPredicatesHTTPWrapper) PredicateSeverityAndState(predicate *Predi case http.StatusOK: fmt.Println("Predicate updated successfully.") return nil, nil + case http.StatusNotModified: + return nil, errors.Errorf("No changes to update.") + case http.StatusForbidden: + return nil, errors.Errorf("No permission to update predicate.") case http.StatusNotFound: return nil, errors.Errorf("Predicate not found.") default: @@ -130,6 +134,8 @@ func handleResponseWithBody(resp *http.Response, err error) (*PredicatesCollecti return responsePredicateParsingFailed(err) } return &model, nil, nil + case http.StatusForbidden: + return nil, nil, errors.Errorf("No permission to show predicate.") case http.StatusNotFound: return nil, nil, errors.Errorf("Predicate not found.") default: diff --git a/internal/wrappers/results-modifier.go b/internal/wrappers/results-modifier.go index f49d6ed71..1c49404fc 100644 --- a/internal/wrappers/results-modifier.go +++ b/internal/wrappers/results-modifier.go @@ -3,6 +3,7 @@ package wrappers import ( "bytes" "encoding/json" + "strings" "github.com/checkmarx/ast-cli/internal/params" ) @@ -23,11 +24,11 @@ func (s *ScanResult) UnmarshalJSON(data []byte) error { return err } - if s.Type == "infrastructure" { + if strings.HasPrefix(s.Type, "infrastructure") { s.Type = params.KicsType } - if s.Type == "dependency" { + if strings.HasPrefix(s.Type, "dependency") || strings.HasPrefix(s.Type, "sca-container") { s.Type = params.ScaType } diff --git a/internal/wrappers/results-sarif.go b/internal/wrappers/results-sarif.go index 392a2eff4..4c5a857cf 100644 --- a/internal/wrappers/results-sarif.go +++ b/internal/wrappers/results-sarif.go @@ -29,13 +29,19 @@ type SarifDriver struct { } type SarifDriverRule struct { - ID string `json:"id"` - Name string `json:"name,omitempty"` - HelpURI string `json:"helpUri"` + ID string `json:"id"` + Name string `json:"name,omitempty"` + HelpURI string `json:"helpUri"` + FullDescription SarifDescription `json:"fullDescription"` +} + +type SarifDescription struct { + Text string `json:"text"` } type SarifScanResult struct { RuleID string `json:"ruleId"` + Level string `json:"level"` Message SarifMessage `json:"message"` PartialFingerprints *SarifResultFingerprint `json:"partialFingerprints,omitempty"` Locations []SarifLocation `json:"locations,omitempty"` diff --git a/test/integration/result_test.go b/test/integration/result_test.go index e4f103510..b4838fb17 100644 --- a/test/integration/result_test.go +++ b/test/integration/result_test.go @@ -70,6 +70,17 @@ func assertResultFilesCreated(t *testing.T) { }() } +func TestResultsShowParamFailed(t *testing.T) { + + args := []string{ + "results", + "show", + } + + err, _ := executeCommand(t, args...) + assertError(t, err, "Failed listing results: Please provide a scan ID") +} + func TestCodeBashingParamFailed(t *testing.T) { args := []string{