Skip to content

Commit 7ee750c

Browse files
authored
Support for JFrog Advanced Security (JAS) in scan command (jfrog#407)
1 parent aaab4d3 commit 7ee750c

File tree

11 files changed

+100
-29
lines changed

11 files changed

+100
-29
lines changed

commands/scan/dockerscan.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ func (dsc *DockerScanCommand) Run() (err error) {
8484
Pattern(imageTarPath).
8585
Target(dsc.resultsContext.RepoPath).
8686
BuildSpec()).SetThreads(1)
87-
dsc.ScanCommand.SetTargetNameOverride(dsc.imageTag).SetRunJasScans(true)
87+
dsc.ScanCommand.SetTargetNameOverride(dsc.imageTag)
8888
err = dsc.setCredentialEnvsForIndexerApp()
8989
if err != nil {
9090
return errorutils.CheckError(err)

commands/scan/scan.go

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ const (
5353
BypassArchiveLimitsMinXrayVersion = "3.59.0"
5454
indexingCommand = "graph"
5555
fileNotSupportedExitCode = 3
56+
typeJASPackageScanTypeDocker = "docker"
57+
typeJASPackageScanTypeGeneric = "generic"
5658
)
5759

5860
type ScanCommand struct {
@@ -70,9 +72,7 @@ type ScanCommand struct {
7072
bypassArchiveLimits bool
7173
fixableOnly bool
7274
progress ioUtils.ProgressMgr
73-
// JAS is only supported for Docker images.
74-
commandSupportsJAS bool
75-
targetNameOverride string
75+
targetNameOverride string
7676

7777
resultsContext results.ResultContext
7878

@@ -97,11 +97,6 @@ func (scanCmd *ScanCommand) SetFixableOnly(fixable bool) *ScanCommand {
9797
return scanCmd
9898
}
9999

100-
func (scanCmd *ScanCommand) SetRunJasScans(run bool) *ScanCommand {
101-
scanCmd.commandSupportsJAS = run
102-
return scanCmd
103-
}
104-
105100
func (scanCmd *ScanCommand) SetTargetNameOverride(targetName string) *ScanCommand {
106101
scanCmd.targetNameOverride = targetName
107102
return scanCmd
@@ -343,7 +338,7 @@ func (scanCmd *ScanCommand) initScanCmdResults(cmdType utils.CommandType) (xrayM
343338
cmdResults.SetStartTime(scanCmd.startTime)
344339
cmdResults.SetResultsContext(scanCmd.resultsContext)
345340
// Send entitlement request
346-
if entitledForJas, err := isEntitledForJas(xrayManager, scanCmd.xrayVersion, scanCmd.commandSupportsJAS); err != nil {
341+
if entitledForJas, err := isEntitledForJas(xrayManager, scanCmd.xrayVersion); err != nil {
347342
return xrayManager, cmdResults.AddGeneralError(err, false)
348343
} else {
349344
cmdResults.SetEntitledForJas(entitledForJas)
@@ -354,11 +349,7 @@ func (scanCmd *ScanCommand) initScanCmdResults(cmdType utils.CommandType) (xrayM
354349
return
355350
}
356351

357-
func isEntitledForJas(xrayManager *xrayClient.XrayServicesManager, xrayVersion string, useJas bool) (bool, error) {
358-
if !useJas {
359-
// No jas scans are needed
360-
return false, nil
361-
}
352+
func isEntitledForJas(xrayManager *xrayClient.XrayServicesManager, xrayVersion string) (bool, error) {
362353
return jas.IsEntitledForJas(xrayManager, xrayVersion)
363354
}
364355

@@ -470,6 +461,7 @@ func (scanCmd *ScanCommand) createIndexerHandlerFunc(file *spec.File, cmdResults
470461
if !cmdResults.EntitledForJas {
471462
return
472463
}
464+
473465
module, err := getJasModule(targetResults)
474466
if err != nil {
475467
return targetResults.AddTargetError(fmt.Errorf("%s jas scanning failed with error: %s", scanLogPrefix, err.Error()), false)
@@ -494,17 +486,29 @@ func (scanCmd *ScanCommand) createIndexerHandlerFunc(file *spec.File, cmdResults
494486
log.Debug("Jas scanner was not created, skipping advance security scans...")
495487
return
496488
}
489+
secretsScanType := secrets.SecretsScannerGenericScanType
490+
applicabilityScanType := applicability.ApplicabilityGenericScanScanType
491+
if cmdResults.CmdType == utils.DockerImage || targetResults.Technology == techutils.Docker || targetResults.Technology == techutils.Oci {
492+
log.Debug("Found root component is a docker container")
493+
secretsScanType = secrets.SecretsScannerDockerScanType
494+
applicabilityScanType = applicability.ApplicabilityDockerScanScanType
495+
} else {
496+
_, _, componentType := techutils.SplitComponentId(graph.Id)
497+
log.Debug("Found root component is not a docker container, type is: ", componentType)
498+
}
499+
497500
jasParams := runner.JasRunnerParams{
498501
Runner: jasFileProducerConsumer,
499502
ServerDetails: scanCmd.serverDetails,
500503
Scanner: scanner,
501504
Module: module,
502505
ScansToPerform: utils.GetAllSupportedScans(),
503-
SecretsScanType: secrets.SecretsScannerDockerScanType,
506+
SecretsScanType: secretsScanType,
504507
DirectDependencies: directDepsListFromVulnerabilities(*graphScanResults),
505-
ApplicableScanType: applicability.ApplicabilityDockerScanScanType,
508+
ApplicableScanType: applicabilityScanType,
506509
ScanResults: targetResults,
507510
}
511+
508512
if generalError := runner.AddJasScannersTasks(jasParams); generalError != nil {
509513
return targetResults.AddTargetError(fmt.Errorf("%s failed to add Jas scan tasks: %s", scanLogPrefix, generalError.Error()), false)
510514
}

jas/applicability/applicabilitymanager.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ const (
2121
applicabilityScanCommand = "ca"
2222
applicabilityDocsUrlSuffix = "contextual-analysis"
2323

24-
ApplicabilityScannerType ApplicabilityScanType = "analyze-applicability"
25-
ApplicabilityDockerScanScanType ApplicabilityScanType = "analyze-applicability-docker-scan"
24+
ApplicabilityScannerType ApplicabilityScanType = "analyze-applicability"
25+
ApplicabilityDockerScanScanType ApplicabilityScanType = "analyze-applicability-docker-scan"
26+
ApplicabilityGenericScanScanType ApplicabilityScanType = "analyze-applicability-generic-scan"
2627
)
2728

2829
type ApplicabilityScanType string

jas/secrets/secretsscanner.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ const (
1919
secretsScanCommand = "sec"
2020
secretsDocsUrlSuffix = "secrets"
2121

22-
SecretsScannerType SecretsScanType = "secrets-scan" // #nosec
23-
SecretsScannerDockerScanType SecretsScanType = "secrets-docker-scan" // #nosec
22+
SecretsScannerType SecretsScanType = "secrets-scan" // #nosec
23+
SecretsScannerDockerScanType SecretsScanType = "secrets-docker-scan" // #nosec
24+
SecretsScannerGenericScanType SecretsScanType = "secrets-generic-scan" // #nosec
2425
)
2526

2627
type SecretsScanType string

scans_test.go

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,42 @@ func TestXrayBinaryScanSimpleJson(t *testing.T) {
5656
})
5757
}
5858

59+
func TestXrayBinaryScanJsonDocker(t *testing.T) {
60+
integration.InitScanTest(t, scangraph.GraphScanMinXrayVersion)
61+
output := testXrayBinaryScanJAS(t, string(format.SimpleJson), "xmas.tar", false)
62+
validations.VerifySimpleJsonResults(t, output, validations.ValidationParams{
63+
Total: &validations.TotalCount{Vulnerabilities: 6},
64+
Vulnerabilities: &validations.VulnerabilityCount{
65+
ValidateScan: &validations.ScanCount{Sca: 4, Secrets: 2},
66+
ValidateApplicabilityStatus: &validations.ApplicabilityStatusCount{Applicable: 2, NotApplicable: 1, NotCovered: 1},
67+
},
68+
})
69+
}
70+
71+
func TestXrayBinaryScanJsonGeneric(t *testing.T) {
72+
integration.InitScanTest(t, scangraph.GraphScanMinXrayVersion)
73+
output := testXrayBinaryScanJAS(t, string(format.SimpleJson), "backupfriend-client.tar.gz", false)
74+
validations.VerifySimpleJsonResults(t, output, validations.ValidationParams{
75+
Total: &validations.TotalCount{Vulnerabilities: 4},
76+
Vulnerabilities: &validations.VulnerabilityCount{
77+
ValidateScan: &validations.ScanCount{Sca: 3, Secrets: 1},
78+
ValidateApplicabilityStatus: &validations.ApplicabilityStatusCount{Applicable: 2, Undetermined: 1},
79+
},
80+
})
81+
}
82+
83+
func TestXrayBinaryScanJsonJar(t *testing.T) {
84+
integration.InitScanTest(t, scangraph.GraphScanMinXrayVersion)
85+
output := testXrayBinaryScanJAS(t, string(format.SimpleJson), "student-services-security-0.0.1.jar", false)
86+
validations.VerifySimpleJsonResults(t, output, validations.ValidationParams{
87+
Total: &validations.TotalCount{Vulnerabilities: 41},
88+
Vulnerabilities: &validations.VulnerabilityCount{
89+
ValidateScan: &validations.ScanCount{Sca: 40, Secrets: 1},
90+
ValidateApplicabilityStatus: &validations.ApplicabilityStatusCount{Applicable: 17, NotCovered: 3, NotApplicable: 20},
91+
},
92+
})
93+
}
94+
5995
func TestXrayBinaryScanJsonWithProgress(t *testing.T) {
6096
integration.InitScanTest(t, scangraph.GraphScanMinXrayVersion)
6197
callback := commonTests.MockProgressInitialization()
@@ -94,6 +130,21 @@ func testXrayBinaryScan(t *testing.T, format, policyName, watchName string, erro
94130
return output
95131
}
96132

133+
func testXrayBinaryScanJAS(t *testing.T, format, artifact string, errorExpected bool) string {
134+
tempDirPath, cleanUp := securityTestUtils.CreateTestProjectEnvAndChdir(t, filepath.Join(filepath.FromSlash(securityTests.GetTestResourcesPath()), "projects", "jas-scan"))
135+
defer cleanUp()
136+
137+
binariesPathTemp := filepath.Join(tempDirPath, artifact)
138+
args := []string{"scan", binariesPathTemp, "--format=" + format}
139+
output, err := securityTests.PlatformCli.RunCliCmdWithOutputs(t, args...)
140+
if errorExpected {
141+
assert.Error(t, err)
142+
} else {
143+
assert.NoError(t, err)
144+
}
145+
return output
146+
}
147+
97148
func TestXrayBinaryScanWithBypassArchiveLimits(t *testing.T) {
98149
integration.InitScanTest(t, scan.BypassArchiveLimitsMinXrayVersion)
99150
unsetEnv := clientTestUtils.SetEnvWithCallbackAndAssert(t, "JF_INDEXER_COMPRESS_MAXENTITIES", "10")
@@ -210,12 +261,12 @@ func runAdvancedSecurityDockerScan(t *testing.T, testCli *coreTests.JfrogCli, im
210261
// Run docker scan on image
211262
output := testCli.WithoutCredentials().RunCliCmdWithOutput(t, args...)
212263
if assert.NotEmpty(t, output) {
213-
verifyAdvancedSecurityScanResults(t, output)
264+
verifyAdvancedSecurityScanResults(t, output, true, true)
214265
}
215266
}
216267
}
217268

218-
func verifyAdvancedSecurityScanResults(t *testing.T, content string) {
269+
func verifyAdvancedSecurityScanResults(t *testing.T, content string, isApplicable bool, isSecret bool) {
219270
var results formats.SimpleJsonResults
220271
err := json.Unmarshal([]byte(content), &results)
221272
assert.NoError(t, err)
@@ -227,11 +278,18 @@ func verifyAdvancedSecurityScanResults(t *testing.T, content string) {
227278
break
228279
}
229280
}
230-
assert.True(t, applicableStatusExists)
231281

232-
// Verify that secretes detection succeeded.
233-
assert.NotEqual(t, 0, len(results.SecretsVulnerabilities))
282+
if isApplicable {
283+
assert.True(t, applicableStatusExists)
284+
}
234285

286+
if isSecret {
287+
// Verify that secretes detection succeeded.
288+
assert.NotEqual(t, 0, len(results.SecretsVulnerabilities))
289+
} else {
290+
// Verify that secretes detection succeeded.
291+
assert.Equal(t, 0, len(results.SecretsVulnerabilities))
292+
}
235293
}
236294

237295
// Curation tests
5.03 MB
Binary file not shown.
Binary file not shown.
1.52 MB
Binary file not shown.

utils/jasutils/jasutils.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ const (
3333
type TokenValidationStatus string
3434

3535
type JasScanType string
36+
type JasPackageScanType string
3637

3738
func (jst JasScanType) String() string {
3839
return string(jst)

utils/results/results.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,10 @@ func (rc *ResultContext) HasViolationContext() bool {
6969
type TargetResults struct {
7070
ScanTarget
7171
// All scan results for the target
72-
ScaResults *ScaScanResults `json:"sca_scans,omitempty"`
73-
Sbom Sbom `json:"sbom,omitempty"`
74-
JasResults *JasScansResults `json:"jas_scans,omitempty"`
72+
ScaResults *ScaScanResults `json:"sca_scans,omitempty"`
73+
Sbom Sbom `json:"sbom,omitempty"`
74+
JasResults *JasScansResults `json:"jas_scans,omitempty"`
75+
JasPackageScanType jasutils.JasPackageScanType `json:"jas_package_scan_type,omitempty"`
7576
// Errors that occurred during the scans
7677
Errors []error `json:"errors,omitempty"`
7778
errorsMutex sync.Mutex `json:"-"`

0 commit comments

Comments
 (0)