4
4
"context"
5
5
"errors"
6
6
"fmt"
7
- "github.com/go-git/go-git/v5"
8
7
"github.com/jfrog/gofrog/datastructures"
9
8
"os"
10
9
"os/exec"
@@ -27,58 +26,43 @@ const (
27
26
noGitHubEnvReviewersErr = "frogbot did not scan this PR, because the existing GitHub Environment named 'frogbot' doesn't have reviewers selected. Please refer to the Frogbot documentation for instructions on how to create the Environment"
28
27
)
29
28
30
- type ScanPullRequestCmd struct {}
29
+ type ScanPullRequestCmd struct {
30
+ // Optional provided pull request details, used in scan-pull-requests command.
31
+ pullRequestDetails vcsclient.PullRequestInfo
32
+ }
31
33
32
34
// Run ScanPullRequest method only works for a single repository scan.
33
35
// Therefore, the first repository config represents the repository on which Frogbot runs, and it is the only one that matters.
34
- func (cmd * ScanPullRequestCmd ) Run (configAggregator utils.RepoAggregator , client vcsclient.VcsClient ) error {
35
- if err : = utils .ValidateSingleRepoConfiguration (& configAggregator ); err != nil {
36
- return err
36
+ func (cmd * ScanPullRequestCmd ) Run (configAggregator utils.RepoAggregator , client vcsclient.VcsClient ) ( err error ) {
37
+ if err = utils .ValidateSingleRepoConfiguration (& configAggregator ); err != nil {
38
+ return
37
39
}
38
40
repoConfig := & (configAggregator )[0 ]
39
41
if repoConfig .GitProvider == vcsutils .GitHub {
40
- if err : = verifyGitHubFrogbotEnvironment (client , repoConfig ); err != nil {
41
- return err
42
+ if err = verifyGitHubFrogbotEnvironment (client , repoConfig ); err != nil {
43
+ return
42
44
}
43
45
}
44
- if err := cmd .verifyDifferentBranches (repoConfig ); err != nil {
45
- return err
46
- }
47
- return scanPullRequest (repoConfig , client )
48
- }
49
46
50
- // Verifies current branch and target branch are not the same.
51
- // The Current branch is the branch the action is triggered on.
52
- // The Target branch is the branch to open pull request to.
53
- func (cmd * ScanPullRequestCmd ) verifyDifferentBranches (repoConfig * utils.Repository ) error {
54
- repo , err := git .PlainOpen ("." )
55
- if err != nil {
56
- return err
57
- }
58
- ref , err := repo .Head ()
59
- if err != nil {
60
- return err
61
- }
62
- currentBranch := ref .Name ().Short ()
63
- defaultBranch := repoConfig .Branches [0 ]
64
- if currentBranch == defaultBranch {
65
- return fmt .Errorf (utils .ErrScanPullRequestSameBranches , currentBranch )
47
+ // PullRequestDetails can be defined already when using the scan-all-pull-requests command.
48
+ if cmd .pullRequestDetails .ID == utils .UndefinedPrID {
49
+ if cmd .pullRequestDetails , err = client .GetPullRequestByID (context .Background (), repoConfig .RepoOwner , repoConfig .RepoName , repoConfig .PullRequestID ); err != nil {
50
+ return
51
+ }
66
52
}
67
- return nil
53
+
54
+ return scanPullRequest (repoConfig , client , cmd .pullRequestDetails )
68
55
}
69
56
70
57
// By default, includeAllVulnerabilities is set to false and the scan goes as follows:
71
58
// a. Audit the dependencies of the source and the target branches.
72
59
// b. Compare the vulnerabilities found in source and target branches, and show only the new vulnerabilities added by the pull request.
73
60
// Otherwise, only the source branch is scanned and all found vulnerabilities are being displayed.
74
- func scanPullRequest (repoConfig * utils.Repository , client vcsclient.VcsClient ) error {
75
- // Validate scan params
76
- if len (repoConfig .Branches ) == 0 {
77
- return & utils.ErrMissingEnv {VariableName : utils .GitBaseBranchEnv }
78
- }
79
-
61
+ func scanPullRequest (repoConfig * utils.Repository , client vcsclient.VcsClient , pullRequestDetails vcsclient.PullRequestInfo ) error {
62
+ log .Info ("Scanning Pull Request ID:" , pullRequestDetails .ID , "Source:" , pullRequestDetails .Source .Name , "Target:" , pullRequestDetails .Target .Name )
63
+ log .Info ("-----------------------------------------------------------" )
80
64
// Audit PR code
81
- vulnerabilitiesRows , iacRows , err := auditPullRequest (repoConfig , client )
65
+ vulnerabilitiesRows , iacRows , err := auditPullRequest (repoConfig , client , pullRequestDetails )
82
66
if err != nil {
83
67
return err
84
68
}
@@ -98,17 +82,23 @@ func scanPullRequest(repoConfig *utils.Repository, client vcsclient.VcsClient) e
98
82
return err
99
83
}
100
84
101
- func auditPullRequest (repoConfig * utils.Repository , client vcsclient.VcsClient ) ([]formats.VulnerabilityOrViolationRow , []formats.IacSecretsRow , error ) {
85
+ // Downloads Pull Requests branches code and audits them
86
+ func auditPullRequest (repoConfig * utils.Repository , client vcsclient.VcsClient , pullRequestDetails vcsclient.PullRequestInfo ) ([]formats.VulnerabilityOrViolationRow , []formats.IacSecretsRow , error ) {
102
87
var vulnerabilitiesRows []formats.VulnerabilityOrViolationRow
103
88
var iacRows []formats.IacSecretsRow
104
- targetBranch := repoConfig .Branches [0 ]
89
+ targetBranch := pullRequestDetails .Target .Name
90
+ sourceBranch := pullRequestDetails .Source .Name
105
91
for i := range repoConfig .Projects {
92
+ // Source scan details
106
93
scanDetails := utils .NewScanDetails (client , & repoConfig .Server , & repoConfig .Git ).
107
94
SetProject (& repoConfig .Projects [i ]).
108
95
SetXrayGraphScanParams (repoConfig .Watches , repoConfig .JFrogProjectKey ).
109
96
SetMinSeverity (repoConfig .MinSeverity ).
110
- SetFixableOnly (repoConfig .FixableOnly )
111
- sourceResults , err := auditSource (scanDetails )
97
+ SetFixableOnly (repoConfig .FixableOnly ).
98
+ SetBranch (sourceBranch ).
99
+ SetRepoOwner (pullRequestDetails .Source .Owner )
100
+
101
+ sourceResults , err := downloadAndAuditBranch (scanDetails )
112
102
if err != nil {
113
103
return nil , nil , err
114
104
}
@@ -123,9 +113,12 @@ func auditPullRequest(repoConfig *utils.Repository, client vcsclient.VcsClient)
123
113
iacRows = append (iacRows , xrayutils .PrepareIacs (sourceResults .ExtendedScanResults .IacScanResults )... )
124
114
continue
125
115
}
126
- // Audit target code
127
- scanDetails .SetFailOnInstallationErrors (* repoConfig .FailOnSecurityIssues ).SetBranch (targetBranch )
128
- targetResults , err := auditTarget (scanDetails )
116
+ // Target scan details
117
+ scanDetails .SetFailOnInstallationErrors (* repoConfig .FailOnSecurityIssues ).
118
+ SetBranch (targetBranch ).
119
+ SetRepoOwner (pullRequestDetails .Target .Owner )
120
+
121
+ targetResults , err := downloadAndAuditBranch (scanDetails )
129
122
if err != nil {
130
123
return nil , nil , err
131
124
}
@@ -235,15 +228,6 @@ func getScanVulnerabilitiesRows(auditResults *audit.Results) ([]formats.Vulnerab
235
228
return []formats.VulnerabilityOrViolationRow {}, nil
236
229
}
237
230
238
- func auditSource (scanSetup * utils.ScanDetails ) (auditResults * audit.Results , err error ) {
239
- wd , err := os .Getwd ()
240
- if err != nil {
241
- return
242
- }
243
- fullPathWds := getFullPathWorkingDirs (scanSetup .WorkingDirs , wd )
244
- return runInstallAndAudit (scanSetup , fullPathWds ... )
245
- }
246
-
247
231
func getFullPathWorkingDirs (workingDirs []string , baseWd string ) []string {
248
232
var fullPathWds []string
249
233
if len (workingDirs ) != 0 {
@@ -260,9 +244,9 @@ func getFullPathWorkingDirs(workingDirs []string, baseWd string) []string {
260
244
return fullPathWds
261
245
}
262
246
263
- func auditTarget (scanSetup * utils.ScanDetails ) (auditResults * audit.Results , err error ) {
247
+ func downloadAndAuditBranch (scanSetup * utils.ScanDetails ) (auditResults * audit.Results , err error ) {
264
248
// First download the target repo to temp dir
265
- log .Info ("Auditing the " , scanSetup .Git .RepoName , "repository on the " , scanSetup .Branch (), "branch" )
249
+ log .Info ("Auditing repository: " , scanSetup .Git .RepoName , "branch: " , scanSetup .Branch ())
266
250
wd , cleanup , err := utils .DownloadRepoToTempDir (scanSetup .Client (), scanSetup .Branch (), scanSetup .Git )
267
251
if err != nil {
268
252
return
0 commit comments