Skip to content

Commit f1f9de8

Browse files
authored
Filter by min severity & no fix version vulnerabilities (#322)
1 parent c47b536 commit f1f9de8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+715
-294
lines changed

commands/createfixpullrequests.go

+21-28
Original file line numberDiff line numberDiff line change
@@ -54,26 +54,24 @@ func (cfp *CreateFixPullRequestsCmd) scanAndFixRepository(repository *utils.Frog
5454
if err != nil {
5555
return err
5656
}
57-
cfp.details = &utils.ScanDetails{
58-
XrayGraphScanParams: createXrayScanParams(repository.Watches, repository.JFrogProjectKey),
59-
ServerDetails: &repository.Server,
60-
Git: &repository.Git,
61-
Client: client,
62-
FailOnInstallationErrors: *repository.FailOnSecurityIssues,
63-
Branch: branch,
64-
ReleasesRepo: repository.JfrogReleasesRepo,
65-
}
66-
for _, project := range repository.Projects {
67-
cfp.details.Project = project
68-
cfp.aggregateFixes = repository.Git.AggregateFixes
69-
projectFullPathWorkingDirs := getFullPathWorkingDirs(project.WorkingDirs, baseWd)
57+
cfp.details = utils.NewScanDetails(client, &repository.Server, &repository.Git).
58+
SetXrayGraphScanParams(repository.Watches, repository.JFrogProjectKey).
59+
SetFailOnInstallationErrors(*repository.FailOnSecurityIssues).
60+
SetBranch(branch).
61+
SetReleasesRepo(repository.JfrogReleasesRepo).
62+
SetFixableOnly(repository.FixableOnly).
63+
SetMinSeverity(repository.MinSeverity)
64+
cfp.aggregateFixes = repository.Git.AggregateFixes
65+
for i := range repository.Projects {
66+
cfp.details.Project = &repository.Projects[i]
67+
projectFullPathWorkingDirs := getFullPathWorkingDirs(cfp.details.Project.WorkingDirs, baseWd)
7068
for _, fullPathWd := range projectFullPathWorkingDirs {
7169
scanResults, isMultipleRoots, err := cfp.scan(cfp.details, fullPathWd)
7270
if err != nil {
7371
return err
7472
}
7573

76-
err = utils.UploadScanToGitProvider(scanResults, repository, cfp.details.Branch, cfp.details.Client, isMultipleRoots)
74+
err = utils.UploadScanToGitProvider(scanResults, repository, cfp.details.Branch(), cfp.details.Client(), isMultipleRoots)
7775
if err != nil {
7876
log.Warn(err)
7977
}
@@ -151,16 +149,15 @@ func (cfp *CreateFixPullRequestsCmd) fixIssuesSeparatePRs(fixVersionsMap map[str
151149
log.Warn(err)
152150
}
153151
// After finishing to work on the current vulnerability, we go back to the base branch to start the next vulnerability fix
154-
log.Info("Running git checkout to base branch:", cfp.details.Branch)
155-
if err = cfp.gitManager.Checkout(cfp.details.Branch); err != nil {
152+
log.Info("Running git checkout to base branch:", cfp.details.Branch())
153+
if err = cfp.gitManager.Checkout(cfp.details.Branch()); err != nil {
156154
return
157155
}
158156
}
159157
return
160158
}
161159

162160
func (cfp *CreateFixPullRequestsCmd) fixIssuesSinglePR(fixVersionsMap map[string]*utils.FixVersionInfo) (err error) {
163-
successfullyFixedPackages := make(map[string]*utils.FixVersionInfo)
164161
log.Info("-----------------------------------------------------------------")
165162
log.Info("Start aggregated packages fix")
166163
aggregatedFixBranchName, err := cfp.gitManager.GenerateAggregatedFixBranchName(fixVersionsMap)
@@ -174,13 +171,10 @@ func (cfp *CreateFixPullRequestsCmd) fixIssuesSinglePR(fixVersionsMap map[string
174171
for impactedPackage, fixVersionInfo := range fixVersionsMap {
175172
if err = cfp.updatePackageToFixedVersion(impactedPackage, fixVersionInfo); err != nil {
176173
log.Error("Could not fix impacted package", impactedPackage, "as part of the PR. Skipping it. Cause:", err.Error())
177-
} else {
178-
log.Info("Successfully fixed", impactedPackage)
179-
successfullyFixedPackages[impactedPackage] = fixVersionInfo
180174
}
181175
}
182176

183-
if err = cfp.openAggregatedPullRequest(aggregatedFixBranchName, successfullyFixedPackages); err != nil {
177+
if err = cfp.openAggregatedPullRequest(aggregatedFixBranchName); err != nil {
184178
return fmt.Errorf("failed while creating aggreagted pull request. Error: \n%s", err.Error())
185179
}
186180
return
@@ -189,7 +183,7 @@ func (cfp *CreateFixPullRequestsCmd) fixIssuesSinglePR(fixVersionsMap map[string
189183
func (cfp *CreateFixPullRequestsCmd) fixSinglePackageAndCreatePR(impactedPackage string, fixVersionInfo *utils.FixVersionInfo) (err error) {
190184
log.Info("-----------------------------------------------------------------")
191185
log.Info("Start fixing", impactedPackage, "with", fixVersionInfo.FixVersion)
192-
fixBranchName, err := cfp.gitManager.GenerateFixBranchName(cfp.details.Branch, impactedPackage, fixVersionInfo.FixVersion)
186+
fixBranchName, err := cfp.gitManager.GenerateFixBranchName(cfp.details.Branch(), impactedPackage, fixVersionInfo.FixVersion)
193187
if err != nil {
194188
return
195189
}
@@ -231,14 +225,14 @@ func (cfp *CreateFixPullRequestsCmd) openFixingPullRequest(impactedPackage, fixB
231225
}
232226

233227
pullRequestTitle := cfp.gitManager.GeneratePullRequestTitle(impactedPackage, fixVersionInfo.FixVersion)
234-
log.Info("Creating Pull Request form:", fixBranchName, " to:", cfp.details.Branch)
228+
log.Info("Creating Pull Request form:", fixBranchName, " to:", cfp.details.Branch())
235229
prBody := commitMessage + "\n\n" + utils.WhatIsFrogbotMd
236-
return cfp.details.Client.CreatePullRequest(context.Background(), cfp.details.RepoOwner, cfp.details.RepoName, fixBranchName, cfp.details.Branch, pullRequestTitle, prBody)
230+
return cfp.details.Client().CreatePullRequest(context.Background(), cfp.details.RepoOwner, cfp.details.RepoName, fixBranchName, cfp.details.Branch(), pullRequestTitle, prBody)
237231
}
238232

239233
// When aggregate mode is active, there can be only one updated pull request to contain all the available fixes.
240234
// In case of an already opened pull request, Frogbot will only update the branch.
241-
func (cfp *CreateFixPullRequestsCmd) openAggregatedPullRequest(fixBranchName string, versionsMap map[string]*utils.FixVersionInfo) (err error) {
235+
func (cfp *CreateFixPullRequestsCmd) openAggregatedPullRequest(fixBranchName string) (err error) {
242236
log.Info("Checking if there are changes to commit")
243237
isClean, err := cfp.gitManager.IsClean()
244238
if err != nil {
@@ -263,7 +257,7 @@ func (cfp *CreateFixPullRequestsCmd) openAggregatedPullRequest(fixBranchName str
263257
if !exists {
264258
log.Info("Creating Pull Request form:", fixBranchName, " to:", cfp.details.Branch)
265259
prBody := commitMessage + "\n\n" + utils.WhatIsFrogbotMd
266-
return cfp.details.Client.CreatePullRequest(context.Background(), cfp.details.RepoOwner, cfp.details.RepoName, fixBranchName, cfp.details.Branch, utils.AggregatedPullRequestTitleTemplate, prBody)
260+
return cfp.details.Client().CreatePullRequest(context.Background(), cfp.details.RepoOwner, cfp.details.RepoName, fixBranchName, cfp.details.Branch(), utils.AggregatedPullRequestTitleTemplate, prBody)
267261
}
268262
log.Info("Pull Request branch:", fixBranchName, "has been updated")
269263
return
@@ -290,8 +284,7 @@ func (cfp *CreateFixPullRequestsCmd) cloneRepository() (tempWd string, restoreDi
290284
log.Debug("Created temp working directory:", tempWd)
291285

292286
// Clone the content of the repo to the new working directory
293-
err = cfp.gitManager.Clone(tempWd, cfp.details.Branch)
294-
if err != nil {
287+
if err = cfp.gitManager.Clone(tempWd, cfp.details.Branch()); err != nil {
295288
return
296289
}
297290

commands/createfixpullrequests_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ func getGenericFixPackageVersionFunc() FixPackagesTestFunc {
112112
return func(test packageFixTest) CreateFixPullRequestsCmd {
113113
return CreateFixPullRequestsCmd{
114114
details: &utils.ScanDetails{
115-
Project: utils.Project{
115+
Project: &utils.Project{
116116
PipRequirementsFile: test.packageDescriptor,
117117
WorkingDirs: []string{test.testPath},
118118
},
@@ -267,8 +267,8 @@ func TestPackageTypeFromScan(t *testing.T) {
267267
frogbotParams.Projects[0].InstallCommandName = pkg.commandName
268268
frogbotParams.Projects[0].InstallCommandArgs = pkg.commandArgs
269269
scanSetup := utils.ScanDetails{
270-
XrayGraphScanParams: services.XrayGraphScanParams{},
271-
Project: frogbotParams.Projects[0],
270+
XrayGraphScanParams: &services.XrayGraphScanParams{},
271+
Project: &frogbotParams.Projects[0],
272272
ServerDetails: &frogbotParams.Server,
273273
}
274274
scanResponse, _, err := testScan.scan(&scanSetup, tmpDir)

commands/scanandfixrepos.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ func (saf *ScanAndFixRepositories) downloadAndRunScanAndFix(repository *utils.Fr
8686
return cfp.scanAndFixRepository(repository, branch, client)
8787
}
8888

89-
func (saf ScanAndFixRepositories) setCommitBuildStatus(client vcsclient.VcsClient, repoConfig *utils.FrogbotRepoConfig, state vcsclient.CommitStatus, commitHash, description string) error {
89+
func (saf *ScanAndFixRepositories) setCommitBuildStatus(client vcsclient.VcsClient, repoConfig *utils.FrogbotRepoConfig, state vcsclient.CommitStatus, commitHash, description string) error {
9090
if err := client.SetCommitStatus(context.Background(), state, repoConfig.RepoOwner, repoConfig.RepoName, commitHash, utils.FrogbotCreatorName, description, utils.CommitStatusDetailsUrl); err != nil {
9191
return fmt.Errorf("failed to mark last commit build status due to: %s", err.Error())
9292
}
@@ -96,7 +96,7 @@ func (saf ScanAndFixRepositories) setCommitBuildStatus(client vcsclient.VcsClien
9696

9797
// Returns true if the latest commit hasn't been scanned
9898
// or the time passed from the last scan exceeded the configured value.
99-
func (saf ScanAndFixRepositories) shouldScanLatestCommit(ctx context.Context, repoConfig *utils.FrogbotRepoConfig, client vcsclient.VcsClient, branch string) (shouldScan bool, commitHash string, err error) {
99+
func (saf *ScanAndFixRepositories) shouldScanLatestCommit(ctx context.Context, repoConfig *utils.FrogbotRepoConfig, client vcsclient.VcsClient, branch string) (shouldScan bool, commitHash string, err error) {
100100
owner := repoConfig.RepoOwner
101101
repo := repoConfig.RepoName
102102
latestCommit, err := client.GetLatestCommit(ctx, owner, repo, branch)

commands/scanpullrequest.go

+18-36
Original file line numberDiff line numberDiff line change
@@ -74,20 +74,16 @@ func scanPullRequest(repoConfig *utils.FrogbotRepoConfig, client vcsclient.VcsCl
7474
}
7575

7676
func auditPullRequest(repoConfig *utils.FrogbotRepoConfig, client vcsclient.VcsClient) ([]formats.VulnerabilityOrViolationRow, error) {
77-
xrayScanParams := createXrayScanParams(repoConfig.Watches, repoConfig.JFrogProjectKey)
7877
var vulnerabilitiesRows []formats.VulnerabilityOrViolationRow
79-
for _, project := range repoConfig.Projects {
80-
scanSetup := &utils.ScanDetails{
81-
XrayGraphScanParams: xrayScanParams,
82-
Project: project,
83-
Client: client,
84-
ServerDetails: &repoConfig.Server,
85-
Git: &repoConfig.Git,
86-
FailOnInstallationErrors: false,
87-
Branch: repoConfig.Branches[0],
88-
ReleasesRepo: repoConfig.JfrogReleasesRepo,
89-
}
90-
currentScan, isMultipleRoot, err := auditSource(scanSetup)
78+
for i := range repoConfig.Projects {
79+
scanDetails := utils.NewScanDetails(client, &repoConfig.Server, &repoConfig.Git).
80+
SetProject(&repoConfig.Projects[i]).
81+
SetBranch(repoConfig.Branches[0]).
82+
SetReleasesRepo(repoConfig.JfrogReleasesRepo).
83+
SetXrayGraphScanParams(repoConfig.Watches, repoConfig.JFrogProjectKey).
84+
SetMinSeverity(repoConfig.MinSeverity).
85+
SetFixableOnly(repoConfig.FixableOnly)
86+
currentScan, isMultipleRoot, err := auditSource(scanDetails)
9187
if err != nil {
9288
return nil, err
9389
}
@@ -101,8 +97,8 @@ func auditPullRequest(repoConfig *utils.FrogbotRepoConfig, client vcsclient.VcsC
10197
continue
10298
}
10399
// Audit target code
104-
scanSetup.FailOnInstallationErrors = *repoConfig.FailOnSecurityIssues
105-
previousScan, isMultipleRoot, err := auditTarget(scanSetup)
100+
scanDetails.SetFailOnInstallationErrors(*repoConfig.FailOnSecurityIssues)
101+
previousScan, isMultipleRoot, err := auditTarget(scanDetails)
106102
if err != nil {
107103
return nil, err
108104
}
@@ -200,22 +196,6 @@ func createAllIssuesRows(currentScan []services.ScanResponse, isMultipleRoot boo
200196
return getScanVulnerabilitiesRows(violations, vulnerabilities, isMultipleRoot)
201197
}
202198

203-
func createXrayScanParams(watches []string, project string) (params services.XrayGraphScanParams) {
204-
params.ScanType = services.Dependency
205-
params.IncludeLicenses = false
206-
if len(watches) > 0 {
207-
params.Watches = watches
208-
return
209-
}
210-
if project != "" {
211-
params.ProjectKey = project
212-
return
213-
}
214-
// No context was supplied, request from Xray to return all known vulnerabilities.
215-
params.IncludeVulnerabilities = true
216-
return
217-
}
218-
219199
func auditSource(scanSetup *utils.ScanDetails) ([]services.ScanResponse, bool, error) {
220200
wd, err := os.Getwd()
221201
if err != nil {
@@ -243,8 +223,8 @@ func getFullPathWorkingDirs(workingDirs []string, baseWd string) []string {
243223

244224
func auditTarget(scanSetup *utils.ScanDetails) (res []services.ScanResponse, isMultipleRoot bool, err error) {
245225
// First download the target repo to temp dir
246-
log.Info("Auditing ", scanSetup.Git.RepoName, scanSetup.Branch)
247-
wd, cleanup, err := utils.DownloadRepoToTempDir(scanSetup.Client, scanSetup.Branch, scanSetup.Git)
226+
log.Info("Auditing the", scanSetup.Git.RepoName, "repository on the", scanSetup.Branch(), "branch")
227+
wd, cleanup, err := utils.DownloadRepoToTempDir(scanSetup.Client(), scanSetup.Branch(), scanSetup.Git)
248228
if err != nil {
249229
return
250230
}
@@ -272,8 +252,10 @@ func runInstallAndAudit(scanSetup *utils.ScanDetails, workDirs ...string) (resul
272252
SetRequirementsFile(scanSetup.PipRequirementsFile).
273253
SetWorkingDirs(workDirs).
274254
SetDepsRepo(scanSetup.Repository).
275-
SetReleasesRepo(scanSetup.ReleasesRepo).
276-
SetIgnoreConfigFile(true)
255+
SetReleasesRepo(scanSetup.ReleasesRepo()).
256+
SetIgnoreConfigFile(true).
257+
SetMinSeverityFilter(scanSetup.MinSeverityFilter()).
258+
SetFixableOnly(scanSetup.FixableOnly())
277259
results, isMultipleRoot, err = audit.GenericAudit(auditParams)
278260
if err != nil {
279261
return nil, false, err
@@ -294,7 +276,7 @@ func runInstallIfNeeded(scanSetup *utils.ScanDetails, workDir string) (err error
294276
}()
295277
log.Info(fmt.Sprintf("Executing '%s %s' at %s", scanSetup.InstallCommandName, scanSetup.InstallCommandArgs, workDir))
296278
output, err := runInstallCommand(scanSetup)
297-
if err != nil && !scanSetup.FailOnInstallationErrors {
279+
if err != nil && !scanSetup.FailOnInstallationErrors() {
298280
log.Info(installationCmdFailedErr, err.Error(), "\n", string(output))
299281
// failOnInstallationErrors set to 'false'
300282
err = nil

commands/scanpullrequest_test.go

+6-29
Original file line numberDiff line numberDiff line change
@@ -35,29 +35,6 @@ const (
3535
testProjConfigPathNoFail = "testdata/config/frogbot-config-test-proj-no-fail.yml"
3636
)
3737

38-
func TestCreateXrayScanParams(t *testing.T) {
39-
// Project
40-
params := createXrayScanParams(nil, "")
41-
assert.Empty(t, params.Watches)
42-
assert.Equal(t, "", params.ProjectKey)
43-
assert.True(t, params.IncludeVulnerabilities)
44-
assert.False(t, params.IncludeLicenses)
45-
46-
// Watches
47-
params = createXrayScanParams([]string{"watch-1", "watch-2"}, "")
48-
assert.Equal(t, []string{"watch-1", "watch-2"}, params.Watches)
49-
assert.Equal(t, "", params.ProjectKey)
50-
assert.False(t, params.IncludeVulnerabilities)
51-
assert.False(t, params.IncludeLicenses)
52-
53-
// Project
54-
params = createXrayScanParams(nil, "project")
55-
assert.Empty(t, params.Watches)
56-
assert.Equal(t, "project", params.ProjectKey)
57-
assert.False(t, params.IncludeVulnerabilities)
58-
assert.False(t, params.IncludeLicenses)
59-
}
60-
6138
func TestCreateVulnerabilitiesRows(t *testing.T) {
6239
// Previous scan with only one violation - XRAY-1
6340
previousScan := services.ScanResponse{
@@ -412,30 +389,30 @@ func TestCreatePullRequestMessage(t *testing.T) {
412389

413390
func TestRunInstallIfNeeded(t *testing.T) {
414391
scanSetup := utils.ScanDetails{
415-
Project: utils.Project{},
416-
FailOnInstallationErrors: true,
392+
Project: &utils.Project{},
417393
}
394+
scanSetup.SetFailOnInstallationErrors(true)
418395
assert.NoError(t, runInstallIfNeeded(&scanSetup, ""))
419396
tmpDir, err := fileutils.CreateTempDir()
420397
assert.NoError(t, err)
421398
params := &utils.Project{
422399
InstallCommandName: "echo",
423400
InstallCommandArgs: []string{"Hello"},
424401
}
425-
scanSetup.Project = *params
402+
scanSetup.Project = params
426403
assert.NoError(t, runInstallIfNeeded(&scanSetup, tmpDir))
427404

428405
scanSetup.InstallCommandName = "not-exist"
429406
scanSetup.InstallCommandArgs = []string{"1", "2"}
430-
scanSetup.FailOnInstallationErrors = false
407+
scanSetup.SetFailOnInstallationErrors(false)
431408
assert.NoError(t, runInstallIfNeeded(&scanSetup, tmpDir))
432409

433410
params = &utils.Project{
434411
InstallCommandName: "not-existed",
435412
InstallCommandArgs: []string{"1", "2"},
436413
}
437-
scanSetup.Project = *params
438-
scanSetup.FailOnInstallationErrors = true
414+
scanSetup.Project = params
415+
scanSetup.SetFailOnInstallationErrors(true)
439416
assert.Error(t, runInstallIfNeeded(&scanSetup, tmpDir))
440417
}
441418

commands/testdata/config/frogbot-config-test-params.yml

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
scan:
1111
includeAllVulnerabilities: true
1212
failOnSecurityIssues: true
13+
minSeverity: high
14+
fixableOnly: true
1315
projects:
1416
- installCommand: nuget restore
1517
workingDirs:

commands/utils/consts.go

+2
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ const (
5858
FailOnSecurityIssuesEnv = "JF_FAIL"
5959
UseWrapperEnv = "JF_USE_WRAPPER"
6060
DepsRepoEnv = "JF_DEPS_REPO"
61+
MinSeverityEnv = "JF_MIN_SEVERITY"
62+
FixableOnlyEnv = "JF_FIXABLE_ONLY"
6163
WatchesDelimiter = ","
6264

6365
//#nosec G101 -- False positive - no hardcoded credentials.

commands/utils/depsutil_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ func TestResolveDependencies(t *testing.T) {
9797
tech: "npm",
9898
scanSetup: &ScanDetails{
9999
ServerDetails: &params,
100-
Project: Project{
100+
Project: &Project{
101101
InstallCommandName: "npm",
102102
InstallCommandArgs: []string{"install"},
103103
}},
@@ -108,7 +108,7 @@ func TestResolveDependencies(t *testing.T) {
108108
tech: "yarn",
109109
scanSetup: &ScanDetails{
110110
ServerDetails: &params,
111-
Project: Project{
111+
Project: &Project{
112112
InstallCommandName: "yarn",
113113
InstallCommandArgs: []string{"install"},
114114
}},
@@ -119,7 +119,7 @@ func TestResolveDependencies(t *testing.T) {
119119
tech: "dotnet",
120120
scanSetup: &ScanDetails{
121121
ServerDetails: &params,
122-
Project: Project{
122+
Project: &Project{
123123
Repository: "frogbot-nuget-remote-tests",
124124
InstallCommandName: "dotnet",
125125
InstallCommandArgs: []string{"restore"},

0 commit comments

Comments
 (0)