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

Add Violations support for JAS scanners #241

Open
wants to merge 132 commits into
base: dev
Choose a base branch
from

Conversation

eranturgeman
Copy link
Contributor

@eranturgeman eranturgeman commented Nov 19, 2024

  • The pull request is targeting the dev branch.
  • The code has been validated to compile successfully by running go vet ./....
  • The code has been formatted properly using go fmt ./....
  • All static analysis checks passed.
  • All tests have passed. If this feature is not already covered by the tests, new tests have been added.
  • Updated the Contributing page / ReadMe page / CI Workflow files if needed.
  • All changes are detailed at the description. if not already covered at JFrog Documentation, new documentation have been added.

Depends on:

Add Support for JAS violations

1. Allow generating JAS violations in the scan by providing watch, GitRepositoryKey, or project attributes.

  • New violation resource GitRepositoryKey: the http/https git clone url of the repository the code related to. (The actual expected value is converted by removing the protocol)
  • Passing the violation context (new and old) variables to Xray (SCA scan) and to the analyzerManager (JAS scans)

2. Generating violations in all output formats (adding attributes to tables/structs where needed)

3. Violations should also be generated for binary scans that support JAS (passing the project key to the analyzerManager)

4. In Frogbot,GitRepositoryKey is always passed to the command, this means the user will start to see only violations and not vulnerabilities as the default behavior without supplying any arguments, to avoid breaking:

  • If audit command is supplied with GitRepositoryKey we will fetch the active watches on this resource, if non exists we will show vulnerabilities (only if the user did not request any other params like watches \ project key \ repo path...)

Additional changes

  • Adds a resultsContext struct to replace commonGraphScanParams to hold and handle all the attributes that can be used to generate results (watches, project key, git repo ....)
  • Fix Typos found in the repository
  • Adds an annotation for each sub-scan about its status: ScanResult[T interface{}].StatusCode (not performed = nil, completed = 0, failed != 0)
  • Improve validations, adding an option to test more specific counts, simplify tests in convertor_test.go
  • Bug Fix - display violations in binary scans (jf scan / jf docker scan) when --repo-path is present
  • Add project key tests when passing: JFROG_SECURITY_CLI_TESTS_JFROG_PLATFORM_PROJECT_KEY

…dded the new parsed violations results to ApplicabilityScanManager.
…ew parsed violations results to IacScanManager.
…new parsed violations results to SastScanManager.
…e new parsed violations results to SecretScanManager.
@eranturgeman eranturgeman marked this pull request as draft November 19, 2024 10:48
@eranturgeman eranturgeman added the new feature Automatically generated release notes label Nov 19, 2024
// Parse parameters for the SCA result
type scaParseParams struct {
CmdType utils.CommandType
IssueId, Summary, MarkdownDescription, CveScore, ImpactedPackagesName, ImpactedPackagesVersion string
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
IssueId, Summary, MarkdownDescription, CveScore, ImpactedPackagesName, ImpactedPackagesVersion string
IssueId string
Summary string
MarkdownDescription string
CveScore string
ImpactedPackagesName string
ImpactedPackagesVersion string

scaCurrentRun *sarif.Run
currentTarget results.ScanTarget
parsedScaKeys *datastructures.Set[string]
currentTarget *currentTargetState
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'd change the name here to currentTargetState so we will not have a mixup with currentTarget inside currentTargetState

if err = sc.parseScaViolations(target, scaResponse, applicableScan...); err != nil {
return
}
return
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: I remomber we said that we can have both vulnerabilities and violations together. should we take out this return or is it not possible in here?

assert.Equal(t, "[CVE-2022-1234] loadsh 1.4.1", getScaVulnerabilitySarifHeadline("loadsh", "1.4.1", "CVE-2022-1234"))
assert.NotEqual(t, "[CVE-2022-1234] comp 1.4.1", getScaVulnerabilitySarifHeadline("comp", "1.2.1", "CVE-2022-1234"))
assert.Equal(t, "[CVE-2022-1234] loadsh 1.4.1", getScaVulnerabilitySarifHeadline("loadsh", "1.4.1", "CVE-2022-1234", ""))
assert.NotEqual(t, "[CVE-2022-1234] comp 1.4.1", getScaVulnerabilitySarifHeadline("comp", "1.2.1", "CVE-2022-1234", ""))
Copy link
Contributor Author

@eranturgeman eranturgeman Dec 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also add a testcase for a watch?

sjc.current.Statuses.ApplicabilityStatusCode = &applicableScan[i].StatusCode
}
}
if violations {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we have both violations and vulnerabilities (includeAllVulnerabilities)

return func(vulnerability services.Vulnerability, cves []formats.CveRow, applicabilityStatus jasutils.ApplicabilityStatus, severity severityutils.Severity, impactedPackagesName, impactedPackagesVersion, impactedPackagesType string, fixedVersion []string, directComponents []formats.ComponentRow, impactPaths [][]formats.ComponentRow) error {
tech := target.Technology
if tech == "" {
tech = techutils.Technology(impactedPackagesType)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is impactedPackagesType always have a value?

func (sc *CmdResultsSummaryConverter) ParseViolations(target results.ScanTarget, scaResponse services.ScanResponse, applicabilityRuns ...*sarif.Run) (err error) {
func (sc *CmdResultsSummaryConverter) ParseScaIssues(target results.ScanTarget, violations bool, scaResponse results.ScanResult[services.ScanResponse], applicableScan ...results.ScanResult[[]*sarif.Run]) (err error) {
if violations {
return sc.parseScaViolations(target, scaResponse, applicableScan...)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as before - can we have both vuln and violations?

@@ -221,77 +249,124 @@ func getCveIds(cves []formats.CveRow, issueId string) []string {
return ids
}

func (sc *CmdResultsSummaryConverter) ParseLicenses(target results.ScanTarget, licenses []services.License) (err error) {
func (sc *CmdResultsSummaryConverter) ParseLicenses(target results.ScanTarget, scaResponse results.ScanResult[services.ScanResponse]) (err error) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
func (sc *CmdResultsSummaryConverter) ParseLicenses(target results.ScanTarget, scaResponse results.ScanResult[services.ScanResponse]) (err error) {
func (sc *CmdResultsSummaryConverter) ParseLicenses(_ results.ScanTarget, _ results.ScanResult[services.ScanResponse]) (err error) {

}

func (sc *CmdResultsSummaryConverter) getJasHandler(scanType jasutils.JasScanType) results.ParseJasFunc {
func (sc *CmdResultsSummaryConverter) getJasHandler(scanType jasutils.JasScanType, violations bool) results.ParseJasFunc {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd add a description about what exactly this handler is doing. it seems that it counts and returns a map with counts of SOMETHING but it is unclear what

return func(run *sarif.Run, rule *sarif.ReportingDescriptor, severity severityutils.Severity, result *sarif.Result, location *sarif.Location) (err error) {
if location == nil {
// Only count the issue if it has a location
return
}
// Get the scanType count
// Get the scanType count and status
resultStatus := formats.NoStatus
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what scanType != Secrets, resultsStatus == NoStatus == ""
it means we enter the map an empty key.
This can be easily overrided by mistake, and anyway it might be best to set NoStatus with some actual non-empty value for debugs and better comprehansion later on

}
if count == nil {
return
}
// PrepareJasIssues calls the handler for each issue (location)
// Calls the handler for each issue (location)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont understand what exactly we are calling here. we are only setting the map with values and returning this handler function

// Set git repo key and check if it has any watches defined in the platform.
context.GitRepoHttpsCloneUrl = gitRepoHttpsCloneUrl
if len(context.PlatformWatches.GitRepositoryWatches) == 0 && len(watches) == 0 && projectKey == "" {
log.Debug(fmt.Sprintf("Git repo key was provided (%s) but no watches were defined in the platform. ignoring git repo key...", context.GitRepoHttpsCloneUrl))
Copy link
Contributor

@orz25 orz25 Dec 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the log should be something like:
"No watches were found in the platform for the given git repo key (%s), and no watches were given by the user (using watches or project flags). Calculating vulnerabilities..."

return
}

// If the user requested to include vulnerabilities, or if the user didn't provide any watches, project key, artifactory repo path or git repo key, we should include vulnerabilities.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the comment here should be:
"If the user requested to include vulnerabilities, or if the user didn't provide any watches, project key, artifactory repo path or no watches configured on the given git repo key, we should include vulnerabilities"

type ResultContext struct {
// If watches are provided, the scan will be performed only with the provided watches.
Watches []string `json:"watches,omitempty"`
// (Resource) If repo_path is provided, the scan will be performed on the repository's project watches.
Copy link
Contributor

@orz25 orz25 Dec 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment should be:
(Resource) If repo_path is provided, the scan will be performed on the repository's watches.

}
}

func CreateTestGitRepoWatch(t *testing.T, policyName, watchName string, gitResources ...string) (string, func()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the name of the function should be different since you can create a watch with git repository or with build type.
Maby we should call it CreateWatchForTests?

@attiasas attiasas added the safe to test Approve running integration tests on a pull request label Dec 26, 2024
@github-actions github-actions bot removed the safe to test Approve running integration tests on a pull request label Dec 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
new feature Automatically generated release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants