@@ -9,16 +9,16 @@ import (
9
9
biutils "github.com/jfrog/build-info-go/utils"
10
10
"github.com/jfrog/build-info-go/utils/pythonutils"
11
11
"github.com/jfrog/gofrog/datastructures"
12
- utils "github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/python"
12
+ artifactoryutils "github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/python"
13
13
"github.com/jfrog/jfrog-cli-core/v2/utils/config"
14
14
"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
15
15
"github.com/jfrog/jfrog-cli-security/commands/audit/sca"
16
- xrayutils2 "github.com/jfrog/jfrog-cli-security/utils"
16
+ "github.com/jfrog/jfrog-cli-security/utils"
17
17
"github.com/jfrog/jfrog-cli-security/utils/techutils"
18
18
"github.com/jfrog/jfrog-client-go/utils/errorutils"
19
19
"github.com/jfrog/jfrog-client-go/utils/io/fileutils"
20
20
"github.com/jfrog/jfrog-client-go/utils/log"
21
- xrayUtils "github.com/jfrog/jfrog-client-go/xray/services/utils"
21
+ clientutils "github.com/jfrog/jfrog-client-go/xray/services/utils"
22
22
23
23
"os"
24
24
"os/exec"
@@ -34,42 +34,33 @@ const (
34
34
CurationPipMinimumVersion = "23.0.0"
35
35
)
36
36
37
- type AuditPython struct {
38
- Server *config.ServerDetails
39
- Tool pythonutils.PythonTool
40
- RemotePypiRepo string
41
- PipRequirementsFile string
42
- InstallCommandArgs []string
43
- IsCurationCmd bool
44
- }
45
-
46
- func BuildDependencyTree(auditPython *AuditPython) (dependencyTree []*xrayUtils.GraphNode, uniqueDeps []string, downloadUrls map[string]string, err error) {
47
- dependenciesGraph, directDependenciesList, pipUrls, errGetTree := getDependencies(auditPython)
37
+ func BuildDependencyTree(params utils.AuditParams, technology techutils.Technology) (dependencyTree []*clientutils.GraphNode, uniqueDeps []string, downloadUrls map[string]string, err error) {
38
+ dependenciesGraph, directDependenciesList, pipUrls, errGetTree := getDependencies(params, technology)
48
39
if errGetTree != nil {
49
40
err = errGetTree
50
41
return
51
42
}
52
43
downloadUrls = pipUrls
53
- directDependencies := []*xrayUtils .GraphNode{}
44
+ directDependencies := []*clientutils .GraphNode{}
54
45
uniqueDepsSet := datastructures.MakeSet[string]()
55
46
for _, rootDep := range directDependenciesList {
56
- directDependency := &xrayUtils .GraphNode{
47
+ directDependency := &clientutils .GraphNode{
57
48
Id: PythonPackageTypeIdentifier + rootDep,
58
- Nodes: []*xrayUtils .GraphNode{},
49
+ Nodes: []*clientutils .GraphNode{},
59
50
}
60
51
populatePythonDependencyTree(directDependency, dependenciesGraph, uniqueDepsSet)
61
52
directDependencies = append(directDependencies, directDependency)
62
53
}
63
- root := &xrayUtils .GraphNode{
54
+ root := &clientutils .GraphNode{
64
55
Id: "root",
65
56
Nodes: directDependencies,
66
57
}
67
- dependencyTree = []*xrayUtils .GraphNode{root}
58
+ dependencyTree = []*clientutils .GraphNode{root}
68
59
uniqueDeps = uniqueDepsSet.ToSlice()
69
60
return
70
61
}
71
62
72
- func getDependencies(auditPython *AuditPython ) (dependenciesGraph map[string][]string, directDependencies []string, pipUrls map[string]string, err error) {
63
+ func getDependencies(params utils.AuditParams, technology techutils.Technology ) (dependenciesGraph map[string][]string, directDependencies []string, pipUrls map[string]string, err error) {
73
64
wd, err := os.Getwd()
74
65
if errorutils.CheckError(err) != nil {
75
66
return
@@ -100,24 +91,28 @@ func getDependencies(auditPython *AuditPython) (dependenciesGraph map[string][]s
100
91
return
101
92
}
102
93
103
- restoreEnv, err := runPythonInstall(auditPython)
104
- defer func() {
105
- err = errors.Join(err, restoreEnv())
106
- }()
107
- if err != nil {
108
- return
94
+ pythonTool := pythonutils.PythonTool(technology)
95
+ if technology == techutils.Pipenv || !params.SkipAutoInstall() {
96
+ var restoreEnv func() error
97
+ restoreEnv, err = runPythonInstall(params, pythonTool)
98
+ defer func() {
99
+ err = errors.Join(err, restoreEnv())
100
+ }()
101
+ if err != nil {
102
+ return
103
+ }
109
104
}
110
105
111
106
localDependenciesPath, err := config.GetJfrogDependenciesPath()
112
107
if err != nil {
113
108
return
114
109
}
115
- dependenciesGraph, directDependencies, err = pythonutils.GetPythonDependencies(auditPython.Tool , tempDirPath, localDependenciesPath, log.GetLogger())
110
+ dependenciesGraph, directDependencies, err = pythonutils.GetPythonDependencies(pythonTool , tempDirPath, localDependenciesPath, log.GetLogger())
116
111
if err != nil {
117
112
sca.LogExecutableVersion("python")
118
- sca.LogExecutableVersion(string(auditPython.Tool ))
113
+ sca.LogExecutableVersion(string(pythonTool ))
119
114
}
120
- if !auditPython .IsCurationCmd {
115
+ if !params .IsCurationCmd() {
121
116
return
122
117
}
123
118
pipUrls, errProcessed := processPipDownloadsUrlsFromReportFile()
@@ -181,29 +176,34 @@ type pypiMetaData struct {
181
176
Version string `json:"version"`
182
177
}
183
178
184
- func runPythonInstall(auditPython *AuditPython ) (restoreEnv func() error, err error) {
185
- switch auditPython.Tool {
179
+ func runPythonInstall(params utils.AuditParams, tool pythonutils.PythonTool ) (restoreEnv func() error, err error) {
180
+ switch tool {
186
181
case pythonutils.Pip:
187
- return installPipDeps(auditPython )
182
+ return installPipDeps(params )
188
183
case pythonutils.Pipenv:
189
- return installPipenvDeps(auditPython )
184
+ return installPipenvDeps(params )
190
185
case pythonutils.Poetry:
191
- return installPoetryDeps(auditPython )
186
+ return installPoetryDeps(params )
192
187
}
193
188
return
194
189
}
195
190
196
- func installPoetryDeps(auditPython *AuditPython ) (restoreEnv func() error, err error) {
191
+ func installPoetryDeps(params utils.AuditParams ) (restoreEnv func() error, err error) {
197
192
restoreEnv = func() error {
198
193
return nil
199
194
}
200
- if auditPython.RemotePypiRepo != "" {
201
- rtUrl, username, password, err := utils.GetPypiRepoUrlWithCredentials(auditPython.Server, auditPython.RemotePypiRepo, false)
195
+ if params.DepsRepo() != "" {
196
+ var serverDetails *config.ServerDetails
197
+ serverDetails, err = params.ServerDetails()
198
+ if err != nil {
199
+ return restoreEnv, err
200
+ }
201
+ rtUrl, username, password, err := artifactoryutils.GetPypiRepoUrlWithCredentials(serverDetails, params.DepsRepo(), false)
202
202
if err != nil {
203
203
return restoreEnv, err
204
204
}
205
205
if password != "" {
206
- err = utils .ConfigPoetryRepo(rtUrl.Scheme+"://"+rtUrl.Host+rtUrl.Path, username, password, auditPython.RemotePypiRepo )
206
+ err = artifactoryutils .ConfigPoetryRepo(rtUrl.Scheme+"://"+rtUrl.Host+rtUrl.Path, username, password, params.DepsRepo() )
207
207
if err != nil {
208
208
return restoreEnv, err
209
209
}
@@ -214,7 +214,7 @@ func installPoetryDeps(auditPython *AuditPython) (restoreEnv func() error, err e
214
214
return restoreEnv, err
215
215
}
216
216
217
- func installPipenvDeps(auditPython *AuditPython ) (restoreEnv func() error, err error) {
217
+ func installPipenvDeps(params utils.AuditParams ) (restoreEnv func() error, err error) {
218
218
// Set virtualenv path to venv dir
219
219
err = os.Setenv("WORKON_HOME", ".jfrog")
220
220
if err != nil {
@@ -223,46 +223,56 @@ func installPipenvDeps(auditPython *AuditPython) (restoreEnv func() error, err e
223
223
restoreEnv = func() error {
224
224
return os.Unsetenv("WORKON_HOME")
225
225
}
226
- if auditPython.RemotePypiRepo != "" {
227
- return restoreEnv, runPipenvInstallFromRemoteRegistry(auditPython.Server, auditPython.RemotePypiRepo)
226
+ if params.DepsRepo() != "" {
227
+ var serverDetails *config.ServerDetails
228
+ serverDetails, err = params.ServerDetails()
229
+ if err != nil {
230
+ return
231
+ }
232
+ return restoreEnv, runPipenvInstallFromRemoteRegistry(serverDetails, params.DepsRepo())
228
233
}
229
234
// Run 'pipenv install -d'
230
235
_, err = executeCommand("pipenv", "install", "-d")
231
236
return restoreEnv, err
232
237
}
233
238
234
- func installPipDeps(auditPython *AuditPython ) (restoreEnv func() error, err error) {
239
+ func installPipDeps(params utils.AuditParams ) (restoreEnv func() error, err error) {
235
240
restoreEnv, err = SetPipVirtualEnvPath()
236
241
if err != nil {
237
242
return
238
243
}
239
244
240
245
remoteUrl := ""
241
- if auditPython.RemotePypiRepo != "" {
242
- remoteUrl, err = utils.GetPypiRepoUrl(auditPython.Server, auditPython.RemotePypiRepo, auditPython.IsCurationCmd)
246
+ if params.DepsRepo() != "" {
247
+ var serverDetails *config.ServerDetails
248
+ serverDetails, err = params.ServerDetails()
249
+ if err != nil {
250
+ return
251
+ }
252
+ remoteUrl, err = artifactoryutils.GetPypiRepoUrl(serverDetails, params.DepsRepo(), params.IsCurationCmd())
243
253
if err != nil {
244
254
return
245
255
}
246
256
}
247
257
248
258
var curationCachePip string
249
259
var reportFileName string
250
- if auditPython .IsCurationCmd {
260
+ if params .IsCurationCmd() {
251
261
// upgrade pip version to 23.0.0, as it is required for the curation command.
252
262
if err = upgradePipVersion(CurationPipMinimumVersion); err != nil {
253
263
log.Warn(fmt.Sprintf("Failed to upgrade pip version, err: %v", err))
254
264
}
255
- if curationCachePip, err = xrayutils2 .GetCurationPipCacheFolder(); err != nil {
265
+ if curationCachePip, err = utils .GetCurationPipCacheFolder(); err != nil {
256
266
return
257
267
}
258
268
reportFileName = pythonReportFile
259
269
}
260
270
261
- pipInstallArgs := getPipInstallArgs(auditPython .PipRequirementsFile, remoteUrl, curationCachePip, reportFileName, auditPython .InstallCommandArgs...)
271
+ pipInstallArgs := getPipInstallArgs(params .PipRequirementsFile() , remoteUrl, curationCachePip, reportFileName, params .InstallCommandArgs() ...)
262
272
var reqErr error
263
273
_, err = executeCommand("python", pipInstallArgs...)
264
- if err != nil && auditPython .PipRequirementsFile == "" {
265
- pipInstallArgs = getPipInstallArgs("requirements.txt", remoteUrl, curationCachePip, reportFileName, auditPython .InstallCommandArgs...)
274
+ if err != nil && params .PipRequirementsFile() == "" {
275
+ pipInstallArgs = getPipInstallArgs("requirements.txt", remoteUrl, curationCachePip, reportFileName, params .InstallCommandArgs() ...)
266
276
_, reqErr = executeCommand("python", pipInstallArgs...)
267
277
if reqErr != nil {
268
278
// Return Pip install error and log the requirements fallback error.
@@ -272,7 +282,7 @@ func installPipDeps(auditPython *AuditPython) (restoreEnv func() error, err erro
272
282
}
273
283
}
274
284
if err != nil || reqErr != nil {
275
- if msgToUser := sca.GetMsgToUserForCurationBlock(auditPython .IsCurationCmd, techutils.Pip, errors.Join(err, reqErr).Error()); msgToUser != "" {
285
+ if msgToUser := sca.GetMsgToUserForCurationBlock(params .IsCurationCmd() , techutils.Pip, errors.Join(err, reqErr).Error()); msgToUser != "" {
276
286
err = errors.Join(err, errors.New(msgToUser))
277
287
}
278
288
}
@@ -318,7 +328,7 @@ func getPipInstallArgs(requirementsFile, remoteUrl, cacheFolder, reportFileName
318
328
args = append(args, "-r", requirementsFile)
319
329
}
320
330
if remoteUrl != "" {
321
- args = append(args, utils .GetPypiRemoteRegistryFlag(pythonutils.Pip), remoteUrl)
331
+ args = append(args, artifactoryutils .GetPypiRemoteRegistryFlag(pythonutils.Pip), remoteUrl)
322
332
}
323
333
if cacheFolder != "" {
324
334
args = append(args, "--cache-dir", cacheFolder)
@@ -359,7 +369,7 @@ func parseCustomArgs(remoteUrl, cacheFolder, reportFileName string, customArgs .
359
369
continue
360
370
}
361
371
}
362
- if remoteUrl != "" && strings.Contains(customArgs[i], utils .GetPypiRemoteRegistryFlag(pythonutils.Pip)) {
372
+ if remoteUrl != "" && strings.Contains(customArgs[i], artifactoryutils .GetPypiRemoteRegistryFlag(pythonutils.Pip)) {
363
373
log.Warn("The remote registry flag is not supported in the custom arguments list. skipping...")
364
374
i++
365
375
continue
@@ -370,11 +380,11 @@ func parseCustomArgs(remoteUrl, cacheFolder, reportFileName string, customArgs .
370
380
}
371
381
372
382
func runPipenvInstallFromRemoteRegistry(server *config.ServerDetails, depsRepoName string) (err error) {
373
- rtUrl, err := utils .GetPypiRepoUrl(server, depsRepoName, false)
383
+ rtUrl, err := artifactoryutils .GetPypiRepoUrl(server, depsRepoName, false)
374
384
if err != nil {
375
385
return err
376
386
}
377
- args := []string{"install", "-d", utils .GetPypiRemoteRegistryFlag(pythonutils.Pipenv), rtUrl}
387
+ args := []string{"install", "-d", artifactoryutils .GetPypiRemoteRegistryFlag(pythonutils.Pipenv), rtUrl}
378
388
_, err = executeCommand("pipenv", args...)
379
389
return err
380
390
}
@@ -424,17 +434,17 @@ func SetPipVirtualEnvPath() (restoreEnv func() error, err error) {
424
434
return
425
435
}
426
436
427
- func populatePythonDependencyTree(currNode *xrayUtils .GraphNode, dependenciesGraph map[string][]string, uniqueDepsSet *datastructures.Set[string]) {
437
+ func populatePythonDependencyTree(currNode *clientutils .GraphNode, dependenciesGraph map[string][]string, uniqueDepsSet *datastructures.Set[string]) {
428
438
if currNode.NodeHasLoop() {
429
439
return
430
440
}
431
441
uniqueDepsSet.Add(currNode.Id)
432
442
currDepChildren := dependenciesGraph[strings.TrimPrefix(currNode.Id, PythonPackageTypeIdentifier)]
433
443
// Recursively create & append all node's dependencies.
434
444
for _, dependency := range currDepChildren {
435
- childNode := &xrayUtils .GraphNode{
445
+ childNode := &clientutils .GraphNode{
436
446
Id: PythonPackageTypeIdentifier + dependency,
437
- Nodes: []*xrayUtils .GraphNode{},
447
+ Nodes: []*clientutils .GraphNode{},
438
448
Parent: currNode,
439
449
}
440
450
currNode.Nodes = append(currNode.Nodes, childNode)
0 commit comments