Skip to content

Commit

Permalink
Merge remote-tracking branch upstream/dev
Browse files Browse the repository at this point in the history
  • Loading branch information
orz25 committed Feb 14, 2024
2 parents 43ad5e2 + d8ecf2a commit 8ad7e03
Show file tree
Hide file tree
Showing 12 changed files with 396 additions and 148 deletions.
1 change: 1 addition & 0 deletions cli/scancommands.go
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,7 @@ func CurationCmd(c *components.Context) error {
return err
}
curationAuditCommand.SetServerDetails(serverDetails).
SetIsCurationCmd(true).
SetExcludeTestDependencies(c.GetBoolFlagValue(flags.ExcludeTestDeps)).
SetOutputFormat(format).
SetUseWrapper(c.GetBoolFlagValue(flags.UseWrapper)).
Expand Down
17 changes: 9 additions & 8 deletions commands/audit/sca/common_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package sca

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

Expand All @@ -12,13 +13,13 @@ import (
)

func TestBuildXrayDependencyTree(t *testing.T) {
treeHelper := make(map[string][]string)
rootDep := []string{"topDep1", "topDep2", "topDep3"}
topDep1 := []string{"midDep1", "midDep2"}
topDep2 := []string{"midDep2", "midDep3"}
midDep1 := []string{"bottomDep1"}
midDep2 := []string{"bottomDep2", "bottomDep3"}
bottomDep3 := []string{"leafDep"}
treeHelper := make(map[string]coreXray.DepTreeNode)
rootDep := coreXray.DepTreeNode{Children: []string{"topDep1", "topDep2", "topDep3"}}
topDep1 := coreXray.DepTreeNode{Children: []string{"midDep1", "midDep2"}}
topDep2 := coreXray.DepTreeNode{Children: []string{"midDep2", "midDep3"}}
midDep1 := coreXray.DepTreeNode{Children: []string{"bottomDep1"}}
midDep2 := coreXray.DepTreeNode{Children: []string{"bottomDep2", "bottomDep3"}}
bottomDep3 := coreXray.DepTreeNode{Children: []string{"leafDep"}}
treeHelper["rootDep"] = rootDep
treeHelper["topDep1"] = topDep1
treeHelper["topDep2"] = topDep2
Expand Down Expand Up @@ -69,7 +70,7 @@ func TestBuildXrayDependencyTree(t *testing.T) {

tree, uniqueDeps := coreXray.BuildXrayDependencyTree(treeHelper, "rootDep")

assert.ElementsMatch(t, expectedUniqueDeps, uniqueDeps)
assert.ElementsMatch(t, expectedUniqueDeps, maps.Keys(uniqueDeps))
assert.True(t, tests.CompareTree(tree, rootNode))
}

Expand Down
15 changes: 10 additions & 5 deletions commands/audit/sca/npm/npm.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/jfrog/jfrog-cli-security/utils"
"github.com/jfrog/jfrog-client-go/utils/log"
xrayUtils "github.com/jfrog/jfrog-client-go/xray/services/utils"
"golang.org/x/exp/maps"
"golang.org/x/exp/slices"
)

Expand Down Expand Up @@ -67,6 +68,7 @@ func configNpmResolutionServerIfNeeded(params utils.AuditParams) (clearResolutio
if params.DepsRepo() == "" {
return
}

serverDetails, err := params.ServerDetails()
if err != nil {
return
Expand Down Expand Up @@ -103,19 +105,22 @@ func addIgnoreScriptsFlag(npmArgs []string) []string {

// Parse the dependencies into an Xray dependency tree format
func parseNpmDependenciesList(dependencies []buildinfo.Dependency, packageInfo *biutils.PackageInfo) (*xrayUtils.GraphNode, []string) {
treeMap := make(map[string][]string)
treeMap := make(map[string]coreXray.DepTreeNode)
for _, dependency := range dependencies {
dependencyId := utils.NpmPackageTypeIdentifier + dependency.Id
for _, requestedByNode := range dependency.RequestedBy {
parent := utils.NpmPackageTypeIdentifier + requestedByNode[0]
if children, ok := treeMap[parent]; ok {
treeMap[parent] = appendUniqueChild(children, dependencyId)
depTreeNode, ok := treeMap[parent]
if ok {
depTreeNode.Children = appendUniqueChild(depTreeNode.Children, dependencyId)
} else {
treeMap[parent] = []string{dependencyId}
depTreeNode.Children = []string{dependencyId}
}
treeMap[parent] = depTreeNode
}
}
return coreXray.BuildXrayDependencyTree(treeMap, utils.NpmPackageTypeIdentifier+packageInfo.BuildInfoModuleId())
graph, nodeMapTypes := coreXray.BuildXrayDependencyTree(treeMap, utils.NpmPackageTypeIdentifier+packageInfo.BuildInfoModuleId())
return graph, maps.Keys(nodeMapTypes)
}

func appendUniqueChild(children []string, candidateDependency string) []string {
Expand Down
13 changes: 8 additions & 5 deletions commands/audit/sca/nuget/nuget.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"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"
Expand Down Expand Up @@ -215,19 +216,21 @@ func runDotnetRestore(wd string, params utils.AuditParams, toolType bidotnet.Too
func parseNugetDependencyTree(buildInfo *entities.BuildInfo) (nodes []*xrayUtils.GraphNode, allUniqueDeps []string) {
uniqueDepsSet := datastructures.MakeSet[string]()
for _, module := range buildInfo.Modules {
treeMap := make(map[string][]string)
treeMap := make(map[string]coreXray.DepTreeNode)
for _, dependency := range module.Dependencies {
dependencyId := nugetPackageTypeIdentifier + dependency.Id
parent := nugetPackageTypeIdentifier + dependency.RequestedBy[0][0]
if children, ok := treeMap[parent]; ok {
treeMap[parent] = append(children, dependencyId)
depTreeNode, ok := treeMap[parent]
if ok {
depTreeNode.Children = append(depTreeNode.Children, dependencyId)
} else {
treeMap[parent] = []string{dependencyId}
depTreeNode.Children = []string{dependencyId}
}
treeMap[parent] = depTreeNode
}
dependencyTree, uniqueDeps := coreXray.BuildXrayDependencyTree(treeMap, nugetPackageTypeIdentifier+module.Id)
nodes = append(nodes, dependencyTree)
for _, uniqueDep := range uniqueDeps {
for _, uniqueDep := range maps.Keys(uniqueDeps) {
uniqueDepsSet.Add(uniqueDep)
}
}
Expand Down
8 changes: 5 additions & 3 deletions commands/audit/sca/yarn/yarn.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package yarn
import (
"errors"
"fmt"
"golang.org/x/exp/maps"
"path/filepath"

"github.com/jfrog/build-info-go/build"
Expand Down Expand Up @@ -199,18 +200,19 @@ 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) {
treeMap := make(map[string][]string)
treeMap := make(map[string]coreXray.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)]))
}
if len(subDeps) > 0 {
treeMap[xrayDepId] = subDeps
treeMap[xrayDepId] = coreXray.DepTreeNode{Children: subDeps}
}
}
return coreXray.BuildXrayDependencyTree(treeMap, rootXrayId)
graph, uniqDeps := coreXray.BuildXrayDependencyTree(treeMap, rootXrayId)
return graph, maps.Keys(uniqDeps)
}

func getXrayDependencyId(yarnDependency *biutils.YarnDependency) string {
Expand Down
67 changes: 53 additions & 14 deletions commands/audit/scarunner.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,19 +190,33 @@ func GetTechDependencyTree(params xrayutils.AuditParams, tech coreutils.Technolo
if params.Progress() != nil {
params.Progress().SetHeadlineMsg(logMessage)
}
serverDetails, err := params.ServerDetails()
err = SetResolutionRepoIfExists(params, tech)
if err != nil {
return
}
err = SetResolutionRepoIfExists(params, tech)
serverDetails, err := params.ServerDetails()
if err != nil {
return
}
var uniqueDeps []string
var uniqDepsWithTypes map[string][]string
startTime := time.Now()
switch tech {
case coreutils.Maven, coreutils.Gradle:
fullDependencyTrees, uniqueDeps, err = java.BuildDependencyTree(serverDetails, params.DepsRepo(), params.UseWrapper(), params.IsMavenDepTreeInstalled(), tech)
curationCacheFolder := ""
if params.IsCurationCmd() {
curationCacheFolder, err = xrayutils.GetCurationMavenCacheFolder()
if err != nil {
return
}
}
fullDependencyTrees, uniqDepsWithTypes, err = java.BuildDependencyTree(java.DepTreeParams{
Server: serverDetails,
DepsRepo: params.DepsRepo(),
IsMavenDepTreeInstalled: params.IsMavenDepTreeInstalled(),
IsCurationCmd: params.IsCurationCmd(),
CurationCacheFolder: curationCacheFolder,
}, tech)
case coreutils.Npm:
fullDependencyTrees, uniqueDeps, err = npm.BuildDependencyTree(params)
case coreutils.Yarn:
Expand All @@ -220,17 +234,21 @@ func GetTechDependencyTree(params xrayutils.AuditParams, tech coreutils.Technolo
default:
err = errorutils.CheckErrorf("%s is currently not supported", string(tech))
}
if err != nil || len(uniqueDeps) == 0 {
if err != nil || (len(uniqueDeps) == 0 && len(uniqDepsWithTypes) == 0) {
return
}
log.Debug(fmt.Sprintf("Created '%s' dependency tree with %d nodes. Elapsed time: %.1f seconds.", tech.ToFormal(), len(uniqueDeps), time.Since(startTime).Seconds()))
if len(uniqDepsWithTypes) > 0 {
flatTree, err = createFlatTreeWithTypes(uniqDepsWithTypes)
return
}
flatTree, err = createFlatTree(uniqueDeps)
return
}

// Associates a technology with another of a different type in the structure.
// Docker is not present, as there is no docker-config command and, consequently, no docker.yaml file we need to operate on.
var techType = map[coreutils.Technology]project.ProjectType{
var TechType = map[coreutils.Technology]project.ProjectType{
coreutils.Maven: project.Maven, coreutils.Gradle: project.Gradle, coreutils.Npm: project.Npm, coreutils.Yarn: project.Yarn, coreutils.Go: project.Go, coreutils.Pip: project.Pip,
coreutils.Pipenv: project.Pipenv, coreutils.Poetry: project.Poetry, coreutils.Nuget: project.Nuget, coreutils.Dotnet: project.Dotnet,
}
Expand All @@ -241,7 +259,7 @@ func SetResolutionRepoIfExists(params xrayutils.AuditParams, tech coreutils.Tech
return
}

configFilePath, exists, err := project.GetProjectConfFilePath(techType[tech])
configFilePath, exists, err := project.GetProjectConfFilePath(TechType[tech])
if err != nil {
err = fmt.Errorf("failed while searching for %s.yaml config file: %s", tech.String(), err.Error())
return
Expand All @@ -250,7 +268,7 @@ func SetResolutionRepoIfExists(params xrayutils.AuditParams, tech coreutils.Tech
// Nuget and Dotnet are identified similarly in the detection process. To prevent redundancy, Dotnet is filtered out earlier in the process, focusing solely on detecting Nuget.
// Consequently, it becomes necessary to verify the presence of dotnet.yaml when Nuget detection occurs.
if tech == coreutils.Nuget {
configFilePath, exists, err = project.GetProjectConfFilePath(techType[coreutils.Dotnet])
configFilePath, exists, err = project.GetProjectConfFilePath(TechType[coreutils.Dotnet])
if err != nil {
err = fmt.Errorf("failed while searching for %s.yaml config file: %s", tech.String(), err.Error())
return
Expand Down Expand Up @@ -292,18 +310,39 @@ func SetResolutionRepoIfExists(params xrayutils.AuditParams, tech coreutils.Tech
return
}

func createFlatTreeWithTypes(uniqueDeps map[string][]string) (*xrayCmdUtils.GraphNode, error) {
if err := logDeps(uniqueDeps); err != nil {
return nil, err
}
var uniqueNodes []*xrayCmdUtils.GraphNode
for uniqueDep, types := range uniqueDeps {
p := types
uniqueNodes = append(uniqueNodes, &xrayCmdUtils.GraphNode{Id: uniqueDep, Types: &p})
}
return &xrayCmdUtils.GraphNode{Id: "root", Nodes: uniqueNodes}, nil
}

func createFlatTree(uniqueDeps []string) (*xrayCmdUtils.GraphNode, error) {
if log.GetLogger().GetLogLevel() == log.DEBUG {
// Avoid printing and marshaling if not on DEBUG mode.
jsonList, err := json.Marshal(uniqueDeps)
if errorutils.CheckError(err) != nil {
return nil, err
}
log.Debug("Unique dependencies list:\n" + clientutils.IndentJsonArray(jsonList))
if err := logDeps(uniqueDeps); err != nil {
return nil, err
}
uniqueNodes := []*xrayCmdUtils.GraphNode{}
for _, uniqueDep := range uniqueDeps {
uniqueNodes = append(uniqueNodes, &xrayCmdUtils.GraphNode{Id: uniqueDep})
}
return &xrayCmdUtils.GraphNode{Id: "root", Nodes: uniqueNodes}, nil
}

func logDeps(uniqueDeps any) (err error) {
if log.GetLogger().GetLogLevel() != log.DEBUG {
// Avoid printing and marshaling if not on DEBUG mode.
return
}
jsonList, err := json.Marshal(uniqueDeps)
if errorutils.CheckError(err) != nil {
return err
}
log.Debug("Unique dependencies list:\n" + clientutils.IndentJsonArray(jsonList))

return
}
Loading

0 comments on commit 8ad7e03

Please sign in to comment.