Skip to content

Commit

Permalink
Support JFrog Apps Config file
Browse files Browse the repository at this point in the history
  • Loading branch information
yahavi committed Sep 26, 2023
1 parent 0414290 commit b4ac8f8
Show file tree
Hide file tree
Showing 14 changed files with 384 additions and 58 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ require (
github.com/jedib0t/go-pretty/v6 v6.4.7
github.com/jfrog/build-info-go v1.9.10
github.com/jfrog/gofrog v1.3.0
github.com/jfrog/jfrog-apps-config v1.0.1
github.com/jfrog/jfrog-client-go v1.32.3
github.com/magiconair/properties v1.8.7
github.com/manifoldco/promptui v0.9.0
Expand Down
4 changes: 3 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ github.com/jfrog/build-info-go v1.9.10 h1:uXnDLVxpqxoAMpXcki00QaBB+M2BoGMMpHODPk
github.com/jfrog/build-info-go v1.9.10/go.mod h1:ujJ8XQZMdT2tMkLSMJNyDd1pCY+duwHdjV+9or9FLIg=
github.com/jfrog/gofrog v1.3.0 h1:o4zgsBZE4QyDbz2M7D4K6fXPTBJht+8lE87mS9bw7Gk=
github.com/jfrog/gofrog v1.3.0/go.mod h1:IFMc+V/yf7rA5WZ74CSbXe+Lgf0iApEQLxRZVzKRUR0=
github.com/jfrog/jfrog-apps-config v1.0.1 h1:mtv6k7g8A8BVhlHGlSveapqf4mJfonwvXYLipdsOFMY=
github.com/jfrog/jfrog-apps-config v1.0.1/go.mod h1:8AIIr1oY9JuH5dylz2S6f8Ym2MaadPLR6noCBO4C22w=
github.com/jfrog/jfrog-client-go v1.32.3 h1:B2M8Gu8EMrokbHWPPDgN1b7YRWwf0oe746epvQASK6c=
github.com/jfrog/jfrog-client-go v1.32.3/go.mod h1:UewnwkIf/77HzBgwCPzOHZCK6V/Nw5/JwdzN/tRb4aU=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
Expand Down Expand Up @@ -319,7 +321,7 @@ github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
Expand Down
28 changes: 18 additions & 10 deletions xray/commands/audit/jas/applicability/applicabilitymanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package applicability
import (
"path/filepath"

jfrogappsconfig "github.com/jfrog/jfrog-apps-config/go"
"github.com/jfrog/jfrog-cli-core/v2/xray/commands/audit/jas"

"github.com/jfrog/gofrog/datastructures"
Expand Down Expand Up @@ -100,19 +101,22 @@ func isDirectComponents(components []string, directDependencies []string) bool {
return false
}

func (asm *ApplicabilityScanManager) Run(wd string) (err error) {
if len(asm.scanner.WorkingDirs) > 1 {
log.Info("Running applicability scanning in the", wd, "directory...")
func (asm *ApplicabilityScanManager) Run(module jfrogappsconfig.Module) (err error) {
if jas.ShouldSkipScanner(module, utils.Applicability) {
return
}
if len(asm.scanner.JFrogAppsConfig.Modules) > 1 {
log.Info("Running applicability scanning in the", module.SourceRoot, "directory...")
} else {
log.Info("Running applicability scanning...")
}
if err = asm.createConfigFile(wd); err != nil {
if err = asm.createConfigFile(module); err != nil {
return
}
if err = asm.runAnalyzerManager(); err != nil {
return
}
workingDirResults, err := jas.ReadJasScanRunsFromFile(asm.scanner.ResultsFileName, wd)
workingDirResults, err := jas.ReadJasScanRunsFromFile(asm.scanner.ResultsFileName, module.SourceRoot)
if err != nil {
return
}
Expand Down Expand Up @@ -141,21 +145,25 @@ type scanConfiguration struct {
SkippedDirs []string `yaml:"skipped-folders"`
}

func (asm *ApplicabilityScanManager) createConfigFile(workingDir string) error {
skipDirs := jas.SkippedDirs
func (asm *ApplicabilityScanManager) createConfigFile(module jfrogappsconfig.Module) error {
roots, err := jas.GetSourceRoots(module, nil)
if err != nil {
return err
}
excludePatterns := jas.GetExcludePatterns(module, nil)
if asm.thirdPartyScan {
log.Info("Including node modules folder in applicability scan")
skipDirs = removeElementFromSlice(skipDirs, jas.NodeModulesPattern)
excludePatterns = removeElementFromSlice(excludePatterns, jas.NodeModulesPattern)
}
configFileContent := applicabilityScanConfig{
Scans: []scanConfiguration{
{
Roots: []string{workingDir},
Roots: roots,
Output: asm.scanner.ResultsFileName,
Type: applicabilityScanType,
GrepDisable: false,
CveWhitelist: asm.directDependenciesCves,
SkippedDirs: skipDirs,
SkippedDirs: excludePatterns,
},
},
}
Expand Down
18 changes: 10 additions & 8 deletions xray/commands/audit/jas/applicability/applicabilitymanager_test.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package applicability

import (
"os"
"path/filepath"
"testing"

jfrogappsconfig "github.com/jfrog/jfrog-apps-config/go"
"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
"github.com/jfrog/jfrog-cli-core/v2/xray/commands/audit/jas"
"github.com/jfrog/jfrog-client-go/xray/services"
"github.com/stretchr/testify/assert"
"os"
"path/filepath"
"testing"
)

var mockDirectDependencies = []string{"issueId_2_direct_dependency", "issueId_1_direct_dependency"}
Expand Down Expand Up @@ -36,7 +38,7 @@ func TestNewApplicabilityScanManager_DependencyTreeDoesntExist(t *testing.T) {
// Assert
if assert.NotNil(t, applicabilityManager) {
assert.NotNil(t, applicabilityManager.scanner.ScannerDirCleanupFunc)
assert.Len(t, applicabilityManager.scanner.WorkingDirs, 1)
assert.Len(t, applicabilityManager.scanner.JFrogAppsConfig.Modules, 1)
assert.NotEmpty(t, applicabilityManager.scanner.ConfigFileName)
assert.NotEmpty(t, applicabilityManager.scanner.ResultsFileName)
assert.Empty(t, applicabilityManager.directDependenciesCves)
Expand Down Expand Up @@ -255,7 +257,7 @@ func TestCreateConfigFile_VerifyFileWasCreated(t *testing.T) {

currWd, err := coreutils.GetWorkingDirectory()
assert.NoError(t, err)
err = applicabilityManager.createConfigFile(currWd)
err = applicabilityManager.createConfigFile(jfrogappsconfig.Module{SourceRoot: currWd})
assert.NoError(t, err)

defer func() {
Expand All @@ -280,7 +282,7 @@ func TestParseResults_EmptyResults_AllCvesShouldGetUnknown(t *testing.T) {

// Act
var err error
applicabilityManager.applicabilityScanResults, err = jas.ReadJasScanRunsFromFile(applicabilityManager.scanner.ResultsFileName, scanner.WorkingDirs[0])
applicabilityManager.applicabilityScanResults, err = jas.ReadJasScanRunsFromFile(applicabilityManager.scanner.ResultsFileName, scanner.JFrogAppsConfig.Modules[0].SourceRoot)

if assert.NoError(t, err) {
assert.Len(t, applicabilityManager.applicabilityScanResults, 1)
Expand All @@ -297,7 +299,7 @@ func TestParseResults_ApplicableCveExist(t *testing.T) {

// Act
var err error
applicabilityManager.applicabilityScanResults, err = jas.ReadJasScanRunsFromFile(applicabilityManager.scanner.ResultsFileName, scanner.WorkingDirs[0])
applicabilityManager.applicabilityScanResults, err = jas.ReadJasScanRunsFromFile(applicabilityManager.scanner.ResultsFileName, scanner.JFrogAppsConfig.Modules[0].SourceRoot)

if assert.NoError(t, err) && assert.NotNil(t, applicabilityManager.applicabilityScanResults) {
assert.Len(t, applicabilityManager.applicabilityScanResults, 1)
Expand All @@ -314,7 +316,7 @@ func TestParseResults_AllCvesNotApplicable(t *testing.T) {

// Act
var err error
applicabilityManager.applicabilityScanResults, err = jas.ReadJasScanRunsFromFile(applicabilityManager.scanner.ResultsFileName, scanner.WorkingDirs[0])
applicabilityManager.applicabilityScanResults, err = jas.ReadJasScanRunsFromFile(applicabilityManager.scanner.ResultsFileName, scanner.JFrogAppsConfig.Modules[0].SourceRoot)

if assert.NoError(t, err) && assert.NotNil(t, applicabilityManager.applicabilityScanResults) {
assert.Len(t, applicabilityManager.applicabilityScanResults, 1)
Expand Down
72 changes: 66 additions & 6 deletions xray/commands/audit/jas/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,24 @@ package jas

import (
"errors"
"fmt"
"os"
"path/filepath"
"strings"
"testing"

jfrogappsconfig "github.com/jfrog/jfrog-apps-config/go"
rtutils "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/xray/utils"
"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"
"github.com/jfrog/jfrog-client-go/xray/services"
"github.com/owenrumney/go-sarif/v2/sarif"
"github.com/stretchr/testify/assert"
"golang.org/x/exp/slices"
"gopkg.in/yaml.v3"
)

Expand All @@ -24,7 +28,7 @@ const (
)

var (
SkippedDirs = []string{"**/*test*/**", "**/*venv*/**", NodeModulesPattern, "**/*target*/**"}
DefaultExcludePatterns = []string{"**/*test*/**", "**/*venv*/**", NodeModulesPattern, "**/*target*/**"}

mapSeverityToScore = map[string]string{
"": "0.0",
Expand All @@ -41,7 +45,7 @@ type JasScanner struct {
ResultsFileName string
AnalyzerManager utils.AnalyzerManager
ServerDetails *config.ServerDetails
WorkingDirs []string
JFrogAppsConfig *jfrogappsconfig.JFrogAppsConfig
ScannerDirCleanupFunc func() error
}

Expand All @@ -60,22 +64,42 @@ func NewJasScanner(workingDirs []string, serverDetails *config.ServerDetails, mu
scanner.ServerDetails = serverDetails
scanner.ConfigFileName = filepath.Join(tempDir, "config.yaml")
scanner.ResultsFileName = filepath.Join(tempDir, "results.sarif")
scanner.WorkingDirs, err = coreutils.GetFullPathsWorkingDirs(workingDirs)
scanner.JFrogAppsConfig, err = createJFrogAppsConfig(workingDirs)
scanner.AnalyzerManager.MultiScanId = multiScanId
return
}

func createJFrogAppsConfig(workingDirs []string) (*jfrogappsconfig.JFrogAppsConfig, error) {
if jfrogAppsConfig, err := jfrogappsconfig.LoadConfigIfExist(); err != nil {
return nil, errorutils.CheckError(err)
} else if jfrogAppsConfig != nil {
// jfrog-apps-config.yml exist in the workspace
return jfrogAppsConfig, nil
}

// jfrog-apps-config.yml does not exist in the workspace
fullPathsWorkingDirs, err := coreutils.GetFullPathsWorkingDirs(workingDirs)
if err != nil {
return nil, err
}
jfrogAppsConfig := new(jfrogappsconfig.JFrogAppsConfig)
for _, workingDir := range fullPathsWorkingDirs {
jfrogAppsConfig.Modules = append(jfrogAppsConfig.Modules, jfrogappsconfig.Module{SourceRoot: workingDir})
}
return jfrogAppsConfig, nil
}

type ScannerCmd interface {
Run(wd string) (err error)
Run(module jfrogappsconfig.Module) (err error)
}

func (a *JasScanner) Run(scannerCmd ScannerCmd) (err error) {
for _, workingDir := range a.WorkingDirs {
for _, module := range a.JFrogAppsConfig.Modules {
func() {
defer func() {
err = errors.Join(err, deleteJasProcessFiles(a.ConfigFileName, a.ResultsFileName))
}()
if err = scannerCmd.Run(workingDir); err != nil {
if err = scannerCmd.Run(module); err != nil {
return
}
}()
Expand Down Expand Up @@ -158,6 +182,7 @@ func CreateScannersConfigFile(fileName string, fileContent interface{}) error {
if errorutils.CheckError(err) != nil {
return err
}
log.Debug("Input YAML:\n" + string(yamlData))
err = os.WriteFile(fileName, yamlData, 0644)
return errorutils.CheckError(err)
}
Expand Down Expand Up @@ -196,3 +221,38 @@ func InitJasTest(t *testing.T, workingDirs ...string) (*JasScanner, func()) {
func GetTestDataPath() string {
return filepath.Join("..", "..", "..", "testdata")
}

func ShouldSkipScanner(module jfrogappsconfig.Module, scanType utils.JasScanType) bool {
lowerScanType := strings.ToLower(string(scanType))
if slices.Contains(module.ExcludeScanners, lowerScanType) {
log.Info(fmt.Sprintf("Skipping %s scanning", scanType))
return true
}
return false
}

func GetSourceRoots(module jfrogappsconfig.Module, scanner *jfrogappsconfig.Scanner) ([]string, error) {
root, err := filepath.Abs(module.SourceRoot)
if err != nil {
return []string{}, errorutils.CheckError(err)
}
if scanner == nil || len(scanner.WorkingDirs) == 0 {
return []string{root}, errorutils.CheckError(err)
}
var roots []string
for _, workingDir := range scanner.WorkingDirs {
roots = append(roots, filepath.Join(root, workingDir))
}
return roots, nil
}

func GetExcludePatterns(module jfrogappsconfig.Module, scanner *jfrogappsconfig.Scanner) []string {
excludePatterns := module.ExcludePatterns
if scanner != nil {
excludePatterns = append(excludePatterns, scanner.ExcludePatterns...)
}
if len(excludePatterns) == 0 {
return DefaultExcludePatterns
}
return excludePatterns
}
Loading

0 comments on commit b4ac8f8

Please sign in to comment.