From 12dbe00bab56822f6d3a94536d3d8f79d837a8f4 Mon Sep 17 00:00:00 2001 From: gail Date: Sun, 24 Mar 2024 17:07:40 +0200 Subject: [PATCH 01/32] Add Xsc General Event --- cli/scancommands.go | 5 ++ commands/audit/audit.go | 26 +++++++--- utils/analyticsmetrics.go | 87 ++++++++++++++++++++++++++++++++++ utils/analyticsmetrics_test.go | 46 ++++++++++++++++++ 4 files changed, 157 insertions(+), 7 deletions(-) create mode 100644 utils/analyticsmetrics.go create mode 100644 utils/analyticsmetrics_test.go diff --git a/cli/scancommands.go b/cli/scancommands.go index ebc6aee6..16f17905 100644 --- a/cli/scancommands.go +++ b/cli/scancommands.go @@ -349,6 +349,11 @@ func createAuditCmd(c *components.Context) (*audit.AuditCommand, error) { if err != nil { return nil, err } + analytics, err := utils.NewAnalyticsMetricsService(serverDetails) + if err != nil { + return nil, err + } + auditCmd.SetAnalyticsMetricsService(analytics) auditCmd.SetTargetRepoPath(addTrailingSlashToRepoPathIfNeeded(c)). SetProject(c.GetStringFlagValue(flags.Project)). SetIncludeVulnerabilities(shouldIncludeVulnerabilities(c)). diff --git a/commands/audit/audit.go b/commands/audit/audit.go index 4d57bd26..66978c5c 100644 --- a/commands/audit/audit.go +++ b/commands/audit/audit.go @@ -17,13 +17,14 @@ import ( ) type AuditCommand struct { - watches []string - projectKey string - targetRepoPath string - IncludeVulnerabilities bool - IncludeLicenses bool - Fail bool - PrintExtendedTable bool + watches []string + projectKey string + targetRepoPath string + IncludeVulnerabilities bool + IncludeLicenses bool + Fail bool + PrintExtendedTable bool + analyticsMetricsService *xrayutils.AnalyticsMetricsService AuditParams } @@ -66,6 +67,11 @@ func (auditCmd *AuditCommand) SetPrintExtendedTable(printExtendedTable bool) *Au return auditCmd } +func (auditCmd *AuditCommand) SetAnalyticsMetricsService(analyticsMetricsService *xrayutils.AnalyticsMetricsService) *AuditCommand { + auditCmd.analyticsMetricsService = analyticsMetricsService + return auditCmd +} + func (auditCmd *AuditCommand) CreateXrayGraphScanParams() *services.XrayGraphScanParams { params := &services.XrayGraphScanParams{ RepoPath: auditCmd.targetRepoPath, @@ -98,6 +104,12 @@ func (auditCmd *AuditCommand) Run() (err error) { SetGraphBasicParams(auditCmd.AuditBasicParams). SetThirdPartyApplicabilityScan(auditCmd.thirdPartyApplicabilityScan) auditParams.SetIsRecursiveScan(isRecursiveScan).SetExclusions(auditCmd.Exclusions()) + + err = auditCmd.analyticsMetricsService.SendNewGeneralEventRequestToXsc() + if err != nil { + return + } + auditResults, err := RunAudit(auditParams) if err != nil { return diff --git a/utils/analyticsmetrics.go b/utils/analyticsmetrics.go new file mode 100644 index 00000000..ee80c5b6 --- /dev/null +++ b/utils/analyticsmetrics.go @@ -0,0 +1,87 @@ +package utils + +import ( + "github.com/jfrog/jfrog-cli-core/v2/utils/config" + clientutils "github.com/jfrog/jfrog-client-go/utils" + "github.com/jfrog/jfrog-client-go/utils/log" + "github.com/jfrog/jfrog-client-go/xsc" + xscservices "github.com/jfrog/jfrog-client-go/xsc/services" + "os" +) + +// TODO VERIFY VERSION +const AnalyticsMetricsMinXscVersion = "1.7.0" + +type AnalyticsMetricsService struct { + xscManager *xsc.XscServicesManager + // Should the CLI reports analytics metrics to XSC. + shouldReportEvents bool + msi string +} + +func NewAnalyticsMetricsService(serviceDetails *config.ServerDetails) (*AnalyticsMetricsService, error) { + ams := AnalyticsMetricsService{} + xscManager, err := CreateXscServiceManager(serviceDetails) + if err != nil { + return nil, err + } + ams.xscManager = xscManager + ams.shouldReportEvents = ams.calcShouldReportEvents() + return &ams, nil +} + +func (ams *AnalyticsMetricsService) calcShouldReportEvents() bool { + // A user who explicitly requests not to send reports will not receive XSC analytics metrics. + if os.Getenv("JFROG_CLI_REPORT_USAGE") == "false" { + return false + } + // There is no need to report the event and generate a new msi for the cli scan if the msi was provided. + if os.Getenv("JF_MSI") != "" { + return false + } + // Verify xsc version. + xscVersion, err := ams.xscManager.GetVersion() + if err != nil { + return false + } + if err = clientutils.ValidateMinimumVersion(clientutils.Xsc, xscVersion, AnalyticsMetricsMinXscVersion); err != nil { + return false + } + return true +} + +func (ams *AnalyticsMetricsService) SetMsi(msi string) { + ams.msi = msi +} + +func (ams *AnalyticsMetricsService) GetMsi() string { + return ams.msi +} + +func (ams *AnalyticsMetricsService) ShouldReportEvents() bool { + return ams.shouldReportEvents +} + +func (ams *AnalyticsMetricsService) SendNewGeneralEventRequestToXsc() error { + if !ams.ShouldReportEvents() { + log.Info("A general event request was not sent to XSC - analytics metrics are disabled.") + return nil + } + event := xscservices.XscGeneralEvent{ + EventType: 0, // ? + EventStatus: "started", + Product: "cli", + ProductVersion: "2.53.1", // add cli version call + IsDefaultConfig: false, // what is this? + JfrogUser: "gail", // add cli user + OsPlatform: "mac", // add + OsArchitecture: "arm", // add + MachineId: "", //? + AnalyzerManagerVersion: "1.1.1", //add + JpdVersion: "1.5", //?, + } + + msi, err := ams.xscManager.PostEvent(event) + ams.SetMsi(msi) + return err +} diff --git a/utils/analyticsmetrics_test.go b/utils/analyticsmetrics_test.go new file mode 100644 index 00000000..b1b0db0b --- /dev/null +++ b/utils/analyticsmetrics_test.go @@ -0,0 +1,46 @@ +package utils + +import ( + "github.com/jfrog/jfrog-cli-security/tests" + "github.com/stretchr/testify/assert" + "os" + "testing" +) + +func TestCalcShouldReportEvents(t *testing.T) { + // Save original environment information. + originalJfMsi := os.Getenv("JF_MSI") + defer func() { + err := os.Setenv("JF_MSI", originalJfMsi) + assert.NoError(t, err) + }() + originalReportUsage := os.Getenv("JFROG_CLI_REPORT_USAGE") + defer func() { + err := os.Setenv("JFROG_CLI_REPORT_USAGE", originalReportUsage) + assert.NoError(t, err) + }() + + // Msi was already provided. + err := os.Setenv("JF_MSI", "msi") + assert.NoError(t, err) + am := AnalyticsMetricsService{} + assert.False(t, am.calcShouldReportEvents()) + + // Report usage is false. + err = os.Setenv("JF_MSI", "") + assert.NoError(t, err) + err = os.Setenv("JFROG_CLI_REPORT_USAGE", "false") + assert.NoError(t, err) + assert.False(t, am.calcShouldReportEvents()) + + //TODO add version verification- i want to create mock and test it in unit test and not with specific env and version +} + +func TestSendNewGeneralEventRequestToXsc(t *testing.T) { + // TODO i need to wirk with a real env although its not full integration test + am, err := NewAnalyticsMetricsService(tests.XscDetails) + assert.NoError(t, err) + err = am.SendNewGeneralEventRequestToXsc() + assert.NoError(t, err) + assert.NotEmpty(t, am.GetMsi()) +} From cbc4fcdd070a6f28aa6fc724658ac200883060ed Mon Sep 17 00:00:00 2001 From: gail Date: Tue, 26 Mar 2024 10:44:30 +0200 Subject: [PATCH 02/32] Add Xsc General Event --- .../jas/applicability/applicabilitymanager.go | 4 +++ commands/audit/jas/common.go | 31 +++++++++++++++++ go.mod | 4 +-- go.sum | 4 --- jfrogclisecurity_test.go | 1 + tests/config.go | 5 +-- tests/consts.go | 1 + utils/analyticsmetrics.go | 33 ++++++++++++------- utils/analyticsmetrics_test.go | 5 ++- utils/xscmanager.go | 21 ++++++++++++ 10 files changed, 89 insertions(+), 20 deletions(-) create mode 100644 utils/xscmanager.go diff --git a/commands/audit/jas/applicability/applicabilitymanager.go b/commands/audit/jas/applicability/applicabilitymanager.go index a727f1fd..f2681575 100644 --- a/commands/audit/jas/applicability/applicabilitymanager.go +++ b/commands/audit/jas/applicability/applicabilitymanager.go @@ -47,6 +47,10 @@ func RunApplicabilityScan(xrayResults []services.ScanResponse, directDependencie log.Debug("The technologies that have been scanned are currently not supported for contextual analysis scanning, or we couldn't find any vulnerable dependencies. Skipping....") return } + err = jas.SetAnalyticsMetricsDataForAnalyzerManager(scannedTechnologies) + if err != nil { + return + } if err = applicabilityScanManager.scanner.Run(applicabilityScanManager); err != nil { err = utils.ParseAnalyzerManagerError(utils.Applicability, err) return diff --git a/commands/audit/jas/common.go b/commands/audit/jas/common.go index 55e2fdc4..20ed690c 100644 --- a/commands/audit/jas/common.go +++ b/commands/audit/jas/common.go @@ -274,3 +274,34 @@ func GetExcludePatterns(module jfrogappsconfig.Module, scanner *jfrogappsconfig. } return excludePatterns } + +func SetAnalyticsMetricsDataForAnalyzerManager(packageManagers []coreutils.Technology) error { + // For now only one value is supported. + if len(packageManagers) != 1 { + return nil + } + pm := packageManagers[0].String() + err := os.Setenv("AM_PACKAGE_MANAGER", pm) + if err != nil { + return err + } + // Version is not supported yet. + err = os.Setenv("AM_PACKAGE_MANAGER_VERSION", "") + if err != nil { + return err + } + // TODO add language + return os.Setenv("AM_LANGUAGE", "") +} + +func ResetAnalyticsMetricsDataForAnalyzerManager(packageManager, packageManagerVersion, language string) error { + err := os.Setenv("AM_PACKAGE_MANAGER", "") + if err != nil { + return err + } + err = os.Setenv("AM_PACKAGE_MANAGER_VERSION", "") + if err != nil { + return err + } + return os.Setenv("AM_LANGUAGE", "") +} diff --git a/go.mod b/go.mod index 3d3f3aea..1e4a9281 100644 --- a/go.mod +++ b/go.mod @@ -98,8 +98,8 @@ require ( gopkg.in/warnings.v0 v0.1.2 // indirect ) -// replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 dev +replace github.com/jfrog/jfrog-cli-core/v2 => ../jfrog-cli-core -// replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go dev +replace github.com/jfrog/jfrog-client-go => ../jfrog-client-go // replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go dev diff --git a/go.sum b/go.sum index 2b33c09c..cb2abefd 100644 --- a/go.sum +++ b/go.sum @@ -102,10 +102,6 @@ github.com/jfrog/gofrog v1.6.3 h1:F7He0+75HcgCe6SGTSHLFCBDxiE2Ja0tekvvcktW6wc= github.com/jfrog/gofrog v1.6.3/go.mod h1:SZ1EPJUruxrVGndOzHd+LTiwWYKMlHqhKD+eu+v5Hqg= github.com/jfrog/jfrog-apps-config v1.0.1 h1:mtv6k7g8A8BVhlHGlSveapqf4mJfonwvXYLipdsOFMY= github.com/jfrog/jfrog-apps-config v1.0.1/go.mod h1:8AIIr1oY9JuH5dylz2S6f8Ym2MaadPLR6noCBO4C22w= -github.com/jfrog/jfrog-cli-core/v2 v2.49.0 h1:HhhwmenyAzRNXUY4KNHKmRH9fcaohCzvcWfzLx/Lt5M= -github.com/jfrog/jfrog-cli-core/v2 v2.49.0/go.mod h1:t7SigeX0Fbzsv0RIDGKkYnNQrwgf2cqIfoASoo5qZ2A= -github.com/jfrog/jfrog-client-go v1.38.0 h1:0QP4/dSmJe0oYUrAqzoPDpGdJHcrOeq9mycnb0pSxqQ= -github.com/jfrog/jfrog-client-go v1.38.0/go.mod h1:EHRLxpu0pIT7+ulYDNQ7IeieYBHMQeEPr8CoBHoJzQY= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= diff --git a/jfrogclisecurity_test.go b/jfrogclisecurity_test.go index 3af50790..94253546 100644 --- a/jfrogclisecurity_test.go +++ b/jfrogclisecurity_test.go @@ -40,6 +40,7 @@ func setupIntegrationTests() { // Init utils.InitTestCliDetails() utils.AuthenticateArtifactory() + utils.AuthenticateXsc() utils.CreateRequiredRepositories() } diff --git a/tests/config.go b/tests/config.go index 9fe0641e..5a38b544 100644 --- a/tests/config.go +++ b/tests/config.go @@ -13,8 +13,9 @@ import ( // Integration tests - global variables var ( - XrDetails *config.ServerDetails - XrAuth auth.ServiceDetails + XrDetails *config.ServerDetails + XscDetails *config.ServerDetails + XrAuth auth.ServiceDetails RtDetails *config.ServerDetails RtAuth auth.ServiceDetails diff --git a/tests/consts.go b/tests/consts.go index 2b39678b..6e6f9f8e 100644 --- a/tests/consts.go +++ b/tests/consts.go @@ -16,6 +16,7 @@ const ( const ( XrayEndpoint = "xray/" + XscEndpoint = "xsc/" ArtifactoryEndpoint = "artifactory/" AccessEndpoint = "access/" RepoDetailsEndpoint = "api/repositories/" diff --git a/utils/analyticsmetrics.go b/utils/analyticsmetrics.go index ee80c5b6..267c141a 100644 --- a/utils/analyticsmetrics.go +++ b/utils/analyticsmetrics.go @@ -2,11 +2,13 @@ package utils import ( "github.com/jfrog/jfrog-cli-core/v2/utils/config" + "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" clientutils "github.com/jfrog/jfrog-client-go/utils" "github.com/jfrog/jfrog-client-go/utils/log" "github.com/jfrog/jfrog-client-go/xsc" xscservices "github.com/jfrog/jfrog-client-go/xsc/services" "os" + "strings" ) // TODO VERIFY VERSION @@ -67,21 +69,30 @@ func (ams *AnalyticsMetricsService) SendNewGeneralEventRequestToXsc() error { log.Info("A general event request was not sent to XSC - analytics metrics are disabled.") return nil } + osAndArc, err := coreutils.GetOSAndArc() + if err != nil { + return err + } + splitOsAndArch := strings.Split(osAndArc, "-") event := xscservices.XscGeneralEvent{ - EventType: 0, // ? + EventType: 1, EventStatus: "started", Product: "cli", - ProductVersion: "2.53.1", // add cli version call - IsDefaultConfig: false, // what is this? - JfrogUser: "gail", // add cli user - OsPlatform: "mac", // add - OsArchitecture: "arm", // add - MachineId: "", //? - AnalyzerManagerVersion: "1.1.1", //add - JpdVersion: "1.5", //?, + ProductVersion: "", // can't have it + IsDefaultConfig: false, // orz will implement it + JfrogUser: ams.xscManager.Config().GetServiceDetails().GetUser(), + OsPlatform: splitOsAndArch[0], + OsArchitecture: splitOsAndArch[1], + MachineId: "", // TODO add + AnalyzerManagerVersion: GetAnalyzerManagerVersion(), + JpdVersion: "", //TODO artifactory version, } - msi, err := ams.xscManager.PostEvent(event) + msi, err := ams.xscManager.PostEvent(xscservices.XscAddGeneralEventRequest{XscGeneralEvent: event}) + if err != nil { + return err + } ams.SetMsi(msi) - return err + // Set environment variable for analyzer manager analytics. + return os.Setenv("JF_MSI", msi) } diff --git a/utils/analyticsmetrics_test.go b/utils/analyticsmetrics_test.go index b1b0db0b..e6771e4b 100644 --- a/utils/analyticsmetrics_test.go +++ b/utils/analyticsmetrics_test.go @@ -2,6 +2,7 @@ package utils import ( "github.com/jfrog/jfrog-cli-security/tests" + "github.com/jfrog/jfrog-client-go/artifactory/services/utils/tests/xsc" "github.com/stretchr/testify/assert" "os" "testing" @@ -37,7 +38,9 @@ func TestCalcShouldReportEvents(t *testing.T) { } func TestSendNewGeneralEventRequestToXsc(t *testing.T) { - // TODO i need to wirk with a real env although its not full integration test + // TODO i need to work with a real env although its not full integration test + // TODO this is clients tests mocks + xsc.StartXscMockServer(t) am, err := NewAnalyticsMetricsService(tests.XscDetails) assert.NoError(t, err) err = am.SendNewGeneralEventRequestToXsc() diff --git a/utils/xscmanager.go b/utils/xscmanager.go new file mode 100644 index 00000000..5eb5edf7 --- /dev/null +++ b/utils/xscmanager.go @@ -0,0 +1,21 @@ +package utils + +import ( + "github.com/jfrog/jfrog-cli-core/v2/utils/config" + clientconfig "github.com/jfrog/jfrog-client-go/config" + "github.com/jfrog/jfrog-client-go/xsc" +) + +func CreateXscServiceManager(serviceDetails *config.ServerDetails) (*xsc.XscServicesManager, error) { + xscDetails, err := serviceDetails.CreateXscAuthConfig() + if err != nil { + return nil, err + } + serviceConfig, err := clientconfig.NewConfigBuilder(). + SetServiceDetails(xscDetails). + Build() + if err != nil { + return nil, err + } + return xsc.New(serviceConfig) +} From 1951727aff04578015c7f19316258fb62336fcd9 Mon Sep 17 00:00:00 2001 From: gail Date: Tue, 26 Mar 2024 14:44:41 +0200 Subject: [PATCH 03/32] Before review fixes. --- commands/audit/audit.go | 2 +- commands/audit/jas/applicability/applicabilitymanager.go | 1 + utils/analyticsmetrics.go | 8 ++++---- utils/analyticsmetrics_test.go | 4 ++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/commands/audit/audit.go b/commands/audit/audit.go index 66978c5c..7093566d 100644 --- a/commands/audit/audit.go +++ b/commands/audit/audit.go @@ -105,7 +105,7 @@ func (auditCmd *AuditCommand) Run() (err error) { SetThirdPartyApplicabilityScan(auditCmd.thirdPartyApplicabilityScan) auditParams.SetIsRecursiveScan(isRecursiveScan).SetExclusions(auditCmd.Exclusions()) - err = auditCmd.analyticsMetricsService.SendNewGeneralEventRequestToXsc() + err = auditCmd.analyticsMetricsService.AddGeneralEvent() if err != nil { return } diff --git a/commands/audit/jas/applicability/applicabilitymanager.go b/commands/audit/jas/applicability/applicabilitymanager.go index f2681575..7655f4cf 100644 --- a/commands/audit/jas/applicability/applicabilitymanager.go +++ b/commands/audit/jas/applicability/applicabilitymanager.go @@ -47,6 +47,7 @@ func RunApplicabilityScan(xrayResults []services.ScanResponse, directDependencie log.Debug("The technologies that have been scanned are currently not supported for contextual analysis scanning, or we couldn't find any vulnerable dependencies. Skipping....") return } + // TODO: for now handled only CA, needs to do rest of scan types. err = jas.SetAnalyticsMetricsDataForAnalyzerManager(scannedTechnologies) if err != nil { return diff --git a/utils/analyticsmetrics.go b/utils/analyticsmetrics.go index 267c141a..6165e42b 100644 --- a/utils/analyticsmetrics.go +++ b/utils/analyticsmetrics.go @@ -64,7 +64,7 @@ func (ams *AnalyticsMetricsService) ShouldReportEvents() bool { return ams.shouldReportEvents } -func (ams *AnalyticsMetricsService) SendNewGeneralEventRequestToXsc() error { +func (ams *AnalyticsMetricsService) AddGeneralEvent() error { if !ams.ShouldReportEvents() { log.Info("A general event request was not sent to XSC - analytics metrics are disabled.") return nil @@ -74,11 +74,11 @@ func (ams *AnalyticsMetricsService) SendNewGeneralEventRequestToXsc() error { return err } splitOsAndArch := strings.Split(osAndArc, "-") - event := xscservices.XscGeneralEvent{ + event := xscservices.XscAnalyticsBasicGeneralEvent{ EventType: 1, EventStatus: "started", Product: "cli", - ProductVersion: "", // can't have it + ProductVersion: "", // can't have it for now IsDefaultConfig: false, // orz will implement it JfrogUser: ams.xscManager.Config().GetServiceDetails().GetUser(), OsPlatform: splitOsAndArch[0], @@ -88,7 +88,7 @@ func (ams *AnalyticsMetricsService) SendNewGeneralEventRequestToXsc() error { JpdVersion: "", //TODO artifactory version, } - msi, err := ams.xscManager.PostEvent(xscservices.XscAddGeneralEventRequest{XscGeneralEvent: event}) + msi, err := ams.xscManager.AddAnalyticsGeneralEvent(xscservices.XscAnalyticsGeneralEvent{XscAnalyticsBasicGeneralEvent: event}) if err != nil { return err } diff --git a/utils/analyticsmetrics_test.go b/utils/analyticsmetrics_test.go index e6771e4b..ebadcb00 100644 --- a/utils/analyticsmetrics_test.go +++ b/utils/analyticsmetrics_test.go @@ -39,11 +39,11 @@ func TestCalcShouldReportEvents(t *testing.T) { func TestSendNewGeneralEventRequestToXsc(t *testing.T) { // TODO i need to work with a real env although its not full integration test - // TODO this is clients tests mocks + // TODO this are clients tests mocks xsc.StartXscMockServer(t) am, err := NewAnalyticsMetricsService(tests.XscDetails) assert.NoError(t, err) - err = am.SendNewGeneralEventRequestToXsc() + err = am.AddGeneralEvent() assert.NoError(t, err) assert.NotEmpty(t, am.GetMsi()) } From c834ad14e8489ca16eb6b605fc62b7a4f26bd40a Mon Sep 17 00:00:00 2001 From: gail Date: Wed, 27 Mar 2024 12:30:07 +0200 Subject: [PATCH 04/32] Add UpdateGeneralEvent. --- commands/audit/audit.go | 18 ++++++------- commands/scan/scan.go | 5 ---- utils/analyticsmetrics.go | 57 ++++++++++++++++++++++++++++++++++++--- utils/xraymanager.go | 26 ------------------ 4 files changed, 62 insertions(+), 44 deletions(-) diff --git a/commands/audit/audit.go b/commands/audit/audit.go index 7093566d..cd36ca69 100644 --- a/commands/audit/audit.go +++ b/commands/audit/audit.go @@ -2,16 +2,15 @@ package audit import ( "errors" - "github.com/jfrog/jfrog-cli-security/scangraph" - "os" - "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" + "github.com/jfrog/jfrog-cli-security/scangraph" "github.com/jfrog/jfrog-cli-security/utils" clientutils "github.com/jfrog/jfrog-client-go/utils" "github.com/jfrog/jfrog-client-go/utils/log" "github.com/jfrog/jfrog-client-go/xray" "github.com/jfrog/jfrog-client-go/xray/services" "golang.org/x/sync/errgroup" + "os" xrayutils "github.com/jfrog/jfrog-cli-security/utils" ) @@ -105,12 +104,16 @@ func (auditCmd *AuditCommand) Run() (err error) { SetThirdPartyApplicabilityScan(auditCmd.thirdPartyApplicabilityScan) auditParams.SetIsRecursiveScan(isRecursiveScan).SetExclusions(auditCmd.Exclusions()) - err = auditCmd.analyticsMetricsService.AddGeneralEvent() + err = auditCmd.analyticsMetricsService.AddGeneralEventAndSetMsi(auditParams.xrayGraphScanParams) if err != nil { return } - auditResults, err := RunAudit(auditParams) + // TODO should report back? + if err != nil { + return + } + err = auditCmd.analyticsMetricsService.UpdateGeneralEvent(auditResults) if err != nil { return } @@ -183,10 +186,7 @@ func RunAudit(auditParams *AuditParams) (results *xrayutils.Results, err error) errGroup.Go(utils.DownloadAnalyzerManagerIfNeeded) } - if auditParams.xrayGraphScanParams.XscGitInfoContext != nil { - if err = xrayutils.SendXscGitInfoRequestIfEnabled(auditParams.xrayGraphScanParams, xrayManager); err != nil { - return nil, err - } + if auditParams.xrayGraphScanParams.MultiScanId != "" { results.MultiScanId = auditParams.xrayGraphScanParams.MultiScanId } diff --git a/commands/scan/scan.go b/commands/scan/scan.go index b21e2ea5..c8035d84 100644 --- a/commands/scan/scan.go +++ b/commands/scan/scan.go @@ -349,11 +349,6 @@ func (scanCmd *ScanCommand) createIndexerHandlerFunc(file *spec.File, indexedFil if err != nil { return err } - if params.XscGitInfoContext != nil { - if err = utils.SendXscGitInfoRequestIfEnabled(scanGraphParams.XrayGraphScanParams(), xrayManager); err != nil { - return err - } - } scanResults, err := scangraph.RunScanGraphAndGetResults(scanGraphParams, xrayManager) if err != nil { log.Error(fmt.Sprintf("scanning '%s' failed with error: %s", graph.Id, err.Error())) diff --git a/utils/analyticsmetrics.go b/utils/analyticsmetrics.go index 6165e42b..7547db8b 100644 --- a/utils/analyticsmetrics.go +++ b/utils/analyticsmetrics.go @@ -1,14 +1,17 @@ package utils import ( + "fmt" "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" clientutils "github.com/jfrog/jfrog-client-go/utils" "github.com/jfrog/jfrog-client-go/utils/log" + "github.com/jfrog/jfrog-client-go/xray/services" "github.com/jfrog/jfrog-client-go/xsc" xscservices "github.com/jfrog/jfrog-client-go/xsc/services" "os" "strings" + "time" ) // TODO VERIFY VERSION @@ -19,6 +22,7 @@ type AnalyticsMetricsService struct { // Should the CLI reports analytics metrics to XSC. shouldReportEvents bool msi string + startTime time.Time } func NewAnalyticsMetricsService(serviceDetails *config.ServerDetails) (*AnalyticsMetricsService, error) { @@ -60,15 +64,38 @@ func (ams *AnalyticsMetricsService) GetMsi() string { return ams.msi } +func (ams *AnalyticsMetricsService) SetStartTime() { + ams.startTime = time.Now() +} + +func (ams *AnalyticsMetricsService) GetStartTime() time.Time { + return ams.startTime +} + func (ams *AnalyticsMetricsService) ShouldReportEvents() bool { return ams.shouldReportEvents } -func (ams *AnalyticsMetricsService) AddGeneralEvent() error { +func (ams *AnalyticsMetricsService) AddGeneralEventAndSetMsi(params *services.XrayGraphScanParams) error { if !ams.ShouldReportEvents() { log.Info("A general event request was not sent to XSC - analytics metrics are disabled.") return nil } + err := ams.AddGeneralEvent() + if err != nil { + return fmt.Errorf("failed sending general event request to XSC service, error: %s ", err.Error()) + } + log.Debug(fmt.Sprintf("New General event added successfully. multi_scan_id %s", ams.GetMsi())) + + if err = os.Setenv("JF_MSI", ams.GetMsi()); err != nil { + // Not a fatal error, if not set the scan will not be shown at the XSC UI, should not fail the scan. + log.Debug(fmt.Sprintf("failed setting MSI as environment variable. Cause: %s", err.Error())) + } + // Before running the audit command, set the msi so the sca scan will be performed on the xsc rather than on the xray server. + params.MultiScanId = ams.GetMsi() + return nil +} +func (ams *AnalyticsMetricsService) AddGeneralEvent() error { osAndArc, err := coreutils.GetOSAndArc() if err != nil { return err @@ -76,7 +103,7 @@ func (ams *AnalyticsMetricsService) AddGeneralEvent() error { splitOsAndArch := strings.Split(osAndArc, "-") event := xscservices.XscAnalyticsBasicGeneralEvent{ EventType: 1, - EventStatus: "started", + EventStatus: xscservices.Started, Product: "cli", ProductVersion: "", // can't have it for now IsDefaultConfig: false, // orz will implement it @@ -92,7 +119,29 @@ func (ams *AnalyticsMetricsService) AddGeneralEvent() error { if err != nil { return err } + // Set event's analytics data. ams.SetMsi(msi) - // Set environment variable for analyzer manager analytics. - return os.Setenv("JF_MSI", msi) + ams.SetStartTime() + return nil +} + +func (ams *AnalyticsMetricsService) UpdateGeneralEvent(auditResults *Results) error { + if !ams.ShouldReportEvents() { + log.Info("A general event update request was not sent to XSC - analytics metrics are disabled.") + return nil + } + totalDuration := time.Now().Sub(ams.GetStartTime()) + totalFindings := len(auditResults.ScaResults) + len(auditResults.ExtendedScanResults.ApplicabilityScanResults) + len(auditResults.ExtendedScanResults.SecretsScanResults) + len(auditResults.ExtendedScanResults.IacScanResults) + len(auditResults.ExtendedScanResults.SastScanResults) + eventStatus := xscservices.Completed + if auditResults.ScaError != nil || auditResults.JasError != nil { + eventStatus = xscservices.Failed + } + event := xscservices.XscAnalyticsGeneralEventFinalize{MultiScanId: ams.msi} + event.XscAnalyticsBasicGeneralEvent = xscservices.XscAnalyticsBasicGeneralEvent{ + EventStatus: eventStatus, + TotalFindings: totalFindings, + TotalIgnoredFindings: 0, + TotalScanDuration: totalDuration.String(), + } + return ams.xscManager.UpdateAnalyticsGeneralEvent(event) } diff --git a/utils/xraymanager.go b/utils/xraymanager.go index 62aa5b92..eb7446a2 100644 --- a/utils/xraymanager.go +++ b/utils/xraymanager.go @@ -1,13 +1,9 @@ package utils import ( - "fmt" "github.com/jfrog/jfrog-cli-core/v2/utils/config" clientconfig "github.com/jfrog/jfrog-client-go/config" - "github.com/jfrog/jfrog-client-go/utils/log" "github.com/jfrog/jfrog-client-go/xray" - "github.com/jfrog/jfrog-client-go/xray/services" - "os" ) func CreateXrayServiceManager(serviceDetails *config.ServerDetails) (*xray.XrayServicesManager, error) { @@ -35,25 +31,3 @@ func CreateXrayServiceManagerAndGetVersion(serviceDetails *config.ServerDetails) } return xrayManager, xrayVersion, nil } - -func SendXscGitInfoRequestIfEnabled(graphScanParams *services.XrayGraphScanParams, xrayManager *xray.XrayServicesManager) (err error) { - if graphScanParams.XscVersion, err = xrayManager.XscEnabled(); err != nil { - return err - } - if graphScanParams.XscVersion == "" || graphScanParams.MultiScanId != "" { - // XSC is not enabled or multiScanId already provided. - return - } - // Generate multiScanId and set it to the scan params. - multiScanId, err := xrayManager.SendXscGitInfoRequest(graphScanParams.XscGitInfoContext) - if err != nil { - return fmt.Errorf("failed sending Git Info request to XSC service, error: %s ", err.Error()) - } - graphScanParams.MultiScanId = multiScanId - log.Debug(fmt.Sprintf("Created xsc git info successfully. multi_scan_id %s", multiScanId)) - if err = os.Setenv("JF_MSI", multiScanId); err != nil { - // Not a fatal error, if not set the scan will not be shown at the XSC UI, should not fail the scan. - log.Debug(fmt.Sprintf("failed setting MSI as environment variable. Cause: %s", err.Error())) - } - return nil -} From f9c9c0eb29e852332003e061aff2f5df779b8de3 Mon Sep 17 00:00:00 2001 From: gail Date: Wed, 27 Mar 2024 13:54:22 +0200 Subject: [PATCH 05/32] Set environments variables for analyzer manager. --- .../jas/applicability/applicabilitymanager.go | 2 -- commands/audit/jas/common.go | 22 +++++-------------- commands/audit/jasrunner.go | 8 +++++++ 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/commands/audit/jas/applicability/applicabilitymanager.go b/commands/audit/jas/applicability/applicabilitymanager.go index 7655f4cf..7eaefeb8 100644 --- a/commands/audit/jas/applicability/applicabilitymanager.go +++ b/commands/audit/jas/applicability/applicabilitymanager.go @@ -47,8 +47,6 @@ func RunApplicabilityScan(xrayResults []services.ScanResponse, directDependencie log.Debug("The technologies that have been scanned are currently not supported for contextual analysis scanning, or we couldn't find any vulnerable dependencies. Skipping....") return } - // TODO: for now handled only CA, needs to do rest of scan types. - err = jas.SetAnalyticsMetricsDataForAnalyzerManager(scannedTechnologies) if err != nil { return } diff --git a/commands/audit/jas/common.go b/commands/audit/jas/common.go index 20ed690c..32286636 100644 --- a/commands/audit/jas/common.go +++ b/commands/audit/jas/common.go @@ -275,33 +275,23 @@ func GetExcludePatterns(module jfrogappsconfig.Module, scanner *jfrogappsconfig. return excludePatterns } -func SetAnalyticsMetricsDataForAnalyzerManager(packageManagers []coreutils.Technology) error { +func SetAnalyticsMetricsDataForAnalyzerManager(technologies []coreutils.Technology) error { // For now only one value is supported. - if len(packageManagers) != 1 { + if len(technologies) != 1 { return nil } - pm := packageManagers[0].String() - err := os.Setenv("AM_PACKAGE_MANAGER", pm) + technology := technologies[0] + err := os.Setenv("AM_PACKAGE_MANAGER", technology.String()) if err != nil { return err } - // Version is not supported yet. - err = os.Setenv("AM_PACKAGE_MANAGER_VERSION", "") - if err != nil { - return err - } - // TODO add language - return os.Setenv("AM_LANGUAGE", "") + return os.Setenv("AM_LANGUAGE", coreutils.TechnologyToLanguage(technology)) } -func ResetAnalyticsMetricsDataForAnalyzerManager(packageManager, packageManagerVersion, language string) error { +func ResetAnalyticsMetricsDataForAnalyzerManager() error { err := os.Setenv("AM_PACKAGE_MANAGER", "") if err != nil { return err } - err = os.Setenv("AM_PACKAGE_MANAGER_VERSION", "") - if err != nil { - return err - } return os.Setenv("AM_LANGUAGE", "") } diff --git a/commands/audit/jasrunner.go b/commands/audit/jasrunner.go index 434d9044..800d3eb2 100644 --- a/commands/audit/jasrunner.go +++ b/commands/audit/jasrunner.go @@ -30,6 +30,14 @@ func runJasScannersAndSetResults(scanResults *utils.Results, directDependencies if progress != nil { progress.SetHeadlineMsg("Running applicability scanning") } + // Set environments variables for analytics in analyzers manager. + err = jas.SetAnalyticsMetricsDataForAnalyzerManager(scanResults.GetScaScannedTechnologies()) + if err != nil { + return + } + defer func() { + err = jas.ResetAnalyticsMetricsDataForAnalyzerManager() + }() scanResults.ExtendedScanResults.ApplicabilityScanResults, err = applicability.RunApplicabilityScan(scanResults.GetScaScansXrayResults(), directDependencies, scanResults.GetScaScannedTechnologies(), scanner, thirdPartyApplicabilityScan) if err != nil { return From a4f05342d79036a7ce4f7cc58d646c565ae6034f Mon Sep 17 00:00:00 2001 From: gail Date: Thu, 28 Mar 2024 16:14:35 +0200 Subject: [PATCH 06/32] Add tests. --- commands/audit/audit.go | 1 - .../jas/applicability/applicabilitymanager.go | 3 - utils/analyticsmetrics.go | 36 ++-- utils/analyticsmetrics_test.go | 168 +++++++++++++++--- 4 files changed, 168 insertions(+), 40 deletions(-) diff --git a/commands/audit/audit.go b/commands/audit/audit.go index cd36ca69..5f974c4e 100644 --- a/commands/audit/audit.go +++ b/commands/audit/audit.go @@ -109,7 +109,6 @@ func (auditCmd *AuditCommand) Run() (err error) { return } auditResults, err := RunAudit(auditParams) - // TODO should report back? if err != nil { return } diff --git a/commands/audit/jas/applicability/applicabilitymanager.go b/commands/audit/jas/applicability/applicabilitymanager.go index 7eaefeb8..a727f1fd 100644 --- a/commands/audit/jas/applicability/applicabilitymanager.go +++ b/commands/audit/jas/applicability/applicabilitymanager.go @@ -47,9 +47,6 @@ func RunApplicabilityScan(xrayResults []services.ScanResponse, directDependencie log.Debug("The technologies that have been scanned are currently not supported for contextual analysis scanning, or we couldn't find any vulnerable dependencies. Skipping....") return } - if err != nil { - return - } if err = applicabilityScanManager.scanner.Run(applicabilityScanManager); err != nil { err = utils.ParseAnalyzerManagerError(utils.Applicability, err) return diff --git a/utils/analyticsmetrics.go b/utils/analyticsmetrics.go index 7547db8b..f55ad1d7 100644 --- a/utils/analyticsmetrics.go +++ b/utils/analyticsmetrics.go @@ -14,8 +14,7 @@ import ( "time" ) -// TODO VERIFY VERSION -const AnalyticsMetricsMinXscVersion = "1.7.0" +const AnalyticsMetricsMinXscVersion = "1.7.1" type AnalyticsMetricsService struct { xscManager *xsc.XscServicesManager @@ -38,11 +37,11 @@ func NewAnalyticsMetricsService(serviceDetails *config.ServerDetails) (*Analytic func (ams *AnalyticsMetricsService) calcShouldReportEvents() bool { // A user who explicitly requests not to send reports will not receive XSC analytics metrics. - if os.Getenv("JFROG_CLI_REPORT_USAGE") == "false" { + if os.Getenv(coreutils.ReportUsage) == "false" { return false } // There is no need to report the event and generate a new msi for the cli scan if the msi was provided. - if os.Getenv("JF_MSI") != "" { + if os.Getenv(jfMsiEnvVariable) != "" { return false } // Verify xsc version. @@ -87,7 +86,7 @@ func (ams *AnalyticsMetricsService) AddGeneralEventAndSetMsi(params *services.Xr } log.Debug(fmt.Sprintf("New General event added successfully. multi_scan_id %s", ams.GetMsi())) - if err = os.Setenv("JF_MSI", ams.GetMsi()); err != nil { + if err = os.Setenv(jfMsiEnvVariable, ams.GetMsi()); err != nil { // Not a fatal error, if not set the scan will not be shown at the XSC UI, should not fail the scan. log.Debug(fmt.Sprintf("failed setting MSI as environment variable. Cause: %s", err.Error())) } @@ -105,12 +104,9 @@ func (ams *AnalyticsMetricsService) AddGeneralEvent() error { EventType: 1, EventStatus: xscservices.Started, Product: "cli", - ProductVersion: "", // can't have it for now - IsDefaultConfig: false, // orz will implement it JfrogUser: ams.xscManager.Config().GetServiceDetails().GetUser(), OsPlatform: splitOsAndArch[0], OsArchitecture: splitOsAndArch[1], - MachineId: "", // TODO add AnalyzerManagerVersion: GetAnalyzerManagerVersion(), JpdVersion: "", //TODO artifactory version, } @@ -130,18 +126,26 @@ func (ams *AnalyticsMetricsService) UpdateGeneralEvent(auditResults *Results) er log.Info("A general event update request was not sent to XSC - analytics metrics are disabled.") return nil } + event := xscservices.XscAnalyticsGeneralEventFinalize{ + MultiScanId: ams.msi, + XscAnalyticsBasicGeneralEvent: ams.createAuditResultsFromXscAnalyticsBasicGeneralEvent(auditResults), + } + return ams.xscManager.UpdateAnalyticsGeneralEvent(event) +} + +func (ams *AnalyticsMetricsService) createAuditResultsFromXscAnalyticsBasicGeneralEvent(auditResults *Results) xscservices.XscAnalyticsBasicGeneralEvent { totalDuration := time.Now().Sub(ams.GetStartTime()) - totalFindings := len(auditResults.ScaResults) + len(auditResults.ExtendedScanResults.ApplicabilityScanResults) + len(auditResults.ExtendedScanResults.SecretsScanResults) + len(auditResults.ExtendedScanResults.IacScanResults) + len(auditResults.ExtendedScanResults.SastScanResults) + totalFindings := len(auditResults.ScaResults) + if auditResults.ExtendedScanResults != nil { + totalFindings += len(auditResults.ExtendedScanResults.ApplicabilityScanResults) + len(auditResults.ExtendedScanResults.SecretsScanResults) + len(auditResults.ExtendedScanResults.IacScanResults) + len(auditResults.ExtendedScanResults.SastScanResults) + } eventStatus := xscservices.Completed if auditResults.ScaError != nil || auditResults.JasError != nil { eventStatus = xscservices.Failed } - event := xscservices.XscAnalyticsGeneralEventFinalize{MultiScanId: ams.msi} - event.XscAnalyticsBasicGeneralEvent = xscservices.XscAnalyticsBasicGeneralEvent{ - EventStatus: eventStatus, - TotalFindings: totalFindings, - TotalIgnoredFindings: 0, - TotalScanDuration: totalDuration.String(), + return xscservices.XscAnalyticsBasicGeneralEvent{ + EventStatus: eventStatus, + TotalFindings: totalFindings, + TotalScanDuration: totalDuration.String(), } - return ams.xscManager.UpdateAnalyticsGeneralEvent(event) } diff --git a/utils/analyticsmetrics_test.go b/utils/analyticsmetrics_test.go index ebadcb00..06a488c0 100644 --- a/utils/analyticsmetrics_test.go +++ b/utils/analyticsmetrics_test.go @@ -1,49 +1,177 @@ package utils import ( - "github.com/jfrog/jfrog-cli-security/tests" - "github.com/jfrog/jfrog-client-go/artifactory/services/utils/tests/xsc" + "errors" + "fmt" + coretests "github.com/jfrog/jfrog-cli-core/v2/common/tests" + "github.com/jfrog/jfrog-cli-core/v2/utils/config" + "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" + "github.com/jfrog/jfrog-client-go/xray/services" + xscservices "github.com/jfrog/jfrog-client-go/xsc/services" + "github.com/owenrumney/go-sarif/v2/sarif" "github.com/stretchr/testify/assert" + "net/http" + "net/http/httptest" "os" "testing" + "time" +) + +const ( + testMsi = "27e175b8-e525-11ee-842b-7aa2c69b8f1f" + lowerAnalyticsMetricsMinXscVersion = "1.6.0" + higherAnalyticsMetricsMinXscVersion = "1.10.0" ) func TestCalcShouldReportEvents(t *testing.T) { // Save original environment information. - originalJfMsi := os.Getenv("JF_MSI") + originalJfMsi := os.Getenv(jfMsiEnvVariable) defer func() { - err := os.Setenv("JF_MSI", originalJfMsi) + err := os.Setenv(jfMsiEnvVariable, originalJfMsi) assert.NoError(t, err) }() - originalReportUsage := os.Getenv("JFROG_CLI_REPORT_USAGE") + originalReportUsage := os.Getenv(coreutils.ReportUsage) defer func() { - err := os.Setenv("JFROG_CLI_REPORT_USAGE", originalReportUsage) + err := os.Setenv(coreutils.ReportUsage, originalReportUsage) assert.NoError(t, err) }() - // Msi was already provided. - err := os.Setenv("JF_MSI", "msi") + err := os.Setenv(coreutils.ReportUsage, "") assert.NoError(t, err) - am := AnalyticsMetricsService{} - assert.False(t, am.calcShouldReportEvents()) + err = os.Setenv(jfMsiEnvVariable, "") + assert.NoError(t, err) + + // Minimum Xsc version. + mockServer, serverDetails := xscServer(t, AnalyticsMetricsMinXscVersion) + defer mockServer.Close() + am, err := NewAnalyticsMetricsService(serverDetails) + assert.True(t, am.calcShouldReportEvents()) - // Report usage is false. - err = os.Setenv("JF_MSI", "") + // Lower Xsc version. + mockServer, serverDetails = xscServer(t, lowerAnalyticsMetricsMinXscVersion) + defer mockServer.Close() + am, err = NewAnalyticsMetricsService(serverDetails) assert.NoError(t, err) - err = os.Setenv("JFROG_CLI_REPORT_USAGE", "false") + assert.False(t, am.calcShouldReportEvents()) + + // Higher Xsc version. + mockServer, serverDetails = xscServer(t, higherAnalyticsMetricsMinXscVersion) + defer mockServer.Close() + am, err = NewAnalyticsMetricsService(serverDetails) + assert.True(t, am.calcShouldReportEvents()) + + // JF_MSI was already provided. + err = os.Setenv(jfMsiEnvVariable, "msi") assert.NoError(t, err) assert.False(t, am.calcShouldReportEvents()) - //TODO add version verification- i want to create mock and test it in unit test and not with specific env and version + // JFROG_CLI_REPORT_USAGE is false. + err = os.Setenv(jfMsiEnvVariable, "") + assert.NoError(t, err) + err = os.Setenv(coreutils.ReportUsage, "false") + assert.NoError(t, err) + assert.False(t, am.calcShouldReportEvents()) } -func TestSendNewGeneralEventRequestToXsc(t *testing.T) { - // TODO i need to work with a real env although its not full integration test - // TODO this are clients tests mocks - xsc.StartXscMockServer(t) - am, err := NewAnalyticsMetricsService(tests.XscDetails) +func TestAddGeneralEventAndSetMsi(t *testing.T) { + originalMsi := os.Getenv(jfMsiEnvVariable) + defer func() { + assert.NoError(t, os.Setenv(jfMsiEnvVariable, originalMsi)) + }() + + // Successful flow. + mockServer, serverDetails := xscServer(t, AnalyticsMetricsMinXscVersion) + defer mockServer.Close() + am, err := NewAnalyticsMetricsService(serverDetails) assert.NoError(t, err) - err = am.AddGeneralEvent() + params := services.XrayGraphScanParams{} + err = am.AddGeneralEventAndSetMsi(¶ms) assert.NoError(t, err) assert.NotEmpty(t, am.GetMsi()) + assert.Equal(t, params.MultiScanId, am.GetMsi()) + assert.Equal(t, am.GetMsi(), os.Getenv(jfMsiEnvVariable)) + + // In case cli should not report analytics, verify that request won't be sent. + am.shouldReportEvents = false + am.SetMsi("test-msi") + err = am.AddGeneralEventAndSetMsi(¶ms) + assert.NoError(t, err) + assert.Equal(t, "test-msi", am.GetMsi()) +} + +func TestUpdateGeneralEvent(t *testing.T) { + mockServer, serverDetails := xscServer(t, AnalyticsMetricsMinXscVersion) + defer mockServer.Close() + am, err := NewAnalyticsMetricsService(serverDetails) + assert.NoError(t, err) + err = am.UpdateGeneralEvent(&Results{}) + assert.NoError(t, err) +} + +func TestCreateAuditResultsFromXscAnalyticsBasicGeneralEvent(t *testing.T) { + mockServer, serverDetails := xscServer(t, AnalyticsMetricsMinXscVersion) + defer mockServer.Close() + am, err := NewAnalyticsMetricsService(serverDetails) + assert.NoError(t, err) + am.SetStartTime() + + // no audit results + event := am.createAuditResultsFromXscAnalyticsBasicGeneralEvent(&Results{}) + assert.Equal(t, 0, event.TotalFindings) + + // audit result, each scan has 2 result (total 10 scan results). + auditResults := Results{ + ScaResults: []ScaScanResult{{}, {}}, + ExtendedScanResults: &ExtendedScanResults{ + ApplicabilityScanResults: []*sarif.Run{{}, {}}, + SecretsScanResults: []*sarif.Run{{}, {}}, + IacScanResults: []*sarif.Run{{}, {}}, + SastScanResults: []*sarif.Run{{}, {}}, + }, + } + event = am.createAuditResultsFromXscAnalyticsBasicGeneralEvent(&auditResults) + + assert.Equal(t, 10, event.TotalFindings) + assert.Equal(t, xscservices.Completed, event.EventStatus) + totalDuration, err := time.ParseDuration(event.TotalScanDuration) + assert.NoError(t, err) + assert.True(t, totalDuration > 0) + + // Scan failed because sca/jas errors. + auditResults.JasError = errors.New("jas error") + event = am.createAuditResultsFromXscAnalyticsBasicGeneralEvent(&auditResults) + assert.Equal(t, 10, event.TotalFindings) + assert.Equal(t, xscservices.Failed, event.EventStatus) + totalDuration, err = time.ParseDuration(event.TotalScanDuration) + assert.NoError(t, err) + assert.True(t, totalDuration > 0) + + auditResults.ScaError = errors.New("sca error") + auditResults.JasError = nil + event = am.createAuditResultsFromXscAnalyticsBasicGeneralEvent(&auditResults) + assert.Equal(t, xscservices.Failed, event.EventStatus) +} + +func xscServer(t *testing.T, xscVersion string) (*httptest.Server, *config.ServerDetails) { + serverMock, serverDetails, _ := coretests.CreateXscRestsMockServer(t, func(w http.ResponseWriter, r *http.Request) { + if r.RequestURI == "/xsc/api/v1/system/version" { + _, err := w.Write([]byte(fmt.Sprintf(`{"xsc_version": "%s"}`, xscVersion))) + if err != nil { + return + } + } + if r.RequestURI == "/xsc/api/v1/event" { + if r.Method == http.MethodPost { + w.WriteHeader(http.StatusCreated) + _, err := w.Write([]byte(fmt.Sprintf(`{"multi_scan_id": "%s"}`, testMsi))) + if err != nil { + return + } + } else if r.Method == http.MethodPut { + w.WriteHeader(http.StatusOK) + } + + } + }) + return serverMock, serverDetails } From abc6553c10780463dadf28dcdb2a81c069bf1f93 Mon Sep 17 00:00:00 2001 From: gail Date: Thu, 28 Mar 2024 17:44:05 +0200 Subject: [PATCH 07/32] Remove error handling for analytics. --- cli/scancommands.go | 6 ++++-- commands/audit/audit.go | 11 ++++------- commands/audit/jas/common.go | 20 +++++++++++++------- commands/audit/jasrunner.go | 9 ++------- tests/config.go | 5 ++--- tests/consts.go | 1 - utils/analyticsmetrics.go | 21 ++++++++++++--------- utils/analyticsmetrics_test.go | 18 ++---------------- 8 files changed, 39 insertions(+), 52 deletions(-) diff --git a/cli/scancommands.go b/cli/scancommands.go index 16f17905..26a0adf2 100644 --- a/cli/scancommands.go +++ b/cli/scancommands.go @@ -1,6 +1,7 @@ package cli import ( + "fmt" "os" "strings" @@ -351,9 +352,10 @@ func createAuditCmd(c *components.Context) (*audit.AuditCommand, error) { } analytics, err := utils.NewAnalyticsMetricsService(serverDetails) if err != nil { - return nil, err + log.Debug(fmt.Sprintf("Failed to create analytics metrics service. %s", err.Error())) + } else { + auditCmd.SetAnalyticsMetricsService(analytics) } - auditCmd.SetAnalyticsMetricsService(analytics) auditCmd.SetTargetRepoPath(addTrailingSlashToRepoPathIfNeeded(c)). SetProject(c.GetStringFlagValue(flags.Project)). SetIncludeVulnerabilities(shouldIncludeVulnerabilities(c)). diff --git a/commands/audit/audit.go b/commands/audit/audit.go index 5f974c4e..14ff93ff 100644 --- a/commands/audit/audit.go +++ b/commands/audit/audit.go @@ -103,18 +103,15 @@ func (auditCmd *AuditCommand) Run() (err error) { SetGraphBasicParams(auditCmd.AuditBasicParams). SetThirdPartyApplicabilityScan(auditCmd.thirdPartyApplicabilityScan) auditParams.SetIsRecursiveScan(isRecursiveScan).SetExclusions(auditCmd.Exclusions()) - - err = auditCmd.analyticsMetricsService.AddGeneralEventAndSetMsi(auditParams.xrayGraphScanParams) - if err != nil { - return + if auditCmd.analyticsMetricsService != nil { + auditCmd.analyticsMetricsService.AddGeneralEventAndSetMsi(auditParams.xrayGraphScanParams) } auditResults, err := RunAudit(auditParams) if err != nil { return } - err = auditCmd.analyticsMetricsService.UpdateGeneralEvent(auditResults) - if err != nil { - return + if auditCmd.analyticsMetricsService != nil { + auditCmd.analyticsMetricsService.UpdateGeneralEvent(auditResults) } if auditCmd.Progress() != nil { if err = auditCmd.Progress().Quit(); err != nil { diff --git a/commands/audit/jas/common.go b/commands/audit/jas/common.go index 32286636..a030c2db 100644 --- a/commands/audit/jas/common.go +++ b/commands/audit/jas/common.go @@ -275,23 +275,29 @@ func GetExcludePatterns(module jfrogappsconfig.Module, scanner *jfrogappsconfig. return excludePatterns } -func SetAnalyticsMetricsDataForAnalyzerManager(technologies []coreutils.Technology) error { +func SetAnalyticsMetricsDataForAnalyzerManager(technologies []coreutils.Technology) { // For now only one value is supported. if len(technologies) != 1 { - return nil + return } technology := technologies[0] err := os.Setenv("AM_PACKAGE_MANAGER", technology.String()) if err != nil { - return err + log.Debug(fmt.Sprintf("failed setting AM_PACKAGE_MANAGER as environment variable. Cause: %s", err.Error())) + } + err = os.Setenv("AM_LANGUAGE", coreutils.TechnologyToLanguage(technology)) + if err != nil { + log.Debug(fmt.Sprintf("failed setting AM_LANGUAGE as environment variable. Cause: %s", err.Error())) } - return os.Setenv("AM_LANGUAGE", coreutils.TechnologyToLanguage(technology)) } -func ResetAnalyticsMetricsDataForAnalyzerManager() error { +func ResetAnalyticsMetricsDataForAnalyzerManager() { err := os.Setenv("AM_PACKAGE_MANAGER", "") if err != nil { - return err + log.Debug(fmt.Sprintf("failed setting AM_PACKAGE_MANAGER as environment variable. Cause: %s", err.Error())) + } + err = os.Setenv("AM_LANGUAGE", "") + if err != nil { + log.Debug(fmt.Sprintf("failed setting AM_LANGUAGE as environment variable. Cause: %s", err.Error())) } - return os.Setenv("AM_LANGUAGE", "") } diff --git a/commands/audit/jasrunner.go b/commands/audit/jasrunner.go index 800d3eb2..c0808cb8 100644 --- a/commands/audit/jasrunner.go +++ b/commands/audit/jasrunner.go @@ -31,13 +31,8 @@ func runJasScannersAndSetResults(scanResults *utils.Results, directDependencies progress.SetHeadlineMsg("Running applicability scanning") } // Set environments variables for analytics in analyzers manager. - err = jas.SetAnalyticsMetricsDataForAnalyzerManager(scanResults.GetScaScannedTechnologies()) - if err != nil { - return - } - defer func() { - err = jas.ResetAnalyticsMetricsDataForAnalyzerManager() - }() + jas.SetAnalyticsMetricsDataForAnalyzerManager(scanResults.GetScaScannedTechnologies()) + defer jas.ResetAnalyticsMetricsDataForAnalyzerManager() scanResults.ExtendedScanResults.ApplicabilityScanResults, err = applicability.RunApplicabilityScan(scanResults.GetScaScansXrayResults(), directDependencies, scanResults.GetScaScannedTechnologies(), scanner, thirdPartyApplicabilityScan) if err != nil { return diff --git a/tests/config.go b/tests/config.go index 5a38b544..9fe0641e 100644 --- a/tests/config.go +++ b/tests/config.go @@ -13,9 +13,8 @@ import ( // Integration tests - global variables var ( - XrDetails *config.ServerDetails - XscDetails *config.ServerDetails - XrAuth auth.ServiceDetails + XrDetails *config.ServerDetails + XrAuth auth.ServiceDetails RtDetails *config.ServerDetails RtAuth auth.ServiceDetails diff --git a/tests/consts.go b/tests/consts.go index 6e6f9f8e..2b39678b 100644 --- a/tests/consts.go +++ b/tests/consts.go @@ -16,7 +16,6 @@ const ( const ( XrayEndpoint = "xray/" - XscEndpoint = "xsc/" ArtifactoryEndpoint = "artifactory/" AccessEndpoint = "access/" RepoDetailsEndpoint = "api/repositories/" diff --git a/utils/analyticsmetrics.go b/utils/analyticsmetrics.go index f55ad1d7..68f9abaa 100644 --- a/utils/analyticsmetrics.go +++ b/utils/analyticsmetrics.go @@ -75,14 +75,15 @@ func (ams *AnalyticsMetricsService) ShouldReportEvents() bool { return ams.shouldReportEvents } -func (ams *AnalyticsMetricsService) AddGeneralEventAndSetMsi(params *services.XrayGraphScanParams) error { +func (ams *AnalyticsMetricsService) AddGeneralEventAndSetMsi(params *services.XrayGraphScanParams) { if !ams.ShouldReportEvents() { - log.Info("A general event request was not sent to XSC - analytics metrics are disabled.") - return nil + log.Debug("A general event request was not sent to XSC - analytics metrics are disabled.") + return } err := ams.AddGeneralEvent() if err != nil { - return fmt.Errorf("failed sending general event request to XSC service, error: %s ", err.Error()) + log.Debug(fmt.Errorf("failed sending general event request to XSC service, error: %s ", err.Error())) + return } log.Debug(fmt.Sprintf("New General event added successfully. multi_scan_id %s", ams.GetMsi())) @@ -92,7 +93,6 @@ func (ams *AnalyticsMetricsService) AddGeneralEventAndSetMsi(params *services.Xr } // Before running the audit command, set the msi so the sca scan will be performed on the xsc rather than on the xray server. params.MultiScanId = ams.GetMsi() - return nil } func (ams *AnalyticsMetricsService) AddGeneralEvent() error { osAndArc, err := coreutils.GetOSAndArc() @@ -121,16 +121,19 @@ func (ams *AnalyticsMetricsService) AddGeneralEvent() error { return nil } -func (ams *AnalyticsMetricsService) UpdateGeneralEvent(auditResults *Results) error { +func (ams *AnalyticsMetricsService) UpdateGeneralEvent(auditResults *Results) { if !ams.ShouldReportEvents() { - log.Info("A general event update request was not sent to XSC - analytics metrics are disabled.") - return nil + log.Debug("A general event update request was not sent to XSC - analytics metrics are disabled.") + return } event := xscservices.XscAnalyticsGeneralEventFinalize{ MultiScanId: ams.msi, XscAnalyticsBasicGeneralEvent: ams.createAuditResultsFromXscAnalyticsBasicGeneralEvent(auditResults), } - return ams.xscManager.UpdateAnalyticsGeneralEvent(event) + err := ams.xscManager.UpdateAnalyticsGeneralEvent(event) + if err != nil { + log.Debug(fmt.Sprintf("failed updading general event request in XSC service for multi_scan_id %s, error: %s \"", ams.GetMsi(), err.Error())) + } } func (ams *AnalyticsMetricsService) createAuditResultsFromXscAnalyticsBasicGeneralEvent(auditResults *Results) xscservices.XscAnalyticsBasicGeneralEvent { diff --git a/utils/analyticsmetrics_test.go b/utils/analyticsmetrics_test.go index 06a488c0..0e140e6e 100644 --- a/utils/analyticsmetrics_test.go +++ b/utils/analyticsmetrics_test.go @@ -85,8 +85,7 @@ func TestAddGeneralEventAndSetMsi(t *testing.T) { am, err := NewAnalyticsMetricsService(serverDetails) assert.NoError(t, err) params := services.XrayGraphScanParams{} - err = am.AddGeneralEventAndSetMsi(¶ms) - assert.NoError(t, err) + am.AddGeneralEventAndSetMsi(¶ms) assert.NotEmpty(t, am.GetMsi()) assert.Equal(t, params.MultiScanId, am.GetMsi()) assert.Equal(t, am.GetMsi(), os.Getenv(jfMsiEnvVariable)) @@ -94,20 +93,10 @@ func TestAddGeneralEventAndSetMsi(t *testing.T) { // In case cli should not report analytics, verify that request won't be sent. am.shouldReportEvents = false am.SetMsi("test-msi") - err = am.AddGeneralEventAndSetMsi(¶ms) - assert.NoError(t, err) + am.AddGeneralEventAndSetMsi(¶ms) assert.Equal(t, "test-msi", am.GetMsi()) } -func TestUpdateGeneralEvent(t *testing.T) { - mockServer, serverDetails := xscServer(t, AnalyticsMetricsMinXscVersion) - defer mockServer.Close() - am, err := NewAnalyticsMetricsService(serverDetails) - assert.NoError(t, err) - err = am.UpdateGeneralEvent(&Results{}) - assert.NoError(t, err) -} - func TestCreateAuditResultsFromXscAnalyticsBasicGeneralEvent(t *testing.T) { mockServer, serverDetails := xscServer(t, AnalyticsMetricsMinXscVersion) defer mockServer.Close() @@ -167,10 +156,7 @@ func xscServer(t *testing.T, xscVersion string) (*httptest.Server, *config.Serve if err != nil { return } - } else if r.Method == http.MethodPut { - w.WriteHeader(http.StatusOK) } - } }) return serverMock, serverDetails From e79cb1e444500e89809e02322215f65d4876a106 Mon Sep 17 00:00:00 2001 From: gail Date: Thu, 28 Mar 2024 21:51:59 +0200 Subject: [PATCH 08/32] Change AnalyticsMetricsService creation. --- cli/scancommands.go | 9 ++------- commands/audit/audit.go | 9 +++------ utils/analyticsmetrics.go | 8 +++++--- utils/analyticsmetrics_test.go | 13 +++++-------- 4 files changed, 15 insertions(+), 24 deletions(-) diff --git a/cli/scancommands.go b/cli/scancommands.go index 26a0adf2..a1bdf275 100644 --- a/cli/scancommands.go +++ b/cli/scancommands.go @@ -1,7 +1,6 @@ package cli import ( - "fmt" "os" "strings" @@ -350,12 +349,8 @@ func createAuditCmd(c *components.Context) (*audit.AuditCommand, error) { if err != nil { return nil, err } - analytics, err := utils.NewAnalyticsMetricsService(serverDetails) - if err != nil { - log.Debug(fmt.Sprintf("Failed to create analytics metrics service. %s", err.Error())) - } else { - auditCmd.SetAnalyticsMetricsService(analytics) - } + auditCmd.SetAnalyticsMetricsService(utils.NewAnalyticsMetricsService(serverDetails)) + auditCmd.SetTargetRepoPath(addTrailingSlashToRepoPathIfNeeded(c)). SetProject(c.GetStringFlagValue(flags.Project)). SetIncludeVulnerabilities(shouldIncludeVulnerabilities(c)). diff --git a/commands/audit/audit.go b/commands/audit/audit.go index 14ff93ff..ca5dd05c 100644 --- a/commands/audit/audit.go +++ b/commands/audit/audit.go @@ -103,16 +103,13 @@ func (auditCmd *AuditCommand) Run() (err error) { SetGraphBasicParams(auditCmd.AuditBasicParams). SetThirdPartyApplicabilityScan(auditCmd.thirdPartyApplicabilityScan) auditParams.SetIsRecursiveScan(isRecursiveScan).SetExclusions(auditCmd.Exclusions()) - if auditCmd.analyticsMetricsService != nil { - auditCmd.analyticsMetricsService.AddGeneralEventAndSetMsi(auditParams.xrayGraphScanParams) - } + + auditCmd.analyticsMetricsService.AddGeneralEventAndSetMsi(auditParams.xrayGraphScanParams) auditResults, err := RunAudit(auditParams) if err != nil { return } - if auditCmd.analyticsMetricsService != nil { - auditCmd.analyticsMetricsService.UpdateGeneralEvent(auditResults) - } + auditCmd.analyticsMetricsService.UpdateGeneralEvent(auditResults) if auditCmd.Progress() != nil { if err = auditCmd.Progress().Quit(); err != nil { return diff --git a/utils/analyticsmetrics.go b/utils/analyticsmetrics.go index 68f9abaa..64bb2fc9 100644 --- a/utils/analyticsmetrics.go +++ b/utils/analyticsmetrics.go @@ -24,15 +24,17 @@ type AnalyticsMetricsService struct { startTime time.Time } -func NewAnalyticsMetricsService(serviceDetails *config.ServerDetails) (*AnalyticsMetricsService, error) { +func NewAnalyticsMetricsService(serviceDetails *config.ServerDetails) *AnalyticsMetricsService { ams := AnalyticsMetricsService{} xscManager, err := CreateXscServiceManager(serviceDetails) if err != nil { - return nil, err + // When an error occurs, shouldReportEvents will be false and no XscServiceManager commands will be executed. + log.Debug(fmt.Sprintf("Failed to create xsc manager for analytics metrics service. %s", err.Error())) + return &ams } ams.xscManager = xscManager ams.shouldReportEvents = ams.calcShouldReportEvents() - return &ams, nil + return &ams } func (ams *AnalyticsMetricsService) calcShouldReportEvents() bool { diff --git a/utils/analyticsmetrics_test.go b/utils/analyticsmetrics_test.go index 0e140e6e..ef94abe9 100644 --- a/utils/analyticsmetrics_test.go +++ b/utils/analyticsmetrics_test.go @@ -44,20 +44,19 @@ func TestCalcShouldReportEvents(t *testing.T) { // Minimum Xsc version. mockServer, serverDetails := xscServer(t, AnalyticsMetricsMinXscVersion) defer mockServer.Close() - am, err := NewAnalyticsMetricsService(serverDetails) + am := NewAnalyticsMetricsService(serverDetails) assert.True(t, am.calcShouldReportEvents()) // Lower Xsc version. mockServer, serverDetails = xscServer(t, lowerAnalyticsMetricsMinXscVersion) defer mockServer.Close() - am, err = NewAnalyticsMetricsService(serverDetails) - assert.NoError(t, err) + am = NewAnalyticsMetricsService(serverDetails) assert.False(t, am.calcShouldReportEvents()) // Higher Xsc version. mockServer, serverDetails = xscServer(t, higherAnalyticsMetricsMinXscVersion) defer mockServer.Close() - am, err = NewAnalyticsMetricsService(serverDetails) + am = NewAnalyticsMetricsService(serverDetails) assert.True(t, am.calcShouldReportEvents()) // JF_MSI was already provided. @@ -82,8 +81,7 @@ func TestAddGeneralEventAndSetMsi(t *testing.T) { // Successful flow. mockServer, serverDetails := xscServer(t, AnalyticsMetricsMinXscVersion) defer mockServer.Close() - am, err := NewAnalyticsMetricsService(serverDetails) - assert.NoError(t, err) + am := NewAnalyticsMetricsService(serverDetails) params := services.XrayGraphScanParams{} am.AddGeneralEventAndSetMsi(¶ms) assert.NotEmpty(t, am.GetMsi()) @@ -100,8 +98,7 @@ func TestAddGeneralEventAndSetMsi(t *testing.T) { func TestCreateAuditResultsFromXscAnalyticsBasicGeneralEvent(t *testing.T) { mockServer, serverDetails := xscServer(t, AnalyticsMetricsMinXscVersion) defer mockServer.Close() - am, err := NewAnalyticsMetricsService(serverDetails) - assert.NoError(t, err) + am := NewAnalyticsMetricsService(serverDetails) am.SetStartTime() // no audit results From b3452da98a50a4615ddee00375b97c53acabf7b0 Mon Sep 17 00:00:00 2001 From: gail Date: Sun, 31 Mar 2024 13:55:21 +0300 Subject: [PATCH 09/32] go.mod+sum --- go.mod | 6 +++--- go.sum | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index d3410083..fa64ecd9 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/jfrog/build-info-go v1.9.25 github.com/jfrog/gofrog v1.6.3 github.com/jfrog/jfrog-apps-config v1.0.1 - github.com/jfrog/jfrog-cli-core/v2 v2.50.0 + github.com/jfrog/jfrog-cli-core/v2 v2.49.0 github.com/jfrog/jfrog-client-go v1.39.0 github.com/magiconair/properties v1.8.7 github.com/owenrumney/go-sarif/v2 v2.3.0 @@ -98,8 +98,8 @@ require ( gopkg.in/warnings.v0 v0.1.2 // indirect ) -replace github.com/jfrog/jfrog-cli-core/v2 => ../jfrog-cli-core +replace github.com/jfrog/jfrog-cli-core/v2 => github.com/gailazar300/jfrog-cli-core/v2 v2.0.0-20240331095546-a03b2d7f67da -replace github.com/jfrog/jfrog-client-go => ../jfrog-client-go +replace github.com/jfrog/jfrog-client-go => github.com/gailazar300/jfrog-client-go v0.18.1-0.20240331091256-e2e7cd419323 // replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go dev diff --git a/go.sum b/go.sum index a5be4576..c363f965 100644 --- a/go.sum +++ b/go.sum @@ -60,6 +60,10 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/gailazar300/jfrog-cli-core/v2 v2.0.0-20240331095546-a03b2d7f67da h1:6v7I8AfW12IK7Sr5zTf3thRO+NyY/YEjfIcud1ieVEM= +github.com/gailazar300/jfrog-cli-core/v2 v2.0.0-20240331095546-a03b2d7f67da/go.mod h1:95AsjwlMLNWU0v71/3dS715e1RAQfvPO47RRHz2xKh8= +github.com/gailazar300/jfrog-client-go v0.18.1-0.20240331091256-e2e7cd419323 h1:s1bOQdculuurDa2BjMRYG3Q+Lz12YMuyc09XRPbTWyo= +github.com/gailazar300/jfrog-client-go v0.18.1-0.20240331091256-e2e7cd419323/go.mod h1:tUyEmxznphh0nwAGo6xz9Sps7RRW/TBMxIJZteo+j2k= github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= @@ -102,10 +106,6 @@ github.com/jfrog/gofrog v1.6.3 h1:F7He0+75HcgCe6SGTSHLFCBDxiE2Ja0tekvvcktW6wc= github.com/jfrog/gofrog v1.6.3/go.mod h1:SZ1EPJUruxrVGndOzHd+LTiwWYKMlHqhKD+eu+v5Hqg= github.com/jfrog/jfrog-apps-config v1.0.1 h1:mtv6k7g8A8BVhlHGlSveapqf4mJfonwvXYLipdsOFMY= github.com/jfrog/jfrog-apps-config v1.0.1/go.mod h1:8AIIr1oY9JuH5dylz2S6f8Ym2MaadPLR6noCBO4C22w= -github.com/jfrog/jfrog-cli-core/v2 v2.50.0 h1:QmjSIktMKAbNH7OGY+eVZKx9husqgMANSI5kB8MlvlA= -github.com/jfrog/jfrog-cli-core/v2 v2.50.0/go.mod h1:95AsjwlMLNWU0v71/3dS715e1RAQfvPO47RRHz2xKh8= -github.com/jfrog/jfrog-client-go v1.39.0 h1:GZ1qbpUDzYz8ZEycYicDkbVMN2H0VSCuz8mUNTyf7tc= -github.com/jfrog/jfrog-client-go v1.39.0/go.mod h1:tUyEmxznphh0nwAGo6xz9Sps7RRW/TBMxIJZteo+j2k= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= From fdb505145e8dffe4acf142bff017227fd70e5ecc Mon Sep 17 00:00:00 2001 From: gail Date: Sun, 31 Mar 2024 14:10:50 +0300 Subject: [PATCH 10/32] Minor fixes. --- commands/audit/jas/common.go | 2 +- jfrogclisecurity_test.go | 1 - utils/analyticsmetrics.go | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/commands/audit/jas/common.go b/commands/audit/jas/common.go index a030c2db..9f4741b1 100644 --- a/commands/audit/jas/common.go +++ b/commands/audit/jas/common.go @@ -285,7 +285,7 @@ func SetAnalyticsMetricsDataForAnalyzerManager(technologies []coreutils.Technolo if err != nil { log.Debug(fmt.Sprintf("failed setting AM_PACKAGE_MANAGER as environment variable. Cause: %s", err.Error())) } - err = os.Setenv("AM_LANGUAGE", coreutils.TechnologyToLanguage(technology)) + err = os.Setenv("AM_LANGUAGE", string(coreutils.TechnologyToLanguage(technology))) if err != nil { log.Debug(fmt.Sprintf("failed setting AM_LANGUAGE as environment variable. Cause: %s", err.Error())) } diff --git a/jfrogclisecurity_test.go b/jfrogclisecurity_test.go index 94253546..3af50790 100644 --- a/jfrogclisecurity_test.go +++ b/jfrogclisecurity_test.go @@ -40,7 +40,6 @@ func setupIntegrationTests() { // Init utils.InitTestCliDetails() utils.AuthenticateArtifactory() - utils.AuthenticateXsc() utils.CreateRequiredRepositories() } diff --git a/utils/analyticsmetrics.go b/utils/analyticsmetrics.go index 64bb2fc9..ea9a91d2 100644 --- a/utils/analyticsmetrics.go +++ b/utils/analyticsmetrics.go @@ -139,7 +139,7 @@ func (ams *AnalyticsMetricsService) UpdateGeneralEvent(auditResults *Results) { } func (ams *AnalyticsMetricsService) createAuditResultsFromXscAnalyticsBasicGeneralEvent(auditResults *Results) xscservices.XscAnalyticsBasicGeneralEvent { - totalDuration := time.Now().Sub(ams.GetStartTime()) + totalDuration := time.Since(ams.GetStartTime()) totalFindings := len(auditResults.ScaResults) if auditResults.ExtendedScanResults != nil { totalFindings += len(auditResults.ExtendedScanResults.ApplicabilityScanResults) + len(auditResults.ExtendedScanResults.SecretsScanResults) + len(auditResults.ExtendedScanResults.IacScanResults) + len(auditResults.ExtendedScanResults.SastScanResults) From 4c689433c5a5706db4c03d8a7e0bf0bd133703c6 Mon Sep 17 00:00:00 2001 From: gail Date: Mon, 1 Apr 2024 12:29:29 +0300 Subject: [PATCH 11/32] Review fixes. --- commands/audit/audit.go | 10 ++-- commands/audit/jas/common.go | 25 ++++---- commands/audit/jas/common_test.go | 36 ++++++++++++ commands/audit/jasrunner.go | 5 +- utils/analyticsmetrics.go | 38 +++++------- utils/analyticsmetrics_test.go | 98 +++++++++++-------------------- utils/analyzermanager.go | 4 +- utils/auditbasicparams.go | 9 +++ utils/xraymanager.go | 4 +- 9 files changed, 118 insertions(+), 111 deletions(-) diff --git a/commands/audit/audit.go b/commands/audit/audit.go index ca5dd05c..8a91f16f 100644 --- a/commands/audit/audit.go +++ b/commands/audit/audit.go @@ -103,8 +103,8 @@ func (auditCmd *AuditCommand) Run() (err error) { SetGraphBasicParams(auditCmd.AuditBasicParams). SetThirdPartyApplicabilityScan(auditCmd.thirdPartyApplicabilityScan) auditParams.SetIsRecursiveScan(isRecursiveScan).SetExclusions(auditCmd.Exclusions()) - - auditCmd.analyticsMetricsService.AddGeneralEventAndSetMsi(auditParams.xrayGraphScanParams) + auditCmd.analyticsMetricsService.AddGeneralEvent() + auditParams.SetMultiScanId(auditCmd.analyticsMetricsService.GetMsi()) auditResults, err := RunAudit(auditParams) if err != nil { return @@ -179,9 +179,7 @@ func RunAudit(auditParams *AuditParams) (results *xrayutils.Results, err error) errGroup.Go(utils.DownloadAnalyzerManagerIfNeeded) } - if auditParams.xrayGraphScanParams.MultiScanId != "" { - results.MultiScanId = auditParams.xrayGraphScanParams.MultiScanId - } + results.MultiScanId = auditParams.MultiScanId() // The sca scan doesn't require the analyzer manager, so it can run separately from the analyzer manager download routine. results.ScaError = runScaScan(auditParams, results) @@ -193,7 +191,7 @@ func RunAudit(auditParams *AuditParams) (results *xrayutils.Results, err error) // Run scanners only if the user is entitled for Advanced Security if results.ExtendedScanResults.EntitledForJas { - results.JasError = runJasScannersAndSetResults(results, auditParams.DirectDependencies(), serverDetails, auditParams.workingDirs, auditParams.Progress(), auditParams.thirdPartyApplicabilityScan) + results.JasError = runJasScannersAndSetResults(results, auditParams.DirectDependencies(), serverDetails, auditParams.workingDirs, auditParams.Progress(), auditParams.thirdPartyApplicabilityScan, auditParams.MultiScanId()) } return } diff --git a/commands/audit/jas/common.go b/commands/audit/jas/common.go index 9f4741b1..dfcb8acf 100644 --- a/commands/audit/jas/common.go +++ b/commands/audit/jas/common.go @@ -3,6 +3,7 @@ package jas import ( "errors" "fmt" + clientutils "github.com/jfrog/jfrog-client-go/utils" "os" "path/filepath" "strings" @@ -24,7 +25,9 @@ import ( ) const ( - NodeModulesPattern = "**/*node_modules*/**" + NodeModulesPattern = "**/*node_modules*/**" + jfPackageManagerEnvVariable = "AM_PACKAGE_MANAGER" + jfLanguageEnvVariable = "AM_LANGUAGE" ) var ( @@ -275,19 +278,19 @@ func GetExcludePatterns(module jfrogappsconfig.Module, scanner *jfrogappsconfig. return excludePatterns } -func SetAnalyticsMetricsDataForAnalyzerManager(technologies []coreutils.Technology) { - // For now only one value is supported. +func SetAnalyticsMetricsDataForAnalyzerManager(msi string, technologies []coreutils.Technology) func() { + resetAnalyzerManageJfMsiVar := clientutils.SetEnvWithResetCallback(utils.JfMsiEnvVariable, msi) if len(technologies) != 1 { - return + // Only report analytics for one technology at a time. + return func() { resetAnalyzerManageJfMsiVar() } } technology := technologies[0] - err := os.Setenv("AM_PACKAGE_MANAGER", technology.String()) - if err != nil { - log.Debug(fmt.Sprintf("failed setting AM_PACKAGE_MANAGER as environment variable. Cause: %s", err.Error())) - } - err = os.Setenv("AM_LANGUAGE", string(coreutils.TechnologyToLanguage(technology))) - if err != nil { - log.Debug(fmt.Sprintf("failed setting AM_LANGUAGE as environment variable. Cause: %s", err.Error())) + resetAnalyzerManagerPackageManagerVar := clientutils.SetEnvWithResetCallback(jfPackageManagerEnvVariable, technology.String()) + resetAnalyzerManagerLanguageVar := clientutils.SetEnvWithResetCallback(jfLanguageEnvVariable, string(coreutils.TechnologyToLanguage(technology))) + return func() { + resetAnalyzerManagerPackageManagerVar() + resetAnalyzerManagerLanguageVar() + resetAnalyzerManageJfMsiVar() } } diff --git a/commands/audit/jas/common_test.go b/commands/audit/jas/common_test.go index 98129bcf..c4e1461b 100644 --- a/commands/audit/jas/common_test.go +++ b/commands/audit/jas/common_test.go @@ -1,6 +1,8 @@ package jas import ( + "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" + "os" "testing" "github.com/jfrog/jfrog-cli-security/utils" @@ -88,3 +90,37 @@ func TestAddScoreToRunRules(t *testing.T) { assert.Equal(t, test.expectedOutput, test.sarifRun.Tool.Driver.Rules) } } + +func TestSetAnalyticsMetricsDataForAnalyzerManager(t *testing.T) { + type args struct { + msi string + technologies []coreutils.Technology + } + tests := []struct { + name string + args args + want func() + }{ + {name: "Valid 1 technology", args: args{msi: "msi", technologies: []coreutils.Technology{coreutils.Maven}}, want: func() { + assert.Equal(t, string(coreutils.Maven), os.Getenv(jfPackageManagerEnvVariable)) + assert.Equal(t, string(coreutils.Java), os.Getenv(jfLanguageEnvVariable)) + assert.Equal(t, "msi", os.Getenv(utils.JfMsiEnvVariable)) + }}, + {name: "multiple technologies", args: args{msi: "msi", technologies: []coreutils.Technology{coreutils.Maven, coreutils.Npm}}, want: func() { + assert.Equal(t, "", os.Getenv(jfPackageManagerEnvVariable)) + assert.Equal(t, "", os.Getenv(jfLanguageEnvVariable)) + assert.Equal(t, "msi", os.Getenv(utils.JfMsiEnvVariable)) + }}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + callback := SetAnalyticsMetricsDataForAnalyzerManager(tt.args.msi, tt.args.technologies) + tt.want() + callback() + assert.Equal(t, "", os.Getenv(jfPackageManagerEnvVariable)) + assert.Equal(t, "", os.Getenv(jfLanguageEnvVariable)) + assert.Equal(t, "", os.Getenv(utils.JfMsiEnvVariable)) + + }) + } +} diff --git a/commands/audit/jasrunner.go b/commands/audit/jasrunner.go index c0808cb8..6c16fd8c 100644 --- a/commands/audit/jasrunner.go +++ b/commands/audit/jasrunner.go @@ -14,7 +14,7 @@ import ( ) func runJasScannersAndSetResults(scanResults *utils.Results, directDependencies []string, - serverDetails *config.ServerDetails, workingDirs []string, progress io.ProgressMgr, thirdPartyApplicabilityScan bool) (err error) { + serverDetails *config.ServerDetails, workingDirs []string, progress io.ProgressMgr, thirdPartyApplicabilityScan bool, msi string) (err error) { if serverDetails == nil || len(serverDetails.Url) == 0 { log.Warn("To include 'Advanced Security' scan as part of the audit output, please run the 'jf c add' command before running this command.") return @@ -31,8 +31,7 @@ func runJasScannersAndSetResults(scanResults *utils.Results, directDependencies progress.SetHeadlineMsg("Running applicability scanning") } // Set environments variables for analytics in analyzers manager. - jas.SetAnalyticsMetricsDataForAnalyzerManager(scanResults.GetScaScannedTechnologies()) - defer jas.ResetAnalyticsMetricsDataForAnalyzerManager() + defer jas.SetAnalyticsMetricsDataForAnalyzerManager(msi, scanResults.GetScaScannedTechnologies()) scanResults.ExtendedScanResults.ApplicabilityScanResults, err = applicability.RunApplicabilityScan(scanResults.GetScaScansXrayResults(), directDependencies, scanResults.GetScaScannedTechnologies(), scanner, thirdPartyApplicabilityScan) if err != nil { return diff --git a/utils/analyticsmetrics.go b/utils/analyticsmetrics.go index ea9a91d2..0d74577a 100644 --- a/utils/analyticsmetrics.go +++ b/utils/analyticsmetrics.go @@ -6,7 +6,6 @@ import ( "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" clientutils "github.com/jfrog/jfrog-client-go/utils" "github.com/jfrog/jfrog-client-go/utils/log" - "github.com/jfrog/jfrog-client-go/xray/services" "github.com/jfrog/jfrog-client-go/xsc" xscservices "github.com/jfrog/jfrog-client-go/xsc/services" "os" @@ -43,7 +42,7 @@ func (ams *AnalyticsMetricsService) calcShouldReportEvents() bool { return false } // There is no need to report the event and generate a new msi for the cli scan if the msi was provided. - if os.Getenv(jfMsiEnvVariable) != "" { + if os.Getenv(JfMsiEnvVariable) != "" { return false } // Verify xsc version. @@ -77,50 +76,41 @@ func (ams *AnalyticsMetricsService) ShouldReportEvents() bool { return ams.shouldReportEvents } -func (ams *AnalyticsMetricsService) AddGeneralEventAndSetMsi(params *services.XrayGraphScanParams) { +func (ams *AnalyticsMetricsService) AddGeneralEvent() { if !ams.ShouldReportEvents() { log.Debug("A general event request was not sent to XSC - analytics metrics are disabled.") return } - err := ams.AddGeneralEvent() - if err != nil { - log.Debug(fmt.Errorf("failed sending general event request to XSC service, error: %s ", err.Error())) - return - } - log.Debug(fmt.Sprintf("New General event added successfully. multi_scan_id %s", ams.GetMsi())) - if err = os.Setenv(jfMsiEnvVariable, ams.GetMsi()); err != nil { - // Not a fatal error, if not set the scan will not be shown at the XSC UI, should not fail the scan. - log.Debug(fmt.Sprintf("failed setting MSI as environment variable. Cause: %s", err.Error())) - } - // Before running the audit command, set the msi so the sca scan will be performed on the xsc rather than on the xray server. - params.MultiScanId = ams.GetMsi() -} -func (ams *AnalyticsMetricsService) AddGeneralEvent() error { osAndArc, err := coreutils.GetOSAndArc() + curOs, curArch := "", "" if err != nil { - return err + log.Debug(fmt.Errorf("failed to get os and arcitucture for general event request to XSC service, error: %s ", err.Error())) + } else { + splitOsAndArch := strings.Split(osAndArc, "-") + curOs = splitOsAndArch[0] + curArch = splitOsAndArch[1] } - splitOsAndArch := strings.Split(osAndArc, "-") + event := xscservices.XscAnalyticsBasicGeneralEvent{ EventType: 1, EventStatus: xscservices.Started, Product: "cli", JfrogUser: ams.xscManager.Config().GetServiceDetails().GetUser(), - OsPlatform: splitOsAndArch[0], - OsArchitecture: splitOsAndArch[1], + OsPlatform: curOs, + OsArchitecture: curArch, AnalyzerManagerVersion: GetAnalyzerManagerVersion(), - JpdVersion: "", //TODO artifactory version, } msi, err := ams.xscManager.AddAnalyticsGeneralEvent(xscservices.XscAnalyticsGeneralEvent{XscAnalyticsBasicGeneralEvent: event}) if err != nil { - return err + log.Debug(fmt.Errorf("failed sending general event request to XSC service, error: %s ", err.Error())) + return } + log.Debug(fmt.Sprintf("New General event added successfully. multi_scan_id %s", ams.GetMsi())) // Set event's analytics data. ams.SetMsi(msi) ams.SetStartTime() - return nil } func (ams *AnalyticsMetricsService) UpdateGeneralEvent(auditResults *Results) { diff --git a/utils/analyticsmetrics_test.go b/utils/analyticsmetrics_test.go index ef94abe9..911fa7dc 100644 --- a/utils/analyticsmetrics_test.go +++ b/utils/analyticsmetrics_test.go @@ -6,7 +6,7 @@ import ( coretests "github.com/jfrog/jfrog-cli-core/v2/common/tests" "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" - "github.com/jfrog/jfrog-client-go/xray/services" + "github.com/jfrog/jfrog-client-go/utils/tests" xscservices "github.com/jfrog/jfrog-client-go/xsc/services" "github.com/owenrumney/go-sarif/v2/sarif" "github.com/stretchr/testify/assert" @@ -25,21 +25,8 @@ const ( func TestCalcShouldReportEvents(t *testing.T) { // Save original environment information. - originalJfMsi := os.Getenv(jfMsiEnvVariable) - defer func() { - err := os.Setenv(jfMsiEnvVariable, originalJfMsi) - assert.NoError(t, err) - }() - originalReportUsage := os.Getenv(coreutils.ReportUsage) - defer func() { - err := os.Setenv(coreutils.ReportUsage, originalReportUsage) - assert.NoError(t, err) - }() - - err := os.Setenv(coreutils.ReportUsage, "") - assert.NoError(t, err) - err = os.Setenv(jfMsiEnvVariable, "") - assert.NoError(t, err) + defer tests.SetEnvWithCallbackAndAssert(t, JfMsiEnvVariable, "") + defer tests.SetEnvWithCallbackAndAssert(t, coreutils.ReportUsage, "") // Minimum Xsc version. mockServer, serverDetails := xscServer(t, AnalyticsMetricsMinXscVersion) @@ -49,63 +36,45 @@ func TestCalcShouldReportEvents(t *testing.T) { // Lower Xsc version. mockServer, serverDetails = xscServer(t, lowerAnalyticsMetricsMinXscVersion) - defer mockServer.Close() am = NewAnalyticsMetricsService(serverDetails) assert.False(t, am.calcShouldReportEvents()) // Higher Xsc version. mockServer, serverDetails = xscServer(t, higherAnalyticsMetricsMinXscVersion) - defer mockServer.Close() am = NewAnalyticsMetricsService(serverDetails) assert.True(t, am.calcShouldReportEvents()) // JF_MSI was already provided. - err = os.Setenv(jfMsiEnvVariable, "msi") + err := os.Setenv(JfMsiEnvVariable, "msi") assert.NoError(t, err) assert.False(t, am.calcShouldReportEvents()) // JFROG_CLI_REPORT_USAGE is false. - err = os.Setenv(jfMsiEnvVariable, "") + err = os.Setenv(JfMsiEnvVariable, "") assert.NoError(t, err) err = os.Setenv(coreutils.ReportUsage, "false") assert.NoError(t, err) assert.False(t, am.calcShouldReportEvents()) } -func TestAddGeneralEventAndSetMsi(t *testing.T) { - originalMsi := os.Getenv(jfMsiEnvVariable) - defer func() { - assert.NoError(t, os.Setenv(jfMsiEnvVariable, originalMsi)) - }() +func TestAddGeneralEvent(t *testing.T) { + defer tests.SetEnvWithCallbackAndAssert(t, JfMsiEnvVariable, "") // Successful flow. mockServer, serverDetails := xscServer(t, AnalyticsMetricsMinXscVersion) defer mockServer.Close() am := NewAnalyticsMetricsService(serverDetails) - params := services.XrayGraphScanParams{} - am.AddGeneralEventAndSetMsi(¶ms) - assert.NotEmpty(t, am.GetMsi()) - assert.Equal(t, params.MultiScanId, am.GetMsi()) - assert.Equal(t, am.GetMsi(), os.Getenv(jfMsiEnvVariable)) + am.AddGeneralEvent() + assert.Equal(t, am.GetMsi(), testMsi) // In case cli should not report analytics, verify that request won't be sent. am.shouldReportEvents = false am.SetMsi("test-msi") - am.AddGeneralEventAndSetMsi(¶ms) + am.AddGeneralEvent() assert.Equal(t, "test-msi", am.GetMsi()) } -func TestCreateAuditResultsFromXscAnalyticsBasicGeneralEvent(t *testing.T) { - mockServer, serverDetails := xscServer(t, AnalyticsMetricsMinXscVersion) - defer mockServer.Close() - am := NewAnalyticsMetricsService(serverDetails) - am.SetStartTime() - - // no audit results - event := am.createAuditResultsFromXscAnalyticsBasicGeneralEvent(&Results{}) - assert.Equal(t, 0, event.TotalFindings) - - // audit result, each scan has 2 result (total 10 scan results). +func TestAnalyticsMetricsService_createAuditResultsFromXscAnalyticsBasicGeneralEvent(t *testing.T) { auditResults := Results{ ScaResults: []ScaScanResult{{}, {}}, ExtendedScanResults: &ExtendedScanResults{ @@ -115,27 +84,30 @@ func TestCreateAuditResultsFromXscAnalyticsBasicGeneralEvent(t *testing.T) { SastScanResults: []*sarif.Run{{}, {}}, }, } - event = am.createAuditResultsFromXscAnalyticsBasicGeneralEvent(&auditResults) - - assert.Equal(t, 10, event.TotalFindings) - assert.Equal(t, xscservices.Completed, event.EventStatus) - totalDuration, err := time.ParseDuration(event.TotalScanDuration) - assert.NoError(t, err) - assert.True(t, totalDuration > 0) - - // Scan failed because sca/jas errors. - auditResults.JasError = errors.New("jas error") - event = am.createAuditResultsFromXscAnalyticsBasicGeneralEvent(&auditResults) - assert.Equal(t, 10, event.TotalFindings) - assert.Equal(t, xscservices.Failed, event.EventStatus) - totalDuration, err = time.ParseDuration(event.TotalScanDuration) - assert.NoError(t, err) - assert.True(t, totalDuration > 0) - - auditResults.ScaError = errors.New("sca error") - auditResults.JasError = nil - event = am.createAuditResultsFromXscAnalyticsBasicGeneralEvent(&auditResults) - assert.Equal(t, xscservices.Failed, event.EventStatus) + testStruct := []struct { + name string + auditResults *Results + want xscservices.XscAnalyticsBasicGeneralEvent + }{ + {name: "No audit results", auditResults: &Results{}, want: xscservices.XscAnalyticsBasicGeneralEvent{EventStatus: xscservices.Completed}}, + {name: "Valid audit result", auditResults: &auditResults, want: xscservices.XscAnalyticsBasicGeneralEvent{TotalFindings: 10, EventStatus: xscservices.Completed}}, + {name: "Scan failed because jas errors.", auditResults: &Results{JasError: errors.New("jas error"), ScaResults: []ScaScanResult{{}, {}}}, want: xscservices.XscAnalyticsBasicGeneralEvent{TotalFindings: 2, EventStatus: xscservices.Failed}}, + {name: "Scan failed because sca errors.", auditResults: &Results{JasError: errors.New("sca error")}, want: xscservices.XscAnalyticsBasicGeneralEvent{TotalFindings: 0, EventStatus: xscservices.Failed}}, + } + mockServer, serverDetails := xscServer(t, AnalyticsMetricsMinXscVersion) + defer mockServer.Close() + am := NewAnalyticsMetricsService(serverDetails) + am.SetStartTime() + for _, tt := range testStruct { + t.Run(tt.name, func(t *testing.T) { + event := am.createAuditResultsFromXscAnalyticsBasicGeneralEvent(tt.auditResults) + assert.Equal(t, tt.want.TotalFindings, event.TotalFindings) + assert.Equal(t, tt.want.EventStatus, event.EventStatus) + totalDuration, err := time.ParseDuration(event.TotalScanDuration) + assert.NoError(t, err) + assert.True(t, totalDuration > 0) + }) + } } func xscServer(t *testing.T, xscVersion string) (*httptest.Server, *config.ServerDetails) { diff --git a/utils/analyzermanager.go b/utils/analyzermanager.go index 5a20be0d..9dacb8c3 100644 --- a/utils/analyzermanager.go +++ b/utils/analyzermanager.go @@ -36,7 +36,7 @@ const ( unsupportedOsExitCode = 55 ErrFailedScannerRun = "failed to run %s scan. Exit code received: %s" jfrogCliAnalyzerManagerVersionEnvVariable = "JFROG_CLI_ANALYZER_MANAGER_VERSION" - jfMsiEnvVariable = "JF_MSI" + JfMsiEnvVariable = "JF_MSI" ) type ApplicabilityStatus string @@ -92,7 +92,7 @@ func (am *AnalyzerManager) ExecWithOutputFile(configFile, scanCommand, workingDi return } var cmd *exec.Cmd - multiScanId := os.Getenv(jfMsiEnvVariable) + multiScanId := os.Getenv(JfMsiEnvVariable) if len(outputFile) > 0 { log.Debug("Executing", am.AnalyzerManagerFullPath, scanCommand, configFile, outputFile, multiScanId) cmd = exec.Command(am.AnalyzerManagerFullPath, scanCommand, configFile, outputFile) diff --git a/utils/auditbasicparams.go b/utils/auditbasicparams.go index e66a618f..faff271a 100644 --- a/utils/auditbasicparams.go +++ b/utils/auditbasicparams.go @@ -61,6 +61,7 @@ type AuditBasicParams struct { dependenciesForApplicabilityScan []string exclusions []string isRecursiveScan bool + multiScanId string } func (abp *AuditBasicParams) DirectDependencies() []string { @@ -144,6 +145,14 @@ func (abp *AuditBasicParams) SetProgress(progress ioUtils.ProgressMgr) { abp.progress = progress } +func (abp *AuditBasicParams) MultiScanId() string { + return abp.multiScanId +} + +func (abp *AuditBasicParams) SetMultiScanId(multiScanId string) { + abp.multiScanId = multiScanId +} + func (abp *AuditBasicParams) Args() []string { return abp.args } diff --git a/utils/xraymanager.go b/utils/xraymanager.go index eb7446a2..56ed02a0 100644 --- a/utils/xraymanager.go +++ b/utils/xraymanager.go @@ -6,8 +6,8 @@ import ( "github.com/jfrog/jfrog-client-go/xray" ) -func CreateXrayServiceManager(serviceDetails *config.ServerDetails) (*xray.XrayServicesManager, error) { - xrayDetails, err := serviceDetails.CreateXrayAuthConfig() +func CreateXrayServiceManager(serverDetails *config.ServerDetails) (*xray.XrayServicesManager, error) { + xrayDetails, err := serverDetails.CreateXrayAuthConfig() if err != nil { return nil, err } From 2c9fcba6b46b44cd7c079646e24bb9b8fd55108a Mon Sep 17 00:00:00 2001 From: gail Date: Mon, 1 Apr 2024 17:22:10 +0300 Subject: [PATCH 12/32] Add integration test. --- audit_test.go | 28 ++++++++++----------- go.mod | 8 ++++-- go.sum | 8 +++--- jfrogclisecurity_test.go | 1 + scans_test.go | 6 ++--- tests/config.go | 3 +++ tests/consts.go | 1 + tests/utils/test_config.go | 22 ++++++++++++++++ tests/utils/test_utils.go | 10 ++++++-- tests/utils/test_validation.go | 12 +++++++++ utils/analyticsmetrics.go | 17 +++++++++++-- utils/analyticsmetrics_test.go | 10 +++++--- utils/resultwriter.go | 1 + xray_test.go | 4 +-- xsc_test.go | 46 ++++++++++++++++++++++++++++++++++ 15 files changed, 144 insertions(+), 33 deletions(-) create mode 100644 xsc_test.go diff --git a/audit_test.go b/audit_test.go index 51bafd55..dbb3a172 100644 --- a/audit_test.go +++ b/audit_test.go @@ -35,7 +35,7 @@ func TestXrayAuditNpmSimpleJson(t *testing.T) { } func testXrayAuditNpm(t *testing.T, format string) string { - securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion) + securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion, "") tempDirPath, createTempDirCallback := coreTests.CreateTempDirWithCallbackAndAssert(t) defer createTempDirCallback() npmProjectPath := filepath.Join(filepath.FromSlash(securityTestUtils.GetTestResourcesPath()), "projects", "package-managers", "npm", "npm") @@ -61,7 +61,7 @@ func TestXrayAuditPnpmSimpleJson(t *testing.T) { } func testXrayAuditPnpm(t *testing.T, format string) string { - securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion) + securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion, "") tempDirPath, createTempDirCallback := coreTests.CreateTempDirWithCallbackAndAssert(t) defer createTempDirCallback() npmProjectPath := filepath.Join(filepath.FromSlash(securityTestUtils.GetTestResourcesPath()), "projects", "package-managers", "npm", "npm-no-lock") @@ -117,7 +117,7 @@ func TestXrayAuditYarnV1SimpleJson(t *testing.T) { } func testXrayAuditYarn(t *testing.T, projectDirName string, yarnCmd func()) { - securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion) + securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion, "") tempDirPath, createTempDirCallback := coreTests.CreateTempDirWithCallbackAndAssert(t) defer createTempDirCallback() yarnProjectPath := filepath.Join(filepath.FromSlash(securityTestUtils.GetTestResourcesPath()), "projects", "package-managers", "yarn", projectDirName) @@ -232,7 +232,7 @@ func TestXrayAuditNugetSimpleJson(t *testing.T) { } func testXrayAuditNuget(t *testing.T, projectName, format string, restoreTech string) string { - securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion) + securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion, "") tempDirPath, createTempDirCallback := coreTests.CreateTempDirWithCallbackAndAssert(t) defer createTempDirCallback() projectPath := filepath.Join(filepath.FromSlash(securityTestUtils.GetTestResourcesPath()), "projects", "package-managers", "nuget", projectName) @@ -261,7 +261,7 @@ func TestXrayAuditGradleSimpleJson(t *testing.T) { } func testXrayAuditGradle(t *testing.T, format string) string { - securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion) + securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion, "") tempDirPath, createTempDirCallback := coreTests.CreateTempDirWithCallbackAndAssert(t) defer createTempDirCallback() gradleProjectPath := filepath.Join(filepath.FromSlash(securityTestUtils.GetTestResourcesPath()), "projects", "package-managers", "gradle", "gradle") @@ -285,7 +285,7 @@ func TestXrayAuditMavenSimpleJson(t *testing.T) { } func testXrayAuditMaven(t *testing.T, format string) string { - securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion) + securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion, "") tempDirPath, createTempDirCallback := coreTests.CreateTempDirWithCallbackAndAssert(t) defer createTempDirCallback() mvnProjectPath := filepath.Join(filepath.FromSlash(securityTestUtils.GetTestResourcesPath()), "projects", "package-managers", "maven", "maven") @@ -299,7 +299,7 @@ func testXrayAuditMaven(t *testing.T, format string) string { } func TestXrayAuditNoTech(t *testing.T) { - securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion) + securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion, "") tempDirPath, createTempDirCallback := coreTests.CreateTempDirWithCallbackAndAssert(t) defer createTempDirCallback() prevWd := securityTestUtils.ChangeWD(t, tempDirPath) @@ -310,7 +310,7 @@ func TestXrayAuditNoTech(t *testing.T) { } func TestXrayAuditMultiProjects(t *testing.T) { - securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion) + securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion, "") tempDirPath, createTempDirCallback := coreTests.CreateTempDirWithCallbackAndAssert(t) defer createTempDirCallback() multiProject := filepath.Join(filepath.FromSlash(securityTestUtils.GetTestResourcesPath()), "projects") @@ -350,7 +350,7 @@ func TestXrayAuditPipSimpleJsonWithRequirementsFile(t *testing.T) { } func testXrayAuditPip(t *testing.T, format, requirementsFile string) string { - securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion) + securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion, "") tempDirPath, createTempDirCallback := coreTests.CreateTempDirWithCallbackAndAssert(t) defer createTempDirCallback() pipProjectPath := filepath.Join(filepath.FromSlash(securityTestUtils.GetTestResourcesPath()), "projects", "package-managers", "python", "pip", "pip-project") @@ -379,7 +379,7 @@ func TestXrayAuditPipenvSimpleJson(t *testing.T) { } func testXrayAuditPipenv(t *testing.T, format string) string { - securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion) + securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion, "") tempDirPath, createTempDirCallback := coreTests.CreateTempDirWithCallbackAndAssert(t) defer createTempDirCallback() pipenvProjectPath := filepath.Join(filepath.FromSlash(securityTestUtils.GetTestResourcesPath()), "projects", "package-managers", "python", "pipenv", "pipenv-project") @@ -403,7 +403,7 @@ func TestXrayAuditPoetrySimpleJson(t *testing.T) { } func testXrayAuditPoetry(t *testing.T, format string) string { - securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion) + securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion, "") tempDirPath, createTempDirCallback := coreTests.CreateTempDirWithCallbackAndAssert(t) defer createTempDirCallback() poetryProjectPath := filepath.Join(filepath.FromSlash(securityTestUtils.GetTestResourcesPath()), "projects", "package-managers", "python", "poetry", "poetry-project") @@ -445,7 +445,7 @@ func TestXrayAuditJasNoViolationsSimpleJson(t *testing.T) { } func testXrayAuditJas(t *testing.T, format string, project string) string { - securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion) + securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion, "") tempDirPath, createTempDirCallback := coreTests.CreateTempDirWithCallbackAndAssert(t) defer createTempDirCallback() projectDir := filepath.Join(filepath.FromSlash(securityTestUtils.GetTestResourcesPath()), filepath.Join("projects", project)) @@ -462,7 +462,7 @@ func testXrayAuditJas(t *testing.T, format string, project string) string { } func TestXrayAuditDetectTech(t *testing.T) { - securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion) + securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion, "") tempDirPath, createTempDirCallback := coreTests.CreateTempDirWithCallbackAndAssert(t) defer createTempDirCallback() mvnProjectPath := filepath.Join(filepath.FromSlash(securityTestUtils.GetTestResourcesPath()), "projects", "package-managers", "maven", "maven") @@ -480,7 +480,7 @@ func TestXrayAuditDetectTech(t *testing.T) { } func TestXrayRecursiveScan(t *testing.T) { - securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion) + securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion, "") tempDirPath, createTempDirCallback := coreTests.CreateTempDirWithCallbackAndAssert(t) defer createTempDirCallback() projectDir := filepath.Join(filepath.FromSlash(securityTestUtils.GetTestResourcesPath()), "projects", "package-managers") diff --git a/go.mod b/go.mod index fa64ecd9..0b11869d 100644 --- a/go.mod +++ b/go.mod @@ -98,8 +98,12 @@ require ( gopkg.in/warnings.v0 v0.1.2 // indirect ) -replace github.com/jfrog/jfrog-cli-core/v2 => github.com/gailazar300/jfrog-cli-core/v2 v2.0.0-20240331095546-a03b2d7f67da +replace github.com/jfrog/jfrog-cli-core/v2 => github.com/gailazar300/jfrog-cli-core/v2 v2.0.0-20240401141758-ff916d692830 -replace github.com/jfrog/jfrog-client-go => github.com/gailazar300/jfrog-client-go v0.18.1-0.20240331091256-e2e7cd419323 +//replace github.com/jfrog/jfrog-cli-core/v2 => ../jfrog-cli-core +replace github.com/jfrog/jfrog-client-go => github.com/gailazar300/jfrog-client-go v0.18.1-0.20240401141433-9b8da01b5758 + +//replace github.com/jfrog/jfrog-client-go => ../jfrog-client-go +// // replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go dev diff --git a/go.sum b/go.sum index c363f965..dd574515 100644 --- a/go.sum +++ b/go.sum @@ -60,10 +60,10 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/gailazar300/jfrog-cli-core/v2 v2.0.0-20240331095546-a03b2d7f67da h1:6v7I8AfW12IK7Sr5zTf3thRO+NyY/YEjfIcud1ieVEM= -github.com/gailazar300/jfrog-cli-core/v2 v2.0.0-20240331095546-a03b2d7f67da/go.mod h1:95AsjwlMLNWU0v71/3dS715e1RAQfvPO47RRHz2xKh8= -github.com/gailazar300/jfrog-client-go v0.18.1-0.20240331091256-e2e7cd419323 h1:s1bOQdculuurDa2BjMRYG3Q+Lz12YMuyc09XRPbTWyo= -github.com/gailazar300/jfrog-client-go v0.18.1-0.20240331091256-e2e7cd419323/go.mod h1:tUyEmxznphh0nwAGo6xz9Sps7RRW/TBMxIJZteo+j2k= +github.com/gailazar300/jfrog-cli-core/v2 v2.0.0-20240401141758-ff916d692830 h1:mfpokH1jRIN+3jEJDrsx4woqI3AQVRlc2l03hZU3KaI= +github.com/gailazar300/jfrog-cli-core/v2 v2.0.0-20240401141758-ff916d692830/go.mod h1:hTG5P+vzf8/hp/GU1o9Ed3DbkwYQopNRw4yPBkgurAU= +github.com/gailazar300/jfrog-client-go v0.18.1-0.20240401141433-9b8da01b5758 h1:NYb4hSqMXCwyvlHVasfvVfuHL9NVzmFHom4cJIvviBc= +github.com/gailazar300/jfrog-client-go v0.18.1-0.20240401141433-9b8da01b5758/go.mod h1:tUyEmxznphh0nwAGo6xz9Sps7RRW/TBMxIJZteo+j2k= github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= diff --git a/jfrogclisecurity_test.go b/jfrogclisecurity_test.go index 3af50790..94253546 100644 --- a/jfrogclisecurity_test.go +++ b/jfrogclisecurity_test.go @@ -40,6 +40,7 @@ func setupIntegrationTests() { // Init utils.InitTestCliDetails() utils.AuthenticateArtifactory() + utils.AuthenticateXsc() utils.CreateRequiredRepositories() } diff --git a/scans_test.go b/scans_test.go index 6d9b6bae..eb257be6 100644 --- a/scans_test.go +++ b/scans_test.go @@ -74,13 +74,13 @@ func TestXrayBinaryScanSimpleJsonWithProgress(t *testing.T) { } func testXrayBinaryScan(t *testing.T, format string) string { - securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion) + securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion, "") binariesPath := filepath.Join(filepath.FromSlash(securityTestUtils.GetTestResourcesPath()), "projects", "binaries", "*") return securityTests.PlatformCli.RunCliCmdWithOutput(t, "scan", binariesPath, "--licenses", "--format="+format) } func TestXrayBinaryScanWithBypassArchiveLimits(t *testing.T) { - securityTestUtils.InitSecurityTest(t, scan.BypassArchiveLimitsMinXrayVersion) + securityTestUtils.InitSecurityTest(t, scan.BypassArchiveLimitsMinXrayVersion, "") unsetEnv := clientTestUtils.SetEnvWithCallbackAndAssert(t, "JF_INDEXER_COMPRESS_MAXENTITIES", "10") defer unsetEnv() binariesPath := filepath.Join(filepath.FromSlash(securityTestUtils.GetTestResourcesPath()), "projects", "binaries", "*") @@ -236,7 +236,7 @@ func createTestWatch(t *testing.T) (string, func()) { // Curation tests func TestCurationAudit(t *testing.T) { - securityTestUtils.InitSecurityTest(t, "") + securityTestUtils.InitSecurityTest(t, "", "") tempDirPath, createTempDirCallback := coreTests.CreateTempDirWithCallbackAndAssert(t) defer createTempDirCallback() multiProject := filepath.Join(filepath.FromSlash(securityTestUtils.GetTestResourcesPath()), "projects", "package-managers", "npm") diff --git a/tests/config.go b/tests/config.go index 9fe0641e..743ab542 100644 --- a/tests/config.go +++ b/tests/config.go @@ -16,6 +16,9 @@ var ( XrDetails *config.ServerDetails XrAuth auth.ServiceDetails + XscDetails *config.ServerDetails + XscAuth auth.ServiceDetails + RtDetails *config.ServerDetails RtAuth auth.ServiceDetails RtHttpDetails httputils.HttpClientDetails diff --git a/tests/consts.go b/tests/consts.go index 2b39678b..6e6f9f8e 100644 --- a/tests/consts.go +++ b/tests/consts.go @@ -16,6 +16,7 @@ const ( const ( XrayEndpoint = "xray/" + XscEndpoint = "xsc/" ArtifactoryEndpoint = "artifactory/" AccessEndpoint = "access/" RepoDetailsEndpoint = "api/repositories/" diff --git a/tests/utils/test_config.go b/tests/utils/test_config.go index 63c2c1e5..57705110 100644 --- a/tests/utils/test_config.go +++ b/tests/utils/test_config.go @@ -78,6 +78,28 @@ func authenticateXray() string { return cred } +func AuthenticateXsc() string { + *configTests.JfrogUrl = clientUtils.AddTrailingSlashIfNeeded(*configTests.JfrogUrl) + configTests.XscDetails = &config.ServerDetails{Url: *configTests.JfrogUrl, ArtifactoryUrl: *configTests.JfrogUrl + configTests.ArtifactoryEndpoint, XrayUrl: *configTests.JfrogUrl + configTests.XrayEndpoint, XscUrl: *configTests.JfrogUrl + configTests.XscEndpoint} + cred := fmt.Sprintf("--url=%s", configTests.XscDetails.XrayUrl) + if *configTests.JfrogAccessToken != "" { + + configTests.XscDetails.AccessToken = *configTests.JfrogAccessToken + cred += fmt.Sprintf(" --access-token=%s", configTests.XscDetails.AccessToken) + } else { + configTests.XscDetails.User = *configTests.JfrogUser + configTests.XscDetails.Password = *configTests.JfrogPassword + cred += fmt.Sprintf(" --user=%s --password=%s", configTests.XscDetails.User, configTests.XscDetails.Password) + } + + var err error + if configTests.XscAuth, err = configTests.XscDetails.CreateXscAuthConfig(); err != nil { + coreutils.ExitOnErr(errors.New("Failed while attempting to authenticate with Xsc: " + err.Error())) + } + configTests.XscDetails.XscUrl = configTests.XscAuth.GetUrl() + return cred +} + func AuthenticateArtifactory() string { *configTests.JfrogUrl = clientUtils.AddTrailingSlashIfNeeded(*configTests.JfrogUrl) configTests.RtDetails = &config.ServerDetails{Url: *configTests.JfrogUrl, ArtifactoryUrl: *configTests.JfrogUrl + configTests.ArtifactoryEndpoint, SshKeyPath: *configTests.JfrogSshKeyPath, SshPassphrase: *configTests.JfrogSshPassphrase} diff --git a/tests/utils/test_utils.go b/tests/utils/test_utils.go index 0988f4b4..9198b15d 100644 --- a/tests/utils/test_utils.go +++ b/tests/utils/test_utils.go @@ -16,11 +16,12 @@ import ( clientTests "github.com/jfrog/jfrog-client-go/utils/tests" ) -func InitSecurityTest(t *testing.T, minVersion string) { +func InitSecurityTest(t *testing.T, xrayMinVersion, xscMinVersion string) { if !*configTests.TestSecurity { t.Skip("Skipping Security test. To run Security test add the '-test.security=true' option.") } - ValidateXrayVersion(t, minVersion) + ValidateXrayVersion(t, xrayMinVersion) + ValidateXscVersion(t, xscMinVersion) } func GetTestResourcesPath() string { @@ -57,6 +58,11 @@ func getXrayVersion() (version.Version, error) { return *version.NewVersion(xrayVersion), err } +func getXscVersion() (version.Version, error) { + xscVersion, err := configTests.XscAuth.GetVersion() + return *version.NewVersion(xscVersion), err +} + func ChangeWD(t *testing.T, newPath string) string { prevDir, err := os.Getwd() assert.NoError(t, err, "Failed to get current dir") diff --git a/tests/utils/test_validation.go b/tests/utils/test_validation.go index b92e451d..dfad3acf 100644 --- a/tests/utils/test_validation.go +++ b/tests/utils/test_validation.go @@ -26,6 +26,18 @@ func ValidateXrayVersion(t *testing.T, minVersion string) { } } +func ValidateXscVersion(t *testing.T, minVersion string) { + xscVersion, err := getXscVersion() + if err != nil { + assert.NoError(t, err) + return + } + err = clientUtils.ValidateMinimumVersion(clientUtils.Xsc, xscVersion.GetVersion(), minVersion) + if err != nil { + t.Skip(err) + } +} + func VerifyJsonScanResults(t *testing.T, content string, minViolations, minVulnerabilities, minLicenses int) { var results []services.ScanResponse err := json.Unmarshal([]byte(content), &results) diff --git a/utils/analyticsmetrics.go b/utils/analyticsmetrics.go index 0d74577a..43671fce 100644 --- a/utils/analyticsmetrics.go +++ b/utils/analyticsmetrics.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" + "github.com/jfrog/jfrog-cli-core/v2/utils/usage" clientutils "github.com/jfrog/jfrog-client-go/utils" "github.com/jfrog/jfrog-client-go/utils/log" "github.com/jfrog/jfrog-client-go/xsc" @@ -38,7 +39,7 @@ func NewAnalyticsMetricsService(serviceDetails *config.ServerDetails) *Analytics func (ams *AnalyticsMetricsService) calcShouldReportEvents() bool { // A user who explicitly requests not to send reports will not receive XSC analytics metrics. - if os.Getenv(coreutils.ReportUsage) == "false" { + if !usage.ShouldReportUsage() { return false } // There is no need to report the event and generate a new msi for the cli scan if the msi was provided. @@ -107,7 +108,7 @@ func (ams *AnalyticsMetricsService) AddGeneralEvent() { log.Debug(fmt.Errorf("failed sending general event request to XSC service, error: %s ", err.Error())) return } - log.Debug(fmt.Sprintf("New General event added successfully. multi_scan_id %s", ams.GetMsi())) + log.Debug(fmt.Sprintf("New General event added successfully. multi_scan_id %s", msi)) // Set event's analytics data. ams.SetMsi(msi) ams.SetStartTime() @@ -128,6 +129,18 @@ func (ams *AnalyticsMetricsService) UpdateGeneralEvent(auditResults *Results) { } } +func (ams *AnalyticsMetricsService) GetGeneralEvent(msi string) (*xscservices.XscAnalyticsGeneralEvent, error) { + if !ams.ShouldReportEvents() { + log.Debug("Can't get general event from XSC - analytics metrics are disabled.") + return nil, nil + } + event, err := ams.xscManager.GetAnalyticsGeneralEvent(msi) + if err != nil { + log.Debug(fmt.Sprintf("failed getting general event from XSC service for multi_scan_id %s, error: %s \"", msi, err.Error())) + } + return event, err +} + func (ams *AnalyticsMetricsService) createAuditResultsFromXscAnalyticsBasicGeneralEvent(auditResults *Results) xscservices.XscAnalyticsBasicGeneralEvent { totalDuration := time.Since(ams.GetStartTime()) totalFindings := len(auditResults.ScaResults) diff --git a/utils/analyticsmetrics_test.go b/utils/analyticsmetrics_test.go index 911fa7dc..149c2aa9 100644 --- a/utils/analyticsmetrics_test.go +++ b/utils/analyticsmetrics_test.go @@ -25,8 +25,10 @@ const ( func TestCalcShouldReportEvents(t *testing.T) { // Save original environment information. - defer tests.SetEnvWithCallbackAndAssert(t, JfMsiEnvVariable, "") - defer tests.SetEnvWithCallbackAndAssert(t, coreutils.ReportUsage, "") + msiCallback := tests.SetEnvWithCallbackAndAssert(t, JfMsiEnvVariable, "") + defer msiCallback() + reportUsageCallback := tests.SetEnvWithCallbackAndAssert(t, coreutils.ReportUsage, "") + defer reportUsageCallback() // Minimum Xsc version. mockServer, serverDetails := xscServer(t, AnalyticsMetricsMinXscVersion) @@ -58,8 +60,8 @@ func TestCalcShouldReportEvents(t *testing.T) { } func TestAddGeneralEvent(t *testing.T) { - defer tests.SetEnvWithCallbackAndAssert(t, JfMsiEnvVariable, "") - + msiCallback := tests.SetEnvWithCallbackAndAssert(t, JfMsiEnvVariable, "") + defer msiCallback() // Successful flow. mockServer, serverDetails := xscServer(t, AnalyticsMetricsMinXscVersion) defer mockServer.Close() diff --git a/utils/resultwriter.go b/utils/resultwriter.go index b7dafea4..ef2a1ed2 100644 --- a/utils/resultwriter.go +++ b/utils/resultwriter.go @@ -365,6 +365,7 @@ func ConvertXrayScanToSimpleJson(results *Results, isMultipleRoots, includeLicen jsonTable.LicensesViolations = licViolationsJsonTable jsonTable.OperationalRiskViolations = opRiskViolationsJsonTable } + jsonTable.MultiScanId = results.MultiScanId return jsonTable, nil } diff --git a/xray_test.go b/xray_test.go index 695162dc..5845cdd6 100644 --- a/xray_test.go +++ b/xray_test.go @@ -11,7 +11,7 @@ import ( ) func TestXrayCurl(t *testing.T) { - securityTestUtils.InitSecurityTest(t, "") + securityTestUtils.InitSecurityTest(t, "", "") // Configure a new server named "default". securityTestUtils.CreateJfrogHomeConfig(t, true) defer securityTestUtils.CleanTestsHomeEnv() @@ -27,7 +27,7 @@ func TestXrayCurl(t *testing.T) { } func TestXrayOfflineDBSyncV3(t *testing.T) { - securityTestUtils.InitSecurityTest(t, "") + securityTestUtils.InitSecurityTest(t, "", "") // Validate license-id err := securityTests.PlatformCli.WithoutCredentials().Exec("xr", "ou") assert.EqualError(t, err, "Mandatory flag 'license-id' is missing") diff --git a/xsc_test.go b/xsc_test.go new file mode 100644 index 00000000..fb1661eb --- /dev/null +++ b/xsc_test.go @@ -0,0 +1,46 @@ +package main + +import ( + "encoding/json" + "github.com/jfrog/jfrog-cli-core/v2/common/format" + "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" + "github.com/jfrog/jfrog-cli-security/formats" + "github.com/jfrog/jfrog-cli-security/scangraph" + securityTests "github.com/jfrog/jfrog-cli-security/tests" + securityTestUtils "github.com/jfrog/jfrog-cli-security/tests/utils" + "github.com/jfrog/jfrog-cli-security/utils" + "github.com/jfrog/jfrog-client-go/utils/tests" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestXscAnalyticsForAudit(t *testing.T) { + securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion, utils.AnalyticsMetricsMinXscVersion) + reportUsageCallBack := tests.SetEnvWithCallbackAndAssert(t, coreutils.ReportUsage, "true") + defer reportUsageCallBack() + // Scan npm project and verify that analytics general event were sent to XSC. + output := testXrayAuditNpm(t, string(format.SimpleJson)) + validateAnalyticsBasicEvent(t, output) +} + +func validateAnalyticsBasicEvent(t *testing.T, output string) { + // Get MSI. + var results formats.SimpleJsonResults + err := json.Unmarshal([]byte(output), &results) + assert.NoError(t, err) + + // Verify analytics metrics. + am := utils.NewAnalyticsMetricsService(securityTests.XscDetails) + assert.NotNil(t, am) + event, err := am.GetGeneralEvent(results.MultiScanId) + assert.NoError(t, err) + + // Event creation and addition information. + assert.Equal(t, "cli", event.Product) + assert.Equal(t, 1, event.EventType) + assert.NotEmpty(t, event.EventStatus) + assert.NotEmpty(t, event.AnalyzerManagerVersion) + // The information that was added after updating the event with the scan's results. + assert.NotEmpty(t, event.TotalScanDuration) + assert.True(t, event.TotalFindings > 0) +} From fc0f2dff39365bdb9608b1657d9657c33d4b1547 Mon Sep 17 00:00:00 2001 From: gail Date: Mon, 1 Apr 2024 17:37:14 +0300 Subject: [PATCH 13/32] Minor fixes. --- commands/audit/jasrunner_test.go | 6 +++--- utils/analyticsmetrics_test.go | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/commands/audit/jasrunner_test.go b/commands/audit/jasrunner_test.go index 20b28c8a..d9587dab 100644 --- a/commands/audit/jasrunner_test.go +++ b/commands/audit/jasrunner_test.go @@ -22,14 +22,14 @@ func TestGetExtendedScanResults_AnalyzerManagerDoesntExist(t *testing.T) { assert.NoError(t, os.Unsetenv(coreutils.HomeDir)) }() scanResults := &utils.Results{ScaResults: []utils.ScaScanResult{{Technology: coreutils.Yarn, XrayResults: jas.FakeBasicXrayResults}}, ExtendedScanResults: &utils.ExtendedScanResults{}} - err = runJasScannersAndSetResults(scanResults, []string{"issueId_1_direct_dependency", "issueId_2_direct_dependency"}, &jas.FakeServerDetails, nil, nil, false) + err = runJasScannersAndSetResults(scanResults, []string{"issueId_1_direct_dependency", "issueId_2_direct_dependency"}, &jas.FakeServerDetails, nil, nil, false, "") // Expect error: assert.Error(t, err) } func TestGetExtendedScanResults_ServerNotValid(t *testing.T) { scanResults := &utils.Results{ScaResults: []utils.ScaScanResult{{Technology: coreutils.Pip, XrayResults: jas.FakeBasicXrayResults}}, ExtendedScanResults: &utils.ExtendedScanResults{}} - err := runJasScannersAndSetResults(scanResults, []string{"issueId_1_direct_dependency", "issueId_2_direct_dependency"}, nil, nil, nil, false) + err := runJasScannersAndSetResults(scanResults, []string{"issueId_1_direct_dependency", "issueId_2_direct_dependency"}, nil, nil, nil, false, "") assert.NoError(t, err) } @@ -37,7 +37,7 @@ func TestGetExtendedScanResults_AnalyzerManagerReturnsError(t *testing.T) { assert.NoError(t, utils.DownloadAnalyzerManagerIfNeeded()) scanResults := &utils.Results{ScaResults: []utils.ScaScanResult{{Technology: coreutils.Yarn, XrayResults: jas.FakeBasicXrayResults}}, ExtendedScanResults: &utils.ExtendedScanResults{}} - err := runJasScannersAndSetResults(scanResults, []string{"issueId_2_direct_dependency", "issueId_1_direct_dependency"}, &jas.FakeServerDetails, nil, nil, false) + err := runJasScannersAndSetResults(scanResults, []string{"issueId_2_direct_dependency", "issueId_1_direct_dependency"}, &jas.FakeServerDetails, nil, nil, false, "") // Expect error: assert.ErrorContains(t, err, "failed to run Applicability scan") diff --git a/utils/analyticsmetrics_test.go b/utils/analyticsmetrics_test.go index 149c2aa9..48f337d3 100644 --- a/utils/analyticsmetrics_test.go +++ b/utils/analyticsmetrics_test.go @@ -37,12 +37,14 @@ func TestCalcShouldReportEvents(t *testing.T) { assert.True(t, am.calcShouldReportEvents()) // Lower Xsc version. - mockServer, serverDetails = xscServer(t, lowerAnalyticsMetricsMinXscVersion) + mockServerLowerVersion, serverDetails := xscServer(t, lowerAnalyticsMetricsMinXscVersion) + defer mockServerLowerVersion.Close() am = NewAnalyticsMetricsService(serverDetails) assert.False(t, am.calcShouldReportEvents()) // Higher Xsc version. - mockServer, serverDetails = xscServer(t, higherAnalyticsMetricsMinXscVersion) + mockServerHigherVersion, serverDetails := xscServer(t, higherAnalyticsMetricsMinXscVersion) + defer mockServerHigherVersion.Close() am = NewAnalyticsMetricsService(serverDetails) assert.True(t, am.calcShouldReportEvents()) From b9560dab306a7cc1161a06b373288330f462504c Mon Sep 17 00:00:00 2001 From: gail Date: Tue, 2 Apr 2024 12:02:51 +0300 Subject: [PATCH 14/32] Change add general event flow for Frogbot. --- commands/audit/audit.go | 2 +- utils/analyticsmetrics.go | 52 +++++++++++++++++++++++----------- utils/analyticsmetrics_test.go | 4 +-- 3 files changed, 39 insertions(+), 19 deletions(-) diff --git a/commands/audit/audit.go b/commands/audit/audit.go index 8a91f16f..7f5fa070 100644 --- a/commands/audit/audit.go +++ b/commands/audit/audit.go @@ -103,7 +103,7 @@ func (auditCmd *AuditCommand) Run() (err error) { SetGraphBasicParams(auditCmd.AuditBasicParams). SetThirdPartyApplicabilityScan(auditCmd.thirdPartyApplicabilityScan) auditParams.SetIsRecursiveScan(isRecursiveScan).SetExclusions(auditCmd.Exclusions()) - auditCmd.analyticsMetricsService.AddGeneralEvent() + auditCmd.analyticsMetricsService.AddGeneralEvent(auditCmd.analyticsMetricsService.CreateGeneralEvent(xrayutils.CliProduct, xrayutils.CliEventType)) auditParams.SetMultiScanId(auditCmd.analyticsMetricsService.GetMsi()) auditResults, err := RunAudit(auditParams) if err != nil { diff --git a/utils/analyticsmetrics.go b/utils/analyticsmetrics.go index 43671fce..d6f29311 100644 --- a/utils/analyticsmetrics.go +++ b/utils/analyticsmetrics.go @@ -14,7 +14,23 @@ import ( "time" ) -const AnalyticsMetricsMinXscVersion = "1.7.1" +const ( + AnalyticsMetricsMinXscVersion = "1.7.1" +) + +type ProductName string + +const ( + CliProduct ProductName = "cli" + FrogbotProduct ProductName = "frogbot" +) + +type EventType int + +const ( + CliEventType EventType = 1 + FrogbotType EventType = 8 +) type AnalyticsMetricsService struct { xscManager *xsc.XscServicesManager @@ -77,12 +93,7 @@ func (ams *AnalyticsMetricsService) ShouldReportEvents() bool { return ams.shouldReportEvents } -func (ams *AnalyticsMetricsService) AddGeneralEvent() { - if !ams.ShouldReportEvents() { - log.Debug("A general event request was not sent to XSC - analytics metrics are disabled.") - return - } - +func (ams *AnalyticsMetricsService) CreateGeneralEvent(product ProductName, eventType EventType) *xscservices.XscAnalyticsGeneralEvent { osAndArc, err := coreutils.GetOSAndArc() curOs, curArch := "", "" if err != nil { @@ -93,17 +104,26 @@ func (ams *AnalyticsMetricsService) AddGeneralEvent() { curArch = splitOsAndArch[1] } - event := xscservices.XscAnalyticsBasicGeneralEvent{ - EventType: 1, - EventStatus: xscservices.Started, - Product: "cli", - JfrogUser: ams.xscManager.Config().GetServiceDetails().GetUser(), - OsPlatform: curOs, - OsArchitecture: curArch, - AnalyzerManagerVersion: GetAnalyzerManagerVersion(), + event := xscservices.XscAnalyticsGeneralEvent{ + XscAnalyticsBasicGeneralEvent: xscservices.XscAnalyticsBasicGeneralEvent{ + EventType: int(eventType), + EventStatus: xscservices.Started, + Product: string(product), + JfrogUser: ams.xscManager.Config().GetServiceDetails().GetUser(), + OsPlatform: curOs, + OsArchitecture: curArch, + AnalyzerManagerVersion: GetAnalyzerManagerVersion(), + }, } + return &event +} - msi, err := ams.xscManager.AddAnalyticsGeneralEvent(xscservices.XscAnalyticsGeneralEvent{XscAnalyticsBasicGeneralEvent: event}) +func (ams *AnalyticsMetricsService) AddGeneralEvent(event *xscservices.XscAnalyticsGeneralEvent) { + if !ams.ShouldReportEvents() { + log.Debug("A general event request was not sent to XSC - analytics metrics are disabled.") + return + } + msi, err := ams.xscManager.AddAnalyticsGeneralEvent(*event) if err != nil { log.Debug(fmt.Errorf("failed sending general event request to XSC service, error: %s ", err.Error())) return diff --git a/utils/analyticsmetrics_test.go b/utils/analyticsmetrics_test.go index 48f337d3..44bad3a4 100644 --- a/utils/analyticsmetrics_test.go +++ b/utils/analyticsmetrics_test.go @@ -68,13 +68,13 @@ func TestAddGeneralEvent(t *testing.T) { mockServer, serverDetails := xscServer(t, AnalyticsMetricsMinXscVersion) defer mockServer.Close() am := NewAnalyticsMetricsService(serverDetails) - am.AddGeneralEvent() + am.AddGeneralEvent(am.CreateGeneralEvent(CliProduct, CliEventType)) assert.Equal(t, am.GetMsi(), testMsi) // In case cli should not report analytics, verify that request won't be sent. am.shouldReportEvents = false am.SetMsi("test-msi") - am.AddGeneralEvent() + am.AddGeneralEvent(am.CreateGeneralEvent(CliProduct, CliEventType)) assert.Equal(t, "test-msi", am.GetMsi()) } From 040ce9becc21f8e686432912b8a5488d6b037c2f Mon Sep 17 00:00:00 2001 From: gail Date: Tue, 2 Apr 2024 15:05:32 +0300 Subject: [PATCH 15/32] Second review fixes. --- commands/audit/audit.go | 12 ++++++++-- commands/audit/jas/common.go | 19 +++------------ commands/audit/jas/common_test.go | 12 +++++----- commands/audit/jasrunner.go | 3 ++- go.mod | 3 ++- go.sum | 4 ++-- utils/analyticsmetrics.go | 39 ++++++++++--------------------- utils/analyticsmetrics_test.go | 10 ++++---- utils/analyzermanager.go | 2 ++ 9 files changed, 44 insertions(+), 60 deletions(-) diff --git a/commands/audit/audit.go b/commands/audit/audit.go index 7f5fa070..03196e82 100644 --- a/commands/audit/audit.go +++ b/commands/audit/audit.go @@ -9,6 +9,7 @@ import ( "github.com/jfrog/jfrog-client-go/utils/log" "github.com/jfrog/jfrog-client-go/xray" "github.com/jfrog/jfrog-client-go/xray/services" + xscservices "github.com/jfrog/jfrog-client-go/xsc/services" "golang.org/x/sync/errgroup" "os" @@ -103,8 +104,15 @@ func (auditCmd *AuditCommand) Run() (err error) { SetGraphBasicParams(auditCmd.AuditBasicParams). SetThirdPartyApplicabilityScan(auditCmd.thirdPartyApplicabilityScan) auditParams.SetIsRecursiveScan(isRecursiveScan).SetExclusions(auditCmd.Exclusions()) - auditCmd.analyticsMetricsService.AddGeneralEvent(auditCmd.analyticsMetricsService.CreateGeneralEvent(xrayutils.CliProduct, xrayutils.CliEventType)) - auditParams.SetMultiScanId(auditCmd.analyticsMetricsService.GetMsi()) + + if auditParams.MultiScanId() == "" { + // There is no need to add/update the event and generate a new msi for the cli scan if the msi was already provided by FrogBot. + auditCmd.analyticsMetricsService.SetShouldReportEvents(false) + } else { + auditCmd.analyticsMetricsService.AddGeneralEvent(auditCmd.analyticsMetricsService.CreateGeneralEvent(xscservices.CliProduct, xscservices.CliEventType)) + auditParams.SetMultiScanId(auditCmd.analyticsMetricsService.GetMsi()) + } + auditResults, err := RunAudit(auditParams) if err != nil { return diff --git a/commands/audit/jas/common.go b/commands/audit/jas/common.go index dfcb8acf..15bf8103 100644 --- a/commands/audit/jas/common.go +++ b/commands/audit/jas/common.go @@ -25,9 +25,7 @@ import ( ) const ( - NodeModulesPattern = "**/*node_modules*/**" - jfPackageManagerEnvVariable = "AM_PACKAGE_MANAGER" - jfLanguageEnvVariable = "AM_LANGUAGE" + NodeModulesPattern = "**/*node_modules*/**" ) var ( @@ -285,22 +283,11 @@ func SetAnalyticsMetricsDataForAnalyzerManager(msi string, technologies []coreut return func() { resetAnalyzerManageJfMsiVar() } } technology := technologies[0] - resetAnalyzerManagerPackageManagerVar := clientutils.SetEnvWithResetCallback(jfPackageManagerEnvVariable, technology.String()) - resetAnalyzerManagerLanguageVar := clientutils.SetEnvWithResetCallback(jfLanguageEnvVariable, string(coreutils.TechnologyToLanguage(technology))) + resetAnalyzerManagerPackageManagerVar := clientutils.SetEnvWithResetCallback(utils.JfPackageManagerEnvVariable, technology.String()) + resetAnalyzerManagerLanguageVar := clientutils.SetEnvWithResetCallback(utils.JfLanguageEnvVariable, string(coreutils.TechnologyToLanguage(technology))) return func() { resetAnalyzerManagerPackageManagerVar() resetAnalyzerManagerLanguageVar() resetAnalyzerManageJfMsiVar() } } - -func ResetAnalyticsMetricsDataForAnalyzerManager() { - err := os.Setenv("AM_PACKAGE_MANAGER", "") - if err != nil { - log.Debug(fmt.Sprintf("failed setting AM_PACKAGE_MANAGER as environment variable. Cause: %s", err.Error())) - } - err = os.Setenv("AM_LANGUAGE", "") - if err != nil { - log.Debug(fmt.Sprintf("failed setting AM_LANGUAGE as environment variable. Cause: %s", err.Error())) - } -} diff --git a/commands/audit/jas/common_test.go b/commands/audit/jas/common_test.go index c4e1461b..d2ad1854 100644 --- a/commands/audit/jas/common_test.go +++ b/commands/audit/jas/common_test.go @@ -102,13 +102,13 @@ func TestSetAnalyticsMetricsDataForAnalyzerManager(t *testing.T) { want func() }{ {name: "Valid 1 technology", args: args{msi: "msi", technologies: []coreutils.Technology{coreutils.Maven}}, want: func() { - assert.Equal(t, string(coreutils.Maven), os.Getenv(jfPackageManagerEnvVariable)) - assert.Equal(t, string(coreutils.Java), os.Getenv(jfLanguageEnvVariable)) + assert.Equal(t, string(coreutils.Maven), os.Getenv(utils.JfPackageManagerEnvVariable)) + assert.Equal(t, string(coreutils.Java), os.Getenv(utils.JfLanguageEnvVariable)) assert.Equal(t, "msi", os.Getenv(utils.JfMsiEnvVariable)) }}, {name: "multiple technologies", args: args{msi: "msi", technologies: []coreutils.Technology{coreutils.Maven, coreutils.Npm}}, want: func() { - assert.Equal(t, "", os.Getenv(jfPackageManagerEnvVariable)) - assert.Equal(t, "", os.Getenv(jfLanguageEnvVariable)) + assert.Equal(t, "", os.Getenv(utils.JfPackageManagerEnvVariable)) + assert.Equal(t, "", os.Getenv(utils.JfLanguageEnvVariable)) assert.Equal(t, "msi", os.Getenv(utils.JfMsiEnvVariable)) }}, } @@ -117,8 +117,8 @@ func TestSetAnalyticsMetricsDataForAnalyzerManager(t *testing.T) { callback := SetAnalyticsMetricsDataForAnalyzerManager(tt.args.msi, tt.args.technologies) tt.want() callback() - assert.Equal(t, "", os.Getenv(jfPackageManagerEnvVariable)) - assert.Equal(t, "", os.Getenv(jfLanguageEnvVariable)) + assert.Equal(t, "", os.Getenv(utils.JfPackageManagerEnvVariable)) + assert.Equal(t, "", os.Getenv(utils.JfLanguageEnvVariable)) assert.Equal(t, "", os.Getenv(utils.JfMsiEnvVariable)) }) diff --git a/commands/audit/jasrunner.go b/commands/audit/jasrunner.go index 6c16fd8c..03398730 100644 --- a/commands/audit/jasrunner.go +++ b/commands/audit/jasrunner.go @@ -31,7 +31,8 @@ func runJasScannersAndSetResults(scanResults *utils.Results, directDependencies progress.SetHeadlineMsg("Running applicability scanning") } // Set environments variables for analytics in analyzers manager. - defer jas.SetAnalyticsMetricsDataForAnalyzerManager(msi, scanResults.GetScaScannedTechnologies()) + callback := jas.SetAnalyticsMetricsDataForAnalyzerManager(msi, scanResults.GetScaScannedTechnologies()) + defer callback() scanResults.ExtendedScanResults.ApplicabilityScanResults, err = applicability.RunApplicabilityScan(scanResults.GetScaScansXrayResults(), directDependencies, scanResults.GetScaScannedTechnologies(), scanner, thirdPartyApplicabilityScan) if err != nil { return diff --git a/go.mod b/go.mod index 0b11869d..65d01154 100644 --- a/go.mod +++ b/go.mod @@ -102,8 +102,9 @@ replace github.com/jfrog/jfrog-cli-core/v2 => github.com/gailazar300/jfrog-cli-c //replace github.com/jfrog/jfrog-cli-core/v2 => ../jfrog-cli-core -replace github.com/jfrog/jfrog-client-go => github.com/gailazar300/jfrog-client-go v0.18.1-0.20240401141433-9b8da01b5758 +replace github.com/jfrog/jfrog-client-go => github.com/gailazar300/jfrog-client-go v0.18.1-0.20240402101728-8df71a319e37 //replace github.com/jfrog/jfrog-client-go => ../jfrog-client-go + // // replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go dev diff --git a/go.sum b/go.sum index dd574515..e4765c71 100644 --- a/go.sum +++ b/go.sum @@ -62,8 +62,8 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/gailazar300/jfrog-cli-core/v2 v2.0.0-20240401141758-ff916d692830 h1:mfpokH1jRIN+3jEJDrsx4woqI3AQVRlc2l03hZU3KaI= github.com/gailazar300/jfrog-cli-core/v2 v2.0.0-20240401141758-ff916d692830/go.mod h1:hTG5P+vzf8/hp/GU1o9Ed3DbkwYQopNRw4yPBkgurAU= -github.com/gailazar300/jfrog-client-go v0.18.1-0.20240401141433-9b8da01b5758 h1:NYb4hSqMXCwyvlHVasfvVfuHL9NVzmFHom4cJIvviBc= -github.com/gailazar300/jfrog-client-go v0.18.1-0.20240401141433-9b8da01b5758/go.mod h1:tUyEmxznphh0nwAGo6xz9Sps7RRW/TBMxIJZteo+j2k= +github.com/gailazar300/jfrog-client-go v0.18.1-0.20240402101728-8df71a319e37 h1:j7IGOEFYL3InQ/UvhZGbfP/zQotjSQ5VXhx75WlNyo8= +github.com/gailazar300/jfrog-client-go v0.18.1-0.20240402101728-8df71a319e37/go.mod h1:tUyEmxznphh0nwAGo6xz9Sps7RRW/TBMxIJZteo+j2k= github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= diff --git a/utils/analyticsmetrics.go b/utils/analyticsmetrics.go index d6f29311..49987b06 100644 --- a/utils/analyticsmetrics.go +++ b/utils/analyticsmetrics.go @@ -9,29 +9,10 @@ import ( "github.com/jfrog/jfrog-client-go/utils/log" "github.com/jfrog/jfrog-client-go/xsc" xscservices "github.com/jfrog/jfrog-client-go/xsc/services" - "os" "strings" "time" ) -const ( - AnalyticsMetricsMinXscVersion = "1.7.1" -) - -type ProductName string - -const ( - CliProduct ProductName = "cli" - FrogbotProduct ProductName = "frogbot" -) - -type EventType int - -const ( - CliEventType EventType = 1 - FrogbotType EventType = 8 -) - type AnalyticsMetricsService struct { xscManager *xsc.XscServicesManager // Should the CLI reports analytics metrics to XSC. @@ -58,16 +39,12 @@ func (ams *AnalyticsMetricsService) calcShouldReportEvents() bool { if !usage.ShouldReportUsage() { return false } - // There is no need to report the event and generate a new msi for the cli scan if the msi was provided. - if os.Getenv(JfMsiEnvVariable) != "" { - return false - } // Verify xsc version. xscVersion, err := ams.xscManager.GetVersion() if err != nil { return false } - if err = clientutils.ValidateMinimumVersion(clientutils.Xsc, xscVersion, AnalyticsMetricsMinXscVersion); err != nil { + if err = clientutils.ValidateMinimumVersion(clientutils.Xsc, xscVersion, xscservices.AnalyticsMetricsMinXscVersion); err != nil { return false } return true @@ -93,7 +70,11 @@ func (ams *AnalyticsMetricsService) ShouldReportEvents() bool { return ams.shouldReportEvents } -func (ams *AnalyticsMetricsService) CreateGeneralEvent(product ProductName, eventType EventType) *xscservices.XscAnalyticsGeneralEvent { +func (ams *AnalyticsMetricsService) SetShouldReportEvents(shouldReportEvents bool) { + ams.shouldReportEvents = shouldReportEvents +} + +func (ams *AnalyticsMetricsService) CreateGeneralEvent(product xscservices.ProductName, eventType xscservices.EventType) *xscservices.XscAnalyticsGeneralEvent { osAndArc, err := coreutils.GetOSAndArc() curOs, curArch := "", "" if err != nil { @@ -106,9 +87,9 @@ func (ams *AnalyticsMetricsService) CreateGeneralEvent(product ProductName, even event := xscservices.XscAnalyticsGeneralEvent{ XscAnalyticsBasicGeneralEvent: xscservices.XscAnalyticsBasicGeneralEvent{ - EventType: int(eventType), + EventType: eventType, EventStatus: xscservices.Started, - Product: string(product), + Product: product, JfrogUser: ams.xscManager.Config().GetServiceDetails().GetUser(), OsPlatform: curOs, OsArchitecture: curArch, @@ -139,6 +120,10 @@ func (ams *AnalyticsMetricsService) UpdateGeneralEvent(auditResults *Results) { log.Debug("A general event update request was not sent to XSC - analytics metrics are disabled.") return } + if ams.msi == "" { + log.Debug("A general event update request was not sent to XSC - failed to add the starting event, and there is no valid multi-scan identifier provided.") + return + } event := xscservices.XscAnalyticsGeneralEventFinalize{ MultiScanId: ams.msi, XscAnalyticsBasicGeneralEvent: ams.createAuditResultsFromXscAnalyticsBasicGeneralEvent(auditResults), diff --git a/utils/analyticsmetrics_test.go b/utils/analyticsmetrics_test.go index 44bad3a4..937062a2 100644 --- a/utils/analyticsmetrics_test.go +++ b/utils/analyticsmetrics_test.go @@ -31,7 +31,7 @@ func TestCalcShouldReportEvents(t *testing.T) { defer reportUsageCallback() // Minimum Xsc version. - mockServer, serverDetails := xscServer(t, AnalyticsMetricsMinXscVersion) + mockServer, serverDetails := xscServer(t, xscservices.AnalyticsMetricsMinXscVersion) defer mockServer.Close() am := NewAnalyticsMetricsService(serverDetails) assert.True(t, am.calcShouldReportEvents()) @@ -65,16 +65,16 @@ func TestAddGeneralEvent(t *testing.T) { msiCallback := tests.SetEnvWithCallbackAndAssert(t, JfMsiEnvVariable, "") defer msiCallback() // Successful flow. - mockServer, serverDetails := xscServer(t, AnalyticsMetricsMinXscVersion) + mockServer, serverDetails := xscServer(t, xscservices.AnalyticsMetricsMinXscVersion) defer mockServer.Close() am := NewAnalyticsMetricsService(serverDetails) - am.AddGeneralEvent(am.CreateGeneralEvent(CliProduct, CliEventType)) + am.AddGeneralEvent(am.CreateGeneralEvent(xscservices.CliProduct, xscservices.CliEventType)) assert.Equal(t, am.GetMsi(), testMsi) // In case cli should not report analytics, verify that request won't be sent. am.shouldReportEvents = false am.SetMsi("test-msi") - am.AddGeneralEvent(am.CreateGeneralEvent(CliProduct, CliEventType)) + am.AddGeneralEvent(am.CreateGeneralEvent(xscservices.CliProduct, xscservices.CliEventType)) assert.Equal(t, "test-msi", am.GetMsi()) } @@ -98,7 +98,7 @@ func TestAnalyticsMetricsService_createAuditResultsFromXscAnalyticsBasicGeneralE {name: "Scan failed because jas errors.", auditResults: &Results{JasError: errors.New("jas error"), ScaResults: []ScaScanResult{{}, {}}}, want: xscservices.XscAnalyticsBasicGeneralEvent{TotalFindings: 2, EventStatus: xscservices.Failed}}, {name: "Scan failed because sca errors.", auditResults: &Results{JasError: errors.New("sca error")}, want: xscservices.XscAnalyticsBasicGeneralEvent{TotalFindings: 0, EventStatus: xscservices.Failed}}, } - mockServer, serverDetails := xscServer(t, AnalyticsMetricsMinXscVersion) + mockServer, serverDetails := xscServer(t, xscservices.AnalyticsMetricsMinXscVersion) defer mockServer.Close() am := NewAnalyticsMetricsService(serverDetails) am.SetStartTime() diff --git a/utils/analyzermanager.go b/utils/analyzermanager.go index 9dacb8c3..6916465b 100644 --- a/utils/analyzermanager.go +++ b/utils/analyzermanager.go @@ -37,6 +37,8 @@ const ( ErrFailedScannerRun = "failed to run %s scan. Exit code received: %s" jfrogCliAnalyzerManagerVersionEnvVariable = "JFROG_CLI_ANALYZER_MANAGER_VERSION" JfMsiEnvVariable = "JF_MSI" + JfPackageManagerEnvVariable = "AM_PACKAGE_MANAGER" + JfLanguageEnvVariable = "AM_LANGUAGE" ) type ApplicabilityStatus string From 40884cb77391a12d89af4f2b0ad8e5bf394fb49d Mon Sep 17 00:00:00 2001 From: gail Date: Tue, 2 Apr 2024 17:02:04 +0300 Subject: [PATCH 16/32] Remove Frogbot's MSI validation - there is no common flow for cli and Frogbot for analytics. --- commands/audit/audit.go | 13 ++++--------- utils/analyticsmetrics.go | 4 ---- utils/auditbasicparams.go | 9 --------- 3 files changed, 4 insertions(+), 22 deletions(-) diff --git a/commands/audit/audit.go b/commands/audit/audit.go index 03196e82..e1912e82 100644 --- a/commands/audit/audit.go +++ b/commands/audit/audit.go @@ -105,13 +105,8 @@ func (auditCmd *AuditCommand) Run() (err error) { SetThirdPartyApplicabilityScan(auditCmd.thirdPartyApplicabilityScan) auditParams.SetIsRecursiveScan(isRecursiveScan).SetExclusions(auditCmd.Exclusions()) - if auditParams.MultiScanId() == "" { - // There is no need to add/update the event and generate a new msi for the cli scan if the msi was already provided by FrogBot. - auditCmd.analyticsMetricsService.SetShouldReportEvents(false) - } else { - auditCmd.analyticsMetricsService.AddGeneralEvent(auditCmd.analyticsMetricsService.CreateGeneralEvent(xscservices.CliProduct, xscservices.CliEventType)) - auditParams.SetMultiScanId(auditCmd.analyticsMetricsService.GetMsi()) - } + auditCmd.analyticsMetricsService.AddGeneralEvent(auditCmd.analyticsMetricsService.CreateGeneralEvent(xscservices.CliProduct, xscservices.CliEventType)) + auditParams.xrayGraphScanParams.MultiScanId = auditCmd.analyticsMetricsService.GetMsi() auditResults, err := RunAudit(auditParams) if err != nil { @@ -187,7 +182,7 @@ func RunAudit(auditParams *AuditParams) (results *xrayutils.Results, err error) errGroup.Go(utils.DownloadAnalyzerManagerIfNeeded) } - results.MultiScanId = auditParams.MultiScanId() + results.MultiScanId = auditParams.XrayGraphScanParams().MultiScanId // The sca scan doesn't require the analyzer manager, so it can run separately from the analyzer manager download routine. results.ScaError = runScaScan(auditParams, results) @@ -199,7 +194,7 @@ func RunAudit(auditParams *AuditParams) (results *xrayutils.Results, err error) // Run scanners only if the user is entitled for Advanced Security if results.ExtendedScanResults.EntitledForJas { - results.JasError = runJasScannersAndSetResults(results, auditParams.DirectDependencies(), serverDetails, auditParams.workingDirs, auditParams.Progress(), auditParams.thirdPartyApplicabilityScan, auditParams.MultiScanId()) + results.JasError = runJasScannersAndSetResults(results, auditParams.DirectDependencies(), serverDetails, auditParams.workingDirs, auditParams.Progress(), auditParams.thirdPartyApplicabilityScan, auditParams.XrayGraphScanParams().MultiScanId) } return } diff --git a/utils/analyticsmetrics.go b/utils/analyticsmetrics.go index 49987b06..e37d87aa 100644 --- a/utils/analyticsmetrics.go +++ b/utils/analyticsmetrics.go @@ -70,10 +70,6 @@ func (ams *AnalyticsMetricsService) ShouldReportEvents() bool { return ams.shouldReportEvents } -func (ams *AnalyticsMetricsService) SetShouldReportEvents(shouldReportEvents bool) { - ams.shouldReportEvents = shouldReportEvents -} - func (ams *AnalyticsMetricsService) CreateGeneralEvent(product xscservices.ProductName, eventType xscservices.EventType) *xscservices.XscAnalyticsGeneralEvent { osAndArc, err := coreutils.GetOSAndArc() curOs, curArch := "", "" diff --git a/utils/auditbasicparams.go b/utils/auditbasicparams.go index faff271a..e66a618f 100644 --- a/utils/auditbasicparams.go +++ b/utils/auditbasicparams.go @@ -61,7 +61,6 @@ type AuditBasicParams struct { dependenciesForApplicabilityScan []string exclusions []string isRecursiveScan bool - multiScanId string } func (abp *AuditBasicParams) DirectDependencies() []string { @@ -145,14 +144,6 @@ func (abp *AuditBasicParams) SetProgress(progress ioUtils.ProgressMgr) { abp.progress = progress } -func (abp *AuditBasicParams) MultiScanId() string { - return abp.multiScanId -} - -func (abp *AuditBasicParams) SetMultiScanId(multiScanId string) { - abp.multiScanId = multiScanId -} - func (abp *AuditBasicParams) Args() []string { return abp.args } From 51de09aa5b05b4657b4d02de094902cf9c0d2502 Mon Sep 17 00:00:00 2001 From: gail Date: Tue, 2 Apr 2024 17:04:04 +0300 Subject: [PATCH 17/32] Minor fix. --- xsc_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xsc_test.go b/xsc_test.go index fb1661eb..95176cb7 100644 --- a/xsc_test.go +++ b/xsc_test.go @@ -10,12 +10,13 @@ import ( securityTestUtils "github.com/jfrog/jfrog-cli-security/tests/utils" "github.com/jfrog/jfrog-cli-security/utils" "github.com/jfrog/jfrog-client-go/utils/tests" + "github.com/jfrog/jfrog-client-go/xsc/services" "github.com/stretchr/testify/assert" "testing" ) func TestXscAnalyticsForAudit(t *testing.T) { - securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion, utils.AnalyticsMetricsMinXscVersion) + securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion, services.AnalyticsMetricsMinXscVersion) reportUsageCallBack := tests.SetEnvWithCallbackAndAssert(t, coreutils.ReportUsage, "true") defer reportUsageCallBack() // Scan npm project and verify that analytics general event were sent to XSC. From df4ef8f9f7d03f690f864b8ab90097206edb7c6f Mon Sep 17 00:00:00 2001 From: gail Date: Wed, 3 Apr 2024 11:24:04 +0300 Subject: [PATCH 18/32] Minor fix. --- commands/audit/jas/common.go | 34 +++++++++++++++++++++++++++------- utils/analyticsmetrics.go | 2 ++ 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/commands/audit/jas/common.go b/commands/audit/jas/common.go index 15bf8103..56621862 100644 --- a/commands/audit/jas/common.go +++ b/commands/audit/jas/common.go @@ -277,17 +277,37 @@ func GetExcludePatterns(module jfrogappsconfig.Module, scanner *jfrogappsconfig. } func SetAnalyticsMetricsDataForAnalyzerManager(msi string, technologies []coreutils.Technology) func() { - resetAnalyzerManageJfMsiVar := clientutils.SetEnvWithResetCallback(utils.JfMsiEnvVariable, msi) + errMsg := "failed %s %s environment variable. Cause: %s" + resetAnalyzerManageJfMsiVar, err := clientutils.SetEnvWithResetCallback(utils.JfMsiEnvVariable, msi) + if err != nil { + log.Debug(fmt.Sprintf(errMsg, "setting", utils.JfMsiEnvVariable, err.Error())) + } if len(technologies) != 1 { // Only report analytics for one technology at a time. - return func() { resetAnalyzerManageJfMsiVar() } + return func() { + if resetAnalyzerManageJfMsiVar() != nil { + log.Debug(fmt.Sprintf(errMsg, "restoring", utils.JfMsiEnvVariable, err.Error())) + } + } } technology := technologies[0] - resetAnalyzerManagerPackageManagerVar := clientutils.SetEnvWithResetCallback(utils.JfPackageManagerEnvVariable, technology.String()) - resetAnalyzerManagerLanguageVar := clientutils.SetEnvWithResetCallback(utils.JfLanguageEnvVariable, string(coreutils.TechnologyToLanguage(technology))) + resetAnalyzerManagerPackageManagerVar, err := clientutils.SetEnvWithResetCallback(utils.JfPackageManagerEnvVariable, technology.String()) + if err != nil { + log.Debug(fmt.Sprintf(errMsg, "setting", utils.JfPackageManagerEnvVariable, err.Error())) + } + resetAnalyzerManagerLanguageVar, err := clientutils.SetEnvWithResetCallback(utils.JfLanguageEnvVariable, string(coreutils.TechnologyToLanguage(technology))) + if err != nil { + log.Debug(fmt.Sprintf(errMsg, "setting", utils.JfLanguageEnvVariable, err.Error())) + } return func() { - resetAnalyzerManagerPackageManagerVar() - resetAnalyzerManagerLanguageVar() - resetAnalyzerManageJfMsiVar() + if resetAnalyzerManageJfMsiVar() != nil { + log.Debug(fmt.Sprintf(errMsg, "restoring", utils.JfMsiEnvVariable, err.Error())) + } + if resetAnalyzerManagerPackageManagerVar() != nil { + log.Debug(fmt.Sprintf(errMsg, "restoring", utils.JfPackageManagerEnvVariable, err.Error())) + } + if resetAnalyzerManagerLanguageVar() != nil { + log.Debug(fmt.Sprintf(errMsg, "restoring", utils.JfLanguageEnvVariable, err.Error())) + } } } diff --git a/utils/analyticsmetrics.go b/utils/analyticsmetrics.go index e37d87aa..39d1b647 100644 --- a/utils/analyticsmetrics.go +++ b/utils/analyticsmetrics.go @@ -19,6 +19,8 @@ type AnalyticsMetricsService struct { shouldReportEvents bool msi string startTime time.Time + // Finalize event combining all audit results. + finalizeEvent *xscservices.XscAnalyticsGeneralEventFinalize } func NewAnalyticsMetricsService(serviceDetails *config.ServerDetails) *AnalyticsMetricsService { From 08b17649c7a41f1d009f8ea626caf06fc9453638 Mon Sep 17 00:00:00 2001 From: gail Date: Wed, 3 Apr 2024 11:25:01 +0300 Subject: [PATCH 19/32] Minor fix. --- utils/analyticsmetrics.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/utils/analyticsmetrics.go b/utils/analyticsmetrics.go index 39d1b647..c43e2c03 100644 --- a/utils/analyticsmetrics.go +++ b/utils/analyticsmetrics.go @@ -72,6 +72,14 @@ func (ams *AnalyticsMetricsService) ShouldReportEvents() bool { return ams.shouldReportEvents } +func (ams *AnalyticsMetricsService) FinalizeEvent() *xscservices.XscAnalyticsGeneralEventFinalize { + return ams.finalizeEvent +} + +func (ams *AnalyticsMetricsService) SetFinalizeEvent(finalizeEvent *xscservices.XscAnalyticsGeneralEventFinalize) { + ams.finalizeEvent = finalizeEvent +} + func (ams *AnalyticsMetricsService) CreateGeneralEvent(product xscservices.ProductName, eventType xscservices.EventType) *xscservices.XscAnalyticsGeneralEvent { osAndArc, err := coreutils.GetOSAndArc() curOs, curArch := "", "" From afc884351de3ef56bb067633edc99cd736a3ed09 Mon Sep 17 00:00:00 2001 From: gail Date: Wed, 3 Apr 2024 12:38:37 +0300 Subject: [PATCH 20/32] Change UpdateGeneralEvent & moving relevant code from core --- commands/audit/audit.go | 2 +- commands/audit/jas/common.go | 2 +- go.mod | 4 ++-- go.sum | 2 -- tests/utils/test_mocks.go | 27 +++++++++++++++++++++++++++ utils/analyticsmetrics.go | 19 ++++++++++--------- utils/analyticsmetrics_test.go | 6 +++--- utils/techutils.go | 30 ++++++++++++++++++++++++++++++ utils/techutils_test.go | 32 ++++++++++++++++++++++++++++++++ 9 files changed, 106 insertions(+), 18 deletions(-) create mode 100644 tests/utils/test_mocks.go create mode 100644 utils/techutils.go create mode 100644 utils/techutils_test.go diff --git a/commands/audit/audit.go b/commands/audit/audit.go index e1912e82..931bb72c 100644 --- a/commands/audit/audit.go +++ b/commands/audit/audit.go @@ -112,7 +112,7 @@ func (auditCmd *AuditCommand) Run() (err error) { if err != nil { return } - auditCmd.analyticsMetricsService.UpdateGeneralEvent(auditResults) + auditCmd.analyticsMetricsService.UpdateGeneralEvent(auditCmd.analyticsMetricsService.CreateXscAnalyticsGeneralEventFinalizeFromAuditResults(auditResults)) if auditCmd.Progress() != nil { if err = auditCmd.Progress().Quit(); err != nil { return diff --git a/commands/audit/jas/common.go b/commands/audit/jas/common.go index 56621862..439da94f 100644 --- a/commands/audit/jas/common.go +++ b/commands/audit/jas/common.go @@ -295,7 +295,7 @@ func SetAnalyticsMetricsDataForAnalyzerManager(msi string, technologies []coreut if err != nil { log.Debug(fmt.Sprintf(errMsg, "setting", utils.JfPackageManagerEnvVariable, err.Error())) } - resetAnalyzerManagerLanguageVar, err := clientutils.SetEnvWithResetCallback(utils.JfLanguageEnvVariable, string(coreutils.TechnologyToLanguage(technology))) + resetAnalyzerManagerLanguageVar, err := clientutils.SetEnvWithResetCallback(utils.JfLanguageEnvVariable, string(utils.TechnologyToLanguage(technology))) if err != nil { log.Debug(fmt.Sprintf(errMsg, "setting", utils.JfLanguageEnvVariable, err.Error())) } diff --git a/go.mod b/go.mod index 65d01154..bc59a039 100644 --- a/go.mod +++ b/go.mod @@ -102,9 +102,9 @@ replace github.com/jfrog/jfrog-cli-core/v2 => github.com/gailazar300/jfrog-cli-c //replace github.com/jfrog/jfrog-cli-core/v2 => ../jfrog-cli-core -replace github.com/jfrog/jfrog-client-go => github.com/gailazar300/jfrog-client-go v0.18.1-0.20240402101728-8df71a319e37 +//replace github.com/jfrog/jfrog-client-go => github.com/gailazar300/jfrog-client-go v0.18.1-0.20240402101728-8df71a319e37 -//replace github.com/jfrog/jfrog-client-go => ../jfrog-client-go +replace github.com/jfrog/jfrog-client-go => ../jfrog-client-go // // replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go dev diff --git a/go.sum b/go.sum index e4765c71..277dbb6d 100644 --- a/go.sum +++ b/go.sum @@ -62,8 +62,6 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/gailazar300/jfrog-cli-core/v2 v2.0.0-20240401141758-ff916d692830 h1:mfpokH1jRIN+3jEJDrsx4woqI3AQVRlc2l03hZU3KaI= github.com/gailazar300/jfrog-cli-core/v2 v2.0.0-20240401141758-ff916d692830/go.mod h1:hTG5P+vzf8/hp/GU1o9Ed3DbkwYQopNRw4yPBkgurAU= -github.com/gailazar300/jfrog-client-go v0.18.1-0.20240402101728-8df71a319e37 h1:j7IGOEFYL3InQ/UvhZGbfP/zQotjSQ5VXhx75WlNyo8= -github.com/gailazar300/jfrog-client-go v0.18.1-0.20240402101728-8df71a319e37/go.mod h1:tUyEmxznphh0nwAGo6xz9Sps7RRW/TBMxIJZteo+j2k= github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= diff --git a/tests/utils/test_mocks.go b/tests/utils/test_mocks.go new file mode 100644 index 00000000..f0807899 --- /dev/null +++ b/tests/utils/test_mocks.go @@ -0,0 +1,27 @@ +package utils + +import ( + "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" + "github.com/jfrog/jfrog-cli-core/v2/utils/config" + "github.com/jfrog/jfrog-client-go/artifactory" + "github.com/stretchr/testify/assert" + "net/http" + "net/http/httptest" + "testing" +) + +type restsTestHandler func(w http.ResponseWriter, r *http.Request) + +// Create mock server to test REST APIs. +// testHandler - The HTTP handler of the test +func CreateRestsMockServer(testHandler restsTestHandler) *httptest.Server { + return httptest.NewServer(http.HandlerFunc(testHandler)) +} +func CreateXscRestsMockServer(t *testing.T, testHandler restsTestHandler) (*httptest.Server, *config.ServerDetails, artifactory.ArtifactoryServicesManager) { + testServer := CreateRestsMockServer(testHandler) + serverDetails := &config.ServerDetails{Url: testServer.URL + "/", XrayUrl: testServer.URL + "/xray/"} + + serviceManager, err := utils.CreateServiceManager(serverDetails, -1, 0, false) + assert.NoError(t, err) + return testServer, serverDetails, serviceManager +} diff --git a/utils/analyticsmetrics.go b/utils/analyticsmetrics.go index c43e2c03..b9ece63b 100644 --- a/utils/analyticsmetrics.go +++ b/utils/analyticsmetrics.go @@ -19,7 +19,7 @@ type AnalyticsMetricsService struct { shouldReportEvents bool msi string startTime time.Time - // Finalize event combining all audit results. + // In the case of multiple scanning, aggregate all audit results into one finalize event. finalizeEvent *xscservices.XscAnalyticsGeneralEventFinalize } @@ -121,7 +121,7 @@ func (ams *AnalyticsMetricsService) AddGeneralEvent(event *xscservices.XscAnalyt ams.SetStartTime() } -func (ams *AnalyticsMetricsService) UpdateGeneralEvent(auditResults *Results) { +func (ams *AnalyticsMetricsService) UpdateGeneralEvent(event *xscservices.XscAnalyticsGeneralEventFinalize) { if !ams.ShouldReportEvents() { log.Debug("A general event update request was not sent to XSC - analytics metrics are disabled.") return @@ -130,11 +130,7 @@ func (ams *AnalyticsMetricsService) UpdateGeneralEvent(auditResults *Results) { log.Debug("A general event update request was not sent to XSC - failed to add the starting event, and there is no valid multi-scan identifier provided.") return } - event := xscservices.XscAnalyticsGeneralEventFinalize{ - MultiScanId: ams.msi, - XscAnalyticsBasicGeneralEvent: ams.createAuditResultsFromXscAnalyticsBasicGeneralEvent(auditResults), - } - err := ams.xscManager.UpdateAnalyticsGeneralEvent(event) + err := ams.xscManager.UpdateAnalyticsGeneralEvent(*event) if err != nil { log.Debug(fmt.Sprintf("failed updading general event request in XSC service for multi_scan_id %s, error: %s \"", ams.GetMsi(), err.Error())) } @@ -152,7 +148,7 @@ func (ams *AnalyticsMetricsService) GetGeneralEvent(msi string) (*xscservices.Xs return event, err } -func (ams *AnalyticsMetricsService) createAuditResultsFromXscAnalyticsBasicGeneralEvent(auditResults *Results) xscservices.XscAnalyticsBasicGeneralEvent { +func (ams *AnalyticsMetricsService) CreateXscAnalyticsGeneralEventFinalizeFromAuditResults(auditResults *Results) *xscservices.XscAnalyticsGeneralEventFinalize { totalDuration := time.Since(ams.GetStartTime()) totalFindings := len(auditResults.ScaResults) if auditResults.ExtendedScanResults != nil { @@ -162,9 +158,14 @@ func (ams *AnalyticsMetricsService) createAuditResultsFromXscAnalyticsBasicGener if auditResults.ScaError != nil || auditResults.JasError != nil { eventStatus = xscservices.Failed } - return xscservices.XscAnalyticsBasicGeneralEvent{ + + basicEvent := xscservices.XscAnalyticsBasicGeneralEvent{ EventStatus: eventStatus, TotalFindings: totalFindings, TotalScanDuration: totalDuration.String(), } + return &xscservices.XscAnalyticsGeneralEventFinalize{ + MultiScanId: ams.msi, + XscAnalyticsBasicGeneralEvent: basicEvent, + } } diff --git a/utils/analyticsmetrics_test.go b/utils/analyticsmetrics_test.go index 937062a2..1e2167cc 100644 --- a/utils/analyticsmetrics_test.go +++ b/utils/analyticsmetrics_test.go @@ -3,9 +3,9 @@ package utils import ( "errors" "fmt" - coretests "github.com/jfrog/jfrog-cli-core/v2/common/tests" "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" + "github.com/jfrog/jfrog-cli-security/tests/utils" "github.com/jfrog/jfrog-client-go/utils/tests" xscservices "github.com/jfrog/jfrog-client-go/xsc/services" "github.com/owenrumney/go-sarif/v2/sarif" @@ -104,7 +104,7 @@ func TestAnalyticsMetricsService_createAuditResultsFromXscAnalyticsBasicGeneralE am.SetStartTime() for _, tt := range testStruct { t.Run(tt.name, func(t *testing.T) { - event := am.createAuditResultsFromXscAnalyticsBasicGeneralEvent(tt.auditResults) + event := am.CreateXscAnalyticsGeneralEventFinalizeFromAuditResults(tt.auditResults) assert.Equal(t, tt.want.TotalFindings, event.TotalFindings) assert.Equal(t, tt.want.EventStatus, event.EventStatus) totalDuration, err := time.ParseDuration(event.TotalScanDuration) @@ -115,7 +115,7 @@ func TestAnalyticsMetricsService_createAuditResultsFromXscAnalyticsBasicGeneralE } func xscServer(t *testing.T, xscVersion string) (*httptest.Server, *config.ServerDetails) { - serverMock, serverDetails, _ := coretests.CreateXscRestsMockServer(t, func(w http.ResponseWriter, r *http.Request) { + serverMock, serverDetails, _ := utils.CreateXscRestsMockServer(t, func(w http.ResponseWriter, r *http.Request) { if r.RequestURI == "/xsc/api/v1/system/version" { _, err := w.Write([]byte(fmt.Sprintf(`{"xsc_version": "%s"}`, xscVersion))) if err != nil { diff --git a/utils/techutils.go b/utils/techutils.go new file mode 100644 index 00000000..874968a8 --- /dev/null +++ b/utils/techutils.go @@ -0,0 +1,30 @@ +package utils + +import "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" + +func TechnologyToLanguage(technology coreutils.Technology) CodeLanguage { + languageMap := map[coreutils.Technology]CodeLanguage{ + coreutils.Npm: JavaScript, + coreutils.Pip: Python, + coreutils.Poetry: Python, + coreutils.Pipenv: Python, + coreutils.Go: GoLang, + coreutils.Maven: Java, + coreutils.Gradle: Java, + coreutils.Nuget: CSharp, + coreutils.Dotnet: CSharp, + coreutils.Yarn: JavaScript, + coreutils.Pnpm: JavaScript, + } + return languageMap[technology] +} + +type CodeLanguage string + +const ( + JavaScript CodeLanguage = "javascript" + Python CodeLanguage = "python" + GoLang CodeLanguage = "go" + Java CodeLanguage = "java" + CSharp CodeLanguage = "C#" +) diff --git a/utils/techutils_test.go b/utils/techutils_test.go new file mode 100644 index 00000000..e231f275 --- /dev/null +++ b/utils/techutils_test.go @@ -0,0 +1,32 @@ +package utils + +import ( + "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestTechnologyToLanguage(t *testing.T) { + tests := []struct { + name string + technology coreutils.Technology + language CodeLanguage + }{ + {name: "Maven to Java", technology: coreutils.Maven, language: Java}, + {name: "Gradle to Java", technology: coreutils.Gradle, language: Java}, + {name: "Npm to JavaScript", technology: coreutils.Npm, language: JavaScript}, + {name: "Pnpm to JavaScript", technology: coreutils.Pnpm, language: JavaScript}, + {name: "Yarn to JavaScript", technology: coreutils.Yarn, language: JavaScript}, + {name: "Go to GoLang", technology: coreutils.Go, language: GoLang}, + {name: "Pip to Python", technology: coreutils.Pip, language: Python}, + {name: "Pipenv to Python", technology: coreutils.Pipenv, language: Python}, + {name: "Poetry to Python", technology: coreutils.Poetry, language: Python}, + {name: "Nuget to CSharp", technology: coreutils.Nuget, language: CSharp}, + {name: "Dotnet to CSharp", technology: coreutils.Dotnet, language: CSharp}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.language, TechnologyToLanguage(tt.technology), "TechnologyToLanguage(%v) == %v", tt.technology, tt.language) + }) + } +} From b133a9aee055d83bc2b13844513265b79ea2698b Mon Sep 17 00:00:00 2001 From: gail Date: Wed, 3 Apr 2024 13:45:21 +0300 Subject: [PATCH 21/32] go.mod+sum --- go.mod | 7 ++----- go.sum | 6 ++++-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index bc59a039..91cc2362 100644 --- a/go.mod +++ b/go.mod @@ -98,13 +98,10 @@ require ( gopkg.in/warnings.v0 v0.1.2 // indirect ) -replace github.com/jfrog/jfrog-cli-core/v2 => github.com/gailazar300/jfrog-cli-core/v2 v2.0.0-20240401141758-ff916d692830 +replace github.com/jfrog/jfrog-cli-core/v2 => github.com/gailazar300/jfrog-cli-core/v2 v2.0.0-20240403103644-317f145c1f66 //replace github.com/jfrog/jfrog-cli-core/v2 => ../jfrog-cli-core -//replace github.com/jfrog/jfrog-client-go => github.com/gailazar300/jfrog-client-go v0.18.1-0.20240402101728-8df71a319e37 +replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20240403100335-8292671b7cc4 -replace github.com/jfrog/jfrog-client-go => ../jfrog-client-go - -// // replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go dev diff --git a/go.sum b/go.sum index 277dbb6d..f98a95e1 100644 --- a/go.sum +++ b/go.sum @@ -60,8 +60,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/gailazar300/jfrog-cli-core/v2 v2.0.0-20240401141758-ff916d692830 h1:mfpokH1jRIN+3jEJDrsx4woqI3AQVRlc2l03hZU3KaI= -github.com/gailazar300/jfrog-cli-core/v2 v2.0.0-20240401141758-ff916d692830/go.mod h1:hTG5P+vzf8/hp/GU1o9Ed3DbkwYQopNRw4yPBkgurAU= +github.com/gailazar300/jfrog-cli-core/v2 v2.0.0-20240403103644-317f145c1f66 h1:1hLXnLn/iA4S6Yg5g8SgvnQDkqNdEC4PMG6+lekehOI= +github.com/gailazar300/jfrog-cli-core/v2 v2.0.0-20240403103644-317f145c1f66/go.mod h1:iQoYSsjLWF8x//rtQCwNPE2ycle2X2x6VFQM0LQE2n0= github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= @@ -104,6 +104,8 @@ github.com/jfrog/gofrog v1.6.3 h1:F7He0+75HcgCe6SGTSHLFCBDxiE2Ja0tekvvcktW6wc= github.com/jfrog/gofrog v1.6.3/go.mod h1:SZ1EPJUruxrVGndOzHd+LTiwWYKMlHqhKD+eu+v5Hqg= github.com/jfrog/jfrog-apps-config v1.0.1 h1:mtv6k7g8A8BVhlHGlSveapqf4mJfonwvXYLipdsOFMY= github.com/jfrog/jfrog-apps-config v1.0.1/go.mod h1:8AIIr1oY9JuH5dylz2S6f8Ym2MaadPLR6noCBO4C22w= +github.com/jfrog/jfrog-client-go v1.28.1-0.20240403100335-8292671b7cc4 h1:A67yoFRYjRzg+xhLYhH0QN7b4/wggRa/lSQKSjzOwNQ= +github.com/jfrog/jfrog-client-go v1.28.1-0.20240403100335-8292671b7cc4/go.mod h1:tUyEmxznphh0nwAGo6xz9Sps7RRW/TBMxIJZteo+j2k= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= From 1a2c6520ce35bdae7016016a7c3085c4923a4e13 Mon Sep 17 00:00:00 2001 From: gail Date: Wed, 3 Apr 2024 13:50:19 +0300 Subject: [PATCH 22/32] minor fix --- commands/audit/jas/common_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commands/audit/jas/common_test.go b/commands/audit/jas/common_test.go index d2ad1854..7a3d4936 100644 --- a/commands/audit/jas/common_test.go +++ b/commands/audit/jas/common_test.go @@ -103,7 +103,7 @@ func TestSetAnalyticsMetricsDataForAnalyzerManager(t *testing.T) { }{ {name: "Valid 1 technology", args: args{msi: "msi", technologies: []coreutils.Technology{coreutils.Maven}}, want: func() { assert.Equal(t, string(coreutils.Maven), os.Getenv(utils.JfPackageManagerEnvVariable)) - assert.Equal(t, string(coreutils.Java), os.Getenv(utils.JfLanguageEnvVariable)) + assert.Equal(t, string(utils.Java), os.Getenv(utils.JfLanguageEnvVariable)) assert.Equal(t, "msi", os.Getenv(utils.JfMsiEnvVariable)) }}, {name: "multiple technologies", args: args{msi: "msi", technologies: []coreutils.Technology{coreutils.Maven, coreutils.Npm}}, want: func() { From abea15c17170a26c79bfb3b6a2d7fb741fadb179 Mon Sep 17 00:00:00 2001 From: gail Date: Wed, 3 Apr 2024 14:07:01 +0300 Subject: [PATCH 23/32] minor fix --- utils/analyticsmetrics_test.go | 34 +-------------------- tests/utils/test_mocks.go => utils/mocks.go | 24 +++++++++++++++ 2 files changed, 25 insertions(+), 33 deletions(-) rename tests/utils/test_mocks.go => utils/mocks.go (58%) diff --git a/utils/analyticsmetrics_test.go b/utils/analyticsmetrics_test.go index 1e2167cc..255aeb16 100644 --- a/utils/analyticsmetrics_test.go +++ b/utils/analyticsmetrics_test.go @@ -2,23 +2,17 @@ package utils import ( "errors" - "fmt" - "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" - "github.com/jfrog/jfrog-cli-security/tests/utils" "github.com/jfrog/jfrog-client-go/utils/tests" xscservices "github.com/jfrog/jfrog-client-go/xsc/services" "github.com/owenrumney/go-sarif/v2/sarif" "github.com/stretchr/testify/assert" - "net/http" - "net/http/httptest" "os" "testing" "time" ) const ( - testMsi = "27e175b8-e525-11ee-842b-7aa2c69b8f1f" lowerAnalyticsMetricsMinXscVersion = "1.6.0" higherAnalyticsMetricsMinXscVersion = "1.10.0" ) @@ -48,13 +42,8 @@ func TestCalcShouldReportEvents(t *testing.T) { am = NewAnalyticsMetricsService(serverDetails) assert.True(t, am.calcShouldReportEvents()) - // JF_MSI was already provided. - err := os.Setenv(JfMsiEnvVariable, "msi") - assert.NoError(t, err) - assert.False(t, am.calcShouldReportEvents()) - // JFROG_CLI_REPORT_USAGE is false. - err = os.Setenv(JfMsiEnvVariable, "") + err := os.Setenv(JfMsiEnvVariable, "") assert.NoError(t, err) err = os.Setenv(coreutils.ReportUsage, "false") assert.NoError(t, err) @@ -113,24 +102,3 @@ func TestAnalyticsMetricsService_createAuditResultsFromXscAnalyticsBasicGeneralE }) } } - -func xscServer(t *testing.T, xscVersion string) (*httptest.Server, *config.ServerDetails) { - serverMock, serverDetails, _ := utils.CreateXscRestsMockServer(t, func(w http.ResponseWriter, r *http.Request) { - if r.RequestURI == "/xsc/api/v1/system/version" { - _, err := w.Write([]byte(fmt.Sprintf(`{"xsc_version": "%s"}`, xscVersion))) - if err != nil { - return - } - } - if r.RequestURI == "/xsc/api/v1/event" { - if r.Method == http.MethodPost { - w.WriteHeader(http.StatusCreated) - _, err := w.Write([]byte(fmt.Sprintf(`{"multi_scan_id": "%s"}`, testMsi))) - if err != nil { - return - } - } - } - }) - return serverMock, serverDetails -} diff --git a/tests/utils/test_mocks.go b/utils/mocks.go similarity index 58% rename from tests/utils/test_mocks.go rename to utils/mocks.go index f0807899..f3d308a0 100644 --- a/tests/utils/test_mocks.go +++ b/utils/mocks.go @@ -1,6 +1,7 @@ package utils import ( + "fmt" "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-client-go/artifactory" @@ -10,6 +11,8 @@ import ( "testing" ) +const testMsi = "27e175b8-e525-11ee-842b-7aa2c69b8f1f" + type restsTestHandler func(w http.ResponseWriter, r *http.Request) // Create mock server to test REST APIs. @@ -25,3 +28,24 @@ func CreateXscRestsMockServer(t *testing.T, testHandler restsTestHandler) (*http assert.NoError(t, err) return testServer, serverDetails, serviceManager } + +func xscServer(t *testing.T, xscVersion string) (*httptest.Server, *config.ServerDetails) { + serverMock, serverDetails, _ := CreateXscRestsMockServer(t, func(w http.ResponseWriter, r *http.Request) { + if r.RequestURI == "/xsc/api/v1/system/version" { + _, err := w.Write([]byte(fmt.Sprintf(`{"xsc_version": "%s"}`, xscVersion))) + if err != nil { + return + } + } + if r.RequestURI == "/xsc/api/v1/event" { + if r.Method == http.MethodPost { + w.WriteHeader(http.StatusCreated) + _, err := w.Write([]byte(fmt.Sprintf(`{"multi_scan_id": "%s"}`, testMsi))) + if err != nil { + return + } + } + } + }) + return serverMock, serverDetails +} From f0fdb3a24e7fc1b4080f5211363534335c8afca7 Mon Sep 17 00:00:00 2001 From: gail Date: Wed, 3 Apr 2024 17:40:27 +0300 Subject: [PATCH 24/32] Fix sending scan to xsc if available. --- commands/audit/audit.go | 16 +++++++++++++--- utils/analyticsmetrics.go | 4 ++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/commands/audit/audit.go b/commands/audit/audit.go index 931bb72c..87776fca 100644 --- a/commands/audit/audit.go +++ b/commands/audit/audit.go @@ -2,6 +2,7 @@ package audit import ( "errors" + "fmt" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" "github.com/jfrog/jfrog-cli-security/scangraph" "github.com/jfrog/jfrog-cli-security/utils" @@ -85,6 +86,16 @@ func (auditCmd *AuditCommand) CreateXrayGraphScanParams() *services.XrayGraphSca } params.IncludeVulnerabilities = auditCmd.IncludeVulnerabilities params.IncludeLicenses = auditCmd.IncludeLicenses + params.MultiScanId = auditCmd.analyticsMetricsService.GetMsi() + xscManager := auditCmd.analyticsMetricsService.XscManager() + if xscManager != nil { + version, err := xscManager.GetVersion() + if err != nil { + log.Debug(fmt.Sprintf("Can't get XSC version for xray graph scan params. Cause: %s", err.Error())) + } + params.XscVersion = version + } + return params } @@ -96,6 +107,8 @@ func (auditCmd *AuditCommand) Run() (err error) { return } + // Should be called before creating the audit params, so the params will contain XSC information. + auditCmd.analyticsMetricsService.AddGeneralEvent(auditCmd.analyticsMetricsService.CreateGeneralEvent(xscservices.CliProduct, xscservices.CliEventType)) auditParams := NewAuditParams(). SetXrayGraphScanParams(auditCmd.CreateXrayGraphScanParams()). SetWorkingDirs(workingDirs). @@ -105,9 +118,6 @@ func (auditCmd *AuditCommand) Run() (err error) { SetThirdPartyApplicabilityScan(auditCmd.thirdPartyApplicabilityScan) auditParams.SetIsRecursiveScan(isRecursiveScan).SetExclusions(auditCmd.Exclusions()) - auditCmd.analyticsMetricsService.AddGeneralEvent(auditCmd.analyticsMetricsService.CreateGeneralEvent(xscservices.CliProduct, xscservices.CliEventType)) - auditParams.xrayGraphScanParams.MultiScanId = auditCmd.analyticsMetricsService.GetMsi() - auditResults, err := RunAudit(auditParams) if err != nil { return diff --git a/utils/analyticsmetrics.go b/utils/analyticsmetrics.go index b9ece63b..d5b80457 100644 --- a/utils/analyticsmetrics.go +++ b/utils/analyticsmetrics.go @@ -52,6 +52,10 @@ func (ams *AnalyticsMetricsService) calcShouldReportEvents() bool { return true } +func (ams *AnalyticsMetricsService) XscManager() *xsc.XscServicesManager { + return ams.xscManager +} + func (ams *AnalyticsMetricsService) SetMsi(msi string) { ams.msi = msi } From e30c3d27033786c55ab50610f7395ff80bdda5a8 Mon Sep 17 00:00:00 2001 From: gail Date: Wed, 3 Apr 2024 17:42:38 +0300 Subject: [PATCH 25/32] Add CountScanResultsFindings. --- commands/audit/jas/common_test.go | 4 ++-- utils/analyticsmetrics.go | 39 +++++++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/commands/audit/jas/common_test.go b/commands/audit/jas/common_test.go index 7a3d4936..e7ccf654 100644 --- a/commands/audit/jas/common_test.go +++ b/commands/audit/jas/common_test.go @@ -101,12 +101,12 @@ func TestSetAnalyticsMetricsDataForAnalyzerManager(t *testing.T) { args args want func() }{ - {name: "Valid 1 technology", args: args{msi: "msi", technologies: []coreutils.Technology{coreutils.Maven}}, want: func() { + {name: "One valid technology", args: args{msi: "msi", technologies: []coreutils.Technology{coreutils.Maven}}, want: func() { assert.Equal(t, string(coreutils.Maven), os.Getenv(utils.JfPackageManagerEnvVariable)) assert.Equal(t, string(utils.Java), os.Getenv(utils.JfLanguageEnvVariable)) assert.Equal(t, "msi", os.Getenv(utils.JfMsiEnvVariable)) }}, - {name: "multiple technologies", args: args{msi: "msi", technologies: []coreutils.Technology{coreutils.Maven, coreutils.Npm}}, want: func() { + {name: "Multiple technologies", args: args{msi: "msi", technologies: []coreutils.Technology{coreutils.Maven, coreutils.Npm}}, want: func() { assert.Equal(t, "", os.Getenv(utils.JfPackageManagerEnvVariable)) assert.Equal(t, "", os.Getenv(utils.JfLanguageEnvVariable)) assert.Equal(t, "msi", os.Getenv(utils.JfMsiEnvVariable)) diff --git a/utils/analyticsmetrics.go b/utils/analyticsmetrics.go index d5b80457..261a7d3e 100644 --- a/utils/analyticsmetrics.go +++ b/utils/analyticsmetrics.go @@ -154,10 +154,6 @@ func (ams *AnalyticsMetricsService) GetGeneralEvent(msi string) (*xscservices.Xs func (ams *AnalyticsMetricsService) CreateXscAnalyticsGeneralEventFinalizeFromAuditResults(auditResults *Results) *xscservices.XscAnalyticsGeneralEventFinalize { totalDuration := time.Since(ams.GetStartTime()) - totalFindings := len(auditResults.ScaResults) - if auditResults.ExtendedScanResults != nil { - totalFindings += len(auditResults.ExtendedScanResults.ApplicabilityScanResults) + len(auditResults.ExtendedScanResults.SecretsScanResults) + len(auditResults.ExtendedScanResults.IacScanResults) + len(auditResults.ExtendedScanResults.SastScanResults) - } eventStatus := xscservices.Completed if auditResults.ScaError != nil || auditResults.JasError != nil { eventStatus = xscservices.Failed @@ -165,7 +161,7 @@ func (ams *AnalyticsMetricsService) CreateXscAnalyticsGeneralEventFinalizeFromAu basicEvent := xscservices.XscAnalyticsBasicGeneralEvent{ EventStatus: eventStatus, - TotalFindings: totalFindings, + TotalFindings: ams.CountScanResultsFindings(auditResults), TotalScanDuration: totalDuration.String(), } return &xscservices.XscAnalyticsGeneralEventFinalize{ @@ -173,3 +169,36 @@ func (ams *AnalyticsMetricsService) CreateXscAnalyticsGeneralEventFinalizeFromAu XscAnalyticsBasicGeneralEvent: basicEvent, } } + +// Counts the total amount of findings in the provided results and updates the AnalyticsMetricsService with the amount of the new added findings +func (ams *AnalyticsMetricsService) CountScanResultsFindings(scanResults *Results) int { + findingsCountMap := make(map[string]int) + var totalFindings int + + // Counting ScaResults + for _, scaResult := range scanResults.ScaResults { + for _, xrayResult := range scaResult.XrayResults { + // XrayResults may contain Vulnerabilities OR Violations, but not both. Therefore, only one of them will be counted + for _, vulnerability := range xrayResult.Vulnerabilities { + findingsCountMap[vulnerability.IssueId] += len(vulnerability.Components) + } + + for _, violation := range xrayResult.Violations { + findingsCountMap[violation.IssueId] += len(violation.Components) + } + } + } + + for _, issueIdCount := range findingsCountMap { + totalFindings += issueIdCount + } + + // Counting ExtendedScanResults + if scanResults.ExtendedScanResults != nil { + totalFindings += len(scanResults.ExtendedScanResults.SastScanResults) + totalFindings += len(scanResults.ExtendedScanResults.IacScanResults) + totalFindings += len(scanResults.ExtendedScanResults.SecretsScanResults) + } + + return totalFindings +} From 15164f40c39bd869f951e0f92210eaa79ebab1b8 Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Wed, 3 Apr 2024 17:58:17 +0300 Subject: [PATCH 26/32] adding function and methods to support analytics report in Frogbot --- utils/analyticsmetrics.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/utils/analyticsmetrics.go b/utils/analyticsmetrics.go index 261a7d3e..73525782 100644 --- a/utils/analyticsmetrics.go +++ b/utils/analyticsmetrics.go @@ -202,3 +202,20 @@ func (ams *AnalyticsMetricsService) CountScanResultsFindings(scanResults *Result return totalFindings } + +func (ams *AnalyticsMetricsService) UpdateXscAnalyticsGeneralEventFinalizeWithTotalScanDuration() { + totalDuration := time.Since(ams.GetStartTime()) + ams.finalizeEvent.TotalScanDuration = totalDuration.String() +} + +func (ams *AnalyticsMetricsService) UpdateXscAnalyticsGeneralEventFinalizeStatus(status xscservices.EventStatus) { + ams.finalizeEvent.EventStatus = status +} + +func (ams *AnalyticsMetricsService) AddScanFindingsToXscAnalyticsGeneralEventFinalize(findingsAmount int) { + ams.finalizeEvent.TotalFindings += findingsAmount +} + +func (ams *AnalyticsMetricsService) SetShouldReportEvents(shouldReportEvents bool) { + ams.shouldReportEvents = shouldReportEvents +} From bd2538000feea443028b778dc6efec9db2b12f95 Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Mon, 8 Apr 2024 17:36:48 +0200 Subject: [PATCH 27/32] resolve conflicts --- utils/analyticsmetrics.go | 33 ------------------------------ utils/results.go | 43 ++++++++++++++++++++++----------------- 2 files changed, 24 insertions(+), 52 deletions(-) diff --git a/utils/analyticsmetrics.go b/utils/analyticsmetrics.go index 6389d270..8405e68d 100644 --- a/utils/analyticsmetrics.go +++ b/utils/analyticsmetrics.go @@ -172,39 +172,6 @@ func (ams *AnalyticsMetricsService) CreateXscAnalyticsGeneralEventFinalizeFromAu } } -// Counts the total amount of findings in the provided results and updates the AnalyticsMetricsService with the amount of the new added findings -func (ams *AnalyticsMetricsService) CountScanResultsFindings(scanResults *Results) int { - findingsCountMap := make(map[string]int) - var totalFindings int - - // Counting ScaResults - for _, scaResult := range scanResults.ScaResults { - for _, xrayResult := range scaResult.XrayResults { - // XrayResults may contain Vulnerabilities OR Violations, but not both. Therefore, only one of them will be counted - for _, vulnerability := range xrayResult.Vulnerabilities { - findingsCountMap[vulnerability.IssueId] += len(vulnerability.Components) - } - - for _, violation := range xrayResult.Violations { - findingsCountMap[violation.IssueId] += len(violation.Components) - } - } - } - - for _, issueIdCount := range findingsCountMap { - totalFindings += issueIdCount - } - - // Counting ExtendedScanResults - if scanResults.ExtendedScanResults != nil { - totalFindings += len(scanResults.ExtendedScanResults.SastScanResults) - totalFindings += len(scanResults.ExtendedScanResults.IacScanResults) - totalFindings += len(scanResults.ExtendedScanResults.SecretsScanResults) - } - - return totalFindings -} - func (ams *AnalyticsMetricsService) UpdateXscAnalyticsGeneralEventFinalizeWithTotalScanDuration() { totalDuration := time.Since(ams.GetStartTime()) ams.finalizeEvent.TotalScanDuration = totalDuration.String() diff --git a/utils/results.go b/utils/results.go index 863826da..5f29007b 100644 --- a/utils/results.go +++ b/utils/results.go @@ -69,37 +69,42 @@ func (r *Results) IsIssuesFound() bool { return false } -// Counts the total amount of findings in the provided results and updates the AnalyticsMetricsService with the amount of the new added findings +// Counts the total of unique findings in the provided Results. +// A unique finding is a unique pair of vulnerability's/violation's issueId along with component id +// A unique finding is any entry in ExtendedScanResults.SastScanResults / ExtendedScanResults.IacScanResults / ExtendedScanResults.SecretsScanResults func (r *Results) CountScanResultsFindings() int { - findingsCountMap := make(map[string]int) var totalFindings int + totalFindings += getScaResultsUniqueFindingsAmount(&r.ScaResults) - // Counting ScaResults - for _, scaResult := range r.ScaResults { + if r.ExtendedScanResults != nil { + totalFindings += len(r.ExtendedScanResults.SastScanResults) + totalFindings += len(r.ExtendedScanResults.IacScanResults) + totalFindings += len(r.ExtendedScanResults.SecretsScanResults) + } + + return totalFindings +} + +func getScaResultsUniqueFindingsAmount(scaScanResults *[]ScaScanResult) int { + uniqueXrayFindings := datastructures.MakeSet[string]() + + for _, scaResult := range *scaScanResults { for _, xrayResult := range scaResult.XrayResults { // XrayResults may contain Vulnerabilities OR Violations, but not both. Therefore, only one of them will be counted for _, vulnerability := range xrayResult.Vulnerabilities { - findingsCountMap[vulnerability.IssueId] += len(vulnerability.Components) + for compId, _ := range vulnerability.Components { + uniqueXrayFindings.Add(vulnerability.IssueId + compId) + } } for _, violation := range xrayResult.Violations { - findingsCountMap[violation.IssueId] += len(violation.Components) + for compId, _ := range violation.Components { + uniqueXrayFindings.Add(violation.IssueId + compId) + } } } } - - for _, issueIdCount := range findingsCountMap { - totalFindings += issueIdCount - } - - // Counting ExtendedScanResults - if r.ExtendedScanResults != nil { - totalFindings += len(r.ExtendedScanResults.SastScanResults) - totalFindings += len(r.ExtendedScanResults.IacScanResults) - totalFindings += len(r.ExtendedScanResults.SecretsScanResults) - } - - return totalFindings + return uniqueXrayFindings.Size() } type ScaScanResult struct { From f2ccfe763638d004eafe1c29e0b0009b23ebed83 Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Mon, 8 Apr 2024 17:40:47 +0200 Subject: [PATCH 28/32] resolve conflicts --- utils/mocks.go | 51 -------------------------------------------------- 1 file changed, 51 deletions(-) delete mode 100644 utils/mocks.go diff --git a/utils/mocks.go b/utils/mocks.go deleted file mode 100644 index f3d308a0..00000000 --- a/utils/mocks.go +++ /dev/null @@ -1,51 +0,0 @@ -package utils - -import ( - "fmt" - "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" - "github.com/jfrog/jfrog-cli-core/v2/utils/config" - "github.com/jfrog/jfrog-client-go/artifactory" - "github.com/stretchr/testify/assert" - "net/http" - "net/http/httptest" - "testing" -) - -const testMsi = "27e175b8-e525-11ee-842b-7aa2c69b8f1f" - -type restsTestHandler func(w http.ResponseWriter, r *http.Request) - -// Create mock server to test REST APIs. -// testHandler - The HTTP handler of the test -func CreateRestsMockServer(testHandler restsTestHandler) *httptest.Server { - return httptest.NewServer(http.HandlerFunc(testHandler)) -} -func CreateXscRestsMockServer(t *testing.T, testHandler restsTestHandler) (*httptest.Server, *config.ServerDetails, artifactory.ArtifactoryServicesManager) { - testServer := CreateRestsMockServer(testHandler) - serverDetails := &config.ServerDetails{Url: testServer.URL + "/", XrayUrl: testServer.URL + "/xray/"} - - serviceManager, err := utils.CreateServiceManager(serverDetails, -1, 0, false) - assert.NoError(t, err) - return testServer, serverDetails, serviceManager -} - -func xscServer(t *testing.T, xscVersion string) (*httptest.Server, *config.ServerDetails) { - serverMock, serverDetails, _ := CreateXscRestsMockServer(t, func(w http.ResponseWriter, r *http.Request) { - if r.RequestURI == "/xsc/api/v1/system/version" { - _, err := w.Write([]byte(fmt.Sprintf(`{"xsc_version": "%s"}`, xscVersion))) - if err != nil { - return - } - } - if r.RequestURI == "/xsc/api/v1/event" { - if r.Method == http.MethodPost { - w.WriteHeader(http.StatusCreated) - _, err := w.Write([]byte(fmt.Sprintf(`{"multi_scan_id": "%s"}`, testMsi))) - if err != nil { - return - } - } - } - }) - return serverMock, serverDetails -} From 7a488916c6d4ef24583a0cea7e77ed4ed0a84ee8 Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Mon, 8 Apr 2024 17:42:54 +0200 Subject: [PATCH 29/32] resolve conflicts --- xsc_test.go | 47 ----------------------------------------------- 1 file changed, 47 deletions(-) delete mode 100644 xsc_test.go diff --git a/xsc_test.go b/xsc_test.go deleted file mode 100644 index 95176cb7..00000000 --- a/xsc_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package main - -import ( - "encoding/json" - "github.com/jfrog/jfrog-cli-core/v2/common/format" - "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" - "github.com/jfrog/jfrog-cli-security/formats" - "github.com/jfrog/jfrog-cli-security/scangraph" - securityTests "github.com/jfrog/jfrog-cli-security/tests" - securityTestUtils "github.com/jfrog/jfrog-cli-security/tests/utils" - "github.com/jfrog/jfrog-cli-security/utils" - "github.com/jfrog/jfrog-client-go/utils/tests" - "github.com/jfrog/jfrog-client-go/xsc/services" - "github.com/stretchr/testify/assert" - "testing" -) - -func TestXscAnalyticsForAudit(t *testing.T) { - securityTestUtils.InitSecurityTest(t, scangraph.GraphScanMinXrayVersion, services.AnalyticsMetricsMinXscVersion) - reportUsageCallBack := tests.SetEnvWithCallbackAndAssert(t, coreutils.ReportUsage, "true") - defer reportUsageCallBack() - // Scan npm project and verify that analytics general event were sent to XSC. - output := testXrayAuditNpm(t, string(format.SimpleJson)) - validateAnalyticsBasicEvent(t, output) -} - -func validateAnalyticsBasicEvent(t *testing.T, output string) { - // Get MSI. - var results formats.SimpleJsonResults - err := json.Unmarshal([]byte(output), &results) - assert.NoError(t, err) - - // Verify analytics metrics. - am := utils.NewAnalyticsMetricsService(securityTests.XscDetails) - assert.NotNil(t, am) - event, err := am.GetGeneralEvent(results.MultiScanId) - assert.NoError(t, err) - - // Event creation and addition information. - assert.Equal(t, "cli", event.Product) - assert.Equal(t, 1, event.EventType) - assert.NotEmpty(t, event.EventStatus) - assert.NotEmpty(t, event.AnalyzerManagerVersion) - // The information that was added after updating the event with the scan's results. - assert.NotEmpty(t, event.TotalScanDuration) - assert.True(t, event.TotalFindings > 0) -} From fdc7dd5601d1b22b2062f35b852fe5f6698021e9 Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Mon, 8 Apr 2024 17:46:13 +0200 Subject: [PATCH 30/32] fix tests issues --- utils/results.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/results.go b/utils/results.go index 5f29007b..ab0098b9 100644 --- a/utils/results.go +++ b/utils/results.go @@ -92,13 +92,13 @@ func getScaResultsUniqueFindingsAmount(scaScanResults *[]ScaScanResult) int { for _, xrayResult := range scaResult.XrayResults { // XrayResults may contain Vulnerabilities OR Violations, but not both. Therefore, only one of them will be counted for _, vulnerability := range xrayResult.Vulnerabilities { - for compId, _ := range vulnerability.Components { + for compId := range vulnerability.Components { uniqueXrayFindings.Add(vulnerability.IssueId + compId) } } for _, violation := range xrayResult.Violations { - for compId, _ := range violation.Components { + for compId := range violation.Components { uniqueXrayFindings.Add(violation.IssueId + compId) } } From 6d95759889bd23f98e51bb289432f638943fe5ac Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Tue, 9 Apr 2024 17:58:56 +0300 Subject: [PATCH 31/32] fix CR comments --- utils/results.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/utils/results.go b/utils/results.go index ab0098b9..3a1d8668 100644 --- a/utils/results.go +++ b/utils/results.go @@ -69,9 +69,8 @@ func (r *Results) IsIssuesFound() bool { return false } -// Counts the total of unique findings in the provided Results. -// A unique finding is a unique pair of vulnerability's/violation's issueId along with component id -// A unique finding is any entry in ExtendedScanResults.SastScanResults / ExtendedScanResults.IacScanResults / ExtendedScanResults.SecretsScanResults +// Counts the total number of unique findings in the provided results. +// A unique SCA finding is identified by a unique pair of vulnerability's/violation's issueId and component id or by a result returned from one of JAS scans. func (r *Results) CountScanResultsFindings() int { var totalFindings int totalFindings += getScaResultsUniqueFindingsAmount(&r.ScaResults) From 3b4cadffe8362b4d2a594b893f518bb9747c71f2 Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Wed, 10 Apr 2024 10:07:06 +0300 Subject: [PATCH 32/32] fix go.mod --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 6885091e..5ef0a482 100644 --- a/go.mod +++ b/go.mod @@ -98,8 +98,8 @@ require ( gopkg.in/warnings.v0 v0.1.2 // indirect ) -replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20240404075604-3df49e9a9d64 +replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20240408074156-13680c04f22e -replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20240403100335-8292671b7cc4 +replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20240409191434-4e96d77edd64 // replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go dev diff --git a/go.sum b/go.sum index f23e834c..cf8ee9d7 100644 --- a/go.sum +++ b/go.sum @@ -102,10 +102,10 @@ github.com/jfrog/gofrog v1.6.3 h1:F7He0+75HcgCe6SGTSHLFCBDxiE2Ja0tekvvcktW6wc= github.com/jfrog/gofrog v1.6.3/go.mod h1:SZ1EPJUruxrVGndOzHd+LTiwWYKMlHqhKD+eu+v5Hqg= github.com/jfrog/jfrog-apps-config v1.0.1 h1:mtv6k7g8A8BVhlHGlSveapqf4mJfonwvXYLipdsOFMY= github.com/jfrog/jfrog-apps-config v1.0.1/go.mod h1:8AIIr1oY9JuH5dylz2S6f8Ym2MaadPLR6noCBO4C22w= -github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20240404075604-3df49e9a9d64 h1:eCAqJ8hqJ6bqgmjswjpqhInJMG80MT5D2r465s/fXzg= -github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20240404075604-3df49e9a9d64/go.mod h1:iQoYSsjLWF8x//rtQCwNPE2ycle2X2x6VFQM0LQE2n0= -github.com/jfrog/jfrog-client-go v1.28.1-0.20240403100335-8292671b7cc4 h1:A67yoFRYjRzg+xhLYhH0QN7b4/wggRa/lSQKSjzOwNQ= -github.com/jfrog/jfrog-client-go v1.28.1-0.20240403100335-8292671b7cc4/go.mod h1:tUyEmxznphh0nwAGo6xz9Sps7RRW/TBMxIJZteo+j2k= +github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20240408074156-13680c04f22e h1:PjCzGWHyJqK4j1MP3osPDDAW6KBXMJlBypOxKtp/ZKo= +github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20240408074156-13680c04f22e/go.mod h1:qXAP68g+DlyX2wk5znNbQdK2CcEHfOLOfYXPzdlnkxI= +github.com/jfrog/jfrog-client-go v1.28.1-0.20240409191434-4e96d77edd64 h1:q0GV0IdhYdTqEkNykRwNZP0qNEE8j9dWfY9uKovDPzM= +github.com/jfrog/jfrog-client-go v1.28.1-0.20240409191434-4e96d77edd64/go.mod h1:tUyEmxznphh0nwAGo6xz9Sps7RRW/TBMxIJZteo+j2k= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=