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 Mar 21, 2024
2 parents 4f8d68d + 6f6d5d3 commit 75b5d25
Show file tree
Hide file tree
Showing 34 changed files with 1,825 additions and 250 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v3
with:
go-version: 1.20.x
go-version: 1.21.x

- name: Static Code Analysis
uses: golangci/golangci-lint-action@v3
Expand All @@ -34,7 +34,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v3
with:
go-version: 1.20.x
go-version: 1.21.x

# Temporarily set version 2.18.0 to workaround https://github.com/securego/gosec/issues/1046
- name: Run Gosec Security Scanner
Expand Down
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@v4

- 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() }}

2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v3
with:
go-version: 1.20.x
go-version: 1.21.x
- name: Install npm
uses: actions/setup-node@v3
with:
Expand Down
15 changes: 15 additions & 0 deletions buildscripts/download-jars.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/sh

# Please use this script to download the JAR files for maven-dep-tree and gradle-dep-tree into the directory utils/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="3.0.2"
# Changing this version also requires a change in mavenDepTreeVersion within utils/java/mvn.go.
MAVEN_DEP_TREE_VERSION="1.1.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 commands/audit/sca/java/resources/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 commands/audit/sca/java/resources/maven-dep-tree.jar
4 changes: 2 additions & 2 deletions cli/docs/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"github.com/jfrog/jfrog-cli-core/v2/common/cliutils"
pluginsCommon "github.com/jfrog/jfrog-cli-core/v2/plugins/common"
"github.com/jfrog/jfrog-cli-core/v2/plugins/components"
"github.com/jfrog/jfrog-cli-security/commands/audit"
"github.com/jfrog/jfrog-cli-security/commands/audit/sca"
"github.com/jfrog/jfrog-cli-security/commands/curation"
"github.com/jfrog/jfrog-cli-security/commands/xray/offlineupdate"
)
Expand Down Expand Up @@ -200,7 +200,7 @@ var flagsMap = map[string]components.Flag{
ExclusionsAudit: components.NewStringFlag(
Exclusions,
"List of exclusions separated by semicolons, utilized to skip sub-projects from undergoing an audit. These exclusions may incorporate the * and ? wildcards.",
components.WithStrDefaultValue(strings.Join(audit.DefaultExcludePatterns, ";")),
components.WithStrDefaultValue(strings.Join(sca.DefaultExcludePatterns, ";")),
),
Mvn: components.NewBoolFlag(Mvn, "Set to true to request audit for a Maven project."),
Gradle: components.NewBoolFlag(Gradle, "Set to true to request audit for a Gradle project."),
Expand Down
6 changes: 3 additions & 3 deletions cli/scancommands.go
Original file line number Diff line number Diff line change
Expand Up @@ -357,8 +357,7 @@ func createAuditCmd(c *components.Context) (*audit.AuditCommand, error) {
SetPrintExtendedTable(c.GetBoolFlagValue(flags.ExtendedTable)).
SetMinSeverityFilter(minSeverity).
SetFixableOnly(c.GetBoolFlagValue(flags.FixableOnly)).
SetThirdPartyApplicabilityScan(c.GetBoolFlagValue(flags.ThirdPartyContextualAnalysis)).
SetExclusions(pluginsCommon.GetStringsArrFlagValue(c, flags.Exclusions))
SetThirdPartyApplicabilityScan(c.GetBoolFlagValue(flags.ThirdPartyContextualAnalysis))

if c.GetStringFlagValue(flags.Watches) != "" {
auditCmd.SetWatches(splitByCommaAndTrim(c.GetStringFlagValue(flags.Watches)))
Expand All @@ -373,7 +372,8 @@ func createAuditCmd(c *components.Context) (*audit.AuditCommand, error) {
SetUseWrapper(c.GetBoolFlagValue(flags.UseWrapper)).
SetInsecureTls(c.GetBoolFlagValue(flags.InsecureTls)).
SetNpmScope(c.GetStringFlagValue(flags.DepType)).
SetPipRequirementsFile(c.GetStringFlagValue(flags.RequirementsFile))
SetPipRequirementsFile(c.GetStringFlagValue(flags.RequirementsFile)).
SetExclusions(pluginsCommon.GetStringsArrFlagValue(c, flags.Exclusions))
return auditCmd, err
}

Expand Down
5 changes: 2 additions & 3 deletions commands/audit/audit.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,8 @@ func (auditCmd *AuditCommand) Run() (err error) {
SetMinSeverityFilter(auditCmd.minSeverityFilter).
SetFixableOnly(auditCmd.fixableOnly).
SetGraphBasicParams(auditCmd.AuditBasicParams).
SetThirdPartyApplicabilityScan(auditCmd.thirdPartyApplicabilityScan).
SetExclusions(auditCmd.exclusions).
SetIsRecursiveScan(isRecursiveScan)
SetThirdPartyApplicabilityScan(auditCmd.thirdPartyApplicabilityScan)
auditParams.SetIsRecursiveScan(isRecursiveScan).SetExclusions(auditCmd.Exclusions())
auditResults, err := RunAudit(auditParams)
if err != nil {
return
Expand Down
16 changes: 0 additions & 16 deletions commands/audit/auditparams.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,13 @@ import (
type AuditParams struct {
xrayGraphScanParams *services.XrayGraphScanParams
workingDirs []string
exclusions []string
installFunc func(tech string) error
fixableOnly bool
minSeverityFilter string
*xrayutils.AuditBasicParams
xrayVersion string
// Include third party dependencies source code in the applicability scan.
thirdPartyApplicabilityScan bool
isRecursiveScan bool
}

func NewAuditParams() *AuditParams {
Expand All @@ -42,20 +40,6 @@ func (params *AuditParams) XrayVersion() string {
return params.xrayVersion
}

func (params *AuditParams) Exclusions() []string {
return params.exclusions
}

func (params *AuditParams) SetExclusions(exclusions []string) *AuditParams {
params.exclusions = exclusions
return params
}

func (params *AuditParams) SetIsRecursiveScan(isRecursiveScan bool) *AuditParams {
params.isRecursiveScan = isRecursiveScan
return params
}

func (params *AuditParams) SetXrayGraphScanParams(xrayGraphScanParams *services.XrayGraphScanParams) *AuditParams {
params.xrayGraphScanParams = xrayGraphScanParams
return params
Expand Down
12 changes: 12 additions & 0 deletions commands/audit/sca/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,25 @@ import (
"github.com/jfrog/jfrog-cli-core/v2/utils/tests"
"github.com/jfrog/jfrog-cli-security/scangraph"
"github.com/jfrog/jfrog-cli-security/utils"
"github.com/jfrog/jfrog-client-go/artifactory/services/fspatterns"
clientutils "github.com/jfrog/jfrog-client-go/utils"
"github.com/jfrog/jfrog-client-go/utils/errorutils"
ioUtils "github.com/jfrog/jfrog-client-go/utils/io"
"github.com/jfrog/jfrog-client-go/utils/log"
"github.com/jfrog/jfrog-client-go/xray/services"
xrayUtils "github.com/jfrog/jfrog-client-go/xray/services/utils"
)

var DefaultExcludePatterns = []string{"*.git*", "*node_modules*", "*target*", "*venv*", "*test*"}

func GetExcludePattern(params utils.AuditParams) string {
exclusions := params.Exclusions()
if len(exclusions) == 0 {
exclusions = append(exclusions, DefaultExcludePatterns...)
}
return fspatterns.PrepareExcludePathPattern(exclusions, clientutils.WildCardPattern, params.IsRecursiveScan())
}

func RunXrayDependenciesTreeScanGraph(dependencyTree *xrayUtils.GraphNode, progress ioUtils.ProgressMgr, technology coreutils.Technology, scanGraphParams *scangraph.ScanGraphParams) (results []services.ScanResponse, err error) {
scanGraphParams.XrayGraphScanParams().DependenciesGraph = dependencyTree
xscGitInfoContext := scanGraphParams.XrayGraphScanParams().XscGitInfoContext
Expand Down
48 changes: 47 additions & 1 deletion commands/audit/sca/common_test.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,63 @@
package sca

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

"golang.org/x/exp/maps"

"github.com/jfrog/jfrog-cli-core/v2/utils/tests"
coreXray "github.com/jfrog/jfrog-cli-core/v2/utils/xray"
"github.com/jfrog/jfrog-cli-security/utils"
"github.com/jfrog/jfrog-client-go/xray/services"
xrayUtils "github.com/jfrog/jfrog-client-go/xray/services/utils"
"github.com/stretchr/testify/assert"
)

func TestGetExcludePattern(t *testing.T) {
tests := []struct {
name string
params func() *utils.AuditBasicParams
expected string
}{
{
name: "Test exclude pattern recursive",
params: func() *utils.AuditBasicParams {
param := &utils.AuditBasicParams{}
param.SetExclusions([]string{"exclude1", "exclude2"}).SetIsRecursiveScan(true)
return param
},
expected: "(^exclude1$)|(^exclude2$)",
},
{
name: "Test no exclude pattern recursive",
params: func() *utils.AuditBasicParams { return (&utils.AuditBasicParams{}).SetIsRecursiveScan(true) },
expected: "(^.*\\.git.*$)|(^.*node_modules.*$)|(^.*target.*$)|(^.*venv.*$)|(^.*test.*$)",
},
{
name: "Test exclude pattern not recursive",
params: func() *utils.AuditBasicParams {
param := &utils.AuditBasicParams{}
param.SetExclusions([]string{"exclude1", "exclude2"})
return param
},
expected: "(^exclude1$)|(^exclude2$)",
},
{
name: "Test no exclude pattern",
params: func() *utils.AuditBasicParams { return &utils.AuditBasicParams{} },
expected: "(^.*\\.git.*$)|(^.*node_modules.*$)|(^.*target.*$)|(^.*venv.*$)|(^.*test.*$)",
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
result := GetExcludePattern(test.params())
assert.Equal(t, test.expected, result)
})
}
}

func TestBuildXrayDependencyTree(t *testing.T) {
treeHelper := make(map[string]coreXray.DepTreeNode)
rootDep := coreXray.DepTreeNode{Children: []string{"topDep1", "topDep2", "topDep3"}}
Expand Down
124 changes: 124 additions & 0 deletions commands/audit/sca/java/deptreemanager.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package java

import (
"encoding/json"
"os"
"strings"

"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/xray"
"github.com/jfrog/jfrog-client-go/utils/errorutils"
xrayUtils "github.com/jfrog/jfrog-client-go/xray/services/utils"
)

const (
GavPackageTypeIdentifier = "gav://"
)

func BuildDependencyTree(depTreeParams DepTreeParams, tech coreutils.Technology) ([]*xrayUtils.GraphNode, map[string][]string, error) {
if tech == coreutils.Maven {
return buildMavenDependencyTree(&depTreeParams)
}
return buildGradleDependencyTree(&depTreeParams)
}

type DepTreeParams struct {
UseWrapper bool
Server *config.ServerDetails
DepsRepo string
IsMavenDepTreeInstalled bool
IsCurationCmd bool
CurationCacheFolder string
}

type DepTreeManager struct {
server *config.ServerDetails
depsRepo string
useWrapper bool
}

func NewDepTreeManager(params *DepTreeParams) DepTreeManager {
return DepTreeManager{useWrapper: params.UseWrapper, depsRepo: params.DepsRepo, server: params.Server}
}

// The structure of a dependency tree of a module in a Gradle/Maven project, as created by the gradle-dep-tree and maven-dep-tree plugins.
type moduleDepTree struct {
Root string `json:"root"`
Nodes map[string]xray.DepTreeNode `json:"nodes"`
}

// Reads the output files of the gradle-dep-tree and maven-dep-tree plugins and returns them as a slice of GraphNodes.
// It takes the output of the plugin's run (which is a byte representation of a list of paths of the output files, separated by newlines) as input.
func getGraphFromDepTree(outputFilePaths string) (depsGraph []*xrayUtils.GraphNode, uniqueDepsMap map[string][]string, err error) {
modules, err := parseDepTreeFiles(outputFilePaths)
if err != nil {
return
}
uniqueDepsMap = map[string][]string{}
for _, module := range modules {
moduleTree, moduleUniqueDeps := GetModuleTreeAndDependencies(module)
depsGraph = append(depsGraph, moduleTree)
for depToAdd, depTypes := range moduleUniqueDeps {
uniqueDepsMap[depToAdd] = depTypes
}
}
return
}

// Returns a dependency tree and a flat list of the module's dependencies for the given module
func GetModuleTreeAndDependencies(module *moduleDepTree) (*xrayUtils.GraphNode, map[string][]string) {
moduleTreeMap := make(map[string]xray.DepTreeNode)
moduleDeps := module.Nodes
for depName, dependency := range moduleDeps {
dependencyId := GavPackageTypeIdentifier + depName
var childrenList []string
for _, childName := range dependency.Children {
childId := GavPackageTypeIdentifier + childName
childrenList = append(childrenList, childId)
}
moduleTreeMap[dependencyId] = xray.DepTreeNode{
Types: dependency.Types,
Children: childrenList,
}
}
return xray.BuildXrayDependencyTree(moduleTreeMap, GavPackageTypeIdentifier+module.Root)
}

func parseDepTreeFiles(jsonFilePaths string) ([]*moduleDepTree, error) {
outputFilePaths := strings.Split(strings.TrimSpace(jsonFilePaths), "\n")
var modules []*moduleDepTree
for _, path := range outputFilePaths {
results, err := parseDepTreeFile(path)
if err != nil {
return nil, err
}
modules = append(modules, results)
}
return modules, nil
}

func parseDepTreeFile(path string) (results *moduleDepTree, err error) {
depTreeJson, err := os.ReadFile(strings.TrimSpace(path))
if errorutils.CheckError(err) != nil {
return
}
results = &moduleDepTree{}
err = errorutils.CheckError(json.Unmarshal(depTreeJson, &results))
return
}

func getArtifactoryAuthFromServer(server *config.ServerDetails) (string, string, error) {
username, password, err := server.GetAuthenticationCredentials()
if err != nil {
return "", "", err
}
if username == "" {
return "", "", errorutils.CheckErrorf("a username is required for authenticating with Artifactory")
}
return username, password, nil
}

func (dtm *DepTreeManager) GetDepsRepo() string {
return dtm.depsRepo
}
Loading

0 comments on commit 75b5d25

Please sign in to comment.