diff --git a/commands/audit/audit.go b/commands/audit/audit.go index 136d8849..76b56c89 100644 --- a/commands/audit/audit.go +++ b/commands/audit/audit.go @@ -257,7 +257,7 @@ func downloadAnalyzerManagerAndRunScanners(auditParallelRunner *utils.SecurityPa if err != nil { return fmt.Errorf("failed to create jas scanner: %s", err.Error()) } - if err = runner.AddJasScannersTasks(auditParallelRunner, scanResults, auditParams.DirectDependencies(), serverDetails, auditParams.thirdPartyApplicabilityScan, scanner, applicability.ApplicabilityScannerType, secrets.SecretsScannerType, auditParallelRunner.AddErrorToChan, auditParams.ScansToPerform()); err != nil { + if err = runner.AddJasScannersTasks(auditParallelRunner, scanResults, auditParams.DirectDependencies(), serverDetails, auditParams.thirdPartyApplicabilityScan, scanner, applicability.ApplicabilityScannerType, secrets.SecretsScannerType, auditParallelRunner.AddErrorToChan, auditParams.ScansToPerform(), auditParams.configProfile); err != nil { return fmt.Errorf("%s failed to run JAS scanners: %s", clientutils.GetLogMsgPrefix(threadId, false), err.Error()) } return diff --git a/commands/audit/audit_test.go b/commands/audit/audit_test.go new file mode 100644 index 00000000..1a1b0acc --- /dev/null +++ b/commands/audit/audit_test.go @@ -0,0 +1,151 @@ +package audit + +import ( + biutils "github.com/jfrog/build-info-go/utils" + "github.com/jfrog/jfrog-cli-core/v2/common/format" + coreTests "github.com/jfrog/jfrog-cli-core/v2/utils/tests" + "github.com/jfrog/jfrog-cli-security/utils" + "github.com/jfrog/jfrog-cli-security/utils/xray/scangraph" + clientTests "github.com/jfrog/jfrog-client-go/utils/tests" + "github.com/jfrog/jfrog-client-go/xsc/services" + "github.com/stretchr/testify/assert" + "os" + "path/filepath" + "testing" +) + +// Note: Currently, if a config profile is provided, the scan will use the profile's settings, IGNORING jfrog-apps-config if exists. +func TestAuditWithConfigProfile(t *testing.T) { + testcases := []struct { + name string + configProfile services.ConfigProfile + expectedSastIssues int + expectedSecretsIssues int + }{ + { + name: "Enable only secrets scanner", + configProfile: services.ConfigProfile{ + ProfileName: "only-secrets", + Modules: []services.Module{{ + ModuleId: 1, + ModuleName: "only-secrets-module", + PathFromRoot: ".", + ScanConfig: services.ScanConfig{ + SastScannerConfig: services.SastScannerConfig{ + EnableSastScan: false, + }, + SecretsScannerConfig: services.SecretsScannerConfig{ + EnableSecretsScan: true, + }, + }, + }}, + IsDefault: false, + }, + expectedSastIssues: 0, + expectedSecretsIssues: 7, + }, + { + name: "Enable only sast scanner", + configProfile: services.ConfigProfile{ + ProfileName: "only-sast", + Modules: []services.Module{{ + ModuleId: 1, + ModuleName: "only-sast-module", + PathFromRoot: ".", + ScanConfig: services.ScanConfig{ + SastScannerConfig: services.SastScannerConfig{ + EnableSastScan: true, + }, + SecretsScannerConfig: services.SecretsScannerConfig{ + EnableSecretsScan: false, + }, + }, + }}, + IsDefault: false, + }, + expectedSastIssues: 1, + expectedSecretsIssues: 0, + }, + { + name: "Enable secrets and sast", + configProfile: services.ConfigProfile{ + ProfileName: "secrets&sast", + Modules: []services.Module{{ + ModuleId: 1, + ModuleName: "secrets&sast-module", + PathFromRoot: ".", + ScanConfig: services.ScanConfig{ + SastScannerConfig: services.SastScannerConfig{ + EnableSastScan: true, + }, + SecretsScannerConfig: services.SecretsScannerConfig{ + EnableSecretsScan: true, + }, + }, + }}, + IsDefault: false, + }, + expectedSastIssues: 1, + expectedSecretsIssues: 7, + }, + } + + for _, testcase := range testcases { + t.Run(testcase.name, func(t *testing.T) { + mockServer, serverDetails := utils.XrayServer(t, utils.EntitlementsMinVersion) + defer mockServer.Close() + + auditBasicParams := (&utils.AuditBasicParams{}). + SetServerDetails(serverDetails). + SetOutputFormat(format.Table). + SetUseJas(true) + + configProfile := testcase.configProfile + auditParams := NewAuditParams(). + SetGraphBasicParams(auditBasicParams). + SetConfigProfile(&configProfile). + SetCommonGraphScanParams(&scangraph.CommonGraphScanParams{ + RepoPath: "", + ProjectKey: "", + Watches: nil, + ScanType: "dependency", + IncludeVulnerabilities: true, + XscVersion: services.ConfigProfileMinXscVersion, + MultiScanId: "random-msi", + }) + auditParams.SetIsRecursiveScan(true) + + tempDirPath, createTempDirCallback := coreTests.CreateTempDirWithCallbackAndAssert(t) + defer createTempDirCallback() + testDirPath := filepath.Join("..", "..", "tests", "testdata", "projects", "jas", "jas") + assert.NoError(t, biutils.CopyDir(testDirPath, tempDirPath, true, nil)) + + baseWd, err := os.Getwd() + assert.NoError(t, err) + chdirCallback := clientTests.ChangeDirWithCallback(t, baseWd, tempDirPath) + defer chdirCallback() + + auditResults, err := RunAudit(auditParams) + assert.NoError(t, err) + + // Currently, the only supported scanners are Secrets and Sast, therefore if a config profile is utilized - all other scanners are disabled. + if testcase.expectedSastIssues > 0 { + assert.NotNil(t, auditResults.ExtendedScanResults.SastScanResults) + assert.Equal(t, testcase.expectedSastIssues, len(auditResults.ExtendedScanResults.SastScanResults[0].Results)) + } else { + assert.Nil(t, auditResults.ExtendedScanResults.SastScanResults) + } + + if testcase.expectedSecretsIssues > 0 { + assert.NotNil(t, auditResults.ExtendedScanResults.SecretsScanResults) + assert.Equal(t, testcase.expectedSecretsIssues, len(auditResults.ExtendedScanResults.SecretsScanResults[0].Results)) + } else { + assert.Nil(t, auditResults.ExtendedScanResults.SecretsScanResults) + } + + assert.Nil(t, auditResults.ScaResults) + assert.Nil(t, auditResults.ExtendedScanResults.ApplicabilityScanResults) + assert.Nil(t, auditResults.ExtendedScanResults.IacScanResults) + }) + } +} diff --git a/commands/audit/auditparams.go b/commands/audit/auditparams.go index edc32174..474bf9b3 100644 --- a/commands/audit/auditparams.go +++ b/commands/audit/auditparams.go @@ -5,6 +5,7 @@ import ( "github.com/jfrog/jfrog-cli-security/utils/severityutils" "github.com/jfrog/jfrog-cli-security/utils/xray/scangraph" "github.com/jfrog/jfrog-client-go/xray/services" + clientservices "github.com/jfrog/jfrog-client-go/xsc/services" ) type AuditParams struct { @@ -19,6 +20,7 @@ type AuditParams struct { // Include third party dependencies source code in the applicability scan. thirdPartyApplicabilityScan bool threads int + configProfile *clientservices.ConfigProfile } func NewAuditParams() *AuditParams { @@ -92,6 +94,11 @@ func (params *AuditParams) SetCommonGraphScanParams(commonParams *scangraph.Comm return params } +func (params *AuditParams) SetConfigProfile(configProfile *clientservices.ConfigProfile) *AuditParams { + params.configProfile = configProfile + return params +} + func (params *AuditParams) createXrayGraphScanParams() *services.XrayGraphScanParams { return &services.XrayGraphScanParams{ RepoPath: params.commonGraphScanParams.RepoPath, diff --git a/commands/audit/scarunner.go b/commands/audit/scarunner.go index e8d47507..14d203d6 100644 --- a/commands/audit/scarunner.go +++ b/commands/audit/scarunner.go @@ -42,6 +42,11 @@ func buildDepTreeAndRunScaScan(auditParallelRunner *utils.SecurityParallelRunner log.Debug("Skipping SCA scan as requested by input...") return } + if auditParams.configProfile != nil { + log.Debug("Skipping SCA scan as a configuration profile is being utilized and currently only Secrets and Sast scanners are supported when utilizing a configuration profile") + return + } + // Prepare currentWorkingDir, err := os.Getwd() if errorutils.CheckError(err) != nil { diff --git a/commands/scan/scan.go b/commands/scan/scan.go index f51a1e39..37bba0c0 100644 --- a/commands/scan/scan.go +++ b/commands/scan/scan.go @@ -452,7 +452,7 @@ func (scanCmd *ScanCommand) createIndexerHandlerFunc(file *spec.File, entitledFo log.Error(fmt.Sprintf("failed to create jas scanner: %s", err.Error())) indexedFileErrors[threadId] = append(indexedFileErrors[threadId], formats.SimpleJsonError{FilePath: filePath, ErrorMessage: err.Error()}) } - err = runner.AddJasScannersTasks(jasFileProducerConsumer, &scanResults, &depsList, scanCmd.serverDetails, false, scanner, applicability.ApplicabilityDockerScanScanType, secrets.SecretsScannerDockerScanType, jasErrHandlerFunc, utils.GetAllSupportedScans()) + err = runner.AddJasScannersTasks(jasFileProducerConsumer, &scanResults, &depsList, scanCmd.serverDetails, false, scanner, applicability.ApplicabilityDockerScanScanType, secrets.SecretsScannerDockerScanType, jasErrHandlerFunc, utils.GetAllSupportedScans(), nil) if err != nil { log.Error(fmt.Sprintf("scanning '%s' failed with error: %s", graph.Id, err.Error())) indexedFileErrors[threadId] = append(indexedFileErrors[threadId], formats.SimpleJsonError{FilePath: filePath, ErrorMessage: err.Error()}) diff --git a/jas/runner/jasrunner.go b/jas/runner/jasrunner.go index 39a72f12..3e284310 100644 --- a/jas/runner/jasrunner.go +++ b/jas/runner/jasrunner.go @@ -2,7 +2,6 @@ package runner import ( "fmt" - "github.com/jfrog/gofrog/parallel" jfrogappsconfig "github.com/jfrog/jfrog-apps-config/go" "github.com/jfrog/jfrog-cli-core/v2/utils/config" @@ -15,11 +14,13 @@ import ( "github.com/jfrog/jfrog-cli-security/utils/jasutils" clientutils "github.com/jfrog/jfrog-client-go/utils" "github.com/jfrog/jfrog-client-go/utils/log" + "github.com/jfrog/jfrog-client-go/xsc/services" "golang.org/x/exp/slices" ) func AddJasScannersTasks(securityParallelRunner *utils.SecurityParallelRunner, scanResults *utils.Results, directDependencies *[]string, - serverDetails *config.ServerDetails, thirdPartyApplicabilityScan bool, scanner *jas.JasScanner, scanType applicability.ApplicabilityScanType, secretsScanType secrets.SecretsScanType, errHandlerFunc func(error), scansToPreform []utils.SubScanType) (err error) { + serverDetails *config.ServerDetails, thirdPartyApplicabilityScan bool, scanner *jas.JasScanner, scanType applicability.ApplicabilityScanType, + secretsScanType secrets.SecretsScanType, errHandlerFunc func(error), scansToPreform []utils.SubScanType, configProfile *services.ConfigProfile) (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,27 +32,51 @@ func AddJasScannersTasks(securityParallelRunner *utils.SecurityParallelRunner, s } // Set environments variables for analytics in analyzers manager. // Don't execute other scanners when scanning third party dependencies. + // Currently, if config profile exists, the only possible scanners to run are: Secrets, Sast if !thirdPartyApplicabilityScan { for _, module := range scanner.JFrogAppsConfig.Modules { if len(scansToPreform) > 0 && !slices.Contains(scansToPreform, utils.SecretsScan) { log.Debug("Skipping secrets scan as requested by input...") + } else if configProfile != nil { + // This code section is related to CentralizedConfig integration in CI Next. + log.Debug(fmt.Sprintf("Using config profile '%s' to determine whether to run secrets scan...", configProfile.ProfileName)) + if configProfile.Modules[0].ScanConfig.SecretsScannerConfig.EnableSecretsScan { + err = addModuleJasScanTask(jfrogappsconfig.Module{}, jasutils.Secrets, securityParallelRunner, runSecretsScan(securityParallelRunner, scanner, scanResults.ExtendedScanResults, module, secretsScanType), errHandlerFunc) + } else { + log.Debug(fmt.Sprintf("Skipping secrets scan as requested by '%s' config profile...", configProfile.ProfileName)) + } } else if err = addModuleJasScanTask(module, jasutils.Secrets, securityParallelRunner, runSecretsScan(securityParallelRunner, scanner, scanResults.ExtendedScanResults, module, secretsScanType), errHandlerFunc); err != nil { return } if runAllScanners { - if len(scansToPreform) > 0 && !slices.Contains(scansToPreform, utils.IacScan) { - log.Debug("Skipping Iac scan as requested by input...") - } else if err = addModuleJasScanTask(module, jasutils.IaC, securityParallelRunner, runIacScan(securityParallelRunner, scanner, scanResults.ExtendedScanResults, module), errHandlerFunc); err != nil { - return + if configProfile == nil { + if len(scansToPreform) > 0 && !slices.Contains(scansToPreform, utils.IacScan) { + log.Debug("Skipping Iac scan as requested by input...") + } else if err = addModuleJasScanTask(module, jasutils.IaC, securityParallelRunner, runIacScan(securityParallelRunner, scanner, scanResults.ExtendedScanResults, module), errHandlerFunc); err != nil { + return + } } if len(scansToPreform) > 0 && !slices.Contains(scansToPreform, utils.SastScan) { log.Debug("Skipping Sast scan as requested by input...") + } else if configProfile != nil { + log.Debug(fmt.Sprintf("Using config profile '%s' to determine whether to run Sast scan...", configProfile.ProfileName)) + if configProfile.Modules[0].ScanConfig.SastScannerConfig.EnableSastScan { + err = addModuleJasScanTask(jfrogappsconfig.Module{}, jasutils.Sast, securityParallelRunner, runSastScan(securityParallelRunner, scanner, scanResults.ExtendedScanResults, module), errHandlerFunc) + } else { + log.Debug(fmt.Sprintf("Skipping Sast scan as requested by '%s' config profile...", configProfile.ProfileName)) + } } else if err = addModuleJasScanTask(module, jasutils.Sast, securityParallelRunner, runSastScan(securityParallelRunner, scanner, scanResults.ExtendedScanResults, module), errHandlerFunc); err != nil { return } } } } + + if configProfile != nil { + log.Debug("Config profile is in use. Skipping Contextual Analysis scan as it is not currently supported with a config profile...") + return + } + if len(scansToPreform) > 0 && !slices.Contains(scansToPreform, utils.ContextualAnalysisScan) { log.Debug("Skipping contextual analysis scan as requested by input...") return err diff --git a/jas/runner/jasrunner_test.go b/jas/runner/jasrunner_test.go index 886b3e3b..4e2a3a06 100644 --- a/jas/runner/jasrunner_test.go +++ b/jas/runner/jasrunner_test.go @@ -39,7 +39,7 @@ func TestGetExtendedScanResults_ServerNotValid(t *testing.T) { scanner := &jas.JasScanner{} jasScanner, err := jas.CreateJasScanner(scanner, nil, &jas.FakeServerDetails, jas.GetAnalyzerManagerXscEnvVars("", scanResults.GetScaScannedTechnologies()...)) assert.NoError(t, err) - err = AddJasScannersTasks(securityParallelRunnerForTest, scanResults, &[]string{"issueId_1_direct_dependency", "issueId_2_direct_dependency"}, nil, false, jasScanner, applicability.ApplicabilityScannerType, secrets.SecretsScannerType, securityParallelRunnerForTest.AddErrorToChan, utils.GetAllSupportedScans()) + err = AddJasScannersTasks(securityParallelRunnerForTest, scanResults, &[]string{"issueId_1_direct_dependency", "issueId_2_direct_dependency"}, nil, false, jasScanner, applicability.ApplicabilityScannerType, secrets.SecretsScannerType, securityParallelRunnerForTest.AddErrorToChan, utils.GetAllSupportedScans(), nil) assert.NoError(t, err) } diff --git a/tests/testdata/other/configProfile/configProfileExample.json b/tests/testdata/other/configProfile/configProfileExample.json new file mode 100644 index 00000000..e4fb139c --- /dev/null +++ b/tests/testdata/other/configProfile/configProfileExample.json @@ -0,0 +1,49 @@ +{ + "profile_name": "default-profile", + "frogbot_config": { + "email_author": "my-user@jfrog.com", + "aggregate_fixes": true, + "avoid_previous_pr_comments_deletion": true, + "branch_name_template": "frogbot-${IMPACTED_PACKAGE}-${BRANCH_NAME_HASH}", + "pr_title_template": "[🐸 Frogbot] Upgrade {IMPACTED_PACKAGE} to {FIX_VERSION}", + "pr_comment_title": "Frogbot notes:", + "commit_message_template": "Upgrade {IMPACTED_PACKAGE} to {FIX_VERSION}", + "show_secrets_as_pr_comment": false + }, + "modules": [ + { + "module_name": "default-module", + "path_from_root": ".", + "releases_repo": "nuget-remote", + "analyzer_manager_version": "1.8.1", + "additional_paths_for_module": ["lib1", "utils/lib2"], + "exclude_paths": ["**/.git/**", "**/*test*/**", "**/*venv*/**", "**/*node_modules*/**", "**/target/**"], + "scan_config": { + "scan_timeout": 600, + "exclude_pattern": "*.md", + "enable_sca_scan": true, + "enable_contextual_analysis_scan": true, + "sast_scanner_config": { + "enable_sast_scan": true + }, + "secrets_scanner_config": { + "enable_secrets_scan": true + }, + "iac_scanner_config": { + "enable_iac_scan": true + }, + "applications_scanner_config": { + "enable_applications_scan": true + }, + "services_scanner_config": { + "enable_services_scan": true + } + }, + "protected_branches": ["main", "master"], + "include_exclude_mode": 0, + "include_exclude_pattern": "*test*", + "report_analytics": true + } + ], + "is_default": true +} \ No newline at end of file diff --git a/utils/test_mocks.go b/utils/test_mocks.go index 09e61942..469b6c19 100644 --- a/utils/test_mocks.go +++ b/utils/test_mocks.go @@ -8,12 +8,17 @@ import ( "github.com/stretchr/testify/assert" "net/http" "net/http/httptest" + "os" "testing" ) -const TestMsi = "27e175b8-e525-11ee-842b-7aa2c69b8f1f" -const TestScaScanId = "3d90ec4b-cf33-4846-6831-4bf9576f2235" -const TestMoreInfoUrl = "https://www.jfrog.com" +const ( + TestMsi = "27e175b8-e525-11ee-842b-7aa2c69b8f1f" + TestScaScanId = "3d90ec4b-cf33-4846-6831-4bf9576f2235" + TestMoreInfoUrl = "https://www.jfrog.com" + TestConfigProfileName = "default-profile" + versionApiUrl = "/%s/api/v1/system/version" +) type restsTestHandler func(w http.ResponseWriter, r *http.Request) @@ -31,11 +36,17 @@ func CreateXscRestsMockServer(t *testing.T, testHandler restsTestHandler) (*http return testServer, serverDetails, serviceManager } +func CreateXrayRestsMockServer(testHandler restsTestHandler) (*httptest.Server, *config.ServerDetails) { + testServer := CreateRestsMockServer(testHandler) + serverDetails := &config.ServerDetails{Url: testServer.URL + "/", XrayUrl: testServer.URL + "/xray/"} + return testServer, serverDetails +} + 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" { + if r.RequestURI == fmt.Sprintf(versionApiUrl, "xsc") { _, err := w.Write([]byte(fmt.Sprintf(`{"xsc_version": "%s"}`, xscVersion))) - if err != nil { + if !assert.NoError(t, err) { return } } @@ -43,7 +54,50 @@ func XscServer(t *testing.T, xscVersion string) (*httptest.Server, *config.Serve if r.Method == http.MethodPost { w.WriteHeader(http.StatusCreated) _, err := w.Write([]byte(fmt.Sprintf(`{"multi_scan_id": "%s"}`, TestMsi))) - if err != nil { + if !assert.NoError(t, err) { + return + } + } + } + if r.RequestURI == "/xsc/api/v1/profile/"+TestConfigProfileName { + if r.Method == http.MethodGet { + w.WriteHeader(http.StatusOK) + content, err := os.ReadFile("../../tests/testdata/other/configProfile/configProfileExample.json") + if !assert.NoError(t, err) { + return + } + _, err = w.Write(content) + if !assert.NoError(t, err) { + return + } + } + } + }) + return serverMock, serverDetails +} + +func XrayServer(t *testing.T, xrayVersion string) (*httptest.Server, *config.ServerDetails) { + serverMock, serverDetails := CreateXrayRestsMockServer(func(w http.ResponseWriter, r *http.Request) { + if r.RequestURI == fmt.Sprintf(versionApiUrl, "xray") { + _, err := w.Write([]byte(fmt.Sprintf(`{"xray_version": "%s", "xray_revision": "xxx"}`, xrayVersion))) + if !assert.NoError(t, err) { + return + } + } + if r.RequestURI == "/xray/api/v1/entitlements/feature/contextual_analysis" { + if r.Method == http.MethodGet { + w.WriteHeader(http.StatusOK) + _, err := w.Write([]byte(`{"entitled": true, "feature_id": "contextual_analysis"}`)) + if !assert.NoError(t, err) { + return + } + } + } + if r.RequestURI == "/xray/api/v1/scan/graph" { + if r.Method == http.MethodPost { + w.WriteHeader(http.StatusCreated) + _, err := w.Write([]byte(fmt.Sprintf(`{"scan_id" : "%s"}`, TestScaScanId))) + if !assert.NoError(t, err) { return } } diff --git a/utils/xsc/configprofile.go b/utils/xsc/configprofile.go new file mode 100644 index 00000000..71eebef2 --- /dev/null +++ b/utils/xsc/configprofile.go @@ -0,0 +1,32 @@ +package xsc + +import ( + "fmt" + "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/services" +) + +func GetConfigProfile(serverDetails *config.ServerDetails, profileName string) (*services.ConfigProfile, error) { + xscManager, err := CreateXscServiceManager(serverDetails) + if err != nil { + return nil, err + } + + xscVersion, err := xscManager.GetVersion() + if err != nil { + return nil, fmt.Errorf("failed to get XSC service version '%s': %q", profileName, err) + } + + if err = clientutils.ValidateMinimumVersion(clientutils.Xsc, xscVersion, services.ConfigProfileMinXscVersion); err != nil { + log.Info("Minimal Xsc version required to utilize config profile is '%s'. All configurations will be induced from provided Env vars and files") + return nil, err + } + + configProfile, err := xscManager.GetConfigProfile(profileName) + if err != nil { + err = fmt.Errorf("failed to get config profile '%s': %q", profileName, err) + } + return configProfile, err +} diff --git a/utils/xsc/configprofile_test.go b/utils/xsc/configprofile_test.go new file mode 100644 index 00000000..86afca0a --- /dev/null +++ b/utils/xsc/configprofile_test.go @@ -0,0 +1,36 @@ +package xsc + +import ( + "encoding/json" + "github.com/jfrog/jfrog-cli-security/utils" + "github.com/jfrog/jfrog-client-go/xsc/services" + "github.com/stretchr/testify/assert" + "os" + "testing" +) + +func TestGetConfigProfile_ValidRequest_SuccessExpected(t *testing.T) { + mockServer, serverDetails := utils.XscServer(t, services.ConfigProfileMinXscVersion) + defer mockServer.Close() + + configProfile, err := GetConfigProfile(serverDetails, utils.TestConfigProfileName) + assert.NoError(t, err) + + profileFileContent, err := os.ReadFile("../../tests/testdata/other/configProfile/configProfileExample.json") + assert.NoError(t, err) + + var configProfileForComparison services.ConfigProfile + err = json.Unmarshal(profileFileContent, &configProfileForComparison) + assert.NoError(t, err) + + assert.Equal(t, &configProfileForComparison, configProfile) +} + +func TestGetConfigProfile_TooLowXscVersion_FailureExpected(t *testing.T) { + mockServer, serverDetails := utils.XscServer(t, "1.0.0") + defer mockServer.Close() + + configProfile, err := GetConfigProfile(serverDetails, utils.TestConfigProfileName) + assert.Error(t, err) + assert.Nil(t, configProfile) +} diff --git a/utils/xsc/errorreport.go b/utils/xsc/errorreport.go index a2654893..ee14e889 100644 --- a/utils/xsc/errorreport.go +++ b/utils/xsc/errorreport.go @@ -3,7 +3,9 @@ package xsc import ( "fmt" "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" "github.com/jfrog/jfrog-client-go/xsc/services" ) @@ -21,5 +23,30 @@ func ReportError(serverDetails *config.ServerDetails, errorToReport error, sourc Source: source, Message: errorToReport.Error(), } - return SendXscLogMessageIfEnabled(errorLog, xscManager) + return sendXscLogMessageIfEnabled(errorLog, xscManager) +} + +func sendXscLogMessageIfEnabled(errorLog *services.ExternalErrorLog, xscManager *xsc.XscServicesManager) error { + if !IsReportLogErrorEventPossible(xscManager) { + return nil + } + return xscManager.SendXscLogErrorRequest(errorLog) +} + +// Determines if reporting the error is feasible. +func IsReportLogErrorEventPossible(xscManager *xsc.XscServicesManager) bool { + xscVersion, err := xscManager.GetVersion() + if err != nil { + log.Debug(fmt.Sprintf("failed to check availability of Xsc service:%s\nReporting to JFrog analytics is skipped...", err.Error())) + return false + } + if xscVersion == "" { + log.Debug("Xsc service is not available. Reporting to JFrog analytics is skipped...") + return false + } + if err = clientutils.ValidateMinimumVersion(clientutils.Xsc, xscVersion, minXscVersionForErrorReport); err != nil { + log.Debug(err.Error()) + return false + } + return true } diff --git a/utils/xsc/xscmanager.go b/utils/xsc/xscmanager.go index 831c15c2..985d6788 100644 --- a/utils/xsc/xscmanager.go +++ b/utils/xsc/xscmanager.go @@ -2,15 +2,11 @@ package xsc 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" + clientconfig "github.com/jfrog/jfrog-client-go/config" "github.com/jfrog/jfrog-client-go/utils/log" "github.com/jfrog/jfrog-client-go/xsc" - "github.com/jfrog/jfrog-client-go/xsc/services" - - clientconfig "github.com/jfrog/jfrog-client-go/config" ) const minXscVersionForErrorReport = "1.7.7" @@ -35,31 +31,6 @@ func CreateXscServiceManager(serviceDetails *config.ServerDetails) (*xsc.XscServ return xsc.New(serviceConfig) } -func SendXscLogMessageIfEnabled(errorLog *services.ExternalErrorLog, xscManager *xsc.XscServicesManager) error { - if !IsReportLogErrorEventPossible(xscManager) { - return nil - } - return xscManager.SendXscLogErrorRequest(errorLog) -} - -// Determines if reporting the error is feasible. -func IsReportLogErrorEventPossible(xscManager *xsc.XscServicesManager) bool { - xscVersion, err := xscManager.GetVersion() - if err != nil { - log.Debug(fmt.Sprintf("failed to check availability of Xsc service:%s\nReporting to JFrog analytics is skipped...", err.Error())) - return false - } - if xscVersion == "" { - log.Debug("Xsc service is not available. Reporting to JFrog analytics is skipped...") - return false - } - if err = clientutils.ValidateMinimumVersion(clientutils.Xsc, xscVersion, minXscVersionForErrorReport); err != nil { - log.Debug(err.Error()) - return false - } - return true -} - func GetXscMsiAndVersion(analyticsMetricsService *AnalyticsMetricsService) (multiScanId, xscVersion string) { var err error if analyticsMetricsService != nil {