Skip to content

Commit

Permalink
refactor: Add assertIaCOptionsFlag()
Browse files Browse the repository at this point in the history
  • Loading branch information
aron committed Mar 23, 2021
1 parent 2a6b3a8 commit d5e1114
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { CustomError } from '../../../../lib/errors';
import { IaCTestOptions } from '../../../../lib/types';
import { args } from '../../../args';

const keys: (keyof IaCTestOptions)[] = [
'debug',
'insecure',
'debug',
'experimental',
'detectionDepth',
'severityThreshold',
'json',
'sarif',
'json-file-output',
'sarif-file-output',
'v',
'version',
'h',
'help',
'q',
'quiet',
];
const allowed = new Set<string>(keys);

function camelcaseToDash(key: string) {
return key.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase());
}

class FlagError extends CustomError {
constructor(key) {
const dashes = key.length === 1 ? '-' : '--';
const flag = camelcaseToDash(key);
const msg = `Unsupported flag "${dashes}${flag}" provided. Run snyk iac test --help for supported flags.`;
super(msg);
this.userMessage = msg;
}
}

/**
* Validates the command line flags passed to the snyk iac test
* command. The current argument parsing is very permissive and
* allows unknown flags to be provided without valdiation.
*
* For snyk iac we need to explictly validate the flags to avoid
* misconfigurations and typos. For example, if the --experimental
* flag were to be mis-spelled we would end up sending the client
* data to our backend rather than running it locally as intended.
* @param argv command line args passed to the process
*/
export function assertIaCOptionsFlags(argv: string[]) {
// We process the process.argv so we don't get default values.
const parsed = args(argv);
for (const key of Object.keys(parsed.options)) {
// The _ property is a special case that contains non
// flag strings passed to the command line (usually files)
// and `iac` is the command provided.
if (key !== '_' && key !== 'iac' && !allowed.has(key)) {
throw new FlagError(key);
}
}
}
10 changes: 9 additions & 1 deletion src/cli/commands/test/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import { generateSnykTestError } from './generate-snyk-test-error';
import { validateTestOptions } from './validate-test-options';
import { setDefaultTestOptions } from './set-default-test-options';
import { processCommandArgs } from '../process-command-args';
import { assertIaCOptionsFlags } from './iac-local-execution/assert-iac-options-flag';

const debug = Debug('snyk-test');
const SEPARATOR = '\n-------------------------------------------------------\n';
Expand Down Expand Up @@ -95,7 +96,14 @@ async function test(...args: MethodArgs): Promise<TestCommandResult> {
let res: (TestResult | TestResult[]) | Error;

try {
if (options.iac && options.experimental) {
if (options.iac) {
// Ensure that all flags are correct. We do this to ensure that the
// caller doesn't accidentally mistype --experimental and send their
// configuration files to our backend by accident.
assertIaCOptionsFlags(process.argv);
}

if (options.iac && testOpts.experimental) {
// this path is an experimental feature feature for IaC which does issue scanning locally without sending files to our Backend servers.
// once ready for GA, it is aimed to deprecate our remote-processing model, so IaC file scanning in the CLI is done locally.
res = await iacLocalExecution.test(path, testOpts);
Expand Down
5 changes: 2 additions & 3 deletions test/acceptance/cli-args.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,8 @@ test('snyk test command should fail when iac --file is specified', (t) => {
}
t.match(
stdout.trim(),
'Not a recognised option, did you mean "snyk iac test ./test/acceptance/workspaces/iac-kubernetes/multi-file.yaml"? ' +
'Check other options by running snyk iac --help',
'correct error output',
'Unsupported flag',
'failed with Unsupported flag error',
);
},
);
Expand Down
48 changes: 48 additions & 0 deletions test/iac-unit-tests/assert-iac-options-flag.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { IaCTestOptions } from '../../src/lib/types';
import { assertIaCOptionsFlags } from '../../src/cli/commands/test/iac-local-execution/assert-iac-options-flag';

describe('assertIaCOptionsFlags()', () => {
const command = ['node', 'cli', 'iac', 'test'];
const files = ['input.tf'];

it('accepts all command line flags accepted by the iac command', () => {
const options = [
'--debug',
'--insecure',
'--experimental',
'--detection-depth',
'--severity-threshold',
'--json',
'--sarif',
'--json-file-output',
'--sarif-file-output',
'-v',
'--version',
'-h',
'--help',
'-q',
'--quiet',
];
expect(() =>
assertIaCOptionsFlags([...command, ...options, ...files]),
).not.toThrow();
});

it('accepts an empty options object', () => {
expect(() => assertIaCOptionsFlags([...command, ...files])).not.toThrow();
});

it('throws an error if an unexpected flag is present', () => {
const options = ['--project-name'];
expect(() =>
assertIaCOptionsFlags([...command, ...options, ...files]),
).toThrow();
});

it('throws an error if a flag contains a typo', () => {
const options = ['--experimenta'];
expect(() =>
assertIaCOptionsFlags([...command, ...options, ...files]),
).toThrow();
});
});
8 changes: 8 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 @@ -6,6 +6,14 @@ Describe "Snyk iac test --experimental command"
Before snyk_login
After snyk_logout

Describe "basic usage"
It "outputs an error if the --experimental flag is mistyped"
When run snyk iac test ../fixtures/iac/kubernetes/pod-invalid.yaml --experimentl
The status should be failure
The output should include "Unsupported flag"
End
End

Describe "logging regression tests"
It "does not include file content in analytics logs"
# Run with the -d flag on directory to output network requests and analytics data.
Expand Down

0 comments on commit d5e1114

Please sign in to comment.