Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor commands output formats #96

Merged
merged 105 commits into from
Oct 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
105 commits
Select commit Hold shift + click to select a range
a10204d
Refactor commands output formats
attiasas Jun 30, 2024
e1f0fbb
some fixes
attiasas Jun 30, 2024
b7718f6
Merge remote-tracking branch 'upstream/dev' into refactor_output
attiasas Jun 30, 2024
03946e9
more refactor
attiasas Jun 30, 2024
fe6d86d
continue refactor
attiasas Jun 30, 2024
9f129e4
add parsers
attiasas Jun 30, 2024
fd8e025
continue implement
attiasas Jul 1, 2024
5fb51d9
some changes
attiasas Jul 2, 2024
adb3de1
continue implement
attiasas Jul 2, 2024
77b3ab2
finish comp errors
attiasas Jul 3, 2024
da0bfb9
format
attiasas Jul 3, 2024
c47d7fc
Merge remote-tracking branch 'upstream/dev' into refactor_output
attiasas Jul 10, 2024
218797a
format
attiasas Jul 10, 2024
c9c2933
continue refactor for tests
attiasas Jul 14, 2024
1d9ff3e
format
attiasas Jul 14, 2024
382b1cf
some static fixes
attiasas Jul 14, 2024
0d46f4f
more static fix
attiasas Jul 15, 2024
47e7f5f
fix static
attiasas Jul 15, 2024
3c9c41d
fix static
attiasas Jul 15, 2024
2523009
fix race condition
attiasas Jul 15, 2024
b368f1c
start sarif
attiasas Jul 15, 2024
5f6fa7f
Merge remote-tracking branch 'upstream/dev' into refactor_output
attiasas Jul 15, 2024
cb0ff02
fix parallel race
attiasas Jul 15, 2024
8736ca6
fix test data location
attiasas Jul 15, 2024
7eeb1e7
continue implement
attiasas Jul 15, 2024
941d60a
Merge remote-tracking branch 'upstream/dev' into refactor_output
attiasas Jul 15, 2024
18015b6
fix tests
attiasas Jul 15, 2024
7241b86
fix tests
attiasas Jul 16, 2024
2f7f319
fix tests
attiasas Jul 16, 2024
a5c66f0
verify sarif
attiasas Jul 18, 2024
f182e22
Merge remote-tracking branch 'upstream/dev' into refactor_output
attiasas Jul 18, 2024
20f24b4
fix merge
attiasas Jul 18, 2024
f93cfa0
continue validations
attiasas Jul 21, 2024
4be27f0
fix tests
attiasas Jul 21, 2024
2ac4d7b
continue fix tests
attiasas Jul 21, 2024
3a3e059
continue fix tests
attiasas Jul 22, 2024
3f8c1df
update test data
attiasas Jul 23, 2024
9c5eb17
Merge remote-tracking branch 'upstream/dev' into refactor_output
attiasas Jul 23, 2024
bcdf8a0
format
attiasas Jul 23, 2024
19e1577
fix static and tests
attiasas Jul 23, 2024
7704abf
fix static
attiasas Jul 23, 2024
4f8a44e
fix tests and cleanup
attiasas Jul 23, 2024
f201811
fix win test and cleanup
attiasas Jul 23, 2024
c723726
fix tests
attiasas Jul 23, 2024
4ee4bc6
fix tests
attiasas Jul 23, 2024
88ae5e5
try fix win tests
attiasas Jul 23, 2024
e871dbe
try fix win tests
attiasas Jul 23, 2024
cd49770
fix win tests
attiasas Jul 23, 2024
735efb4
try fix tests
attiasas Jul 23, 2024
11da7ef
Merge remote-tracking branch 'upstream/dev' into refactor_output
attiasas Jul 24, 2024
70b74c4
try fix tests
attiasas Jul 24, 2024
1f1235a
Merge remote-tracking branch 'upstream/dev' into refactor_output
attiasas Jul 28, 2024
7a810c1
fix merge and a tech bug
attiasas Jul 28, 2024
8844dd6
try fix tests
attiasas Jul 29, 2024
0844c65
fix
attiasas Jul 29, 2024
ea50014
Merge remote-tracking branch 'upstream/dev' into refactor_output
attiasas Jul 29, 2024
ce719c9
fix static
attiasas Jul 29, 2024
99893f3
Merge remote-tracking branch 'upstream/dev' into refactor_output
attiasas Aug 7, 2024
08d101f
Merge remote-tracking branch 'upstream/dev' into refactor_output
attiasas Sep 5, 2024
3ded757
merge dev
attiasas Sep 9, 2024
944d192
fix tests
attiasas Sep 9, 2024
9448af0
Merge remote-tracking branch 'upstream/dev' into refactor_output
attiasas Sep 9, 2024
38671cc
fix merge
attiasas Sep 9, 2024
272591c
fix static tests
attiasas Sep 9, 2024
ae39323
CR changes
attiasas Sep 10, 2024
3c98706
start add docker tests
attiasas Sep 11, 2024
2840382
fixing bugs adding docker tests
attiasas Sep 15, 2024
00e13c4
Merge remote-tracking branch 'upstream/dev' into refactor_output
attiasas Sep 15, 2024
6c3a32c
fix merge
attiasas Sep 15, 2024
6815d23
format
attiasas Sep 15, 2024
650547f
fix static
attiasas Sep 15, 2024
bc48efa
Merge remote-tracking branch 'upstream/dev' into refactor_output
attiasas Sep 15, 2024
9e20652
merge
attiasas Sep 15, 2024
6d95290
fix conflict
attiasas Sep 15, 2024
a610cf5
Merge remote-tracking branch 'upstream/dev' into refactor_output
attiasas Sep 23, 2024
7952aee
continue merge
attiasas Sep 23, 2024
a3372e1
done fix merge conflicts
attiasas Sep 24, 2024
5689bdb
Merge remote-tracking branch 'upstream/dev' into refactor_output
attiasas Sep 24, 2024
16b9392
continue fix tests
attiasas Sep 24, 2024
7ac5949
continue
attiasas Sep 25, 2024
4c2df26
fix tests
attiasas Sep 26, 2024
ba468e5
Merge remote-tracking branch 'upstream/dev' into refactor_output
attiasas Sep 26, 2024
99b964f
attrib rename
attiasas Sep 26, 2024
92c32fe
Merge remote-tracking branch 'upstream/dev' into refactor_output
attiasas Sep 26, 2024
8358e8d
fix static
attiasas Sep 26, 2024
fc7def7
fix tests
attiasas Sep 26, 2024
3edfa27
Merge remote-tracking branch 'upstream/dev' into refactor_output
attiasas Sep 26, 2024
50cbd47
push log
attiasas Sep 26, 2024
882ec7b
Merge remote-tracking branch 'upstream/dev' into refactor_output
attiasas Sep 29, 2024
b33b31f
cr review finish
attiasas Sep 30, 2024
8b3c1ab
fix tests
attiasas Sep 30, 2024
6c0b4b6
fix tests
attiasas Sep 30, 2024
a8ae841
try debug
attiasas Oct 1, 2024
7b0c1e2
fix texts + cr review
attiasas Oct 1, 2024
fd5a13b
Merge remote-tracking branch 'upstream/dev' into refactor_output
attiasas Oct 1, 2024
d240a31
fix merge
attiasas Oct 1, 2024
511a21d
try debug
attiasas Oct 1, 2024
b5e6931
fix tests
attiasas Oct 1, 2024
3c71a65
add sca run id to sarif result
attiasas Oct 7, 2024
d4dbf93
remove scan id
attiasas Oct 7, 2024
7ecb1be
update AM to 1.9.4
attiasas Oct 7, 2024
dfe804c
Merge remote-tracking branch 'upstream/dev' into refactor_output
attiasas Oct 13, 2024
2f324ee
fix conflicts
attiasas Oct 13, 2024
fa4d95e
Merge remote-tracking branch 'upstream/dev' into refactor_output
attiasas Oct 13, 2024
290a1fe
fix tests
attiasas Oct 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
252 changes: 161 additions & 91 deletions audit_test.go

Large diffs are not rendered by default.

146 changes: 113 additions & 33 deletions commands/audit/audit.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,26 @@ import (
"errors"
"fmt"

"github.com/jfrog/gofrog/log"
jfrogappsconfig "github.com/jfrog/jfrog-apps-config/go"
"github.com/jfrog/jfrog-cli-core/v2/utils/config"
"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
"github.com/jfrog/jfrog-cli-security/commands/audit/sca"
"github.com/jfrog/jfrog-cli-security/jas"
"github.com/jfrog/jfrog-cli-security/jas/applicability"
"github.com/jfrog/jfrog-cli-security/jas/runner"
"github.com/jfrog/jfrog-cli-security/jas/secrets"
"github.com/jfrog/jfrog-cli-security/utils"
"github.com/jfrog/jfrog-cli-security/utils/results"
"github.com/jfrog/jfrog-cli-security/utils/results/output"
"github.com/jfrog/jfrog-cli-security/utils/techutils"
"github.com/jfrog/jfrog-cli-security/utils/xray/scangraph"
"github.com/jfrog/jfrog-cli-security/utils/xsc"
"golang.org/x/exp/slices"

xrayutils "github.com/jfrog/jfrog-cli-security/utils/xray"
clientutils "github.com/jfrog/jfrog-client-go/utils"
"github.com/jfrog/jfrog-client-go/utils/io/fileutils"
"github.com/jfrog/jfrog-client-go/utils/log"
"github.com/jfrog/jfrog-client-go/xray"
"github.com/jfrog/jfrog-client-go/xray/services"
xscservices "github.com/jfrog/jfrog-client-go/xsc/services"
Expand Down Expand Up @@ -130,11 +136,10 @@ func (auditCmd *AuditCommand) Run() (err error) {
}
}
var messages []string
if !auditResults.ExtendedScanResults.EntitledForJas {
messages = []string{coreutils.PrintTitle("The ‘jf audit’ command also supports JFrog Advanced Security features, such as 'Contextual Analysis', 'Secret Detection', 'IaC Scan' and ‘SAST’.\nThis feature isn't enabled on your system. Read more - ") + coreutils.PrintLink("https://jfrog.com/xray/")}
if !auditResults.EntitledForJas {
messages = []string{coreutils.PrintTitle("The ‘jf audit’ command also supports JFrog Advanced Security features, such as 'Contextual Analysis', 'Secret Detection', 'IaC Scan' and ‘SAST’.\nThis feature isn't enabled on your system. Read more - ") + coreutils.PrintLink(utils.JasInfoURL)}
}
if err = utils.NewResultsWriter(auditResults).
SetIsMultipleRootProject(auditResults.IsMultipleProject()).
attiasas marked this conversation as resolved.
Show resolved Hide resolved
if err = output.NewResultsWriter(auditResults).
SetHasViolationContext(auditCmd.HasViolationContext()).
SetIncludeVulnerabilities(auditCmd.IncludeVulnerabilities).
SetIncludeLicenses(auditCmd.IncludeLicenses).
Expand All @@ -146,13 +151,13 @@ func (auditCmd *AuditCommand) Run() (err error) {
return
}

if auditResults.ScansErr != nil {
return auditResults.ScansErr
if err = auditResults.GetErrors(); err != nil {
return
}

// Only in case Xray's context was given (!auditCmd.IncludeVulnerabilities), and the user asked to fail the build accordingly, do so.
if auditCmd.Fail && !auditCmd.IncludeVulnerabilities && utils.CheckIfFailBuild(auditResults.GetScaScansXrayResults()) {
err = utils.NewFailBuildError()
if auditCmd.Fail && !auditCmd.IncludeVulnerabilities && results.CheckIfFailBuild(auditResults.GetScaScansXrayResults()) {
err = results.NewFailBuildError()
}
return
}
Expand All @@ -168,9 +173,8 @@ func (auditCmd *AuditCommand) HasViolationContext() bool {
// 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(utils.SourceCode)
func RunAudit(auditParams *AuditParams) (cmdResults *results.SecurityCommandResults, err error) {
// Prepare
serverDetails, err := auditParams.ServerDetails()
if err != nil {
return
Expand All @@ -182,26 +186,34 @@ func RunAudit(auditParams *AuditParams) (results *utils.Results, err error) {
if err = clientutils.ValidateMinimumVersion(clientutils.Xray, auditParams.xrayVersion, scangraph.GraphScanMinXrayVersion); err != nil {
return
}
results.XrayVersion = auditParams.xrayVersion
results.ExtendedScanResults.EntitledForJas, err = isEntitledForJas(xrayManager, auditParams)
entitledForJas, err := isEntitledForJas(xrayManager, auditParams)
if err != nil {
return
}
results.ExtendedScanResults.SecretValidation = jas.CheckForSecretValidation(xrayManager, auditParams.xrayVersion, slices.Contains(auditParams.AuditBasicParams.ScansToPerform(), utils.SecretTokenValidationScan))
results.MultiScanId = auditParams.commonGraphScanParams.MultiScanId
auditParallelRunner := utils.CreateSecurityParallelRunner(auditParams.threads)
auditParallelRunner.ErrWg.Add(1)
jfrogAppsConfig, err := jas.CreateJFrogAppsConfig(auditParams.workingDirs)
// Initialize Results struct
cmdResults = initCmdResults(
entitledForJas,
jas.CheckForSecretValidation(xrayManager, auditParams.xrayVersion, slices.Contains(auditParams.AuditBasicParams.ScansToPerform(), utils.SecretTokenValidationScan)),
auditParams,
)
jfrogAppsConfig, err := jas.CreateJFrogAppsConfig(cmdResults.GetTargetsPaths())
if err != nil {
return results, fmt.Errorf("failed to create JFrogAppsConfig: %s", err.Error())
return cmdResults, fmt.Errorf("failed to create JFrogAppsConfig: %s", err.Error())
}
// Initialize the parallel runner
auditParallelRunner := utils.CreateSecurityParallelRunner(auditParams.threads)
auditParallelRunner.ErrWg.Add(1)
// Add the JAS scans to the parallel runner
var jasScanner *jas.JasScanner
var jasScanErr error
if jasScanner, jasScanErr = RunJasScans(auditParallelRunner, auditParams, results, jfrogAppsConfig); jasScanErr != nil {
if jasScanner, jasScanErr = RunJasScans(auditParallelRunner, auditParams, cmdResults, jfrogAppsConfig); jasScanErr != nil {
auditParallelRunner.AddErrorToChan(jasScanErr)
}
if auditParams.Progress() != nil {
auditParams.Progress().SetHeadlineMsg("Scanning for issues")
}
// The sca scan doesn't require the analyzer manager, so it can run separately from the analyzer manager download routine.
if scaScanErr := buildDepTreeAndRunScaScan(auditParallelRunner, auditParams, results); scaScanErr != nil {
if scaScanErr := buildDepTreeAndRunScaScan(auditParallelRunner, auditParams, cmdResults); scaScanErr != nil {
// If error to be caught, we add it to the auditParallelRunner error queue and continue. The error need not be returned
_ = createErrorIfPartialResultsDisabled(auditParams, auditParallelRunner, fmt.Sprintf("An error has occurred during SCA scan process. SCA scan is skipped for the following directories: %s.", auditParams.workingDirs), scaScanErr)
}
Expand All @@ -220,12 +232,9 @@ func RunAudit(auditParams *AuditParams) (results *utils.Results, err error) {
go func() {
defer auditParallelRunner.ErrWg.Done()
for e := range auditParallelRunner.ErrorsQueue {
results.ScansErr = errors.Join(results.ScansErr, e)
cmdResults.Error = errors.Join(cmdResults.Error, e)
}
}()
if auditParams.Progress() != nil {
auditParams.Progress().SetHeadlineMsg("Scanning for issues")
}
auditParallelRunner.Runner.Run()
auditParallelRunner.ErrWg.Wait()
return
Expand All @@ -239,8 +248,8 @@ func isEntitledForJas(xrayManager *xray.XrayServicesManager, auditParams *AuditP
return jas.IsEntitledForJas(xrayManager, auditParams.xrayVersion)
}

func RunJasScans(auditParallelRunner *utils.SecurityParallelRunner, auditParams *AuditParams, results *utils.Results, jfrogAppsConfig *jfrogappsconfig.JFrogAppsConfig) (jasScanner *jas.JasScanner, err error) {
if !results.ExtendedScanResults.EntitledForJas {
func RunJasScans(auditParallelRunner *utils.SecurityParallelRunner, auditParams *AuditParams, scanResults *results.SecurityCommandResults, jfrogAppsConfig *jfrogappsconfig.JFrogAppsConfig) (jasScanner *jas.JasScanner, err error) {
if !scanResults.EntitledForJas {
log.Info("Not entitled for JAS, skipping advance security scans...")
return
}
Expand All @@ -249,7 +258,9 @@ func RunJasScans(auditParallelRunner *utils.SecurityParallelRunner, auditParams
err = fmt.Errorf("failed to get server details: %s", err.Error())
return
}
jasScanner, err = jas.CreateJasScanner(jfrogAppsConfig, serverDetails, auditParams.minSeverityFilter, jas.GetAnalyzerManagerXscEnvVars(auditParams.commonGraphScanParams.MultiScanId, results.ExtendedScanResults.SecretValidation, results.GetScaScannedTechnologies()...), auditParams.Exclusions()...)
auditParallelRunner.ResultsMu.Lock()
jasScanner, err = jas.CreateJasScanner(serverDetails, scanResults.SecretValidation, auditParams.minSeverityFilter, jas.GetAnalyzerManagerXscEnvVars(auditParams.commonGraphScanParams.MultiScanId, scanResults.GetTechnologies()...), auditParams.Exclusions()...)
auditParallelRunner.ResultsMu.Unlock()
if err != nil {
err = fmt.Errorf("failed to create jas scanner: %s", err.Error())
return
Expand All @@ -259,26 +270,95 @@ func RunJasScans(auditParallelRunner *utils.SecurityParallelRunner, auditParams
}
auditParallelRunner.JasWg.Add(1)
if _, jasErr := auditParallelRunner.Runner.AddTaskWithError(func(threadId int) error {
return downloadAnalyzerManagerAndRunScanners(auditParallelRunner, jasScanner, results, auditParams, threadId)
return downloadAnalyzerManagerAndRunScanners(auditParallelRunner, scanResults, serverDetails, auditParams, jasScanner, jfrogAppsConfig, threadId)
}, auditParallelRunner.AddErrorToChan); jasErr != nil {
auditParallelRunner.AddErrorToChan(fmt.Errorf("failed to create AM downloading task, skipping JAS scans...: %s", jasErr.Error()))
}
return
}

func downloadAnalyzerManagerAndRunScanners(auditParallelRunner *utils.SecurityParallelRunner, scanner *jas.JasScanner, scanResults *utils.Results, auditParams *AuditParams, threadId int) (err error) {
func downloadAnalyzerManagerAndRunScanners(auditParallelRunner *utils.SecurityParallelRunner, scanResults *results.SecurityCommandResults,
serverDetails *config.ServerDetails, auditParams *AuditParams, scanner *jas.JasScanner, jfrogAppsConfig *jfrogappsconfig.JFrogAppsConfig, threadId int) (err error) {
defer func() {
auditParallelRunner.JasWg.Done()
}()
if err = jas.DownloadAnalyzerManagerIfNeeded(threadId); err != nil {
return fmt.Errorf("%s failed to download analyzer manager: %s", clientutils.GetLogMsgPrefix(threadId, false), err.Error())
}
if err = runner.AddJasScannersTasks(auditParallelRunner, scanResults, auditParams.DirectDependencies(), auditParams.thirdPartyApplicabilityScan, scanner, applicability.ApplicabilityScannerType, secrets.SecretsScannerType, auditParallelRunner.AddErrorToChan, auditParams.ScansToPerform(), auditParams.configProfile, auditParams.scanResultsOutputDir); err != nil {
return fmt.Errorf("%s failed to run JAS scanners: %s", clientutils.GetLogMsgPrefix(threadId, false), err.Error())
// Run JAS scanners for each scan target
for _, scan := range scanResults.Targets {
module := jas.GetModule(scan.Target, jfrogAppsConfig)
if module == nil {
scan.AddError(fmt.Errorf("can't find module for path %s", scan.Target))
continue
}
params := runner.JasRunnerParams{
Runner: auditParallelRunner,
ServerDetails: serverDetails,
Scanner: scanner,
Module: *module,
ConfigProfile: auditParams.configProfile,
ScansToPreform: auditParams.ScansToPerform(),
SecretsScanType: secrets.SecretsScannerType,
DirectDependencies: auditParams.DirectDependencies(),
ThirdPartyApplicabilityScan: auditParams.thirdPartyApplicabilityScan,
ApplicableScanType: applicability.ApplicabilityScannerType,
ScanResults: scan,
TargetOutputDir: auditParams.scanResultsOutputDir,
}
if err = runner.AddJasScannersTasks(params); err != nil {
return fmt.Errorf("%s failed to run JAS scanners: %s", clientutils.GetLogMsgPrefix(threadId, false), err.Error())
}
}
return
}

func initCmdResults(entitledForJas, secretValidation bool, params *AuditParams) (cmdResults *results.SecurityCommandResults) {
cmdResults = results.NewCommandResults(utils.SourceCode, params.xrayVersion, entitledForJas, secretValidation).SetMultiScanId(params.commonGraphScanParams.MultiScanId)
detectScanTargets(cmdResults, params)
if params.IsRecursiveScan() && len(params.workingDirs) == 1 && len(cmdResults.Targets) == 0 {
// No SCA targets were detected, add the root directory as a target for JAS scans.
cmdResults.NewScanResults(results.ScanTarget{Target: params.workingDirs[0]})
}
scanInfo, err := coreutils.GetJsonIndent(cmdResults)
if err != nil {
return
}
log.Info(fmt.Sprintf("Preforming scans on %d targets:\n%s", len(cmdResults.Targets), scanInfo))
return
}

func detectScanTargets(cmdResults *results.SecurityCommandResults, params *AuditParams) {
for _, requestedDirectory := range params.workingDirs {
if !fileutils.IsPathExists(requestedDirectory, false) {
log.Warn("The working directory", requestedDirectory, "doesn't exist. Skipping SCA scan...")
continue
}
// Detect descriptors and technologies in the requested directory.
techToWorkingDirs, err := techutils.DetectTechnologiesDescriptors(requestedDirectory, params.IsRecursiveScan(), params.Technologies(), getRequestedDescriptors(params), sca.GetExcludePattern(params.AuditBasicParams))
if err != nil {
log.Warn("Couldn't detect technologies in", requestedDirectory, "directory.", err.Error())
continue
}
// Create scans to preform
for tech, workingDirs := range techToWorkingDirs {
if tech == techutils.Dotnet {
// We detect Dotnet and Nuget the same way, if one detected so does the other.
// We don't need to scan for both and get duplicate results.
continue
}
if len(workingDirs) == 0 {
// Requested technology (from params) descriptors/indicators were not found, scan only requested directory for this technology.
cmdResults.NewScanResults(results.ScanTarget{Target: requestedDirectory, Technology: tech})
}
for workingDir, descriptors := range workingDirs {
// Add scan for each detected working directory.
cmdResults.NewScanResults(results.ScanTarget{Target: workingDir, Technology: tech}).SetDescriptors(descriptors...)
}
}
}
}

// This function checks if partial results are allowed. If so we log the error and continue.
// If partial results are not allowed and a SecurityParallelRunner is provided we add the error to its error queue and return without an error, since the errors will be later collected from the queue.
// If partial results are not allowed and a SecurityParallelRunner is not provided we return the error.
Expand Down
Loading
Loading