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

IaC local execution experimental release #1 #1601

Merged
merged 1 commit into from
Feb 3, 2021

Conversation

rontalx
Copy link
Contributor

@rontalx rontalx commented Jan 31, 2021

What does this PR do?

This PR adds a new --experimental flag to be used with snyk iac test.
It is part of a wider project called Local Execution.
It adds new logic which does issue scanning locally with a provided .wasm file that will be manually given to Snykers for a dog-fooding release.
This is intentionally not exposed yet under --help.
This flag currently supports the following functionality:

  • Single K8s file scanning
  • Sarif & JSON support
  • Severity threshold support
  • Yaml MultiDoc support

It does not support yet:

  • TF Scanning
  • Directory Support
  • Issue to Line Number support

Feb-02-2021 12-14-49

Running Locally

In order to run locally, checkout the branch, build and run the local built version.
make sure to have a folder called .iac-data in your CWD where you're running the CLI from, and have the policy.wasm & data.json files in it (can be found in the attachments of: https://snyksec.atlassian.net/browse/CC-601)

snyk iac test ./k8s-configs/multi-file.yaml --experimental

TODO

  • Adding E2E integration tests. (WIP)

@github-actions
Copy link
Contributor

github-actions bot commented Jan 31, 2021

Warnings
⚠️

Looks like you added a new Tap test. Consider making it a Jest test instead. See files like test/*.spec.ts for examples. Files found:

  • test/smoke/.iac-data/data.json
  • test/smoke/.iac-data/policy.wasm
  • test/smoke/spec/iac/snyk_test_local_exec_spec.sh
Messages
📖 You are modifying something in test/smoke directory, yet you are not on the branch starting with smoke/. You can prefix your branch with smoke/ and Smoke tests will trigger for this PR.

Generated by 🚫 dangerJS against f8bd3f3

@rontalx rontalx force-pushed the feat/iac-experimental-local-exec branch 5 times, most recently from 067a821 to 913c536 Compare February 1, 2021 16:52
@rontalx rontalx changed the title feat: iac experimental test - single k8s file Iac local execution experimental release #1 Feb 2, 2021
@rontalx rontalx changed the title Iac local execution experimental release #1 IaC local execution experimental release #1 Feb 2, 2021
@rontalx rontalx marked this pull request as ready for review February 2, 2021 10:20
@rontalx rontalx requested review from a team as code owners February 2, 2021 10:20
@rontalx rontalx requested a review from a team February 2, 2021 10:29
@rontalx rontalx force-pushed the feat/iac-experimental-local-exec branch from 913c536 to 806b5e6 Compare February 2, 2021 10:34
package.json Outdated Show resolved Hide resolved
@rontalx rontalx force-pushed the feat/iac-experimental-local-exec branch 4 times, most recently from fb7cad4 to 51e3e76 Compare February 2, 2021 14:20
package.json Outdated Show resolved Hide resolved
Copy link
Contributor

@aron aron left a comment

Choose a reason for hiding this comment

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

👏 This looks great from my side. Only high level comments I have is that we should better document the entry-point in index.ts to be clear about what this new code path is and that the current code makes many uses of the term "legacy" but nowhere do we say what is legacy or why.


const readFileContentsAsync = util.promisify(fs.readFile);

export default async function legacyWrapper(pathToScan: string, options) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this a legacy wrapper? What are legacy results? Can we add types for options and the return value?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

maybe the naming is inaccurate...
I didn't want the old structure and types to dictate how we re-build the new experience.
So this basically just does some "adapter" logic for the results to "plug&play" with the rest of the CLI, which made it easier to achieve lots of extra functionality like the --json & --sarif support.
got ideas for better naming?

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh I see, yes let's avoid legacy as the rest of the CLI will continue to use it. How about we refer to the output of this function as the "cli results" and the legacy-adapter.ts as the cli-results-formatter with a comment about how it takes the internal data model and formats it for consumption by the wider snyk cli helpers.

We can just call this function execute() I think or test() with a comment above to explain why it's doing the formatting.

Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed all use of legacy and renamed.

}

return [
{ filePath: pathToScan, fileType: getFileType(pathToScan) as IacFileTypes },
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we avoid this cast? Or document why it is needed.

docId: yamlDocuments.length > 1 ? docId : undefined,
});
} else {
throw new Error('Invalid K8s File!');
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we include the missing fields here to help with debugging.

Copy link
Contributor

Choose a reason for hiding this comment

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

If we throw in one of the iterations, are we ok w/ throwing away all the process?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@aviadatsnyk
for now yes, as it supports a single file scan.
when we add directory support (upcoming follow-up work), probably partial results are the right approach, which is also how it works now if I remember correctly..
Anyway, ones of our goal along this migration to the local-exec model, is to align with the experience we currently have today for the iac remote-processing cli flow.

src/cli/commands/test/iac-local-execution/index.ts Outdated Show resolved Hide resolved
src/cli/commands/test/iac-local-execution/policy-engine.ts Outdated Show resolved Hide resolved
src/cli/commands/test/index.ts Show resolved Hide resolved
@rontalx rontalx force-pushed the feat/iac-experimental-local-exec branch 2 times, most recently from c91706d to 6ef4f48 Compare February 2, 2021 17:02
Copy link
Contributor

@aron aron 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, very excited to see this used internally.

src/cli/commands/test/iac-local-execution/index.ts Outdated Show resolved Hide resolved
src/cli/commands/test/iac-local-execution/index.ts Outdated Show resolved Hide resolved
src/cli/commands/test/index.ts Outdated Show resolved Hide resolved
src/cli/commands/test/iac-local-execution/policy-engine.ts Outdated Show resolved Hide resolved
src/cli/commands/test/iac-local-execution/index.ts Outdated Show resolved Hide resolved
// }
// }

function iacLocalFileScanToFormattedResult(
Copy link
Contributor

Choose a reason for hiding this comment

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

Should return a TestResult type (defined in src/lib/snyk-test/legacy.ts).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

absolutely correct, but for now adding a TODO on these as it's a typing rabbit-hole due to lack of accurate typing down the road in the rest of the CLI..

// CloudConfigFileTypes,
// } from '@snyk/cloud-config-parser';

export function formatResults(
Copy link
Contributor

Choose a reason for hiding this comment

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

Should return a TestResult[] type (defined in src/lib/snyk-test/legacy.ts).

src/lib/snyk-test/common.ts Show resolved Hide resolved
src/cli/commands/test/iac-local-execution/index.ts Outdated Show resolved Hide resolved
const fileDataToScan = await parseFileContentsForPolicyEngine(
filePathsToScan,
);
const scanResults = await policyEngine.scanFiles(fileDataToScan);
Copy link

Choose a reason for hiding this comment

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

maybe worth align this with the evaluate of CCPE (I saw that there is an internal evaluate function there - but maybe there it should be evaluateData or something similar)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

will consider that for next release.
although I don't want to have our old types & terminology restrict us here, as it's an opportunity to rethink naming as well.

@@ -58,6 +58,7 @@
"author": "snyk.io",
"license": "Apache-2.0",
"dependencies": {
"@open-policy-agent/opa-wasm": "git+https://github.com/open-policy-agent/npm-opa-wasm.git#f4a21fe6f4d70706f85106dc6ea867983747e040",
Copy link
Contributor

Choose a reason for hiding this comment

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

why are we binding to a git commit and not the npm distro?
https://www.npmjs.com/package/@open-policy-agent/opa-wasm

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

intentionally.
the package is not mature, and the latest tagged release is missing functionality that we are dependent on.
therefore, until they do a new release, we're targeting a specific commit-hash.
see:
open-policy-agent/npm-opa-wasm#31

// without these files this method would fail.
// if you're interested in trying out the experimental local execution model for IaC scanning, please reach-out.
export async function test(pathToScan: string, options) {
// TODO: add support for proper typing of old TestResult interface.
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 a future todo?

Copy link
Contributor Author

@rontalx rontalx Feb 3, 2021

Choose a reason for hiding this comment

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

yes, as it is a typing rabbit-hole, and I prefer not having the old types in the CLI dictate how we build the new experience.
+I want to focus on the bare-minimum of fields for the new experience data-structures, and not jam tons of fields just because the main CLI flow requires them.
so this will be typed, but soon :)

];
}

const REQUIRED_K8S_FIELDS = ['apiVersion', 'kind', 'metadata'];
Copy link
Contributor

Choose a reason for hiding this comment

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

can we hoist this?

docId: yamlDocuments.length > 1 ? docId : undefined,
});
} else {
throw new Error('Invalid K8s File!');
Copy link
Contributor

Choose a reason for hiding this comment

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

If we throw in one of the iterations, are we ok w/ throwing away all the process?

import * as fs from 'fs';

const LOCAL_POLICY_ENGINE_DIR = `.iac-data`;
const LOCAL_POLICY_ENGINE_WASM_PATH = `${LOCAL_POLICY_ENGINE_DIR}/policy.wasm`;
Copy link
Contributor

Choose a reason for hiding this comment

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

please use path.sep instead of / :)

}

//
// function getFileTypeForLineNumber(
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹💨

Copy link
Contributor Author

@rontalx rontalx Feb 3, 2021

Choose a reason for hiding this comment

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

generally I 100% agree.
but keeping these intentionally, as this is logic that will be entered in one of the next follow-up PR's and is commented out due to a blocker.
wrote a comment on it here:
https://github.com/snyk/snyk/pull/1601/files#diff-2e4fd6421898cc5c5947d03530196bee66469cd25276fcdfcc0ba4381268b2c9R44

otherwise it will just get re-implemented soon.

return Object.values(groupedData);
}

const SEVERITIES = [SEVERITY.LOW, SEVERITY.MEDIUM, SEVERITY.HIGH];
Copy link
Contributor

Choose a reason for hiding this comment

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

hoist please

import { SEVERITY } from '../../../../lib/snyk-test/common';
import { IacFileInDirectory } from '../../../../lib/types';

// eslint-disable-next-line
Copy link
Contributor

Choose a reason for hiding this comment

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

?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

wanted to do aliasing, but the linter doesn't like it.
replacing with:

export type IacFileMetadata = IacFileInDirectory;

which the linter is ok with.

@@ -0,0 +1,50 @@
#shellcheck shell=sh
Copy link
Contributor

Choose a reason for hiding this comment

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

why not #!/bin/sh?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

we're mainly adapting the standards used here.
@JackuB do you have an answer for that?

After snyk_logout

Describe "k8s single file scan"
It "finds issues in k8s file"
Copy link
Contributor

Choose a reason for hiding this comment

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

why are we testing this way?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

  1. it has lots of benefits for E2E integration tests which we can easily cover most of the core flows of our product.
  2. it's a new testing framework Hammer introduced to the CLI and we are ones of the first to adopt it out.
  3. our old test-coverage for test iac are mainly E2E tests which are written in Tap, and are deprecated and no longer maintained.
  4. We will probably add later-on some Jest unit-tests, but for now we're fine with that coverage.

Copy link

@almog27 almog27 left a comment

Choose a reason for hiding this comment

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

Exciting!

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.

LGTM.
Please squash commit messages :)

@rontalx rontalx force-pushed the feat/iac-experimental-local-exec branch from 87b270b to f8bd3f3 Compare February 3, 2021 16:48
@github-actions
Copy link
Contributor

github-actions bot commented Feb 3, 2021

Expected release notes (by @rontalx)

features:
iac experimental single k8s file (f8bd3f3)

  • I hereby acknowledge these release notes are 🥙 AWESOME 🥙

@rontalx rontalx merged commit 40e7136 into master Feb 3, 2021
@rontalx rontalx deleted the feat/iac-experimental-local-exec branch February 3, 2021 17:27
@snyksec
Copy link

snyksec commented Feb 4, 2021

🎉 This PR is included in version 1.441.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
Development

Successfully merging this pull request may close these issues.

6 participants