Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/dev' into add-disable-proxy
Browse files Browse the repository at this point in the history
  • Loading branch information
sarao1310 committed Jul 24, 2023
2 parents 68c1ede + fb04650 commit 175bf5e
Show file tree
Hide file tree
Showing 19 changed files with 251 additions and 227 deletions.
29 changes: 29 additions & 0 deletions .github/workflows/embedded-jar-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# This test verifies that gradle-dep-tree.jar and maven-dep-tree.jar are kept up-to-date with the version specified in buildscripts/download-jars.js.
# It accomplishes this by downloading the JARs and executing a "git diff" command.
# In case there are any differences detected, the test will result in failure.
name: Embedded Jars Tests
on:
push:
branches:
- '**'
tags-ignore:
- '**'
pull_request:
jobs:
test:
runs-on: ubuntu-latest
env:
GOPROXY: direct
steps:
- uses: actions/checkout@v3

- name: Download JARs
run: buildscripts/download-jars.sh

- name: Check Diff
run: git diff --exit-code

- name: Log if Failure
run: echo "::warning::Please run ./buildscripts/download-jars to use compatible Maven and Gradle dependency tree JARs."
if: ${{ failure() }}

14 changes: 14 additions & 0 deletions buildscripts/download-jars.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/sh

# Please use this script to download the JAR files for maven-dep-tree and gradle-dep-tree into the directory xray/audit/java/.
# These JARs allow us to build Maven and Gradle dependency trees efficiently and without compilation.
# Learn more about them here:
# https://github.com/jfrog/gradle-dep-tree
# https://github.com/jfrog/maven-dep-tree

# Once you have updated the versions mentioned below, please execute this script from the root directory of the jfrog-cli-core to ensure the JAR files are updated.
GRADLE_DEP_TREE_VERSION="2.2.0"
MAVEN_DEP_TREE_VERSION="1.0.0"

curl -fL https://releases.jfrog.io/artifactory/oss-release-local/com/jfrog/gradle-dep-tree/${GRADLE_DEP_TREE_VERSION}/gradle-dep-tree-${GRADLE_DEP_TREE_VERSION}.jar -o xray/audit/java/gradle-dep-tree.jar
# curl -fL https://releases.jfrog.io/artifactory/oss-release-local/com/jfrog/maven-dep-tree/${MAVEN_DEP_TREE_VERSION}/maven-dep-tree-${MAVEN_DEP_TREE_VERSION}.jar -o xray/audit/java/maven-dep-tree.jar
47 changes: 10 additions & 37 deletions xray/audit/commonutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,22 @@ import (
)

func BuildXrayDependencyTree(treeHelper map[string][]string, nodeId string) *xrayUtils.GraphNode {
return buildXrayDependencyTree(treeHelper, []string{nodeId})
exceededDepthCounter := 0
xrayDependencyTree := buildXrayDependencyTree(treeHelper, []string{nodeId}, &exceededDepthCounter)
if exceededDepthCounter > 0 {
log.Debug("buildXrayDependencyTree exceeded max tree depth", exceededDepthCounter, "times")
}
return xrayDependencyTree
}

func buildXrayDependencyTree(treeHelper map[string][]string, impactPath []string) *xrayUtils.GraphNode {
func buildXrayDependencyTree(treeHelper map[string][]string, impactPath []string, exceededDepthCounter *int) *xrayUtils.GraphNode {
nodeId := impactPath[len(impactPath)-1]
// Initialize the new node
xrDependencyTree := &xrayUtils.GraphNode{}
xrDependencyTree.Id = nodeId
xrDependencyTree.Nodes = []*xrayUtils.GraphNode{}
if len(impactPath) >= buildinfo.RequestedByMaxLength {
log.Debug("buildXrayDependencyTree exceeded max tree depth")
*exceededDepthCounter++
return xrDependencyTree
}
// Recursively create & append all node's dependencies.
Expand All @@ -43,7 +48,7 @@ func buildXrayDependencyTree(treeHelper map[string][]string, impactPath []string
if slices.Contains(impactPath, dependency) {
continue
}
xrDependencyTree.Nodes = append(xrDependencyTree.Nodes, buildXrayDependencyTree(treeHelper, append(impactPath, dependency)))
xrDependencyTree.Nodes = append(xrDependencyTree.Nodes, buildXrayDependencyTree(treeHelper, append(impactPath, dependency), exceededDepthCounter))
}
return xrDependencyTree
}
Expand Down Expand Up @@ -205,41 +210,9 @@ func updateComponentsWithImpactPaths(components map[string]services.Component, i
func setPathsForIssues(dependency *xrayUtils.GraphNode, issuesImpactPathsMap map[string]*services.Component, pathFromRoot []services.ImpactPathNode) {
pathFromRoot = append(pathFromRoot, services.ImpactPathNode{ComponentId: dependency.Id})
if _, exists := issuesImpactPathsMap[dependency.Id]; exists {
appendPath(issuesImpactPathsMap, dependency, pathFromRoot)
issuesImpactPathsMap[dependency.Id].ImpactPaths = append(issuesImpactPathsMap[dependency.Id].ImpactPaths, pathFromRoot)
}
for _, depChild := range dependency.Nodes {
setPathsForIssues(depChild, issuesImpactPathsMap, pathFromRoot)
}
}

// Appends paths to impact paths tree.
// When we have multiple paths to the same CVE, the following logic applies:
// If we have a direct path for the vulnerable dependency, show only the direct paths, as fixing it will resolve all the vulnerabilities.
// If we have multiple different paths to an indirect dependency, show all possible paths.
func appendPath(currentTree map[string]*services.Component, dependency *xrayUtils.GraphNode, pathFromRoot []services.ImpactPathNode) {
if len(currentTree[dependency.Id].ImpactPaths) == 0 {
currentTree[dependency.Id].ImpactPaths = append(currentTree[dependency.Id].ImpactPaths, pathFromRoot)
return
}
currentHasDirectPath := atLeastOneDirectPath(currentTree[dependency.Id].ImpactPaths)
suggestHasDirectPath := atLeastOneDirectPath([][]services.ImpactPathNode{pathFromRoot})
// If neither the current path nor the suggested path is direct, append the suggested path.
if !currentHasDirectPath && !suggestHasDirectPath {
currentTree[dependency.Id].ImpactPaths = append(currentTree[dependency.Id].ImpactPaths, pathFromRoot)
return
}
// If the current path is not direct but a direct path is found, overwrite the existing path.
if !currentHasDirectPath && suggestHasDirectPath {
currentTree[dependency.Id].ImpactPaths[0] = pathFromRoot
return
}
}

func atLeastOneDirectPath(nodes [][]services.ImpactPathNode) bool {
for index := range nodes {
if len(nodes[index]) == 2 {
return true
}
}
return false
}
47 changes: 0 additions & 47 deletions xray/audit/commonutils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,53 +41,6 @@ func TestSetPathsForIssues(t *testing.T) {
assert.Equal(t, issuesMap["child5"].ImpactPaths[0][2].ComponentId, "child5")
}

// In the edge case where we have the same CVE with direct & indirect dependency,
// we want to show only the direct path, as it will fix both problems
func TestSetPathsForIssuesAvoidsDuplicates_RemovePath(t *testing.T) {
rootNode := &xrayUtils.GraphNode{Id: "root"}
childNode1 := &xrayUtils.GraphNode{Id: "child4"}
childNode2 := &xrayUtils.GraphNode{Id: "child2", Nodes: []*xrayUtils.GraphNode{{Id: "child3", Nodes: []*xrayUtils.GraphNode{{Id: "child4"}}}}}
rootNode.Nodes = []*xrayUtils.GraphNode{childNode1, childNode2}

issuesMap := make(map[string]*services.Component)
issuesMap["child4"] = &services.Component{ImpactPaths: [][]services.ImpactPathNode{}}

setPathsForIssues(rootNode, issuesMap, []services.ImpactPathNode{})

assert.Equal(t, "root", issuesMap["child4"].ImpactPaths[0][0].ComponentId)
assert.Equal(t, "child4", issuesMap["child4"].ImpactPaths[0][1].ComponentId)
assert.Len(t, issuesMap["child4"].ImpactPaths, 1)
assert.Len(t, issuesMap["child4"].ImpactPaths[0], 2)
}

// This verifies that we are not removing unwanted paths
// If we have multiple paths for the same vulnerable indirect dependency, show all the paths.
func TestSetPathsForIssuesAvoidsDuplicates_AppendPath(t *testing.T) {
rootNode := &xrayUtils.GraphNode{Id: "root"}
childNode1 := &xrayUtils.GraphNode{Id: "child1"}
childNode2 := &xrayUtils.GraphNode{Id: "child2"}
childNode3 := &xrayUtils.GraphNode{Id: "child3"}
childNode4 := &xrayUtils.GraphNode{Id: "child4"}
childNode5 := &xrayUtils.GraphNode{Id: "child5"}

rootNode.Nodes = []*xrayUtils.GraphNode{childNode1, childNode2}
childNode1.Nodes = []*xrayUtils.GraphNode{childNode4, childNode5}
childNode2.Nodes = []*xrayUtils.GraphNode{childNode3, childNode5}

issuesMap := make(map[string]*services.Component)
issuesMap["child5"] = &services.Component{ImpactPaths: [][]services.ImpactPathNode{}}

setPathsForIssues(rootNode, issuesMap, []services.ImpactPathNode{})

assert.Equal(t, "root", issuesMap["child5"].ImpactPaths[0][0].ComponentId)
assert.Equal(t, "child1", issuesMap["child5"].ImpactPaths[0][1].ComponentId)
assert.Equal(t, "child5", issuesMap["child5"].ImpactPaths[0][2].ComponentId)

assert.Equal(t, "root", issuesMap["child5"].ImpactPaths[1][0].ComponentId)
assert.Equal(t, "child2", issuesMap["child5"].ImpactPaths[1][1].ComponentId)
assert.Equal(t, "child5", issuesMap["child5"].ImpactPaths[1][2].ComponentId)
}

func TestUpdateVulnerableComponent(t *testing.T) {
// Create test data
components := map[string]services.Component{
Expand Down
15 changes: 5 additions & 10 deletions xray/audit/jas/applicabilitymanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package jas

import (
"errors"
"fmt"
"github.com/jfrog/gofrog/datastructures"
"github.com/jfrog/jfrog-cli-core/v2/utils/config"
"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
Expand All @@ -21,10 +20,9 @@ import (
)

const (
ApplicabilityFeatureId = "contextual_analysis"
applicabilityScanType = "analyze-applicability"
applicabilityScanFailureMessage = "failed to run applicability scan. Cause: %s"
applicabilityScanCommand = "ca"
ApplicabilityFeatureId = "contextual_analysis"
applicabilityScanType = "analyze-applicability"
applicabilityScanCommand = "ca"
)

// The getApplicabilityScanResults function runs the applicability scan flow, which includes the following steps:
Expand All @@ -40,7 +38,7 @@ func getApplicabilityScanResults(results []services.ScanResponse, dependencyTree
serverDetails *config.ServerDetails, scannedTechnologies []coreutils.Technology, analyzerManager utils.AnalyzerManagerInterface) (map[string]string, bool, error) {
applicabilityScanManager, cleanupFunc, err := newApplicabilityScanManager(results, dependencyTrees, serverDetails, analyzerManager)
if err != nil {
return nil, false, fmt.Errorf(applicabilityScanFailureMessage, err.Error())
return nil, false, utils.Applicability.FormattedError(err)
}
defer func() {
if cleanupFunc != nil {
Expand All @@ -52,10 +50,7 @@ func getApplicabilityScanResults(results []services.ScanResponse, dependencyTree
return nil, false, nil
}
if err = applicabilityScanManager.run(); err != nil {
if utils.IsNotEntitledError(err) || utils.IsUnsupportedCommandError(err) {
return nil, false, nil
}
return nil, true, fmt.Errorf(applicabilityScanFailureMessage, err.Error())
return nil, false, utils.ParseAnalyzerManagerError(utils.Applicability, err)
}
return applicabilityScanManager.applicabilityScanResults, true, nil
}
Expand Down
3 changes: 1 addition & 2 deletions xray/audit/jas/applicabilitymanager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package jas

import (
"errors"
"fmt"
"github.com/jfrog/gofrog/datastructures"
"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
"github.com/jfrog/jfrog-cli-core/v2/xray/utils"
Expand Down Expand Up @@ -366,6 +365,6 @@ func TestGetExtendedScanResults_AnalyzerManagerReturnsError(t *testing.T) {

// Assert
assert.Error(t, err)
assert.Equal(t, fmt.Sprintf(applicabilityScanFailureMessage, analyzerManagerErrorMessage), err.Error())
assert.Equal(t, "failed to run Applicability scan. Exit code received: analyzer manager failure message", err.Error())
assert.Nil(t, extendedResults)
}
5 changes: 1 addition & 4 deletions xray/audit/jas/iacscanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,7 @@ func getIacScanResults(serverDetails *config.ServerDetails, analyzerManager util
}()
log.Info("Running IaC scanning...")
if err = iacScanManager.run(); err != nil {
if utils.IsNotEntitledError(err) || utils.IsUnsupportedCommandError(err) {
return nil, false, nil
}
return nil, true, fmt.Errorf(iacScanFailureMessage, err.Error())
return nil, false, utils.ParseAnalyzerManagerError(utils.IaC, err)
}
if len(iacScanManager.iacScannerResults) > 0 {
log.Info("Found", len(iacScanManager.iacScannerResults), "IaC vulnerabilities")
Expand Down
2 changes: 1 addition & 1 deletion xray/audit/jas/jasmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func GetExtendedScanResults(xrayResults []services.ScanResponse, dependencyTrees
serverDetails *config.ServerDetails, scannedTechnologies []coreutils.Technology) (*utils.ExtendedScanResults, error) {
if serverDetails == nil || len(serverDetails.Url) == 0 {
log.Warn("To include 'Advanced Security' scan as part of the audit output, please run the 'jf c add' command before running this command.")
return nil, nil
return &utils.ExtendedScanResults{XrayResults: xrayResults}, nil
}
analyzerManagerExist, err := analyzerManagerExecuter.ExistLocally()
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion xray/audit/jas/jasmanager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,6 @@ func TestGetExtendedScanResults_ServerNotValid(t *testing.T) {
extendedResults, err := GetExtendedScanResults(fakeBasicXrayResults, fakeBasicDependencyGraph, nil, []coreutils.Technology{coreutils.Pip})

// Assert
assert.Nil(t, extendedResults)
assert.NotNil(t, extendedResults)
assert.NoError(t, err)
}
5 changes: 1 addition & 4 deletions xray/audit/jas/secretsscanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,7 @@ func getSecretsScanResults(serverDetails *config.ServerDetails, analyzerManager
}()
log.Info("Running secrets scanning...")
if err = secretScanManager.run(); err != nil {
if utils.IsNotEntitledError(err) || utils.IsUnsupportedCommandError(err) {
return nil, false, nil
}
return nil, true, fmt.Errorf(secScanFailureMessage, err.Error())
return nil, false, utils.ParseAnalyzerManagerError(utils.Secrets, err)
}
if len(secretScanManager.secretsScannerResults) > 0 {
log.Info(len(secretScanManager.secretsScannerResults), "secrets were found")
Expand Down
5 changes: 2 additions & 3 deletions xray/audit/jas/secretsscanner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package jas

import (
"errors"
"fmt"
"github.com/stretchr/testify/assert"
"os"
"path/filepath"
Expand Down Expand Up @@ -105,9 +104,9 @@ func TestGetSecretsScanResults_AnalyzerManagerReturnsError(t *testing.T) {

// Assert
assert.Error(t, err)
assert.Equal(t, fmt.Sprintf(secScanFailureMessage, analyzerManagerErrorMessage), err.Error())
assert.Equal(t, "failed to run Secrets scan. Exit code received: analyzer manager failure message", err.Error())
assert.Nil(t, secretsResults)
assert.True(t, entitledForSecrets)
assert.False(t, entitledForSecrets)
}

func TestHideSecret(t *testing.T) {
Expand Down
Binary file added xray/audit/java/gradle-dep-tree.jar
Binary file not shown.
45 changes: 29 additions & 16 deletions xray/audit/java/gradle.go
Original file line number Diff line number Diff line change
@@ -1,43 +1,47 @@
package java

import (
_ "embed"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"

"github.com/jfrog/build-info-go/build"
"github.com/jfrog/jfrog-cli-core/v2/artifactory/utils"
"github.com/jfrog/jfrog-cli-core/v2/utils/config"
"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
"github.com/jfrog/jfrog-cli-core/v2/utils/ioutils"
"github.com/jfrog/jfrog-client-go/auth"
"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"
"os"
"os/exec"
"path/filepath"
"strings"
)

const (
remoteDepTreePath = "artifactory/oss-release-local"
gradlew = "gradlew"
depTreeInitFile = "gradledeptree.init"
depTreeOutputFile = "gradledeptree.out"
depTreeInitScript = `initscript {
repositories { %s
remoteDepTreePath = "artifactory/oss-release-local"
gradlew = "gradlew"
gradleDepTreeJarFile = "gradle-dep-tree.jar"
depTreeInitFile = "gradledeptree.init"
depTreeOutputFile = "gradledeptree.out"
depTreeInitScript = `initscript {
repositories { %s
mavenCentral()
}
dependencies {
classpath 'com.jfrog:gradle-dep-tree:2.2.0'
}
}
dependencies {
classpath files('%s')
}
}
allprojects {
repositories { %s
}
apply plugin: com.jfrog.GradleDepTree
apply plugin: com.jfrog.GradleDepTree
}`
artifactoryRepository = `
maven {
Expand All @@ -49,6 +53,9 @@ allprojects {
}`
)

//go:embed gradle-dep-tree.jar
var gradleDepTreeJar []byte

type depTreeManager struct {
dependenciesTree
server *config.ServerDetails
Expand Down Expand Up @@ -152,7 +159,13 @@ func (dtp *depTreeManager) createDepTreeScriptAndGetDir() (tmpDir string, err er
if err != nil {
return
}
depTreeInitScript := fmt.Sprintf(depTreeInitScript, dtp.releasesRepo, dtp.depsRepo)
gradleDepTreeJarPath := filepath.Join(tmpDir, string(gradleDepTreeJarFile))
if err = errorutils.CheckError(os.WriteFile(gradleDepTreeJarPath, gradleDepTreeJar, 0666)); err != nil {
return
}
gradleDepTreeJarPath = ioutils.DoubleWinPathSeparator(gradleDepTreeJarPath)

depTreeInitScript := fmt.Sprintf(depTreeInitScript, dtp.releasesRepo, gradleDepTreeJarPath, dtp.depsRepo)
return tmpDir, errorutils.CheckError(os.WriteFile(filepath.Join(tmpDir, depTreeInitFile), []byte(depTreeInitScript), 0666))
}

Expand Down
Loading

0 comments on commit 175bf5e

Please sign in to comment.