Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding new fields to analytics finalize event report #284

Open
wants to merge 11 commits into
base: dev
Choose a base branch
from
2 changes: 1 addition & 1 deletion commands/audit/audit.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()...,
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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/eranturgeman/jfrog-client-go v0.0.0-20250112092141-9aa3d0a6016e

// replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 dev

Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcej
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/eranturgeman/jfrog-client-go v0.0.0-20250112092141-9aa3d0a6016e h1:spRZuyinFDk2vjlmajTNvnhj827/wcJuXc7mquRQ8bQ=
github.com/eranturgeman/jfrog-client-go v0.0.0-20250112092141-9aa3d0a6016e/go.mod h1:ohIfKpMBCQsE9kunrKQ1wvoExpqsPLaluRFO186B5EM=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/forPelevin/gomoji v1.2.0 h1:9k4WVSSkE1ARO/BWywxgEUBvR/jMnao6EZzrql5nxJ8=
Expand Down Expand Up @@ -129,8 +131,6 @@ 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/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=
Expand Down
9 changes: 0 additions & 9 deletions jas/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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 != "" {
Expand Down
9 changes: 9 additions & 0 deletions utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
}
17 changes: 13 additions & 4 deletions utils/xsc/analyticsmetrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package xsc

import (
"fmt"
"github.com/jfrog/jfrog-cli-security/utils"
"strings"
"time"

Expand Down Expand Up @@ -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
}
Expand All @@ -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()))
Expand All @@ -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,
Expand All @@ -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) {
Expand Down
41 changes: 32 additions & 9 deletions utils/xsc/analyticsmetrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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},
},
},
}

Expand All @@ -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)
})
Expand All @@ -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)
Expand Down Expand Up @@ -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
}
2 changes: 1 addition & 1 deletion xsc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
},
}
Expand Down
Loading