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

feat: SARIF format support for IaC and containers #1384

Merged
merged 1 commit into from
Sep 15, 2020
Merged

Conversation

orkamara
Copy link
Contributor

@orkamara orkamara commented Sep 2, 2020

  • Ready for review
  • Follows CONTRIBUTING rules
  • Reviewed by Snyk internal team

What does this PR do?

Introduces SARIF support for both containers and IaC.
Support for --sarif flag to output SARIF to stdout.
Support for --sarif-file-output to save SARIF results to specified file.

How should this be manually tested?

snyk container test alpine --file=Dockerfile --sarif --sarif-output-file=test-container-sarif.json
snyk iac test file.yaml --sarif --sarif-file-output=test-iac-sarif.json

@RotemS RotemS force-pushed the feat/sarif-support branch 3 times, most recently from ac37eec to 03694e7 Compare September 2, 2020 15:58
@orkamara orkamara force-pushed the feat/sarif-support branch 7 times, most recently from 821a5f3 to 2fa7a29 Compare September 3, 2020 13:33
@RotemS RotemS force-pushed the feat/sarif-support branch 2 times, most recently from cd2618b to 650a062 Compare September 9, 2020 11:58
@RotemS RotemS marked this pull request as ready for review September 9, 2020 13:21
@RotemS RotemS requested a review from a team as a code owner September 9, 2020 13:21
@RotemS RotemS requested a review from a team September 9, 2020 13:21
@RotemS RotemS requested a review from a team as a code owner September 9, 2020 13:21
@ghost ghost requested review from aviadhahami and ekbsnyk September 9, 2020 13:22
Copy link
Contributor

@rontalx rontalx left a comment

Choose a reason for hiding this comment

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

Nice work on this PR! 💪 🚀
Left a few comments

src/cli/commands/test/iac-output.ts Outdated Show resolved Hide resolved
src/cli/commands/test/iac-output.ts Outdated Show resolved Hide resolved
src/cli/commands/test/iac-output.ts Outdated Show resolved Hide resolved
src/cli/commands/test/iac-output.ts Show resolved Hide resolved
src/cli/commands/test/iac-output.ts Outdated Show resolved Hide resolved
src/cli/commands/test/iac-output.ts Outdated Show resolved Hide resolved
src/cli/commands/test/index.ts Outdated Show resolved Hide resolved
src/cli/commands/test/index.ts Outdated Show resolved Hide resolved
@almog27 almog27 self-requested a review September 9, 2020 15:06
@RotemS RotemS force-pushed the feat/sarif-support branch 2 times, most recently from a9d1958 to ef2dc07 Compare September 10, 2020 11:53
@RotemS RotemS requested a review from rontalx September 10, 2020 11:53

test('flags not allowed with --sarif', (t) => {
t.plan(1);
exec(`node ${main} test --sarif --json`, (err, stdout) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Quick note here: we have a --json flag set in our CLI Docker containers. Would that be an issue for your use case?

Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't be, the only problem is if you try to use both --sarif and --json (can't output to stdout two different formats)

Copy link
Contributor

Choose a reason for hiding this comment

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

I meant that you won't be able to run Snyk CLI Docker image to get a SARIF output

package.json Outdated
@@ -61,6 +61,7 @@
"@snyk/lodash": "^4.17.15-patch",
"@snyk/ruby-semver": "2.2.0",
"@snyk/snyk-cocoapods-plugin": "2.5.0",
"@types/sarif": "^2.1.2",
Copy link
Contributor

@JackuB JackuB Sep 10, 2020

Choose a reason for hiding this comment

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

We are usually keeping @types in devDependencies

}

function uppercaseFirstLetter(str: string): string {
return str.charAt(0).toUpperCase() + str.slice(1);
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd recommend using https://lodash.com/docs/4.17.15#upperFirst

Suggested change
return str.charAt(0).toUpperCase() + str.slice(1);
import upperFirst from `lodash/upperFirst`
...
return upperFirst(str);

Copy link
Contributor

Choose a reason for hiding this comment

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

removed that function and replaced

tool.driver.rules?.push({
id: iacIssue.id,
shortDescription: {
text: `${uppercaseFirstLetter(iacIssue.severity)} - ${
Copy link
Contributor

Choose a reason for hiding this comment

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

upperFirst

if (pushedIds.includes(iacIssue.id)) {
return;
}
tool.driver.rules?.push({
Copy link
Contributor

Choose a reason for hiding this comment

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

rules is defined on top, no need for ?

const pushedIds: string[] = [];
iacTestResponse.result.cloudConfigResults.forEach(
(iacIssue: AnnotatedIacIssue) => {
if (pushedIds.includes(iacIssue.id)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Non blocking
I'd suggest swapping the array w/ an object;
This will be lighter on the computational side for when searching previously seen ids

const pushedIds = {};
...
if( pushedIds[iacIssue.id]){
   ...
}
pushedIds[iacIssue.id] = true;

): Sarif.Result[] {
const results: Sarif.Result[] = [];

iacTestResponse.result.cloudConfigResults.forEach(
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd use map here such as:

return iacTestResponse
    .result
    .cloudConfigResults.map(iacIssue => {...})

: stringifiedJsonData;

return {
dataToSend,
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe sarifData?

Also - wouldn't you like to know which handler was called? iac/containers? (returning a type can be useful here)

};

testResult.forEach((testResult) => {
sarifRes.runs.push({
Copy link
Contributor

Choose a reason for hiding this comment

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

another place to use map (if desired) :)

src/cli/commands/test/sarif-output.ts Outdated Show resolved Hide resolved
}
const level = vuln.severity == 'high' ? 'error' : 'warning';
const cve = vuln['identifiers']['CVE'][0];
tool.driver.rules?.push({
Copy link
Contributor

Choose a reason for hiding this comment

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

rules defined on top

Copy link
Contributor

Choose a reason for hiding this comment

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

For some reason my local linter doesn't like that, but trying

Copy link
Contributor

Choose a reason for hiding this comment

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

This definitely not accepted by linter 🤷

return sarifRes;
}

export function getTool(testResult): Sarif.Tool {
Copy link
Contributor

Choose a reason for hiding this comment

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

this is almost a clone of the IaC to SARIF logic. Maybe can be merged?

Copy link
Contributor

Choose a reason for hiding this comment

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

The actual mapping between the snyk test results and sarif is quite different depending on whether it's container or IaC. That's why we did this separately originally. If you think it's necessary, can we do the rest of the changes and leave refactoring for after this PR is merged? We're on a schedule with a planned 3rd party release.

@RotemS RotemS force-pushed the feat/sarif-support branch 8 times, most recently from b674aca to c14f685 Compare September 15, 2020 13:15

if (options.json) {
const {
stdout: dataToSend,
Copy link
Contributor

@rontalx rontalx Sep 15, 2020

Choose a reason for hiding this comment

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

minor:
In this line we are renaming the returned stdout property to dataToSend.

but here:
https://github.com/snyk/snyk/pull/1384/files#diff-84cda4aeafd8ad5236629ac4ec27445cR781
We are renaming dataToSend to the stdout property.

Is this intentional?

Copy link
Contributor

Choose a reason for hiding this comment

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

Went with stdout as per a previous request to make the type itself a bit more understandable. In the original context where it's decided what info to actually show to the user, it seemed personally that dataToSend was more understandable, so left it as it was before. No strong feelings if there are other opinions though.

Copy link
Contributor

Choose a reason for hiding this comment

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

@rontalx I lack to see where we return dataToSend?

@@ -13,6 +13,7 @@ export interface AnnotatedIacIssue {
// Legacy fields from Registry, unused.
name?: string;
from?: string[];
lineNumber?: number;
Copy link
Contributor

Choose a reason for hiding this comment

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

minor:
can you please move this to be above the comment?
// Legacy fields from Registry, unused.

Comment on lines +133 to +149
'`iac test multi-file.yaml --json - no issues`': (params, utils) => async (
t,
) => {
utils.chdirWorkspaces();
let testableObject;
try {
await params.cli.test('iac-kubernetes/multi-file.yaml', {
iac: true,
json: true,
});
t.fail('should have thrown');
} catch (error) {
testableObject = error;
}
const res: any = JSON.parse(testableObject.message);
iacTestJsonAssertions(t, res, null, false);
},
Copy link
Contributor

Choose a reason for hiding this comment

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

minor:
is there any reason behind moving this test?

Copy link
Contributor

Choose a reason for hiding this comment

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

No idea, @orkamara added most of the tests there, might have an answer :)

@@ -7,6 +7,9 @@ import {
import { getSeverityValue } from './formatters';
import { printPath } from './formatters/remediation-based-format-issues';
import { titleCaseText } from './formatters/legacy-format-issue';
import * as Sarif from 'sarif';
Copy link
Contributor

Choose a reason for hiding this comment

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

imo should be sarif

@@ -7,6 +7,9 @@ import {
import { getSeverityValue } from './formatters';
import { printPath } from './formatters/remediation-based-format-issues';
import { titleCaseText } from './formatters/legacy-format-issue';
import * as Sarif from 'sarif';
import { SEVERITY } from '../../../lib/snyk-test/legacy';
import { upperFirst } from 'lodash';
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
import { upperFirst } from 'lodash';
import upperFirst from 'lodash/upperFirst';

prefer module import rather than plucking (smaller bundle size)


if (options.json) {
const {
stdout: dataToSend,
Copy link
Contributor

Choose a reason for hiding this comment

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

@rontalx I lack to see where we return dataToSend?

@github-actions
Copy link
Contributor

github-actions bot commented Sep 15, 2020

Expected release notes (by @RotemS)

features:
SARIF format support for IaC and containers (02e9bf8)

  • I hereby acknowledge these release notes are 🥙 AWESOME 🥙

Copy link
Contributor

@aviadhahami aviadhahami left a comment

Choose a reason for hiding this comment

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

Drive blessing

@RotemS RotemS merged commit c3212af into master Sep 15, 2020
@RotemS RotemS deleted the feat/sarif-support branch September 15, 2020 15:55
@snyksec
Copy link

snyksec commented Sep 15, 2020

🎉 This PR is included in version 1.398.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
7 participants