-
Notifications
You must be signed in to change notification settings - Fork 534
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
Conversation
ac37eec
to
03694e7
Compare
821a5f3
to
2fa7a29
Compare
cd2618b
to
650a062
Compare
There was a problem hiding this 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
a9d1958
to
ef2dc07
Compare
ef2dc07
to
5f44a7c
Compare
|
||
test('flags not allowed with --sarif', (t) => { | ||
t.plan(1); | ||
exec(`node ${main} test --sarif --json`, (err, stdout) => { |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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", |
There was a problem hiding this comment.
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
5f44a7c
to
d686529
Compare
src/cli/commands/test/iac-output.ts
Outdated
} | ||
|
||
function uppercaseFirstLetter(str: string): string { | ||
return str.charAt(0).toUpperCase() + str.slice(1); |
There was a problem hiding this comment.
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
return str.charAt(0).toUpperCase() + str.slice(1); | |
import upperFirst from `lodash/upperFirst` | |
... | |
return upperFirst(str); |
There was a problem hiding this comment.
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
src/cli/commands/test/iac-output.ts
Outdated
tool.driver.rules?.push({ | ||
id: iacIssue.id, | ||
shortDescription: { | ||
text: `${uppercaseFirstLetter(iacIssue.severity)} - ${ |
There was a problem hiding this comment.
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({ |
There was a problem hiding this comment.
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 ?
src/cli/commands/test/iac-output.ts
Outdated
const pushedIds: string[] = []; | ||
iacTestResponse.result.cloudConfigResults.forEach( | ||
(iacIssue: AnnotatedIacIssue) => { | ||
if (pushedIds.includes(iacIssue.id)) { |
There was a problem hiding this comment.
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;
src/cli/commands/test/iac-output.ts
Outdated
): Sarif.Result[] { | ||
const results: Sarif.Result[] = []; | ||
|
||
iacTestResponse.result.cloudConfigResults.forEach( |
There was a problem hiding this comment.
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 => {...})
src/cli/commands/test/index.ts
Outdated
: stringifiedJsonData; | ||
|
||
return { | ||
dataToSend, |
There was a problem hiding this comment.
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({ |
There was a problem hiding this comment.
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) :)
} | ||
const level = vuln.severity == 'high' ? 'error' : 'warning'; | ||
const cve = vuln['identifiers']['CVE'][0]; | ||
tool.driver.rules?.push({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rules
defined on top
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
b674aca
to
c14f685
Compare
|
||
if (options.json) { | ||
const { | ||
stdout: dataToSend, |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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.
'`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); | ||
}, |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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 :)
src/cli/commands/test/iac-output.ts
Outdated
@@ -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'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
imo should be sarif
src/cli/commands/test/iac-output.ts
Outdated
@@ -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'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
import { upperFirst } from 'lodash'; | |
import upperFirst from 'lodash/upperFirst'; |
prefer module import rather than plucking (smaller bundle size)
|
||
if (options.json) { | ||
const { | ||
stdout: dataToSend, |
There was a problem hiding this comment.
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
?
c14f685
to
02e9bf8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Drive blessing
🎉 This PR is included in version 1.398.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
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