diff --git a/commands/audit/audit.go b/commands/audit/audit.go index 548e1e03..d4e713f9 100644 --- a/commands/audit/audit.go +++ b/commands/audit/audit.go @@ -282,7 +282,7 @@ func RunJasScans(auditParallelRunner *utils.SecurityParallelRunner, auditParams auditParams.minSeverityFilter, jas.GetAnalyzerManagerXscEnvVars( auditParams.GetMultiScanId(), - jas.GetGitRepoUrlKey(auditParams.resultsContext.GitRepoHttpsCloneUrl), + utils.GetGitRepoUrlKey(auditParams.resultsContext.GitRepoHttpsCloneUrl), auditParams.resultsContext.ProjectKey, auditParams.resultsContext.Watches, scanResults.GetTechnologies()..., diff --git a/go.mod b/go.mod index 63e4fc20..81153d53 100644 --- a/go.mod +++ b/go.mod @@ -112,7 +112,7 @@ require ( gopkg.in/warnings.v0 v0.1.2 // indirect ) -// replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go dev +replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20250112124833-a16b038d8ff2 // replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 dev diff --git a/go.sum b/go.sum index 3ce66d00..fda9980a 100644 --- a/go.sum +++ b/go.sum @@ -129,8 +129,8 @@ github.com/jfrog/jfrog-apps-config v1.0.1 h1:mtv6k7g8A8BVhlHGlSveapqf4mJfonwvXYL github.com/jfrog/jfrog-apps-config v1.0.1/go.mod h1:8AIIr1oY9JuH5dylz2S6f8Ym2MaadPLR6noCBO4C22w= github.com/jfrog/jfrog-cli-core/v2 v2.57.6 h1:kI5BqDW8Q4R5HkTUPSAObTqyIgQ9z7DqeFYGOEC1zPk= github.com/jfrog/jfrog-cli-core/v2 v2.57.6/go.mod h1:h5pzOZUb5ChGcGrXCYr3nPyXcTZjeGW2Rm1Zceo8Afg= -github.com/jfrog/jfrog-client-go v1.49.0 h1:NaTK6+LQBEJafL//6ntnS/eVx1dZMJnxydALwWHKORQ= -github.com/jfrog/jfrog-client-go v1.49.0/go.mod h1:ohIfKpMBCQsE9kunrKQ1wvoExpqsPLaluRFO186B5EM= +github.com/jfrog/jfrog-client-go v1.28.1-0.20250112124833-a16b038d8ff2 h1:QuIEMPcyS1PnrFSBlyXGv6GKyBcJ82IzD3poleC375c= +github.com/jfrog/jfrog-client-go v1.28.1-0.20250112124833-a16b038d8ff2/go.mod h1:ohIfKpMBCQsE9kunrKQ1wvoExpqsPLaluRFO186B5EM= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= github.com/k0kubun/pp v3.0.1+incompatible/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3tgzSScAn6HmfYukg= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= diff --git a/jas/common.go b/jas/common.go index 9ac16c2f..37d31a99 100644 --- a/jas/common.go +++ b/jas/common.go @@ -25,7 +25,6 @@ import ( "github.com/jfrog/jfrog-client-go/utils/log" "github.com/jfrog/jfrog-client-go/xray" "github.com/jfrog/jfrog-client-go/xray/services" - xscutils "github.com/jfrog/jfrog-client-go/xsc/services/utils" "github.com/owenrumney/go-sarif/v2/sarif" "github.com/stretchr/testify/assert" "golang.org/x/exp/slices" @@ -374,14 +373,6 @@ func CheckForSecretValidation(xrayManager *xray.XrayServicesManager, xrayVersion return err == nil && isEnabled } -// Analyzer Manager expect the git repo url to be in the env vars in a specific way, this function will return the key for the git repo url -func GetGitRepoUrlKey(gitRepoHttpsCloneUrl string) string { - if gitRepoHttpsCloneUrl == "" { - return "" - } - return xscutils.GetGitRepoUrlKey(gitRepoHttpsCloneUrl) -} - func GetAnalyzerManagerXscEnvVars(msi string, gitRepoUrl, projectKey string, watches []string, technologies ...techutils.Technology) map[string]string { envVars := map[string]string{utils.JfMsiEnvVariable: msi} if gitRepoUrl != "" { diff --git a/utils/utils.go b/utils/utils.go index 77e8ee2d..453f16ad 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -6,6 +6,7 @@ import ( "encoding/hex" "encoding/json" "fmt" + xscutils "github.com/jfrog/jfrog-client-go/xsc/services/utils" orderedJson "github.com/virtuald/go-ordered-json" "os" "path/filepath" @@ -272,3 +273,11 @@ func DumpContentToFile(fileContent []byte, scanResultsOutputDir string, scanType } return } + +// Returns the key for the git reop Url, as expected by the Analyzer Manager and the Analytics event report +func GetGitRepoUrlKey(gitRepoHttpsCloneUrl string) string { + if gitRepoHttpsCloneUrl == "" { + return "" + } + return xscutils.GetGitRepoUrlKey(gitRepoHttpsCloneUrl) +} diff --git a/utils/xsc/analyticsmetrics.go b/utils/xsc/analyticsmetrics.go index 27cd7c95..4ea8895f 100644 --- a/utils/xsc/analyticsmetrics.go +++ b/utils/xsc/analyticsmetrics.go @@ -2,6 +2,7 @@ package xsc import ( "fmt" + "github.com/jfrog/jfrog-cli-security/utils" "strings" "time" @@ -51,7 +52,7 @@ func SendNewScanEvent(xrayVersion, xscVersion string, serviceDetails *config.Ser return } -func SendScanEndedEvent(xrayVersion, xscVersion string, serviceDetails *config.ServerDetails, multiScanId string, startTime time.Time, totalFindings int, scanError error) { +func SendScanEndedEvent(xrayVersion, xscVersion string, serviceDetails *config.ServerDetails, multiScanId string, startTime time.Time, totalFindings int, resultsContext *results.ResultContext, scanError error) { if !shouldReportEvents(xscVersion) { return } @@ -66,7 +67,7 @@ func SendScanEndedEvent(xrayVersion, xscVersion string, serviceDetails *config.S return } - event := CreateFinalizedEvent(multiScanId, startTime, totalFindings, scanError) + event := CreateFinalizedEvent(multiScanId, startTime, totalFindings, resultsContext, scanError) if err = xscService.UpdateAnalyticsGeneralEvent(event); err != nil { log.Debug(fmt.Sprintf("failed updating general event in XSC service for multi_scan_id %s, error: %s \"", multiScanId, err.Error())) @@ -86,18 +87,26 @@ func SendScanEndedWithResults(serviceDetails *config.ServerDetails, cmdResults * cmdResults.MultiScanId, cmdResults.StartTime, getTotalFindings(cmdResults), + &cmdResults.ResultContext, cmdResults.GetErrors(), ) } -func CreateFinalizedEvent(multiScanId string, startTime time.Time, totalFindings int, err error) xscservices.XscAnalyticsGeneralEventFinalize { +func CreateFinalizedEvent(multiScanId string, startTime time.Time, totalFindings int, resultsContext *results.ResultContext, err error) xscservices.XscAnalyticsGeneralEventFinalize { totalDuration := time.Since(startTime) eventStatus := xscservices.Completed if err != nil { eventStatus = xscservices.Failed } + + var gitRepoUrlKey string + if resultsContext != nil { + gitRepoUrlKey = utils.GetGitRepoUrlKey(resultsContext.GitRepoHttpsCloneUrl) + } + return xscservices.XscAnalyticsGeneralEventFinalize{ MultiScanId: multiScanId, + GitRepoUrl: gitRepoUrlKey, XscAnalyticsBasicGeneralEvent: xscservices.XscAnalyticsBasicGeneralEvent{ EventStatus: eventStatus, TotalFindings: totalFindings, @@ -107,7 +116,7 @@ func CreateFinalizedEvent(multiScanId string, startTime time.Time, totalFindings } func createFinalizedEvent(cmdResults *results.SecurityCommandResults) xscservices.XscAnalyticsGeneralEventFinalize { - return CreateFinalizedEvent(cmdResults.MultiScanId, cmdResults.StartTime, getTotalFindings(cmdResults), cmdResults.GetErrors()) + return CreateFinalizedEvent(cmdResults.MultiScanId, cmdResults.StartTime, getTotalFindings(cmdResults), &cmdResults.ResultContext, cmdResults.GetErrors()) } func GetScanEvent(xrayVersion, xscVersion, multiScanId string, serviceDetails *config.ServerDetails) (*xscservices.XscAnalyticsGeneralEvent, error) { diff --git a/utils/xsc/analyticsmetrics_test.go b/utils/xsc/analyticsmetrics_test.go index db9905db..0e1bf10c 100644 --- a/utils/xsc/analyticsmetrics_test.go +++ b/utils/xsc/analyticsmetrics_test.go @@ -145,27 +145,43 @@ func TestCreateFinalizedEvent(t *testing.T) { testCases := []struct { name string auditResults *results.SecurityCommandResults - expected xscservices.XscAnalyticsBasicGeneralEvent + expected xscservices.XscAnalyticsGeneralEventFinalize }{ { name: "No audit results", auditResults: &results.SecurityCommandResults{MultiScanId: "msi", StartTime: time}, - expected: xscservices.XscAnalyticsBasicGeneralEvent{EventStatus: xscservices.Completed}, + expected: xscservices.XscAnalyticsGeneralEventFinalize{ + XscAnalyticsBasicGeneralEvent: xscservices.XscAnalyticsBasicGeneralEvent{EventStatus: xscservices.Completed}, + }, }, { name: "Valid audit result", - auditResults: getDummyContentForGeneralEvent(true, false), - expected: xscservices.XscAnalyticsBasicGeneralEvent{TotalFindings: 7, EventStatus: xscservices.Completed}, + auditResults: getDummyContentForGeneralEvent(true, false, false), + expected: xscservices.XscAnalyticsGeneralEventFinalize{ + XscAnalyticsBasicGeneralEvent: xscservices.XscAnalyticsBasicGeneralEvent{TotalFindings: 7, EventStatus: xscservices.Completed}, + }, + }, + { + name: "Scan failed with findings", + auditResults: getDummyContentForGeneralEvent(false, true, false), + expected: xscservices.XscAnalyticsGeneralEventFinalize{ + XscAnalyticsBasicGeneralEvent: xscservices.XscAnalyticsBasicGeneralEvent{TotalFindings: 1, EventStatus: xscservices.Failed}, + }, }, { - name: "Scan failed with findings.", - auditResults: getDummyContentForGeneralEvent(false, true), - expected: xscservices.XscAnalyticsBasicGeneralEvent{TotalFindings: 1, EventStatus: xscservices.Failed}, + name: "Valid audit results with Watches and GitRepoUrl", + auditResults: getDummyContentForGeneralEvent(false, false, true), + expected: xscservices.XscAnalyticsGeneralEventFinalize{ + XscAnalyticsBasicGeneralEvent: xscservices.XscAnalyticsBasicGeneralEvent{TotalFindings: 1, EventStatus: xscservices.Completed}, + GitRepoUrl: "github.com/my-user/my-repo.git", + }, }, { name: "Scan failed no findings.", auditResults: &results.SecurityCommandResults{MultiScanId: "msi", StartTime: time, Targets: []*results.TargetResults{{Errors: []error{errors.New("an error")}}}}, - expected: xscservices.XscAnalyticsBasicGeneralEvent{TotalFindings: 0, EventStatus: xscservices.Failed}, + expected: xscservices.XscAnalyticsGeneralEventFinalize{ + XscAnalyticsBasicGeneralEvent: xscservices.XscAnalyticsBasicGeneralEvent{TotalFindings: 0, EventStatus: xscservices.Failed}, + }, }, } @@ -174,6 +190,7 @@ func TestCreateFinalizedEvent(t *testing.T) { event := createFinalizedEvent(testCase.auditResults) assert.Equal(t, testCase.expected.TotalFindings, event.TotalFindings) assert.Equal(t, testCase.expected.EventStatus, event.EventStatus) + assert.Equal(t, testCase.expected.GitRepoUrl, event.GitRepoUrl) assert.Equal(t, testCase.auditResults.MultiScanId, event.MultiScanId) assert.NotEmpty(t, event.TotalScanDuration) }) @@ -183,7 +200,7 @@ func TestCreateFinalizedEvent(t *testing.T) { // Create a dummy content for general event. 1 SCA scan with 1 vulnerability // withJas - Add 2 JAS results for each scan type. // withErr - Add an error to the results. -func getDummyContentForGeneralEvent(withJas, withErr bool) *results.SecurityCommandResults { +func getDummyContentForGeneralEvent(withJas, withErr, withResultContext bool) *results.SecurityCommandResults { vulnerabilities := []services.Vulnerability{{IssueId: "XRAY-ID", Severity: "medium", Cves: []services.Cve{{Id: "CVE-123"}}, Components: map[string]services.Component{"issueId_2_direct_dependency": {}}}} cmdResults := results.NewCommandResults(utils.SourceCode).SetEntitledForJas(true).SetSecretValidation(true) @@ -213,5 +230,11 @@ func getDummyContentForGeneralEvent(withJas, withErr bool) *results.SecurityComm scanResults.Errors = []error{errors.New("an error")} } + if withResultContext { + cmdResults.SetResultsContext(results.ResultContext{ + GitRepoHttpsCloneUrl: "https://github.com/my-user/my-repo", + }) + } + return cmdResults } diff --git a/xsc_test.go b/xsc_test.go index 740afc15..1f19fe9c 100644 --- a/xsc_test.go +++ b/xsc_test.go @@ -209,7 +209,7 @@ func getAuditCommandWithXscGitContext(gitInfoContext xscservices.XscGitInfoConte auditCmd.SetGitRepoHttpsCloneUrl(gitInfoContext.GitRepoHttpsCloneUrl) err = progressbar.ExecWithProgress(auditCmd) // Send the final event to the platform. - xsc.SendScanEndedEvent(xrayVersion, xscVersion, serverDetails, multiScanId, startTime, 0, err) + xsc.SendScanEndedEvent(xrayVersion, xscVersion, serverDetails, multiScanId, startTime, 0, nil, err) return err }, }