Skip to content

Commit

Permalink
refactor: Scanning Helm files for iac test fails for --experimental
Browse files Browse the repository at this point in the history
  • Loading branch information
Ilianna Papastefanou committed Apr 6, 2021
1 parent 29be51b commit 3ca490a
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 10 deletions.
7 changes: 4 additions & 3 deletions src/cli/commands/test/iac-local-execution/file-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import { CustomError } from '../../../../lib/errors';
export async function parseFiles(
filesData: IacFileData[],
): Promise<ParsingResults> {
const parsedFiles: Array<IacFileParsed> = [];
const failedFiles: Array<IacFileParseFailure> = [];
const parsedFiles: IacFileParsed[] = [];
const failedFiles: IacFileParseFailure[] = [];
for (const fileData of filesData) {
try {
parsedFiles.push(...tryParseIacFile(fileData));
Expand Down Expand Up @@ -52,11 +52,12 @@ function generateFailedParsedFile(

const TF_PLAN_NAME = 'tf-plan.json';

export function tryParseIacFile(fileData: IacFileData): Array<IacFileParsed> {
export function tryParseIacFile(fileData: IacFileData): IacFileParsed[] {
analytics.add('iac-terraform-plan', false);
switch (fileData.fileType) {
case 'yaml':
case 'yml':
return tryParsingKubernetesFile(fileData);
case 'json':
// TODO: this is a temporary approach for the internal release only
if (path.basename(fileData.filePath) === TF_PLAN_NAME) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,30 @@ import * as YAML from 'js-yaml';
import { CustomError } from '../../../../../lib/errors';
import {
EngineType,
IacFileParsed,
IacFileData,
IaCErrorCodes,
IacFileData,
IacFileParsed,
} from '../types';

const REQUIRED_K8S_FIELDS = ['apiVersion', 'kind', 'metadata'];

export function assertHelmAndThrow(fileData: IacFileData) {
const lines: string[] = fileData.fileContent.split(/\r\n|\r|\n/);

lines.forEach((line) => {
const isHelmFile = line.includes('{{') && line.includes('}}');
if (isHelmFile) {
throw new HelmFileNotSupportedError(fileData.filePath);
}
});
}

export function tryParsingKubernetesFile(
fileData: IacFileData,
): IacFileParsed[] {
let yamlDocuments;

assertHelmAndThrow(fileData);
try {
yamlDocuments = YAML.safeLoadAll(fileData.fileContent);
} catch (e) {
Expand Down Expand Up @@ -44,6 +57,15 @@ class FailedToParseKubernetesYamlError extends CustomError {
this.userMessage = `We were unable to parse the YAML file "${filename}". Please ensure that it contains properly structured YAML`;
}
}

export class HelmFileNotSupportedError extends CustomError {
constructor(filename: string) {
super('Failed to parse Helm file');
this.code = IaCErrorCodes.FailedToParseHelmError;
this.userMessage = `We were unable to parse the YAML file "${filename}" as we currently do not support scanning of Helm files. More information can be found through our documentation:\nhttps://support.snyk.io/hc/en-us/articles/360012429477-Test-your-Kubernetes-files-with-our-CLI-tool`;
}
}

export class MissingRequiredFieldsInKubernetesYamlError extends CustomError {
constructor(filename: string) {
super('Failed to detect Kubernetes file, missing required fields');
Expand Down
1 change: 1 addition & 0 deletions src/cli/commands/test/iac-local-execution/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ export enum IaCErrorCodes {
// kubernetes-parser errors
FailedToParseKubernetesYamlError = 1030,
MissingRequiredFieldsInKubernetesYamlError = 1031,
FailedToParseHelmError = 1032,

// terraform-file-parser errors
FailedToParseTerraformFileError = 1040,
Expand Down
15 changes: 15 additions & 0 deletions test/fixtures/iac/kubernetes/helm-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.app.svc.myapp }}
labels:
app: {{ template "myapp.name" . }}
chart: {{ template "myapp.chart" . }}
release: {{ .Release.Name }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
29 changes: 24 additions & 5 deletions test/jest/unit/iac-unit-tests/file-parser.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import * as fileParser from '../../../../src/cli/commands/test/iac-local-execution/file-parser';
import {
parseFiles,
UnsupportedFileTypeError,
} from '../../../../src/cli/commands/test/iac-local-execution/file-parser';
import * as fileParser from '../../../../src/cli/commands/test/iac-local-execution/file-parser';
import * as k8sParser from '../../../../src/cli/commands/test/iac-local-execution/parsers/kubernetes-parser';
import {
HelmFileNotSupportedError,
MissingRequiredFieldsInKubernetesYamlError,
} from '../../../../src/cli/commands/test/iac-local-execution/parsers/kubernetes-parser';
import {
expectedInvalidK8sFileParsingResult,
expectedKubernetesParsingResult,
Expand All @@ -11,12 +16,14 @@ import {
kubernetesFileDataStub,
terraformFileDataStub,
} from './file-parser.fixtures';
import { MissingRequiredFieldsInKubernetesYamlError } from '../../../../src/cli/commands/test/iac-local-execution/parsers/kubernetes-parser';
import { IacFileData } from '../../../../src/cli/commands/test/iac-local-execution/types';
import { tryParsingKubernetesFile } from '../../../../dist/cli/commands/test/iac-local-execution/parsers/kubernetes-parser';
import { IacFileTypes } from '../../../../dist/lib/iac/constants';
import { UnsupportedError } from 'snyk-nodejs-lockfile-parser/dist/errors';
import * as fileLoader from '../../../../src/cli/commands/test/iac-local-execution/file-loader';
import { FailedToLoadFileError } from '../../../../src/cli/commands/test/iac-local-execution/file-loader';
import {
MissingRequiredFieldsInTerraformPlanError,
tryParsingTerraformPlan,
} from '../../../../src/cli/commands/test/iac-local-execution/parsers/terraform-plan-parser';
import { iacFileDataWithoutResourceChanges } from './terraform-plan-parser.fixtures';

const filesToParse: IacFileData[] = [
kubernetesFileDataStub,
Expand Down Expand Up @@ -63,4 +70,16 @@ describe('parseFiles', () => {

await expect(parseFilesFn).rejects.toThrow(UnsupportedFileTypeError);
});

it('throws an error for a Helm file', async () => {
const helmFileData: IacFileData = {
fileContent: ' {{ something }}',
filePath: 'path/to/file',
fileType: 'yaml',
};

expect(() => tryParsingKubernetesFile(helmFileData)).toThrowError(
'Failed to parse Helm file',
);
});
});
7 changes: 7 additions & 0 deletions test/smoke/spec/iac/snyk_test_local_exec_spec.sh
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ Describe "Snyk iac test --experimental command"
The output should include "We were unable to detect whether the YAML file"
End

It "outputs an error for Helm files"
When run snyk iac test ../fixtures/iac/kubernetes/helm-config.yaml --experimental
The status should be failure
The output should include "We were unable to parse the YAML file"
The output should include "do not support scanning of Helm files"
End

It "outputs the expected text when running with --sarif flag"
When run snyk iac test ../fixtures/iac/kubernetes/pod-privileged.yaml --experimental --sarif
The status should be failure
Expand Down

0 comments on commit 3ca490a

Please sign in to comment.