Skip to content

Commit

Permalink
Merge branch 'dev' into missing-context
Browse files Browse the repository at this point in the history
  • Loading branch information
barv-jfrog authored Sep 5, 2024
2 parents ac53ed0 + 64585a6 commit 25cd6cb
Show file tree
Hide file tree
Showing 35 changed files with 1,558 additions and 230 deletions.
10 changes: 7 additions & 3 deletions commands/audit/audit.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,12 @@ func (auditCmd *AuditCommand) Run() (err error) {
}
if err = utils.NewResultsWriter(auditResults).
SetIsMultipleRootProject(auditResults.IsMultipleProject()).
SetHasViolationContext(auditCmd.HasViolationContext()).
SetIncludeVulnerabilities(auditCmd.IncludeVulnerabilities).
SetIncludeLicenses(auditCmd.IncludeLicenses).
SetOutputFormat(auditCmd.OutputFormat()).
SetPrintExtendedTable(auditCmd.PrintExtendedTable).
SetExtraMessages(messages).
SetScanType(services.Dependency).
SetSubScansPreformed(auditCmd.ScansToPerform()).
PrintScanResults(); err != nil {
return
Expand All @@ -160,12 +160,16 @@ func (auditCmd *AuditCommand) CommandName() string {
return "generic_audit"
}

func (auditCmd *AuditCommand) HasViolationContext() bool {
return len(auditCmd.watches) > 0 || auditCmd.projectKey != "" || auditCmd.targetRepoPath != ""
}

// Runs an audit scan based on the provided auditParams.
// Returns an audit Results object containing all the scan results.
// If the current server is entitled for JAS, the advanced security results will be included in the scan results.
func RunAudit(auditParams *AuditParams) (results *utils.Results, err error) {
// Initialize Results struct
results = utils.NewAuditResults()
results = utils.NewAuditResults(utils.SourceCode)
serverDetails, err := auditParams.ServerDetails()
if err != nil {
return
Expand Down Expand Up @@ -252,7 +256,7 @@ func downloadAnalyzerManagerAndRunScanners(auditParallelRunner *utils.SecurityPa
if err != nil {
return fmt.Errorf("failed to create jas scanner: %s", err.Error())
}
if err = runner.AddJasScannersTasks(auditParallelRunner, scanResults, auditParams.DirectDependencies(), serverDetails, auditParams.thirdPartyApplicabilityScan, scanner, applicability.ApplicabilityScannerType, secrets.SecretsScannerType, auditParallelRunner.AddErrorToChan, auditParams.ScansToPerform()); err != nil {
if err = runner.AddJasScannersTasks(auditParallelRunner, scanResults, auditParams.DirectDependencies(), serverDetails, auditParams.thirdPartyApplicabilityScan, scanner, applicability.ApplicabilityScannerType, secrets.SecretsScannerType, auditParallelRunner.AddErrorToChan, auditParams.ScansToPerform(), auditParams.configProfile); err != nil {
return fmt.Errorf("%s failed to run JAS scanners: %s", clientutils.GetLogMsgPrefix(threadId, false), err.Error())
}
return
Expand Down
151 changes: 151 additions & 0 deletions commands/audit/audit_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package audit

import (
biutils "github.com/jfrog/build-info-go/utils"
"github.com/jfrog/jfrog-cli-core/v2/common/format"
coreTests "github.com/jfrog/jfrog-cli-core/v2/utils/tests"
"github.com/jfrog/jfrog-cli-security/utils"
"github.com/jfrog/jfrog-cli-security/utils/xray/scangraph"
clientTests "github.com/jfrog/jfrog-client-go/utils/tests"
"github.com/jfrog/jfrog-client-go/xsc/services"
"github.com/stretchr/testify/assert"
"os"
"path/filepath"
"testing"
)

// Note: Currently, if a config profile is provided, the scan will use the profile's settings, IGNORING jfrog-apps-config if exists.
func TestAuditWithConfigProfile(t *testing.T) {
testcases := []struct {
name string
configProfile services.ConfigProfile
expectedSastIssues int
expectedSecretsIssues int
}{
{
name: "Enable only secrets scanner",
configProfile: services.ConfigProfile{
ProfileName: "only-secrets",
Modules: []services.Module{{
ModuleId: 1,
ModuleName: "only-secrets-module",
PathFromRoot: ".",
ScanConfig: services.ScanConfig{
SastScannerConfig: services.SastScannerConfig{
EnableSastScan: false,
},
SecretsScannerConfig: services.SecretsScannerConfig{
EnableSecretsScan: true,
},
},
}},
IsDefault: false,
},
expectedSastIssues: 0,
expectedSecretsIssues: 7,
},
{
name: "Enable only sast scanner",
configProfile: services.ConfigProfile{
ProfileName: "only-sast",
Modules: []services.Module{{
ModuleId: 1,
ModuleName: "only-sast-module",
PathFromRoot: ".",
ScanConfig: services.ScanConfig{
SastScannerConfig: services.SastScannerConfig{
EnableSastScan: true,
},
SecretsScannerConfig: services.SecretsScannerConfig{
EnableSecretsScan: false,
},
},
}},
IsDefault: false,
},
expectedSastIssues: 1,
expectedSecretsIssues: 0,
},
{
name: "Enable secrets and sast",
configProfile: services.ConfigProfile{
ProfileName: "secrets&sast",
Modules: []services.Module{{
ModuleId: 1,
ModuleName: "secrets&sast-module",
PathFromRoot: ".",
ScanConfig: services.ScanConfig{
SastScannerConfig: services.SastScannerConfig{
EnableSastScan: true,
},
SecretsScannerConfig: services.SecretsScannerConfig{
EnableSecretsScan: true,
},
},
}},
IsDefault: false,
},
expectedSastIssues: 1,
expectedSecretsIssues: 7,
},
}

for _, testcase := range testcases {
t.Run(testcase.name, func(t *testing.T) {
mockServer, serverDetails := utils.XrayServer(t, utils.EntitlementsMinVersion)
defer mockServer.Close()

auditBasicParams := (&utils.AuditBasicParams{}).
SetServerDetails(serverDetails).
SetOutputFormat(format.Table).
SetUseJas(true)

configProfile := testcase.configProfile
auditParams := NewAuditParams().
SetGraphBasicParams(auditBasicParams).
SetConfigProfile(&configProfile).
SetCommonGraphScanParams(&scangraph.CommonGraphScanParams{
RepoPath: "",
ProjectKey: "",
Watches: nil,
ScanType: "dependency",
IncludeVulnerabilities: true,
XscVersion: services.ConfigProfileMinXscVersion,
MultiScanId: "random-msi",
})
auditParams.SetIsRecursiveScan(true)

tempDirPath, createTempDirCallback := coreTests.CreateTempDirWithCallbackAndAssert(t)
defer createTempDirCallback()
testDirPath := filepath.Join("..", "..", "tests", "testdata", "projects", "jas", "jas")
assert.NoError(t, biutils.CopyDir(testDirPath, tempDirPath, true, nil))

baseWd, err := os.Getwd()
assert.NoError(t, err)
chdirCallback := clientTests.ChangeDirWithCallback(t, baseWd, tempDirPath)
defer chdirCallback()

auditResults, err := RunAudit(auditParams)
assert.NoError(t, err)

// Currently, the only supported scanners are Secrets and Sast, therefore if a config profile is utilized - all other scanners are disabled.
if testcase.expectedSastIssues > 0 {
assert.NotNil(t, auditResults.ExtendedScanResults.SastScanResults)
assert.Equal(t, testcase.expectedSastIssues, len(auditResults.ExtendedScanResults.SastScanResults[0].Results))
} else {
assert.Nil(t, auditResults.ExtendedScanResults.SastScanResults)
}

if testcase.expectedSecretsIssues > 0 {
assert.NotNil(t, auditResults.ExtendedScanResults.SecretsScanResults)
assert.Equal(t, testcase.expectedSecretsIssues, len(auditResults.ExtendedScanResults.SecretsScanResults[0].Results))
} else {
assert.Nil(t, auditResults.ExtendedScanResults.SecretsScanResults)
}

assert.Nil(t, auditResults.ScaResults)
assert.Nil(t, auditResults.ExtendedScanResults.ApplicabilityScanResults)
assert.Nil(t, auditResults.ExtendedScanResults.IacScanResults)
})
}
}
7 changes: 7 additions & 0 deletions commands/audit/auditparams.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"github.com/jfrog/jfrog-cli-security/utils/severityutils"
"github.com/jfrog/jfrog-cli-security/utils/xray/scangraph"
"github.com/jfrog/jfrog-client-go/xray/services"
clientservices "github.com/jfrog/jfrog-client-go/xsc/services"
)

type AuditParams struct {
Expand All @@ -19,6 +20,7 @@ type AuditParams struct {
// Include third party dependencies source code in the applicability scan.
thirdPartyApplicabilityScan bool
threads int
configProfile *clientservices.ConfigProfile
}

func NewAuditParams() *AuditParams {
Expand Down Expand Up @@ -92,6 +94,11 @@ func (params *AuditParams) SetCommonGraphScanParams(commonParams *scangraph.Comm
return params
}

func (params *AuditParams) SetConfigProfile(configProfile *clientservices.ConfigProfile) *AuditParams {
params.configProfile = configProfile
return params
}

func (params *AuditParams) createXrayGraphScanParams() *services.XrayGraphScanParams {
return &services.XrayGraphScanParams{
RepoPath: params.commonGraphScanParams.RepoPath,
Expand Down
5 changes: 5 additions & 0 deletions commands/audit/scarunner.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ func buildDepTreeAndRunScaScan(auditParallelRunner *utils.SecurityParallelRunner
log.Debug("Skipping SCA scan as requested by input...")
return
}
if auditParams.configProfile != nil {
log.Debug("Skipping SCA scan as a configuration profile is being utilized and currently only Secrets and Sast scanners are supported when utilizing a configuration profile")
return
}

// Prepare
currentWorkingDir, err := os.Getwd()
if errorutils.CheckError(err) != nil {
Expand Down
15 changes: 8 additions & 7 deletions commands/curation/curationaudit.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ import (
"encoding/json"
"errors"
"fmt"
"net/http"
"os"
"path/filepath"
"regexp"
"sort"
"strings"
"sync"

"golang.org/x/exp/maps"

"github.com/jfrog/gofrog/datastructures"
Expand All @@ -28,13 +36,6 @@ import (
"github.com/jfrog/jfrog-client-go/utils/log"
xrayClient "github.com/jfrog/jfrog-client-go/xray"
xrayUtils "github.com/jfrog/jfrog-client-go/xray/services/utils"
"net/http"
"os"
"path/filepath"
"regexp"
"sort"
"strings"
"sync"
)

const (
Expand Down
9 changes: 8 additions & 1 deletion commands/curation/curationaudit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -979,7 +979,14 @@ func Test_convertResultsToSummary(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.ElementsMatch(t, tt.expected.Scans, convertResultsToSummary(tt.input).Scans)
summary := convertResultsToSummary(tt.input)
// Sort Blocked base on count (low first) to make the test deterministic
for _, scan := range summary.Scans {
sort.Slice(scan.CuratedPackages.Blocked, func(i, j int) bool {
return len(scan.CuratedPackages.Blocked[i].Packages) < len(scan.CuratedPackages.Blocked[j].Packages)
})
}
assert.Equal(t, tt.expected, summary)
})
}
}
2 changes: 1 addition & 1 deletion commands/enrich/enrich.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ func (enrichCmd *EnrichCommand) Run() (err error) {
scanErrors = appendErrorSlice(scanErrors, fileProducerErrors)
scanErrors = appendErrorSlice(scanErrors, indexedFileProducerErrors)

scanResults := xrutils.NewAuditResults()
scanResults := xrutils.NewAuditResults(utils.SBOM)
scanResults.XrayVersion = xrayVersion
scanResults.ScaResults = flatResults

Expand Down
10 changes: 7 additions & 3 deletions commands/scan/buildscan.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,17 +149,17 @@ func (bsc *BuildScanCommand) runBuildScanAndPrintResults(xrayManager *xray.XrayS
XrayDataUrl: buildScanResults.MoreDetailsUrl,
}}

scanResults := utils.NewAuditResults()
scanResults := utils.NewAuditResults(utils.Build)
scanResults.XrayVersion = xrayVersion
scanResults.ScaResults = []*utils.ScaScanResult{{Target: fmt.Sprintf("%s (%s)", params.BuildName, params.BuildNumber), XrayResults: scanResponse}}

resultsPrinter := utils.NewResultsWriter(scanResults).
SetOutputFormat(bsc.outputFormat).
SetHasViolationContext(bsc.hasViolationContext()).
SetIncludeVulnerabilities(bsc.includeVulnerabilities).
SetIncludeLicenses(false).
SetIsMultipleRootProject(true).
SetPrintExtendedTable(bsc.printExtendedTable).
SetScanType(services.Binary).
SetExtraMessages(nil)

if bsc.outputFormat != outputFormat.Table {
Expand Down Expand Up @@ -187,7 +187,7 @@ func (bsc *BuildScanCommand) runBuildScanAndPrintResults(xrayManager *xray.XrayS
scanResults,
bsc.serverDetails,
bsc.includeVulnerabilities,
bsc.buildConfiguration.GetProject() != "",
bsc.hasViolationContext(),
params.BuildName, params.BuildNumber,
))
return
Expand All @@ -197,6 +197,10 @@ func (bsc *BuildScanCommand) CommandName() string {
return "xr_build_scan"
}

func (bsc *BuildScanCommand) hasViolationContext() bool {
return bsc.buildConfiguration.GetProject() != ""
}

// There are two cases. when serverDetails.Url is configured and when serverDetails.XrayUrl and serverDetails.ArtifactoryUrl are configured
// The function will return the Url if configured and will trim xray if serverDetails.Url is not configured
func getActualUrl(serverDetails config.ServerDetails) (string, error) {
Expand Down
13 changes: 10 additions & 3 deletions commands/scan/dockerscan.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,17 +96,24 @@ func (dsc *DockerScanCommand) Run() (err error) {
err = errorutils.CheckError(e)
}
}()
return dsc.ScanCommand.RunAndRecordResults(func(scanResults *utils.Results) (err error) {
return dsc.ScanCommand.RunAndRecordResults(utils.DockerImage, func(scanResults *utils.Results) (err error) {
if scanResults == nil {
return
}
if scanResults.ScaResults != nil {
for _, result := range scanResults.ScaResults {
result.Name = dsc.imageTag
}
}
dsc.analyticsMetricsService.UpdateGeneralEvent(dsc.analyticsMetricsService.CreateXscAnalyticsGeneralEventFinalizeFromAuditResults(scanResults))

if err = utils.RecordSarifOutput(scanResults); err != nil {
return
}
return utils.RecordSecurityCommandSummary(utils.NewDockerScanSummary(
scanResults,
dsc.ScanCommand.serverDetails,
dsc.ScanCommand.includeVulnerabilities,
hasViolationContext(dsc.ScanCommand.watches, dsc.ScanCommand.projectKey),
dsc.ScanCommand.hasViolationContext(),
dsc.imageTag,
))
})
Expand Down
Loading

0 comments on commit 25cd6cb

Please sign in to comment.