Skip to content

Commit

Permalink
Use exclude pattern when building dotnet dependency tree (#24)
Browse files Browse the repository at this point in the history
  • Loading branch information
attiasas authored Feb 25, 2024
1 parent f8617ea commit cc8b9f3
Show file tree
Hide file tree
Showing 13 changed files with 121 additions and 108 deletions.
4 changes: 2 additions & 2 deletions cli/docs/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"github.com/jfrog/jfrog-cli-core/v2/common/cliutils"
pluginsCommon "github.com/jfrog/jfrog-cli-core/v2/plugins/common"
"github.com/jfrog/jfrog-cli-core/v2/plugins/components"
"github.com/jfrog/jfrog-cli-security/commands/audit"
"github.com/jfrog/jfrog-cli-security/commands/audit/sca"
"github.com/jfrog/jfrog-cli-security/commands/curation"
"github.com/jfrog/jfrog-cli-security/commands/xray/offlineupdate"
)
Expand Down Expand Up @@ -200,7 +200,7 @@ var flagsMap = map[string]components.Flag{
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.",
components.WithStrDefaultValue(strings.Join(audit.DefaultExcludePatterns, ";")),
components.WithStrDefaultValue(strings.Join(sca.DefaultExcludePatterns, ";")),
),
Mvn: components.NewBoolFlag(Mvn, "Set to true to request audit for a Maven project."),
Gradle: components.NewBoolFlag(Gradle, "Set to true to request audit for a Gradle project."),
Expand Down
6 changes: 3 additions & 3 deletions cli/scancommands.go
Original file line number Diff line number Diff line change
Expand Up @@ -357,8 +357,7 @@ func createAuditCmd(c *components.Context) (*audit.AuditCommand, error) {
SetPrintExtendedTable(c.GetBoolFlagValue(flags.ExtendedTable)).
SetMinSeverityFilter(minSeverity).
SetFixableOnly(c.GetBoolFlagValue(flags.FixableOnly)).
SetThirdPartyApplicabilityScan(c.GetBoolFlagValue(flags.ThirdPartyContextualAnalysis)).
SetExclusions(pluginsCommon.GetStringsArrFlagValue(c, flags.Exclusions))
SetThirdPartyApplicabilityScan(c.GetBoolFlagValue(flags.ThirdPartyContextualAnalysis))

if c.GetStringFlagValue(flags.Watches) != "" {
auditCmd.SetWatches(splitByCommaAndTrim(c.GetStringFlagValue(flags.Watches)))
Expand All @@ -373,7 +372,8 @@ func createAuditCmd(c *components.Context) (*audit.AuditCommand, error) {
SetUseWrapper(c.GetBoolFlagValue(flags.UseWrapper)).
SetInsecureTls(c.GetBoolFlagValue(flags.InsecureTls)).
SetNpmScope(c.GetStringFlagValue(flags.DepType)).
SetPipRequirementsFile(c.GetStringFlagValue(flags.RequirementsFile))
SetPipRequirementsFile(c.GetStringFlagValue(flags.RequirementsFile)).
SetExclusions(pluginsCommon.GetStringsArrFlagValue(c, flags.Exclusions))
return auditCmd, err
}

Expand Down
5 changes: 2 additions & 3 deletions commands/audit/audit.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,8 @@ func (auditCmd *AuditCommand) Run() (err error) {
SetMinSeverityFilter(auditCmd.minSeverityFilter).
SetFixableOnly(auditCmd.fixableOnly).
SetGraphBasicParams(auditCmd.AuditBasicParams).
SetThirdPartyApplicabilityScan(auditCmd.thirdPartyApplicabilityScan).
SetExclusions(auditCmd.exclusions).
SetIsRecursiveScan(isRecursiveScan)
SetThirdPartyApplicabilityScan(auditCmd.thirdPartyApplicabilityScan)
auditParams.SetIsRecursiveScan(isRecursiveScan).SetExclusions(auditCmd.Exclusions())
auditResults, err := RunAudit(auditParams)
if err != nil {
return
Expand Down
16 changes: 0 additions & 16 deletions commands/audit/auditparams.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,13 @@ import (
type AuditParams struct {
xrayGraphScanParams *services.XrayGraphScanParams
workingDirs []string
exclusions []string
installFunc func(tech string) error
fixableOnly bool
minSeverityFilter string
*xrayutils.AuditBasicParams
xrayVersion string
// Include third party dependencies source code in the applicability scan.
thirdPartyApplicabilityScan bool
isRecursiveScan bool
}

func NewAuditParams() *AuditParams {
Expand All @@ -42,20 +40,6 @@ func (params *AuditParams) XrayVersion() string {
return params.xrayVersion
}

func (params *AuditParams) Exclusions() []string {
return params.exclusions
}

func (params *AuditParams) SetExclusions(exclusions []string) *AuditParams {
params.exclusions = exclusions
return params
}

func (params *AuditParams) SetIsRecursiveScan(isRecursiveScan bool) *AuditParams {
params.isRecursiveScan = isRecursiveScan
return params
}

func (params *AuditParams) SetXrayGraphScanParams(xrayGraphScanParams *services.XrayGraphScanParams) *AuditParams {
params.xrayGraphScanParams = xrayGraphScanParams
return params
Expand Down
12 changes: 12 additions & 0 deletions commands/audit/sca/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,25 @@ import (
"github.com/jfrog/jfrog-cli-core/v2/utils/tests"
"github.com/jfrog/jfrog-cli-security/scangraph"
"github.com/jfrog/jfrog-cli-security/utils"
"github.com/jfrog/jfrog-client-go/artifactory/services/fspatterns"
clientutils "github.com/jfrog/jfrog-client-go/utils"
"github.com/jfrog/jfrog-client-go/utils/errorutils"
ioUtils "github.com/jfrog/jfrog-client-go/utils/io"
"github.com/jfrog/jfrog-client-go/utils/log"
"github.com/jfrog/jfrog-client-go/xray/services"
xrayUtils "github.com/jfrog/jfrog-client-go/xray/services/utils"
)

var DefaultExcludePatterns = []string{"*.git*", "*node_modules*", "*target*", "*venv*", "*test*"}

func GetExcludePattern(params utils.AuditParams) string {
exclusions := params.Exclusions()
if len(exclusions) == 0 {
exclusions = append(exclusions, DefaultExcludePatterns...)
}
return fspatterns.PrepareExcludePathPattern(exclusions, clientutils.WildCardPattern, params.IsRecursiveScan())
}

func RunXrayDependenciesTreeScanGraph(dependencyTree *xrayUtils.GraphNode, progress ioUtils.ProgressMgr, technology coreutils.Technology, scanGraphParams *scangraph.ScanGraphParams) (results []services.ScanResponse, err error) {
scanGraphParams.XrayGraphScanParams().DependenciesGraph = dependencyTree
xscGitInfoContext := scanGraphParams.XrayGraphScanParams().XscGitInfoContext
Expand Down
48 changes: 47 additions & 1 deletion commands/audit/sca/common_test.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,63 @@
package sca

import (
"golang.org/x/exp/maps"
"reflect"
"testing"

"golang.org/x/exp/maps"

"github.com/jfrog/jfrog-cli-core/v2/utils/tests"
coreXray "github.com/jfrog/jfrog-cli-core/v2/utils/xray"
"github.com/jfrog/jfrog-cli-security/utils"
"github.com/jfrog/jfrog-client-go/xray/services"
xrayUtils "github.com/jfrog/jfrog-client-go/xray/services/utils"
"github.com/stretchr/testify/assert"
)

func TestGetExcludePattern(t *testing.T) {
tests := []struct {
name string
params func() *utils.AuditBasicParams
expected string
}{
{
name: "Test exclude pattern recursive",
params: func() *utils.AuditBasicParams {
param := &utils.AuditBasicParams{}
param.SetExclusions([]string{"exclude1", "exclude2"}).SetIsRecursiveScan(true)
return param
},
expected: "(^exclude1$)|(^exclude2$)",
},
{
name: "Test no exclude pattern recursive",
params: func() *utils.AuditBasicParams { return (&utils.AuditBasicParams{}).SetIsRecursiveScan(true) },
expected: "(^.*\\.git.*$)|(^.*node_modules.*$)|(^.*target.*$)|(^.*venv.*$)|(^.*test.*$)",
},
{
name: "Test exclude pattern not recursive",
params: func() *utils.AuditBasicParams {
param := &utils.AuditBasicParams{}
param.SetExclusions([]string{"exclude1", "exclude2"})
return param
},
expected: "(^exclude1$)|(^exclude2$)",
},
{
name: "Test no exclude pattern",
params: func() *utils.AuditBasicParams { return &utils.AuditBasicParams{} },
expected: "(^.*\\.git.*$)|(^.*node_modules.*$)|(^.*target.*$)|(^.*venv.*$)|(^.*test.*$)",
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
result := GetExcludePattern(test.params())
assert.Equal(t, test.expected, result)
})
}
}

func TestBuildXrayDependencyTree(t *testing.T) {
treeHelper := make(map[string]coreXray.DepTreeNode)
rootDep := coreXray.DepTreeNode{Children: []string{"topDep1", "topDep2", "topDep3"}}
Expand Down
21 changes: 12 additions & 9 deletions commands/audit/sca/nuget/nuget.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ package nuget
import (
"errors"
"fmt"
"io/fs"
"os"
"os/exec"
"path/filepath"
"strings"

bidotnet "github.com/jfrog/build-info-go/build/utils/dotnet"
"github.com/jfrog/build-info-go/build/utils/dotnet/solution"
"github.com/jfrog/build-info-go/entities"
Expand All @@ -11,17 +17,13 @@ import (
"github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/dotnet"
"github.com/jfrog/jfrog-cli-core/v2/utils/config"
coreXray "github.com/jfrog/jfrog-cli-core/v2/utils/xray"
"github.com/jfrog/jfrog-cli-security/commands/audit/sca"
"github.com/jfrog/jfrog-cli-security/utils"
"github.com/jfrog/jfrog-client-go/utils/errorutils"
"github.com/jfrog/jfrog-client-go/utils/io/fileutils"
"github.com/jfrog/jfrog-client-go/utils/log"
xrayUtils "github.com/jfrog/jfrog-client-go/xray/services/utils"
"golang.org/x/exp/maps"
"io/fs"
"os"
"os/exec"
"path/filepath"
"strings"
)

const (
Expand All @@ -40,7 +42,8 @@ func BuildDependencyTree(params utils.AuditParams) (dependencyTree []*xrayUtils.
if err != nil {
return
}
sol, err := solution.Load(wd, "", log.Logger)
exclusionPattern := sca.GetExcludePattern(params)
sol, err := solution.Load(wd, "", exclusionPattern, log.Logger)
if err != nil && !strings.Contains(err.Error(), globalPackagesNotFoundErrorMessage) {
// In older NuGet projects that utilize NuGet Cli and package.config, if the project is not installed, the solution.Load function raises an error because it cannot find global package paths.
// This issue is resolved by executing the 'nuget restore' command followed by running solution.Load again. Therefore, in this scenario, we need to proceed with this process.
Expand All @@ -49,7 +52,7 @@ func BuildDependencyTree(params utils.AuditParams) (dependencyTree []*xrayUtils.

if isInstallRequired(params, sol) {
log.Info("Dependencies sources were not detected nor 'install' command provided. Running 'restore' command")
sol, err = runDotnetRestoreAndLoadSolution(params, wd)
sol, err = runDotnetRestoreAndLoadSolution(params, wd, exclusionPattern)
if err != nil {
return
}
Expand All @@ -74,7 +77,7 @@ func isInstallRequired(params utils.AuditParams, sol solution.Solution) bool {

// Generates a temporary duplicate of the project to execute the 'install' command without impacting the original directory and establishing the JFrog configuration file for Artifactory resolution
// Additionally, re-loads the project's Solution so the dependencies sources will be identified
func runDotnetRestoreAndLoadSolution(params utils.AuditParams, originalWd string) (sol solution.Solution, err error) {
func runDotnetRestoreAndLoadSolution(params utils.AuditParams, originalWd, exclusionPattern string) (sol solution.Solution, err error) {
// Creating a temporary copy of the project in order to run 'install' command without effecting the original directory + creating the jfrog config for artifactory resolution
tmpWd, err := fileutils.CreateTempDir()
if err != nil {
Expand Down Expand Up @@ -129,7 +132,7 @@ func runDotnetRestoreAndLoadSolution(params utils.AuditParams, originalWd string
if err != nil {
return
}
sol, err = solution.Load(tmpWd, "", log.Logger)
sol, err = solution.Load(tmpWd, "", exclusionPattern, log.Logger)
return
}

Expand Down
4 changes: 2 additions & 2 deletions commands/audit/sca/nuget/nuget_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,13 +134,13 @@ func TestRunDotnetRestoreAndLoadSolution(t *testing.T) {
dotnetProjectPath := filepath.Join(testDataDir, "dotnet", projectName)
assert.NoError(t, utils.CopyDir(dotnetProjectPath, tempDirPath, true, nil))

sol, err := solution.Load(tempDirPath, "", log.Logger)
sol, err := solution.Load(tempDirPath, "", "", log.Logger)
assert.NoError(t, err)
assert.Empty(t, sol.GetProjects())
assert.Empty(t, sol.GetDependenciesSources())

params := &xrayUtils2.AuditBasicParams{}
sol, err = runDotnetRestoreAndLoadSolution(params, tempDirPath)
sol, err = runDotnetRestoreAndLoadSolution(params, tempDirPath, "")
assert.NoError(t, err)
assert.NotEmpty(t, sol.GetProjects())
assert.NotEmpty(t, sol.GetDependenciesSources())
Expand Down
13 changes: 1 addition & 12 deletions commands/audit/scarunner.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,13 @@ import (
"github.com/jfrog/jfrog-cli-security/commands/audit/sca/yarn"
"github.com/jfrog/jfrog-cli-security/scangraph"
xrayutils "github.com/jfrog/jfrog-cli-security/utils"
"github.com/jfrog/jfrog-client-go/artifactory/services/fspatterns"
clientutils "github.com/jfrog/jfrog-client-go/utils"
"github.com/jfrog/jfrog-client-go/utils/errorutils"
"github.com/jfrog/jfrog-client-go/utils/log"
"github.com/jfrog/jfrog-client-go/xray/services"
xrayCmdUtils "github.com/jfrog/jfrog-client-go/xray/services/utils"
)

var DefaultExcludePatterns = []string{"*.git*", "*node_modules*", "*target*", "*venv*", "*test*"}

func runScaScan(params *AuditParams, results *xrayutils.Results) (err error) {
// Prepare
currentWorkingDir, err := os.Getwd()
Expand Down Expand Up @@ -75,7 +72,7 @@ func runScaScan(params *AuditParams, results *xrayutils.Results) (err error) {
func getScaScansToPreform(params *AuditParams) (scansToPreform []*xrayutils.ScaScanResult) {
for _, requestedDirectory := range params.workingDirs {
// Detect descriptors and technologies in the requested directory.
techToWorkingDirs, err := coreutils.DetectTechnologiesDescriptors(requestedDirectory, params.isRecursiveScan, params.Technologies(), getRequestedDescriptors(params), getExcludePattern(params, params.isRecursiveScan))
techToWorkingDirs, err := coreutils.DetectTechnologiesDescriptors(requestedDirectory, params.IsRecursiveScan(), params.Technologies(), getRequestedDescriptors(params), sca.GetExcludePattern(params.AuditBasicParams))
if err != nil {
log.Warn("Couldn't detect technologies in", requestedDirectory, "directory.", err.Error())
continue
Expand Down Expand Up @@ -108,14 +105,6 @@ func getRequestedDescriptors(params *AuditParams) map[coreutils.Technology][]str
return requestedDescriptors
}

func getExcludePattern(params *AuditParams, recursive bool) string {
exclusions := params.Exclusions()
if len(exclusions) == 0 {
exclusions = append(exclusions, DefaultExcludePatterns...)
}
return fspatterns.PrepareExcludePathPattern(exclusions, clientutils.WildCardPattern, recursive)
}

// Preform the SCA scan for the given scan information.
// This method will change the working directory to the scan's working directory.
func executeScaScan(serverDetails *config.ServerDetails, params *AuditParams, scan *xrayutils.ScaScanResult) (err error) {
Expand Down
57 changes: 5 additions & 52 deletions commands/audit/scarunner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,55 +117,6 @@ func createEmptyFile(t *testing.T, path string) {
assert.NoError(t, file.Close())
}

func TestGetExcludePattern(t *testing.T) {
tests := []struct {
name string
params func() *AuditParams
recursive bool
expected string
}{
{
name: "Test exclude pattern recursive",
params: func() *AuditParams {
param := NewAuditParams()
param.SetExclusions([]string{"exclude1", "exclude2"})
return param
},
recursive: true,
expected: "(^exclude1$)|(^exclude2$)",
},
{
name: "Test no exclude pattern recursive",
params: NewAuditParams,
recursive: true,
expected: "(^.*\\.git.*$)|(^.*node_modules.*$)|(^.*target.*$)|(^.*venv.*$)|(^.*test.*$)",
},
{
name: "Test exclude pattern not recursive",
params: func() *AuditParams {
param := NewAuditParams()
param.SetExclusions([]string{"exclude1", "exclude2"})
return param
},
recursive: false,
expected: "(^exclude1$)|(^exclude2$)",
},
{
name: "Test no exclude pattern",
params: NewAuditParams,
recursive: false,
expected: "(^.*\\.git.*$)|(^.*node_modules.*$)|(^.*target.*$)|(^.*venv.*$)|(^.*test.*$)",
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
result := getExcludePattern(test.params(), test.recursive)
assert.Equal(t, test.expected, result)
})
}
}

func TestGetScaScansToPreform(t *testing.T) {

dir, cleanUp := createTestDir(t)
Expand All @@ -180,8 +131,8 @@ func TestGetScaScansToPreform(t *testing.T) {
name: "Test specific technologies",
wd: dir,
params: func() *AuditParams {
param := NewAuditParams().SetIsRecursiveScan(true).SetWorkingDirs([]string{dir})
param.SetTechnologies([]string{"maven", "npm", "go"})
param := NewAuditParams().SetWorkingDirs([]string{dir})
param.SetTechnologies([]string{"maven", "npm", "go"}).SetIsRecursiveScan(true)
return param
},
expected: []*xrayutils.ScaScanResult{
Expand Down Expand Up @@ -210,7 +161,9 @@ func TestGetScaScansToPreform(t *testing.T) {
name: "Test all",
wd: dir,
params: func() *AuditParams {
return NewAuditParams().SetIsRecursiveScan(true).SetWorkingDirs([]string{dir})
param := NewAuditParams().SetWorkingDirs([]string{dir})
param.SetIsRecursiveScan(true)
return param
},
expected: []*xrayutils.ScaScanResult{
{
Expand Down
6 changes: 4 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +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 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20240225124040-0941c5ce1007

// replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go dev
replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20240222155638-e55c7d7acbee

replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go v1.8.9-0.20240225113943-096bf22ca54c
Loading

0 comments on commit cc8b9f3

Please sign in to comment.