Skip to content

Commit

Permalink
Merge pull request #4235 from snyk/chore/HMMR-577_integrate_sbom
Browse files Browse the repository at this point in the history
Integrate local sbom extension
  • Loading branch information
PeterSchafer authored Dec 13, 2022
2 parents 6a26463 + b9b5c20 commit dd0dd88
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 27 deletions.
42 changes: 38 additions & 4 deletions cliv2/cmd/cliv2/main.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package main

import (
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
"strings"

"github.com/snyk/cli-extension-sbom/pkg/sbom"
"github.com/snyk/cli/cliv2/internal/cliv2"
"github.com/snyk/cli/cliv2/internal/constants"
"github.com/snyk/cli/cliv2/pkg/basic_workflows"
Expand Down Expand Up @@ -84,11 +87,12 @@ func runCommand(cmd *cobra.Command, args []string) error {
func sendAnalytics(analytics analytics.Analytics, debugLogger *log.Logger) {
debugLogger.Println("Sending Analytics")

_, err := analytics.Send()
if err == nil {
res, err := analytics.Send()
errorCodeReceived := res != nil && 200 <= res.StatusCode && res.StatusCode < 300
if err == nil && !errorCodeReceived {
debugLogger.Println("Analytics sucessfully send")
} else {
debugLogger.Println("Failed to send Analytics", err)
debugLogger.Println("Failed to send Analytics:", err)
}
}

Expand Down Expand Up @@ -159,6 +163,33 @@ func prepareRootCommand() *cobra.Command {
return &rootCommand
}

func doFallback(err error, helped bool) (fallback bool) {
fallback = false
preCondition := err != nil && helpProvided == false
if preCondition {
errString := err.Error()
flagError := strings.Contains(errString, "unknown flag") ||
strings.Contains(errString, "flag needs") ||
strings.Contains(errString, "invalid argument")
commandError := strings.Contains(errString, "unknown command")

// filter for known cobra errors, since cobra errors shall trigger a fallback, but not others.
if commandError || flagError {
fallback = true
}
}

return fallback
}

func displayError(err error) {
if err != nil {
if _, ok := err.(*exec.ExitError); !ok {
fmt.Println(err)
}
}
}

func MainWithErrorCode() int {
var err error

Expand All @@ -178,6 +209,7 @@ func MainWithErrorCode() int {

// initialize the extensions -> they register themselves at the engine
engine.AddExtensionInitializer(basic_workflows.Init)
engine.AddExtensionInitializer(sbom.Init)

// init engine
err = engine.Init()
Expand Down Expand Up @@ -213,7 +245,7 @@ func MainWithErrorCode() int {
err = rootCommand.Execute()

// fallback to the legacy cli
if err != nil && helpProvided == false {
if doFallback(err, helpProvided) {
debugLogger.Printf("Falling back to legacy cli. (reason: %v)\n", err)
err = defaultCmd(nil, []string{})
}
Expand All @@ -222,6 +254,8 @@ func MainWithErrorCode() int {
cliAnalytics.AddError(err)
}

displayError(err)

exitCode := cliv2.DeriveExitCode(err)
debugLogger.Printf("Exiting with %d\n", exitCode)

Expand Down
3 changes: 2 additions & 1 deletion cliv2/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ require (
github.com/elazarl/goproxy/ext v0.0.0-20220901064549-fbd10ff4f5a1
github.com/google/uuid v1.3.0
github.com/pkg/errors v0.9.1
github.com/snyk/go-application-framework v0.0.0-20221201145925-ee0ec4cf2688
github.com/snyk/cli-extension-sbom v0.0.0-20221212093410-6b474ed1a42a
github.com/snyk/go-application-framework v0.0.0-20221213122015-81ad8dd6311d
github.com/snyk/go-httpauth v0.0.0-20220915135832-0edf62cf8cdd
github.com/spf13/cobra v1.6.0
github.com/spf13/pflag v1.0.5
Expand Down
6 changes: 4 additions & 2 deletions cliv2/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,10 @@ github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYe
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/snyk/go-application-framework v0.0.0-20221201145925-ee0ec4cf2688 h1:2WOMtq2WSgP/WL9qsQJBIxctf9vuvv+xn/xl6/qgNUY=
github.com/snyk/go-application-framework v0.0.0-20221201145925-ee0ec4cf2688/go.mod h1:cmEA75r0NIy0dyNx5AIKLtczEg6YF0oOPXIKHWiLyWc=
github.com/snyk/cli-extension-sbom v0.0.0-20221212093410-6b474ed1a42a h1:kImXWA4kbwaREeC+kaJ8H0aOukWzpK8K/UzAsExj6MU=
github.com/snyk/cli-extension-sbom v0.0.0-20221212093410-6b474ed1a42a/go.mod h1:ohrrgC94Gx82/cgSiac02JQrsMjFtggvhAvXGuGjDGU=
github.com/snyk/go-application-framework v0.0.0-20221213122015-81ad8dd6311d h1:5//WGQrFXri33xGuLgVEHOsBD0aU2ZHU8JFEGJBBc68=
github.com/snyk/go-application-framework v0.0.0-20221213122015-81ad8dd6311d/go.mod h1:5hLGqObbxLWnZkhn3Xc5PblESjQOfjN509ucQ4dtqz8=
github.com/snyk/go-httpauth v0.0.0-20220915135832-0edf62cf8cdd h1:zjDhcQ642rIVI8aIjfG5uVcw+OGotQtX2l9VHe7IqCQ=
github.com/snyk/go-httpauth v0.0.0-20220915135832-0edf62cf8cdd/go.mod h1:v6t6wKizOcHXT3p4qKn6Bda7yNIjCQ54Xyl31NjgXkY=
github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw=
Expand Down
1 change: 0 additions & 1 deletion cliv2/internal/cliv2/cliv2.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,6 @@ func DeriveExitCode(err error) int {
returnCode = exitError.ExitCode()
} else {
// got an error but it's not an ExitError
fmt.Println(err)
returnCode = constants.SNYK_EXIT_CODE_ERROR
}
}
Expand Down
48 changes: 36 additions & 12 deletions test/jest/acceptance/analytics.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,16 @@ describe('analytics module', () => {

expect(code).toBe(0);

const requests = server.getRequests().filter((value) => {
return value.url == '/api/v1/analytics/cli';
});

if (isCLIV2()) {
// in this case an extra analytics event is being sent, which needs to be dropped
server.popRequest();
requests.pop();
}

const lastRequest = server.popRequest();
const lastRequest = requests.pop();

expect(lastRequest).toMatchObject({
headers: {
Expand Down Expand Up @@ -121,12 +125,16 @@ describe('analytics module', () => {

expect(code).toBe(1);

const requests = server.getRequests().filter((value) => {
return value.url == '/api/v1/analytics/cli';
});

if (isCLIV2()) {
// in this case an extra analytics event is being sent, which needs to be dropped
server.popRequest();
requests.pop();
}

const lastRequest = server.popRequest();
const lastRequest = requests.pop();
expect(lastRequest).toMatchObject({
headers: {
host: 'localhost:12345',
Expand Down Expand Up @@ -197,12 +205,16 @@ describe('analytics module', () => {

expect(code).toBe(2);

const requests = server.getRequests().filter((value) => {
return value.url == '/api/v1/analytics/cli';
});

if (isCLIV2()) {
// in this case an extra analytics event is being sent, which needs to be dropped
server.popRequest();
requests.pop();
}

const lastRequest = server.popRequest();
const lastRequest = requests.pop();
expect(lastRequest).toMatchObject({
headers: {
host: 'localhost:12345',
Expand Down Expand Up @@ -261,19 +273,23 @@ describe('analytics module', () => {
'npm/with-vulnerable-lodash-dep',
);

const { code } = await runSnykCLI('test', {
const { code } = await runSnykCLI('test --org=1234', {
cwd: project.path(),
env,
});

expect(code).toBe(2);

const requests = server.getRequests().filter((value) => {
return value.url.includes('/api/v1/analytics/cli');
});

if (isCLIV2()) {
// in this case an extra analytics event is being sent, which needs to be dropped
server.popRequest();
requests.pop();
}

const lastRequest = server.popRequest();
const lastRequest = requests.pop();
expect(lastRequest).toMatchObject({
query: {},
body: {
Expand Down Expand Up @@ -335,12 +351,16 @@ describe('analytics module', () => {

expect(code).toBe(0);

const requests = server.getRequests().filter((value) => {
return value.url == '/api/v1/analytics/cli';
});

if (isCLIV2()) {
// in this case an extra analytics event is being sent, which needs to be dropped
server.popRequest();
requests.pop();
}

const lastRequest = server.popRequest();
const lastRequest = requests.pop();
expect(lastRequest).toMatchObject({
headers: {
host: 'localhost:12345',
Expand Down Expand Up @@ -452,7 +472,11 @@ describe('analytics module', () => {
});
expect(code).toBe(0);

const lastRequest = server.popRequest();
const requests = server.getRequests().filter((value) => {
return value.url == '/api/v1/analytics/cli';
});

const lastRequest = requests.pop();
expect(lastRequest).toBeUndefined();
});
});
2 changes: 1 addition & 1 deletion test/jest/acceptance/iac/cli-share-results.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ describe('CLI Share Results', () => {
server.setNextStatusCode(429);

const { stdout, exitCode } = await run(
'snyk iac test ./iac/arm/rule_test.json --report --project-business-criticality=high',
'snyk iac test ./iac/arm/rule_test.json --report --project-business-criticality=high --org=1234',
);

expect(stdout).toMatch(/test limit reached/i);
Expand Down
2 changes: 1 addition & 1 deletion test/jest/acceptance/snyk-fix/fix.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ describe('snyk fix', () => {
it('fails when api requests fail', async () => {
const project = await createProjectFromWorkspace('no-vulns');
server.setNextStatusCode(500);
const { code, stdout, stderr } = await runSnykCLI('fix', {
const { code, stdout, stderr } = await runSnykCLI('fix --org=1234', {
cwd: project.path(),
env,
});
Expand Down
3 changes: 2 additions & 1 deletion test/jest/acceptance/snyk-test/fail-on.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ describe('snyk test --fail-on', () => {
const project = await createProjectFromWorkspace('fail-on/' + workspace);
server.setNextResponse(await project.read('vulns-result.json'));

const { code } = await runSnykCLI(`test --fail-on=${failOn}`, {
// setting the "org" is a workaround to fix this test, the limitation of a single next response is actually the root cause because it requires the first request to be the test request.
const { code } = await runSnykCLI(`test --fail-on=${failOn} --org=1234`, {
cwd: project.path(),
env,
});
Expand Down
4 changes: 2 additions & 2 deletions test/jest/acceptance/snyk-test/missing-node-modules.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ describe('snyk test with missing node_modules', () => {
test('does not throw when missing node_modules & package.json has no dependencies', async () => {
server.setNextResponse(noVulnsResult);
const project = await createProject('npm/no-dependencies');
const { code, stdout } = await runSnykCLI('test', {
const { code, stdout } = await runSnykCLI('test --org=1234', {
cwd: project.path(),
env,
});
Expand All @@ -64,7 +64,7 @@ describe('snyk test with missing node_modules', () => {
test('does not throw when missing node_modules & package.json has no dependencies (with --dev)', async () => {
server.setNextResponse(noVulnsResult);
const project = await createProject('npm/no-dependencies');
const { code, stdout } = await runSnykCLI('test --dev', {
const { code, stdout } = await runSnykCLI('test --dev --org=1234', {
cwd: project.path(),
env,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,9 @@ describe('`snyk test` with `--file=`', () => {

// check that we're including the policy file in the request and that the policy
// includes the ignored vuln id from the .snyk file
const testDepGraphRequest = server.getRequests()[0];
const testDepGraphRequest = server.getRequests().find((value) => {
return value.url == '/api/v1/test-dep-graph?org=';
});
expect(testDepGraphRequest.body.policy).toBeDefined();
expect(testDepGraphRequest.body.policy).toContain(
'SNYK-JS-LODASH-590103',
Expand All @@ -128,7 +130,9 @@ describe('`snyk test` with `--file=`', () => {

// check that we're including the policy file in the request and that the policy
// includes the ignored vuln id from the .snyk file
const testDepGraphRequest = server.getRequests()[0];
const testDepGraphRequest = server.getRequests().find((value) => {
return value.url == '/api/v1/test-dep-graph?org=';
});
expect(testDepGraphRequest.body.policy).toBeDefined();
expect(testDepGraphRequest.body.policy).toContain(
'SNYK-JS-LODASH-590103',
Expand Down

0 comments on commit dd0dd88

Please sign in to comment.