From a938b49d4725a8253dc6a06866331be54e085135 Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Wed, 25 Sep 2024 15:32:48 +0300 Subject: [PATCH 01/18] changed yarn project installation logic during Dependency Tree construction + added test case for the new scenario --- commands/audit/sca/yarn/yarn.go | 35 +++++++++++++----------- commands/audit/sca/yarn/yarn_test.go | 40 +++++++++++++++++----------- 2 files changed, 44 insertions(+), 31 deletions(-) diff --git a/commands/audit/sca/yarn/yarn.go b/commands/audit/sca/yarn/yarn.go index c59c4074..02144c5c 100644 --- a/commands/audit/sca/yarn/yarn.go +++ b/commands/audit/sca/yarn/yarn.go @@ -3,12 +3,13 @@ package yarn import ( "errors" "fmt" + biutils "github.com/jfrog/build-info-go/utils" "path/filepath" "golang.org/x/exp/maps" "github.com/jfrog/build-info-go/build" - biutils "github.com/jfrog/build-info-go/build/utils" + bibuildutils "github.com/jfrog/build-info-go/build/utils" "github.com/jfrog/gofrog/version" "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/yarn" "github.com/jfrog/jfrog-cli-core/v2/utils/config" @@ -46,17 +47,17 @@ func BuildDependencyTree(params utils.AuditParams) (dependencyTrees []*xrayUtils if err != nil { return } - executablePath, err := biutils.GetYarnExecutable() + executablePath, err := bibuildutils.GetYarnExecutable() if errorutils.CheckError(err) != nil { return } - packageInfo, err := biutils.ReadPackageInfoFromPackageJsonIfExists(currentDir, nil) + packageInfo, err := bibuildutils.ReadPackageInfoFromPackageJsonIfExists(currentDir, nil) if errorutils.CheckError(err) != nil { return } - installRequired, err := isInstallRequired(currentDir, params.InstallCommandArgs()) + installRequired, err := isInstallRequired(currentDir, params.InstallCommandArgs(), params.SkipAutoInstall()) if err != nil { return } @@ -70,7 +71,7 @@ func BuildDependencyTree(params utils.AuditParams) (dependencyTrees []*xrayUtils } // Calculate Yarn dependencies - dependenciesMap, root, err := biutils.GetYarnDependencies(executablePath, currentDir, packageInfo, log.Logger) + dependenciesMap, root, err := bibuildutils.GetYarnDependencies(executablePath, currentDir, packageInfo, log.Logger) if err != nil { return } @@ -89,7 +90,7 @@ func configureYarnResolutionServerAndRunInstall(params utils.AuditParams, curWd, return runYarnInstallAccordingToVersion(curWd, yarnExecPath, params.InstallCommandArgs()) } - executableYarnVersion, err := biutils.GetVersion(yarnExecPath, curWd) + executableYarnVersion, err := bibuildutils.GetVersion(yarnExecPath, curWd) if err != nil { return } @@ -136,19 +137,23 @@ func configureYarnResolutionServerAndRunInstall(params utils.AuditParams, curWd, return runYarnInstallAccordingToVersion(curWd, yarnExecPath, params.InstallCommandArgs()) } -func isInstallRequired(currentDir string, installCommandArgs []string) (installRequired bool, err error) { +// We verify the project's installation status by examining the presence of the yarn.lock file and the presence of an installation command provided by the user. +// If install command was provided - we install +// If yarn.lock is missing, we should install unless the user has explicitly disabled auto-install. In this case we return an error +// Notice!: If alterations are made manually in the package.json file, it necessitates a manual update to the yarn.lock file as well. +func isInstallRequired(currentDir string, installCommandArgs []string, skipAutoInstall bool) (installRequired bool, err error) { yarnLockExits, err := fileutils.IsFileExists(filepath.Join(currentDir, yarn.YarnLockFileName), false) if err != nil { err = fmt.Errorf("failed to check the existence of '%s' file: %s", filepath.Join(currentDir, yarn.YarnLockFileName), err.Error()) return } - // We verify the project's installation status by examining the presence of the yarn.lock file and the presence of an installation command provided by the user. - // Notice!: If alterations are made manually in the package.json file, it necessitates a manual update to the yarn.lock file as well. - if len(installCommandArgs) > 0 || !yarnLockExits { + if len(installCommandArgs) > 0 { installRequired = true + } else if !yarnLockExits && skipAutoInstall { + return false, &biutils.ErrInstallForbidden{UninstalledDir: currentDir} } - return + return !yarnLockExits, nil } // Executes the user-defined 'install' command; if absent, defaults to running an 'install' command with specific flags suited to the current yarn version. @@ -162,7 +167,7 @@ func runYarnInstallAccordingToVersion(curWd, yarnExecPath string, installCommand } installCommandArgs = []string{"install"} - executableVersionStr, err := biutils.GetVersion(yarnExecPath, curWd) + executableVersionStr, err := bibuildutils.GetVersion(yarnExecPath, curWd) if err != nil { return } @@ -200,13 +205,13 @@ func runYarnInstallAccordingToVersion(curWd, yarnExecPath string, installCommand } // Parse the dependencies into a Xray dependency tree format -func parseYarnDependenciesMap(dependencies map[string]*biutils.YarnDependency, rootXrayId string) (*xrayUtils.GraphNode, []string) { +func parseYarnDependenciesMap(dependencies map[string]*bibuildutils.YarnDependency, rootXrayId string) (*xrayUtils.GraphNode, []string) { treeMap := make(map[string]xray.DepTreeNode) for _, dependency := range dependencies { xrayDepId := getXrayDependencyId(dependency) var subDeps []string for _, subDepPtr := range dependency.Details.Dependencies { - subDeps = append(subDeps, getXrayDependencyId(dependencies[biutils.GetYarnDependencyKeyFromLocator(subDepPtr.Locator)])) + subDeps = append(subDeps, getXrayDependencyId(dependencies[bibuildutils.GetYarnDependencyKeyFromLocator(subDepPtr.Locator)])) } if len(subDeps) > 0 { treeMap[xrayDepId] = xray.DepTreeNode{Children: subDeps} @@ -216,6 +221,6 @@ func parseYarnDependenciesMap(dependencies map[string]*biutils.YarnDependency, r return graph, maps.Keys(uniqDeps) } -func getXrayDependencyId(yarnDependency *biutils.YarnDependency) string { +func getXrayDependencyId(yarnDependency *bibuildutils.YarnDependency) string { return utils.NpmPackageTypeIdentifier + yarnDependency.Name() + ":" + yarnDependency.Details.Version } diff --git a/commands/audit/sca/yarn/yarn_test.go b/commands/audit/sca/yarn/yarn_test.go index faad4d64..2cfc0116 100644 --- a/commands/audit/sca/yarn/yarn_test.go +++ b/commands/audit/sca/yarn/yarn_test.go @@ -1,9 +1,10 @@ package yarn import ( + "errors" "github.com/jfrog/build-info-go/build" - biutils "github.com/jfrog/build-info-go/build/utils" - utils2 "github.com/jfrog/build-info-go/utils" + bibuildutils "github.com/jfrog/build-info-go/build/utils" + biutils "github.com/jfrog/build-info-go/utils" "github.com/jfrog/jfrog-cli-core/v2/utils/tests" "github.com/jfrog/jfrog-cli-security/utils" "github.com/jfrog/jfrog-client-go/utils/io/fileutils" @@ -14,12 +15,12 @@ import ( ) func TestParseYarnDependenciesList(t *testing.T) { - yarnDependencies := map[string]*biutils.YarnDependency{ - "pack1@npm:1.0.0": {Value: "pack1@npm:1.0.0", Details: biutils.YarnDepDetails{Version: "1.0.0", Dependencies: []biutils.YarnDependencyPointer{{Locator: "pack4@npm:4.0.0"}}}}, - "pack2@npm:2.0.0": {Value: "pack2@npm:2.0.0", Details: biutils.YarnDepDetails{Version: "2.0.0", Dependencies: []biutils.YarnDependencyPointer{{Locator: "pack4@npm:4.0.0"}, {Locator: "pack5@npm:5.0.0"}}}}, - "@jfrog/pack3@npm:3.0.0": {Value: "@jfrog/pack3@npm:3.0.0", Details: biutils.YarnDepDetails{Version: "3.0.0", Dependencies: []biutils.YarnDependencyPointer{{Locator: "pack1@virtual:c192f6b3b32cd5d11a443144e162ec3bc#npm:1.0.0"}, {Locator: "pack2@npm:2.0.0"}}}}, - "pack4@npm:4.0.0": {Value: "pack4@npm:4.0.0", Details: biutils.YarnDepDetails{Version: "4.0.0"}}, - "pack5@npm:5.0.0": {Value: "pack5@npm:5.0.0", Details: biutils.YarnDepDetails{Version: "5.0.0", Dependencies: []biutils.YarnDependencyPointer{{Locator: "pack2@npm:2.0.0"}}}}, + yarnDependencies := map[string]*bibuildutils.YarnDependency{ + "pack1@npm:1.0.0": {Value: "pack1@npm:1.0.0", Details: bibuildutils.YarnDepDetails{Version: "1.0.0", Dependencies: []bibuildutils.YarnDependencyPointer{{Locator: "pack4@npm:4.0.0"}}}}, + "pack2@npm:2.0.0": {Value: "pack2@npm:2.0.0", Details: bibuildutils.YarnDepDetails{Version: "2.0.0", Dependencies: []bibuildutils.YarnDependencyPointer{{Locator: "pack4@npm:4.0.0"}, {Locator: "pack5@npm:5.0.0"}}}}, + "@jfrog/pack3@npm:3.0.0": {Value: "@jfrog/pack3@npm:3.0.0", Details: bibuildutils.YarnDepDetails{Version: "3.0.0", Dependencies: []bibuildutils.YarnDependencyPointer{{Locator: "pack1@virtual:c192f6b3b32cd5d11a443144e162ec3bc#npm:1.0.0"}, {Locator: "pack2@npm:2.0.0"}}}}, + "pack4@npm:4.0.0": {Value: "pack4@npm:4.0.0", Details: bibuildutils.YarnDepDetails{Version: "4.0.0"}}, + "pack5@npm:5.0.0": {Value: "pack5@npm:5.0.0", Details: bibuildutils.YarnDepDetails{Version: "5.0.0", Dependencies: []bibuildutils.YarnDependencyPointer{{Locator: "pack2@npm:2.0.0"}}}}, } rootXrayId := utils.NpmPackageTypeIdentifier + "@jfrog/pack3:3.0.0" @@ -57,8 +58,8 @@ func TestIsInstallRequired(t *testing.T) { tempDirPath, createTempDirCallback := tests.CreateTempDirWithCallbackAndAssert(t) defer createTempDirCallback() yarnProjectPath := filepath.Join("..", "..", "..", "..", "tests", "testdata", "projects", "package-managers", "yarn", "yarn-project") - assert.NoError(t, utils2.CopyDir(yarnProjectPath, tempDirPath, true, nil)) - installRequired, err := isInstallRequired(tempDirPath, []string{}) + assert.NoError(t, biutils.CopyDir(yarnProjectPath, tempDirPath, true, nil)) + installRequired, err := isInstallRequired(tempDirPath, []string{}, false) assert.NoError(t, err) assert.True(t, installRequired) @@ -66,17 +67,24 @@ func TestIsInstallRequired(t *testing.T) { assert.NoError(t, err) assert.False(t, isTempDirEmpty) - executablePath, err := biutils.GetYarnExecutable() + executablePath, err := bibuildutils.GetYarnExecutable() assert.NoError(t, err) // We provide a user defined 'install' command and expect to get 'true' as an answer - installRequired, err = isInstallRequired(tempDirPath, []string{"yarn", "install"}) + installRequired, err = isInstallRequired(tempDirPath, []string{"yarn", "install"}, false) assert.NoError(t, err) assert.True(t, installRequired) + // We specifically state that we should skip install even if the project is not installed + installRequired, err = isInstallRequired(tempDirPath, []string{}, true) + assert.False(t, installRequired) + assert.Error(t, err) + var installForbiddenErr *biutils.ErrInstallForbidden + assert.True(t, errors.As(err, &installForbiddenErr)) + // We install the project so yarn.lock will be created and expect to get 'false' as an answer assert.NoError(t, build.RunYarnCommand(executablePath, tempDirPath, "install")) - installRequired, err = isInstallRequired(tempDirPath, []string{}) + installRequired, err = isInstallRequired(tempDirPath, []string{}, false) assert.NoError(t, err) assert.False(t, installRequired) } @@ -92,20 +100,20 @@ func executeRunYarnInstallAccordingToVersionAndVerifyInstallation(t *testing.T, tempDirPath, createTempDirCallback := tests.CreateTempDirWithCallbackAndAssert(t) defer createTempDirCallback() yarnProjectPath := filepath.Join("..", "..", "..", "..", "tests", "testdata", "projects", "package-managers", "yarn", "yarn-project") - assert.NoError(t, utils2.CopyDir(yarnProjectPath, tempDirPath, true, nil)) + assert.NoError(t, biutils.CopyDir(yarnProjectPath, tempDirPath, true, nil)) isTempDirEmpty, err := fileutils.IsDirEmpty(tempDirPath) assert.NoError(t, err) assert.False(t, isTempDirEmpty) - executablePath, err := biutils.GetYarnExecutable() + executablePath, err := bibuildutils.GetYarnExecutable() assert.NoError(t, err) err = runYarnInstallAccordingToVersion(tempDirPath, executablePath, params) assert.NoError(t, err) // Checking the installation worked - we expect to get a 'false' answer when checking whether the project is installed - installRequired, err := isInstallRequired(tempDirPath, []string{}) + installRequired, err := isInstallRequired(tempDirPath, []string{}, false) assert.NoError(t, err) assert.False(t, installRequired) } From 697cdd4644bfa0ab26594f8cc5675a74edf1e266 Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Wed, 25 Sep 2024 16:39:38 +0300 Subject: [PATCH 02/18] added another yarn test to test BuildDependencyTree with skip installation --- commands/audit/sca/yarn/yarn_test.go | 47 ++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/commands/audit/sca/yarn/yarn_test.go b/commands/audit/sca/yarn/yarn_test.go index 2cfc0116..273abfb6 100644 --- a/commands/audit/sca/yarn/yarn_test.go +++ b/commands/audit/sca/yarn/yarn_test.go @@ -6,10 +6,12 @@ import ( bibuildutils "github.com/jfrog/build-info-go/build/utils" biutils "github.com/jfrog/build-info-go/utils" "github.com/jfrog/jfrog-cli-core/v2/utils/tests" + "github.com/jfrog/jfrog-cli-security/commands/audit/sca" "github.com/jfrog/jfrog-cli-security/utils" "github.com/jfrog/jfrog-client-go/utils/io/fileutils" xrayUtils "github.com/jfrog/jfrog-client-go/xray/services/utils" "github.com/stretchr/testify/assert" + "os" "path/filepath" "testing" ) @@ -117,3 +119,48 @@ func executeRunYarnInstallAccordingToVersionAndVerifyInstallation(t *testing.T, assert.NoError(t, err) assert.False(t, installRequired) } + +// This test checks that the tree construction is skipped when the project is not installed and the user prohibited installation +func TestSkipBuildDepTreeWhenInstallForbidden(t *testing.T) { + testCases := []struct { + name string + testDir string + }{ + { + name: "yarn V1", + testDir: filepath.Join("projects", "package-managers", "yarn", "yarn-v1"), + }, + { + name: "yarn V2", + testDir: filepath.Join("projects", "package-managers", "yarn", "yarn-v2"), + }, + { + name: "yarn V3", + testDir: filepath.Join("projects", "package-managers", "yarn", "yarn-v3"), + }, + } + + for _, test := range testCases { + t.Run(test.name, func(t *testing.T) { + // Create and change directory to test workspace + dirPath, cleanUp := sca.CreateTestWorkspace(t, test.testDir) + defer cleanUp() + + expectedLockFilePath := filepath.Join(dirPath, "yarn.lock") + exists, err := fileutils.IsFileExists(expectedLockFilePath, false) + assert.NoError(t, err) + + if exists { + err = os.Remove(filepath.Join(dirPath, "yarn.lock")) + assert.NoError(t, err) + } + + params := (&utils.AuditBasicParams{}).SetSkipAutoInstall(true) + dependencyTrees, uniqueDeps, err := BuildDependencyTree(params) + assert.Nil(t, dependencyTrees) + assert.Nil(t, uniqueDeps) + assert.Error(t, err) + assert.IsType(t, &biutils.ErrInstallForbidden{}, err) + }) + } +} From 831d6903138fc88b3e0aaff36d74a15c5492e09b Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Wed, 25 Sep 2024 16:43:31 +0300 Subject: [PATCH 03/18] applied new 'skip install' logic in NPM BuildDependencyTree + added test for this scenario --- commands/audit/sca/npm/npm.go | 3 +-- commands/audit/sca/npm/npm_test.go | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/commands/audit/sca/npm/npm.go b/commands/audit/sca/npm/npm.go index e596f37d..6cb84df3 100644 --- a/commands/audit/sca/npm/npm.go +++ b/commands/audit/sca/npm/npm.go @@ -3,7 +3,6 @@ package npm import ( "errors" "fmt" - biutils "github.com/jfrog/build-info-go/build/utils" buildinfo "github.com/jfrog/build-info-go/entities" "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/npm" @@ -48,7 +47,7 @@ func BuildDependencyTree(params utils.AuditParams) (dependencyTrees []*xrayUtils }() // Calculate npm dependencies - dependenciesMap, err := biutils.CalculateDependenciesMap(npmExecutablePath, currentDir, packageInfo.BuildInfoModuleId(), treeDepsParam, log.Logger) + dependenciesMap, err := biutils.CalculateDependenciesMap(npmExecutablePath, currentDir, packageInfo.BuildInfoModuleId(), treeDepsParam, log.Logger, params.SkipAutoInstall()) if err != nil { log.Info("Used npm version:", npmVersion.GetVersion()) return diff --git a/commands/audit/sca/npm/npm_test.go b/commands/audit/sca/npm/npm_test.go index def8bfe4..98895d7f 100644 --- a/commands/audit/sca/npm/npm_test.go +++ b/commands/audit/sca/npm/npm_test.go @@ -2,6 +2,8 @@ package npm import ( "encoding/json" + utils2 "github.com/jfrog/build-info-go/utils" + "github.com/jfrog/jfrog-client-go/utils/io/fileutils" "os" "path/filepath" "testing" @@ -122,3 +124,21 @@ func TestIgnoreScripts(t *testing.T) { _, _, err := BuildDependencyTree(params) assert.NoError(t, err) } + +// This test checks that the tree construction is skipped when the project is not installed and the user prohibited installation +func TestSkipBuildDepTreeWhenInstallForbidden(t *testing.T) { + // Create and change directory to test workspace + dirPath, cleanUp := sca.CreateTestWorkspace(t, filepath.Join("projects", "package-managers", "npm", "npm-no-lock")) + defer cleanUp() + + exists, err := fileutils.IsFileExists(filepath.Join(dirPath, "package-lock.json"), false) + assert.NoError(t, err) + assert.False(t, exists) + + params := (&utils.AuditBasicParams{}).SetSkipAutoInstall(true) + dependencyTrees, uniqueDeps, err := BuildDependencyTree(params) + assert.Nil(t, dependencyTrees) + assert.Nil(t, uniqueDeps) + assert.Error(t, err) + assert.IsType(t, &utils2.ErrInstallForbidden{}, err) +} From e6c976d396e3e10895e6ba2780904b05081b46f6 Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Wed, 25 Sep 2024 16:46:57 +0300 Subject: [PATCH 04/18] added 'skipAutoInstall' to auditBasicParams + setter and getter --- utils/auditbasicparams.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/utils/auditbasicparams.go b/utils/auditbasicparams.go index df3a23fd..0c5660fc 100644 --- a/utils/auditbasicparams.go +++ b/utils/auditbasicparams.go @@ -40,6 +40,7 @@ type AuditParams interface { Exclusions() []string SetIsRecursiveScan(isRecursiveScan bool) *AuditBasicParams IsRecursiveScan() bool + SkipAutoInstall() bool } type AuditBasicParams struct { @@ -63,6 +64,7 @@ type AuditBasicParams struct { dependenciesForApplicabilityScan []string exclusions []string isRecursiveScan bool + skipAutoInstall bool } func (abp *AuditBasicParams) DirectDependencies() *[]string { @@ -98,6 +100,11 @@ func (abp *AuditBasicParams) SetUseJas(useJas bool) *AuditBasicParams { return abp } +func (abp *AuditBasicParams) SetSkipAutoInstall(skipAutoInstall bool) *AuditBasicParams { + abp.skipAutoInstall = skipAutoInstall + return abp +} + func (abp *AuditBasicParams) UseJas() bool { return abp.useJas } @@ -253,3 +260,7 @@ func (abp *AuditBasicParams) SetIsRecursiveScan(isRecursiveScan bool) *AuditBasi func (abp *AuditBasicParams) IsRecursiveScan() bool { return abp.isRecursiveScan } + +func (abp *AuditBasicParams) SkipAutoInstall() bool { + return abp.skipAutoInstall +} From c7afa64ceb6d37bc339dcb776a78536f3fc77148 Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Wed, 25 Sep 2024 16:48:53 +0300 Subject: [PATCH 05/18] question about curation --- commands/curation/curationaudit.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commands/curation/curationaudit.go b/commands/curation/curationaudit.go index e95b2188..27d4d1b8 100644 --- a/commands/curation/curationaudit.go +++ b/commands/curation/curationaudit.go @@ -378,7 +378,7 @@ func (ca *CurationAuditCommand) auditTree(tech techutils.Technology, results map return err } // Validate the graph isn't empty. - if len(depTreeResult.FullDepTrees) == 0 { + if len(depTreeResult.FullDepTrees) == 0 { // TODO should we make any change here in Curation if install is disabled but was required? return errorutils.CheckErrorf("found no dependencies for the audited project using '%v' as the package manager", tech.String()) } rtManager, serverDetails, err := ca.getRtManagerAndAuth(tech) From 16bbd14e469e2080dbf70f5d234cf75283db96a9 Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Wed, 25 Sep 2024 16:58:49 +0300 Subject: [PATCH 06/18] small fix --- commands/audit/sca/yarn/yarn.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commands/audit/sca/yarn/yarn.go b/commands/audit/sca/yarn/yarn.go index 02144c5c..69ec06d6 100644 --- a/commands/audit/sca/yarn/yarn.go +++ b/commands/audit/sca/yarn/yarn.go @@ -149,7 +149,7 @@ func isInstallRequired(currentDir string, installCommandArgs []string, skipAutoI } if len(installCommandArgs) > 0 { - installRequired = true + return true, nil } else if !yarnLockExits && skipAutoInstall { return false, &biutils.ErrInstallForbidden{UninstalledDir: currentDir} } From 6bbe3ff966fbb0c7f215f479b73e0c05d1941010 Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Wed, 25 Sep 2024 17:05:55 +0300 Subject: [PATCH 07/18] adjustments for support skipInstallation: checking new error type --- commands/audit/scarunner.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/commands/audit/scarunner.go b/commands/audit/scarunner.go index 36c58864..6187235c 100644 --- a/commands/audit/scarunner.go +++ b/commands/audit/scarunner.go @@ -4,6 +4,7 @@ import ( "encoding/json" "errors" "fmt" + biutils "github.com/jfrog/build-info-go/utils" "github.com/jfrog/build-info-go/utils/pythonutils" "github.com/jfrog/jfrog-client-go/utils/io/fileutils" "golang.org/x/exp/slices" @@ -75,6 +76,11 @@ func buildDepTreeAndRunScaScan(auditParallelRunner *utils.SecurityParallelRunner // Get the dependency tree for the technology in the working directory. treeResult, bdtErr := buildDependencyTree(scan, auditParams) if bdtErr != nil { + var installForbiddenErr *biutils.ErrInstallForbidden + if errors.As(bdtErr, &installForbiddenErr) { + log.Warn(bdtErr.Error()) + continue + } err = errors.Join(err, fmt.Errorf("audit command in '%s' failed:\n%s", scan.Target, bdtErr.Error())) continue } @@ -303,7 +309,7 @@ func getCurationCacheFolderAndLogMsg(params xrayutils.AuditParams, tech techutil return logMessage, curationCacheFolder, err } -func SetResolutionRepoIfExists(params utils.AuditParams, tech techutils.Technology) (serverDetails *config.ServerDetails, err error) { +func SetResolutionRepoInAuditParamsIfExists(params utils.AuditParams, tech techutils.Technology) (serverDetails *config.ServerDetails, err error) { if serverDetails, err = params.ServerDetails(); err != nil { return } @@ -371,13 +377,13 @@ func buildDependencyTree(scan *utils.ScaScanResult, params *AuditParams) (*Depen if err := os.Chdir(scan.Target); err != nil { return nil, errorutils.CheckError(err) } - serverDetails, err := SetResolutionRepoIfExists(params.AuditBasicParams, scan.Technology) + serverDetails, err := SetResolutionRepoInAuditParamsIfExists(params.AuditBasicParams, scan.Technology) if err != nil { return nil, err } treeResult, techErr := GetTechDependencyTree(params.AuditBasicParams, serverDetails, scan.Technology) if techErr != nil { - return nil, fmt.Errorf("failed while building '%s' dependency tree:\n%s", scan.Technology, techErr.Error()) + return nil, fmt.Errorf("failed while building '%s' dependency tree:\n%w", scan.Technology, techErr) } if treeResult.FlatTree == nil || len(treeResult.FlatTree.Nodes) == 0 { return nil, errorutils.CheckErrorf("no dependencies were found. Please try to build your project and re-run the audit command") From ee37fc2bbfbaa33ce701bff746e3eb812bb4e4c0 Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Wed, 25 Sep 2024 17:07:02 +0300 Subject: [PATCH 08/18] func name change --- commands/curation/curationaudit.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commands/curation/curationaudit.go b/commands/curation/curationaudit.go index 27d4d1b8..4895743c 100644 --- a/commands/curation/curationaudit.go +++ b/commands/curation/curationaudit.go @@ -369,7 +369,7 @@ func (ca *CurationAuditCommand) getAuditParamsByTech(tech techutils.Technology) func (ca *CurationAuditCommand) auditTree(tech techutils.Technology, results map[string]*CurationReport) error { params := ca.getAuditParamsByTech(tech) - serverDetails, err := audit.SetResolutionRepoIfExists(params, tech) + serverDetails, err := audit.SetResolutionRepoInAuditParamsIfExists(params, tech) if err != nil { return err } From 6991d4756662491456e10b6d7216396469c312ff Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Wed, 25 Sep 2024 17:19:58 +0300 Subject: [PATCH 09/18] updating go mod --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index db05b5d2..6d263cb8 100644 --- a/go.mod +++ b/go.mod @@ -118,6 +118,6 @@ require ( // replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go dev -// replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go dev +replace github.com/jfrog/build-info-go => github.com/eranturgeman/build-info-go v0.0.0-20240925131522-917a37299b8b // replace github.com/jfrog/froggit-go => github.com/jfrog/froggit-go dev diff --git a/go.sum b/go.sum index 48357587..e2aeec3d 100644 --- a/go.sum +++ b/go.sum @@ -709,6 +709,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= +github.com/eranturgeman/build-info-go v0.0.0-20240925131522-917a37299b8b h1:QCL2lDPTaxXgEbbXIcP+uCL923QFzKreF35wcFf0ANw= +github.com/eranturgeman/build-info-go v0.0.0-20240925131522-917a37299b8b/go.mod h1:JcISnovFXKx3wWf3p1fcMmlPdt6adxScXvoJN4WXqIE= github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= @@ -890,8 +892,6 @@ github.com/jedib0t/go-pretty/v6 v6.5.9 h1:ACteMBRrrmm1gMsXe9PSTOClQ63IXDUt03H5U+ github.com/jedib0t/go-pretty/v6 v6.5.9/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E= github.com/jfrog/archiver/v3 v3.6.1 h1:LOxnkw9pOn45DzCbZNFV6K0+6dCsQ0L8mR3ZcujO5eI= github.com/jfrog/archiver/v3 v3.6.1/go.mod h1:VgR+3WZS4N+i9FaDwLZbq+jeU4B4zctXL+gL4EMzfLw= -github.com/jfrog/build-info-go v1.10.1 h1:5nLrpFjbV2zuBdmJXW2nybAz5vyu+qDkOtR7v0ehi8s= -github.com/jfrog/build-info-go v1.10.1/go.mod h1:JcISnovFXKx3wWf3p1fcMmlPdt6adxScXvoJN4WXqIE= github.com/jfrog/froggit-go v1.16.1 h1:FBIM1qevX/ag9unfmpGzfmZ36D8ulOJ+DPTSFUk3l5U= github.com/jfrog/froggit-go v1.16.1/go.mod h1:TEJSzgiV+3D/GVGE8Y6j46ut1jrBLD1FL6WdMdKwwCE= github.com/jfrog/gofrog v1.7.6 h1:QmfAiRzVyaI7JYGsB7cxfAJePAZTzFz0gRWZSE27c6s= From 794813c1445ec771903d409474ba9e3db5502442 Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Wed, 25 Sep 2024 18:14:41 +0300 Subject: [PATCH 10/18] removing comment --- commands/curation/curationaudit.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commands/curation/curationaudit.go b/commands/curation/curationaudit.go index 4895743c..780a317f 100644 --- a/commands/curation/curationaudit.go +++ b/commands/curation/curationaudit.go @@ -378,7 +378,7 @@ func (ca *CurationAuditCommand) auditTree(tech techutils.Technology, results map return err } // Validate the graph isn't empty. - if len(depTreeResult.FullDepTrees) == 0 { // TODO should we make any change here in Curation if install is disabled but was required? + if len(depTreeResult.FullDepTrees) == 0 { return errorutils.CheckErrorf("found no dependencies for the audited project using '%v' as the package manager", tech.String()) } rtManager, serverDetails, err := ca.getRtManagerAndAuth(tech) From 153032055434431c885dd76acebeed8e1653ee49 Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Mon, 30 Sep 2024 14:52:25 +0300 Subject: [PATCH 11/18] update go mod --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 6d263cb8..5ae77e9a 100644 --- a/go.mod +++ b/go.mod @@ -118,6 +118,6 @@ require ( // replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go dev -replace github.com/jfrog/build-info-go => github.com/eranturgeman/build-info-go v0.0.0-20240925131522-917a37299b8b +replace github.com/jfrog/build-info-go => github.com/eranturgeman/build-info-go v0.0.0-20240930115102-002856a2c70e // replace github.com/jfrog/froggit-go => github.com/jfrog/froggit-go dev diff --git a/go.sum b/go.sum index e2aeec3d..64fcc704 100644 --- a/go.sum +++ b/go.sum @@ -709,8 +709,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= -github.com/eranturgeman/build-info-go v0.0.0-20240925131522-917a37299b8b h1:QCL2lDPTaxXgEbbXIcP+uCL923QFzKreF35wcFf0ANw= -github.com/eranturgeman/build-info-go v0.0.0-20240925131522-917a37299b8b/go.mod h1:JcISnovFXKx3wWf3p1fcMmlPdt6adxScXvoJN4WXqIE= +github.com/eranturgeman/build-info-go v0.0.0-20240930115102-002856a2c70e h1:vMjXv6zR+GuSeSWzlAVI+iLYvs27aFELe4Un/NIjYrI= +github.com/eranturgeman/build-info-go v0.0.0-20240930115102-002856a2c70e/go.mod h1:JcISnovFXKx3wWf3p1fcMmlPdt6adxScXvoJN4WXqIE= github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= From 730c64b86cc51bedde110aef33f4166c3fd8588e Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Mon, 30 Sep 2024 14:53:22 +0300 Subject: [PATCH 12/18] added test cases - CR --- commands/audit/sca/npm/npm_test.go | 90 +++++++++++++++++++++------- commands/audit/sca/yarn/yarn_test.go | 77 +++++++++++++++++++----- 2 files changed, 129 insertions(+), 38 deletions(-) diff --git a/commands/audit/sca/npm/npm_test.go b/commands/audit/sca/npm/npm_test.go index 98895d7f..93bc9649 100644 --- a/commands/audit/sca/npm/npm_test.go +++ b/commands/audit/sca/npm/npm_test.go @@ -2,20 +2,19 @@ package npm import ( "encoding/json" - utils2 "github.com/jfrog/build-info-go/utils" - "github.com/jfrog/jfrog-client-go/utils/io/fileutils" - "os" - "path/filepath" - "testing" - + bibuildutils "github.com/jfrog/build-info-go/build/utils" + buildinfo "github.com/jfrog/build-info-go/entities" + biutils "github.com/jfrog/build-info-go/utils" + "github.com/jfrog/jfrog-cli-core/v2/utils/tests" "github.com/jfrog/jfrog-cli-security/commands/audit/sca" "github.com/jfrog/jfrog-cli-security/utils" + "github.com/jfrog/jfrog-client-go/utils/io/fileutils" xrayUtils "github.com/jfrog/jfrog-client-go/xray/services/utils" - - biutils "github.com/jfrog/build-info-go/build/utils" - buildinfo "github.com/jfrog/build-info-go/entities" - "github.com/jfrog/jfrog-cli-core/v2/utils/tests" "github.com/stretchr/testify/assert" + "os" + "path/filepath" + "strings" + "testing" ) func TestParseNpmDependenciesList(t *testing.T) { @@ -27,7 +26,7 @@ func TestParseNpmDependenciesList(t *testing.T) { var dependencies []buildinfo.Dependency err = json.Unmarshal(dependenciesJson, &dependencies) assert.NoError(t, err) - packageInfo := &biutils.PackageInfo{Name: "npmexmaple", Version: "0.1.0"} + packageInfo := &bibuildutils.PackageInfo{Name: "npmexmaple", Version: "0.1.0"} looseEnvifyJsTokens := []*xrayUtils.GraphNode{{Id: "npm://loose-envify:1.4.0", Nodes: []*xrayUtils.GraphNode{{Id: "npm://js-tokens:4.0.0"}}}} expectedTree := &xrayUtils.GraphNode{ Id: "npm://npmexmaple:0.1.0", @@ -127,18 +126,63 @@ func TestIgnoreScripts(t *testing.T) { // This test checks that the tree construction is skipped when the project is not installed and the user prohibited installation func TestSkipBuildDepTreeWhenInstallForbidden(t *testing.T) { - // Create and change directory to test workspace - dirPath, cleanUp := sca.CreateTestWorkspace(t, filepath.Join("projects", "package-managers", "npm", "npm-no-lock")) - defer cleanUp() + testCases := []struct { + name string + testDir string + installCommand string + shouldBeInstalled bool + successfulTreeBuiltExpected bool + }{ + { + name: "not installed | install required - install command", + testDir: filepath.Join("projects", "package-managers", "npm", "npm-no-lock"), + installCommand: "npm install", + shouldBeInstalled: false, + successfulTreeBuiltExpected: true, + }, + { + name: "not installed | install required - install forbidden", + testDir: filepath.Join("projects", "package-managers", "npm", "npm-no-lock"), + shouldBeInstalled: false, + successfulTreeBuiltExpected: false, + }, + { + name: "installed | install not required", + testDir: filepath.Join("projects", "package-managers", "npm", "npm-project"), + shouldBeInstalled: true, + successfulTreeBuiltExpected: true, + }, + } - exists, err := fileutils.IsFileExists(filepath.Join(dirPath, "package-lock.json"), false) - assert.NoError(t, err) - assert.False(t, exists) + for _, test := range testCases { + t.Run(test.name, func(t *testing.T) { + dirPath, cleanUp := sca.CreateTestWorkspace(t, test.testDir) + defer cleanUp() - params := (&utils.AuditBasicParams{}).SetSkipAutoInstall(true) - dependencyTrees, uniqueDeps, err := BuildDependencyTree(params) - assert.Nil(t, dependencyTrees) - assert.Nil(t, uniqueDeps) - assert.Error(t, err) - assert.IsType(t, &utils2.ErrInstallForbidden{}, err) + exists, err := fileutils.IsFileExists(filepath.Join(dirPath, "package-lock.json"), false) + assert.NoError(t, err) + + if !test.shouldBeInstalled && exists { + err = os.Remove(filepath.Join(dirPath, "package-lock.json")) + assert.NoError(t, err) + } + + params := (&utils.AuditBasicParams{}).SetSkipAutoInstall(true) + if test.installCommand != "" { + splitInstallCommand := strings.Split(test.installCommand, " ") + params = params.SetInstallCommandName(splitInstallCommand[0]).SetInstallCommandArgs(splitInstallCommand[1:]) + } + dependencyTrees, uniqueDeps, err := BuildDependencyTree(params) + if !test.successfulTreeBuiltExpected { + assert.Nil(t, dependencyTrees) + assert.Nil(t, uniqueDeps) + assert.Error(t, err) + assert.IsType(t, &biutils.ErrProjectNotInstalled{}, err) + } else { + assert.NotNil(t, dependencyTrees) + assert.NotNil(t, uniqueDeps) + assert.NoError(t, err) + } + }) + } } diff --git a/commands/audit/sca/yarn/yarn_test.go b/commands/audit/sca/yarn/yarn_test.go index 273abfb6..9369d175 100644 --- a/commands/audit/sca/yarn/yarn_test.go +++ b/commands/audit/sca/yarn/yarn_test.go @@ -13,6 +13,7 @@ import ( "github.com/stretchr/testify/assert" "os" "path/filepath" + "strings" "testing" ) @@ -81,8 +82,8 @@ func TestIsInstallRequired(t *testing.T) { installRequired, err = isInstallRequired(tempDirPath, []string{}, true) assert.False(t, installRequired) assert.Error(t, err) - var installForbiddenErr *biutils.ErrInstallForbidden - assert.True(t, errors.As(err, &installForbiddenErr)) + var projectNotInstalledErr *biutils.ErrProjectNotInstalled + assert.True(t, errors.As(err, &projectNotInstalledErr)) // We install the project so yarn.lock will be created and expect to get 'false' as an answer assert.NoError(t, build.RunYarnCommand(executablePath, tempDirPath, "install")) @@ -123,20 +124,55 @@ func executeRunYarnInstallAccordingToVersionAndVerifyInstallation(t *testing.T, // This test checks that the tree construction is skipped when the project is not installed and the user prohibited installation func TestSkipBuildDepTreeWhenInstallForbidden(t *testing.T) { testCases := []struct { - name string - testDir string + name string + testDir string + installCommand string + shouldBeInstalled bool + successfulTreeBuiltExpected bool }{ { - name: "yarn V1", - testDir: filepath.Join("projects", "package-managers", "yarn", "yarn-v1"), + name: "yarn V1 - not installed | install required - install command", + testDir: filepath.Join("projects", "package-managers", "yarn", "yarn-v1"), + installCommand: "yarn install", + shouldBeInstalled: false, + successfulTreeBuiltExpected: true, }, { - name: "yarn V2", - testDir: filepath.Join("projects", "package-managers", "yarn", "yarn-v2"), + name: "yarn V3 - not installed | install required - install command", + testDir: filepath.Join("projects", "package-managers", "yarn", "yarn-v3"), + installCommand: "yarn install", + shouldBeInstalled: false, + successfulTreeBuiltExpected: true, }, { - name: "yarn V3", - testDir: filepath.Join("projects", "package-managers", "yarn", "yarn-v3"), + name: "yarn V1 - not installed | install required - install forbidden", + testDir: filepath.Join("projects", "package-managers", "yarn", "yarn-v1"), + shouldBeInstalled: false, + successfulTreeBuiltExpected: false, + }, + { + name: "yarn V2 - not installed | install required - install forbidden", + testDir: filepath.Join("projects", "package-managers", "yarn", "yarn-v2"), + shouldBeInstalled: false, + successfulTreeBuiltExpected: false, + }, + { + name: "yarn V3 - not installed | install required - install forbidden", + testDir: filepath.Join("projects", "package-managers", "yarn", "yarn-v3"), + shouldBeInstalled: false, + successfulTreeBuiltExpected: false, + }, + { + name: "yarn V1 - installed | install not required", + testDir: filepath.Join("projects", "package-managers", "yarn", "yarn-v1"), + shouldBeInstalled: true, + successfulTreeBuiltExpected: true, + }, + { + name: "yarn V3 - installed | install not required", + testDir: filepath.Join("projects", "package-managers", "yarn", "yarn-v3"), + shouldBeInstalled: true, + successfulTreeBuiltExpected: true, }, } @@ -150,17 +186,28 @@ func TestSkipBuildDepTreeWhenInstallForbidden(t *testing.T) { exists, err := fileutils.IsFileExists(expectedLockFilePath, false) assert.NoError(t, err) - if exists { + if !test.shouldBeInstalled && exists { err = os.Remove(filepath.Join(dirPath, "yarn.lock")) assert.NoError(t, err) } params := (&utils.AuditBasicParams{}).SetSkipAutoInstall(true) + if test.installCommand != "" { + splitInstallCommand := strings.Split(test.installCommand, " ") + params = params.SetInstallCommandName(splitInstallCommand[0]).SetInstallCommandArgs(splitInstallCommand[1:]) + } + dependencyTrees, uniqueDeps, err := BuildDependencyTree(params) - assert.Nil(t, dependencyTrees) - assert.Nil(t, uniqueDeps) - assert.Error(t, err) - assert.IsType(t, &biutils.ErrInstallForbidden{}, err) + if !test.successfulTreeBuiltExpected { + assert.Nil(t, dependencyTrees) + assert.Nil(t, uniqueDeps) + assert.Error(t, err) + assert.IsType(t, &biutils.ErrProjectNotInstalled{}, err) + } else { + assert.NotNil(t, dependencyTrees) + assert.NotNil(t, uniqueDeps) + assert.NoError(t, err) + } }) } } From c8152368ebbf11e51970c5156efa46c451cd1549 Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Mon, 30 Sep 2024 14:53:35 +0300 Subject: [PATCH 13/18] changed error name --- commands/audit/sca/yarn/yarn.go | 2 +- commands/audit/scarunner.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/commands/audit/sca/yarn/yarn.go b/commands/audit/sca/yarn/yarn.go index 69ec06d6..94df520e 100644 --- a/commands/audit/sca/yarn/yarn.go +++ b/commands/audit/sca/yarn/yarn.go @@ -151,7 +151,7 @@ func isInstallRequired(currentDir string, installCommandArgs []string, skipAutoI if len(installCommandArgs) > 0 { return true, nil } else if !yarnLockExits && skipAutoInstall { - return false, &biutils.ErrInstallForbidden{UninstalledDir: currentDir} + return false, &biutils.ErrProjectNotInstalled{UninstalledDir: currentDir} } return !yarnLockExits, nil } diff --git a/commands/audit/scarunner.go b/commands/audit/scarunner.go index 6187235c..22f14b4e 100644 --- a/commands/audit/scarunner.go +++ b/commands/audit/scarunner.go @@ -76,8 +76,8 @@ func buildDepTreeAndRunScaScan(auditParallelRunner *utils.SecurityParallelRunner // Get the dependency tree for the technology in the working directory. treeResult, bdtErr := buildDependencyTree(scan, auditParams) if bdtErr != nil { - var installForbiddenErr *biutils.ErrInstallForbidden - if errors.As(bdtErr, &installForbiddenErr) { + var projectNotInstalledErr *biutils.ErrProjectNotInstalled + if errors.As(bdtErr, &projectNotInstalledErr) { log.Warn(bdtErr.Error()) continue } From 0cdbfde4e00d5dbe1a7f14e59bc1ad880d9eeed8 Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Tue, 1 Oct 2024 09:23:22 +0300 Subject: [PATCH 14/18] . --- go.mod | 4 ++-- go.sum | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index a471f463..1f82e24c 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/beevik/etree v1.4.0 github.com/google/go-github/v56 v56.0.0 github.com/gookit/color v1.5.4 - github.com/jfrog/build-info-go v1.10.1 + github.com/jfrog/build-info-go v1.10.2 github.com/jfrog/froggit-go v1.16.1 github.com/jfrog/gofrog v1.7.6 github.com/jfrog/jfrog-apps-config v1.0.1 @@ -118,6 +118,6 @@ require ( // replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go dev -replace github.com/jfrog/build-info-go => github.com/eranturgeman/build-info-go v0.0.0-20240930115102-002856a2c70e +// replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go dev // replace github.com/jfrog/froggit-go => github.com/jfrog/froggit-go dev diff --git a/go.sum b/go.sum index 4131ba6c..904f2f20 100644 --- a/go.sum +++ b/go.sum @@ -709,8 +709,6 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= -github.com/eranturgeman/build-info-go v0.0.0-20240930115102-002856a2c70e h1:vMjXv6zR+GuSeSWzlAVI+iLYvs27aFELe4Un/NIjYrI= -github.com/eranturgeman/build-info-go v0.0.0-20240930115102-002856a2c70e/go.mod h1:JcISnovFXKx3wWf3p1fcMmlPdt6adxScXvoJN4WXqIE= github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= @@ -892,6 +890,8 @@ github.com/jedib0t/go-pretty/v6 v6.5.9 h1:ACteMBRrrmm1gMsXe9PSTOClQ63IXDUt03H5U+ github.com/jedib0t/go-pretty/v6 v6.5.9/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E= github.com/jfrog/archiver/v3 v3.6.1 h1:LOxnkw9pOn45DzCbZNFV6K0+6dCsQ0L8mR3ZcujO5eI= github.com/jfrog/archiver/v3 v3.6.1/go.mod h1:VgR+3WZS4N+i9FaDwLZbq+jeU4B4zctXL+gL4EMzfLw= +github.com/jfrog/build-info-go v1.10.2 h1:RCCBsahRNYOm3W7Z9tAL/ixBLzrOzm4mTgI2N6jvqsw= +github.com/jfrog/build-info-go v1.10.2/go.mod h1:JcISnovFXKx3wWf3p1fcMmlPdt6adxScXvoJN4WXqIE= github.com/jfrog/froggit-go v1.16.1 h1:FBIM1qevX/ag9unfmpGzfmZ36D8ulOJ+DPTSFUk3l5U= github.com/jfrog/froggit-go v1.16.1/go.mod h1:TEJSzgiV+3D/GVGE8Y6j46ut1jrBLD1FL6WdMdKwwCE= github.com/jfrog/gofrog v1.7.6 h1:QmfAiRzVyaI7JYGsB7cxfAJePAZTzFz0gRWZSE27c6s= From a18723f15f83bb89ac14a189dc7acbe75a345317 Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Tue, 8 Oct 2024 15:25:32 +0300 Subject: [PATCH 15/18] added --skip-auto-install flag to enable feature usage from CLI --- cli/docs/flags.go | 8 +++++--- cli/scancommands.go | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/cli/docs/flags.go b/cli/docs/flags.go index bf9643e7..08bc62f9 100644 --- a/cli/docs/flags.go +++ b/cli/docs/flags.go @@ -118,6 +118,7 @@ const ( RequirementsFile = "requirements-file" WorkingDirs = "working-dirs" OutputDir = "output-dir" + SkipAutoInstall = "skip-auto-install" // Unique curation flags CurationOutput = "curation-format" @@ -154,7 +155,7 @@ var commandFlags = map[string][]string{ url, user, password, accessToken, ServerId, InsecureTls, Project, Watches, RepoPath, Licenses, OutputFormat, ExcludeTestDeps, useWrapperAudit, DepType, RequirementsFile, Fail, ExtendedTable, WorkingDirs, ExclusionsAudit, Mvn, Gradle, Npm, Pnpm, Yarn, Go, Nuget, Pip, Pipenv, Poetry, MinSeverity, FixableOnly, ThirdPartyContextualAnalysis, Threads, - Sca, Iac, Sast, Secrets, WithoutCA, ScanVuln, SecretValidation, OutputDir, + Sca, Iac, Sast, Secrets, WithoutCA, ScanVuln, SecretValidation, OutputDir, SkipAutoInstall, }, CurationAudit: { CurationOutput, WorkingDirs, Threads, RequirementsFile, @@ -229,8 +230,9 @@ var flagsMap = map[string]components.Flag{ "Set to false if you wish to not use the gradle or maven wrapper.", components.WithBoolDefaultValue(true), ), - WorkingDirs: components.NewStringFlag(WorkingDirs, "A comma-separated list of relative working directories, to determine audit targets locations."), - OutputDir: components.NewStringFlag(OutputDir, "Target directory to save partial results to.", components.SetHiddenStrFlag()), + WorkingDirs: components.NewStringFlag(WorkingDirs, "A comma-separated list of relative working directories, to determine audit targets locations."), + OutputDir: components.NewStringFlag(OutputDir, "Target directory to save partial results to.", components.SetHiddenStrFlag()), + SkipAutoInstall: components.NewBoolFlag(SkipAutoInstall, "Set to true to skip auto-install of dependencies in un-built modules. Currently supported for Yarn and NPM only."), ExclusionsAudit: components.NewStringFlag( Exclusions, "List of exclusions separated by semicolons, utilized to skip sub-projects from undergoing an audit. These exclusions may incorporate the * and ? wildcards.", diff --git a/cli/scancommands.go b/cli/scancommands.go index fcd620e3..a84747cd 100644 --- a/cli/scancommands.go +++ b/cli/scancommands.go @@ -477,7 +477,8 @@ func CreateAuditCmd(c *components.Context) (*audit.AuditCommand, error) { SetMinSeverityFilter(minSeverity). SetFixableOnly(c.GetBoolFlagValue(flags.FixableOnly)). SetThirdPartyApplicabilityScan(c.GetBoolFlagValue(flags.ThirdPartyContextualAnalysis)). - SetScansResultsOutputDir(scansOutputDir) + SetScansResultsOutputDir(scansOutputDir). + SetSkipAutoInstall(c.GetBoolFlagValue(flags.SkipAutoInstall)) if c.GetStringFlagValue(flags.Watches) != "" { auditCmd.SetWatches(splitByCommaAndTrim(c.GetStringFlagValue(flags.Watches))) From 4fa0e0ca28fcef26a7ba5ba30f879ee6dbe47ddc Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Thu, 10 Oct 2024 15:08:15 +0300 Subject: [PATCH 16/18] marked new flag as hidden --- cli/docs/flags.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/docs/flags.go b/cli/docs/flags.go index 08bc62f9..c9173fb0 100644 --- a/cli/docs/flags.go +++ b/cli/docs/flags.go @@ -232,7 +232,7 @@ var flagsMap = map[string]components.Flag{ ), WorkingDirs: components.NewStringFlag(WorkingDirs, "A comma-separated list of relative working directories, to determine audit targets locations."), OutputDir: components.NewStringFlag(OutputDir, "Target directory to save partial results to.", components.SetHiddenStrFlag()), - SkipAutoInstall: components.NewBoolFlag(SkipAutoInstall, "Set to true to skip auto-install of dependencies in un-built modules. Currently supported for Yarn and NPM only."), + SkipAutoInstall: components.NewBoolFlag(SkipAutoInstall, "Set to true to skip auto-install of dependencies in un-built modules. Currently supported for Yarn and NPM only.", components.SetHiddenBoolFlag()), ExclusionsAudit: components.NewStringFlag( Exclusions, "List of exclusions separated by semicolons, utilized to skip sub-projects from undergoing an audit. These exclusions may incorporate the * and ? wildcards.", From e010476918b0ead45ae9753a1da1a9d41cba7e06 Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Thu, 10 Oct 2024 15:08:28 +0300 Subject: [PATCH 17/18] attempt to fix failing test --- commands/audit/sca/yarn/yarn_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commands/audit/sca/yarn/yarn_test.go b/commands/audit/sca/yarn/yarn_test.go index 9369d175..7dc7fcd6 100644 --- a/commands/audit/sca/yarn/yarn_test.go +++ b/commands/audit/sca/yarn/yarn_test.go @@ -140,7 +140,7 @@ func TestSkipBuildDepTreeWhenInstallForbidden(t *testing.T) { { name: "yarn V3 - not installed | install required - install command", testDir: filepath.Join("projects", "package-managers", "yarn", "yarn-v3"), - installCommand: "yarn install", + installCommand: "yarn install --immutable", shouldBeInstalled: false, successfulTreeBuiltExpected: true, }, From 0af08f90ac1e286c9a957187a155529533b064ef Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Thu, 10 Oct 2024 15:45:30 +0300 Subject: [PATCH 18/18] removing problematic test case --- commands/audit/sca/yarn/yarn_test.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/commands/audit/sca/yarn/yarn_test.go b/commands/audit/sca/yarn/yarn_test.go index 7dc7fcd6..023e93c8 100644 --- a/commands/audit/sca/yarn/yarn_test.go +++ b/commands/audit/sca/yarn/yarn_test.go @@ -137,13 +137,6 @@ func TestSkipBuildDepTreeWhenInstallForbidden(t *testing.T) { shouldBeInstalled: false, successfulTreeBuiltExpected: true, }, - { - name: "yarn V3 - not installed | install required - install command", - testDir: filepath.Join("projects", "package-managers", "yarn", "yarn-v3"), - installCommand: "yarn install --immutable", - shouldBeInstalled: false, - successfulTreeBuiltExpected: true, - }, { name: "yarn V1 - not installed | install required - install forbidden", testDir: filepath.Join("projects", "package-managers", "yarn", "yarn-v1"),