diff --git a/src/cli/commands/test/iac-local-execution/extract-line-number.ts b/src/cli/commands/test/iac-local-execution/extract-line-number.ts index c273815ea07..dd4e75feaa5 100644 --- a/src/cli/commands/test/iac-local-execution/extract-line-number.ts +++ b/src/cli/commands/test/iac-local-execution/extract-line-number.ts @@ -1,4 +1,4 @@ -import { IaCErrorCodes, IacFileScanResult, PolicyMetadata } from './types'; +import { IaCErrorCodes } from './types'; import { CustomError } from '../../../../lib/errors'; import { CloudConfigFileTypes, @@ -25,14 +25,15 @@ function getFileTypeForLineNumber(fileType: string): CloudConfigFileTypes { } export function extractLineNumber( - scanResult: IacFileScanResult, - policy: PolicyMetadata, + fileContent: string, + fileType: string, + cloudConfigPath: string[], ): number { try { return issuesToLineNumbers( - scanResult.fileContent, - getFileTypeForLineNumber(scanResult.fileType), - policy.msg.split('.'), // parser defaults to docId:0 and checks for the rest of the path + fileContent, + getFileTypeForLineNumber(fileType), + cloudConfigPath, ); } catch { const err = new FailedToExtractLineNumberError(); diff --git a/src/cli/commands/test/iac-local-execution/results-formatter.ts b/src/cli/commands/test/iac-local-execution/results-formatter.ts index 0aa33be5dd6..92dc80cc1bc 100644 --- a/src/cli/commands/test/iac-local-execution/results-formatter.ts +++ b/src/cli/commands/test/iac-local-execution/results-formatter.ts @@ -23,11 +23,18 @@ export function formatScanResults( meta: TestMeta, ): FormattedResult[] { try { - // Relevant only for multi-doc yaml files - const scannedResultsGroupedByDocId = groupMultiDocResults(scanResults); - return scannedResultsGroupedByDocId.map((iacScanResult) => - formatScanResult(iacScanResult, meta, options), - ); + const groupedByFile = scanResults.reduce((memo, scanResult) => { + const res = formatScanResult(scanResult, meta, options); + if (memo[scanResult.filePath]) { + memo[scanResult.filePath].result.cloudConfigResults.push( + ...res.result.cloudConfigResults, + ); + } else { + memo[scanResult.filePath] = res; + } + return memo; + }, {} as { [key: string]: FormattedResult }); + return Object.values(groupedByFile); } catch (e) { throw new FailedToFormatResults(); } @@ -48,7 +55,7 @@ function formatScanResult( const formattedIssues = scanResult.violatedPolicies.map((policy) => { const cloudConfigPath = scanResult.docId !== undefined - ? [`[DocId:${scanResult.docId}]`].concat(policy.msg.split('.')) + ? [`[DocId: ${scanResult.docId}]`].concat(policy.msg.split('.')) : policy.msg.split('.'); const flagsRequiringLineNumber = [ @@ -61,7 +68,11 @@ function formatScanResult( (flag) => options[flag], ); const lineNumber: number = shouldExtractLineNumber - ? extractLineNumber(scanResult, policy) + ? extractLineNumber( + scanResult.fileContent, + scanResult.fileType, + cloudConfigPath, + ) : -1; return { @@ -145,24 +156,6 @@ function computePaths( }; } -function groupMultiDocResults( - scanResults: IacFileScanResult[], -): IacFileScanResult[] { - const groupedData = scanResults.reduce((memo, result) => { - if (memo[result.filePath]) { - memo[result.filePath].violatedPolicies = memo[ - result.filePath - ].violatedPolicies.concat(result.violatedPolicies); - } else { - memo[result.filePath] = result; - } - - return memo; - }, {} as IacFileScanResult); - - return Object.values(groupedData); -} - export function filterPoliciesBySeverity( violatedPolicies: PolicyMetadata[], severityThreshold?: SEVERITY, diff --git a/test/jest/unit/iac-unit-tests/results-formatter.fixtures.ts b/test/jest/unit/iac-unit-tests/results-formatter.fixtures.ts index 5a63518437f..b8156d3284f 100644 --- a/test/jest/unit/iac-unit-tests/results-formatter.fixtures.ts +++ b/test/jest/unit/iac-unit-tests/results-formatter.fixtures.ts @@ -28,7 +28,6 @@ export const policyStub: PolicyMetadata = { subType: 'Deployment', title: 'Container is running in privileged mode', type: 'k8s', - documentation: 'https://snyk.io/security-rules/SNYK-CC-K8S-2', }; const anotherPolicyStub: PolicyMetadata = { @@ -38,6 +37,12 @@ const anotherPolicyStub: PolicyMetadata = { publicId: 'SNYK-CC-K8S-2', }; +const yetAnotherPolicyStub: PolicyMetadata = { + ...anotherPolicyStub, + id: '3', + publicId: 'SNYK-CC-K8S-3', +}; + const relativeFilePath = 'dont-care.yaml'; const absoluteFilePath = path.resolve(relativeFilePath, '.'); @@ -63,6 +68,16 @@ export function generateScanResults(): Array { filePath: relativeFilePath, fileType: 'yaml', }, + { + violatedPolicies: [{ ...yetAnotherPolicyStub }], + jsonContent: { dontCare: null }, + docId: 1, + projectType: IacProjectType.K8S, + engineType: EngineType.Kubernetes, + fileContent: 'dont-care', + filePath: relativeFilePath, + fileType: 'yaml', + }, ]; } @@ -80,7 +95,7 @@ export function generateCloudConfigResults( ...anotherPolicyStub, id: anotherPolicyStub.publicId, name: anotherPolicyStub.title, - cloudConfigPath: ['[DocId:0]'].concat(anotherPolicyStub.msg.split('.')), + cloudConfigPath: ['[DocId: 0]'].concat(anotherPolicyStub.msg.split('.')), isIgnored: false, iacDescription: { issue: anotherPolicyStub.issue, @@ -89,7 +104,24 @@ export function generateCloudConfigResults( }, severity: anotherPolicyStub.severity, lineNumber: withLineNumber ? 3 : -1, - documentation: anotherPolicyStub.documentation, + documentation: 'https://snyk.io/security-rules/SNYK-CC-K8S-2', + }, + { + ...yetAnotherPolicyStub, + id: yetAnotherPolicyStub.publicId, + name: yetAnotherPolicyStub.title, + cloudConfigPath: ['[DocId: 1]'].concat( + yetAnotherPolicyStub.msg.split('.'), + ), + isIgnored: false, + iacDescription: { + issue: yetAnotherPolicyStub.issue, + impact: yetAnotherPolicyStub.impact, + resolve: yetAnotherPolicyStub.resolve, + }, + severity: yetAnotherPolicyStub.severity, + lineNumber: withLineNumber ? 3 : -1, + documentation: 'https://snyk.io/security-rules/SNYK-CC-K8S-3', }, ]; }