Skip to content

Commit

Permalink
feat: adding cta for docker users
Browse files Browse the repository at this point in the history
  • Loading branch information
RotemS committed Aug 23, 2020
1 parent 3dfe96b commit 4f16863
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 19 deletions.
69 changes: 50 additions & 19 deletions src/cli/commands/test/index.ts
Expand Up @@ -49,6 +49,7 @@ import {
import * as utils from './utils';
import { getIacDisplayedOutput } from './iac-output';
import { getEcosystem, testEcosystem } from '../../../lib/ecosystems';
import { TestLimitReachedError } from '../../../lib/errors';

const debug = Debug('snyk-test');
const SEPARATOR = '\n-------------------------------------------------------\n';
Expand Down Expand Up @@ -100,6 +101,7 @@ async function test(...args: MethodArgs): Promise<TestCommandResult> {
} catch (err) {
if (options.docker && getDockerToken()) {
options.testDepGraphDockerEndpoint = '/docker-jwt/test-dep-graph';
options.isDockerUser = true;
} else {
throw err;
}
Expand Down Expand Up @@ -274,6 +276,13 @@ async function test(...args: MethodArgs): Promise<TestCommandResult> {
// first one
error.code = errorResults[0].code;
error.userMessage = errorResults[0].userMessage;
if (
error.userMessage === TestLimitReachedError().userMessage &&
options.isDockerUser
) {
error.userMessage =
'You have reached your scan limit. Sign up to Snyk for additional free scans https://dockr.ly/3ePqVcp';
}
throw error;
}

Expand Down Expand Up @@ -472,13 +481,17 @@ function displayResult(
)
? '\n\nTip: Snyk only tests production dependencies by default. You can try re-running with the `--dev` flag.'
: '';

const dockerCTA = dockerUserCTA(options);
return (
prefix +
meta +
'\n\n' +
summaryOKText +
multiProjAdvice +
(isCI() ? '' : dockerAdvice + nextStepsText + snykPackageTestTip)
(isCI()
? ''
: dockerAdvice + nextStepsText + snykPackageTestTip + dockerCTA)
);
}

Expand Down Expand Up @@ -562,23 +575,7 @@ function getDisplayedOutput(
'\n\nRun `snyk wizard` to address these issues.',
);
}
let dockerSuggestion = '';
if (options.docker && config.disableSuggestions !== 'true') {
const optOutSuggestions =
'\n\nTo remove this message in the future, please run `snyk config set disableSuggestions=true`';
if (!options.file) {
dockerSuggestion +=
chalk.bold.white(
'\n\nPro tip: use `--file` option to get base image remediation advice.' +
`\nExample: $ snyk test --docker ${options.path} --file=path/to/Dockerfile`,
) + optOutSuggestions;
} else if (!options['exclude-base-image-vulns']) {
dockerSuggestion +=
chalk.bold.white(
'\n\nPro tip: use `--exclude-base-image-vulns` to exclude from display Docker base image vulnerabilities.',
) + optOutSuggestions;
}
}
const dockerSuggestion = getDockerSuggestionText(options, config);

const vulns = res.vulnerabilities || [];
const groupedVulns: GroupedVuln[] = groupVulnerabilities(vulns);
Expand Down Expand Up @@ -632,13 +629,15 @@ function getDisplayedOutput(
}

const ignoredIssues = '';
const dockerCTA = dockerUserCTA(options);
return (
prefix +
body +
multiProjAdvice +
ignoredIssues +
dockerAdvice +
dockerSuggestion
dockerSuggestion +
dockerCTA
);
}

Expand Down Expand Up @@ -708,3 +707,35 @@ function metadataForVuln(vuln): VulnMetaData {
packageManager: vuln.packageManager,
};
}

function getDockerSuggestionText(options, config): string {
if (!options.docker || options.isDockerUser) {
return '';
}

let dockerSuggestion = '';
if (config && config.disableSuggestions !== 'true') {
const optOutSuggestions =
'\n\nTo remove this message in the future, please run `snyk config set disableSuggestions=true`';
if (!options.file) {
dockerSuggestion +=
chalk.bold.white(
'\n\nPro tip: use `--file` option to get base image remediation advice.' +
`\nExample: $ snyk test --docker ${options.path} --file=path/to/Dockerfile`,
) + optOutSuggestions;
} else if (!options['exclude-base-image-vulns']) {
dockerSuggestion +=
chalk.bold.white(
'\n\nPro tip: use `--exclude-base-image-vulns` to exclude from display Docker base image vulnerabilities.',
) + optOutSuggestions;
}
}
return dockerSuggestion;
}

function dockerUserCTA(options) {
if (options.isDockerUser) {
return '\n\nFor more free scans that keep your images secure, sign up to Snyk at https://dockr.ly/3ePqVcp';
}
return '';
}
1 change: 1 addition & 0 deletions src/lib/errors/index.ts
Expand Up @@ -23,3 +23,4 @@ export {
NotSupportedIacFileError,
IllegalIacFileError,
} from './invalid-iac-file';
export { TestLimitReachedError } from './test-limit-reached-error';
12 changes: 12 additions & 0 deletions src/lib/errors/test-limit-reached-error.ts
@@ -0,0 +1,12 @@
import { CustomError } from './custom-error';

export function TestLimitReachedError(
errorMessage = 'Test limit reached!',
errorCode = 429,
) {
const error = new CustomError(errorMessage);
error.code = errorCode;
error.strCode = 'TEST_LIMIT_REACHED';
error.userMessage = errorMessage;
return error;
}
1 change: 1 addition & 0 deletions src/lib/types.ts
Expand Up @@ -22,6 +22,7 @@ export interface TestOptions {
reachableVulnsTimeout?: number;
yarnWorkspaces?: boolean;
testDepGraphDockerEndpoint?: string | null;
isDockerUser?: boolean;
}

export interface WizardOptions {
Expand Down
88 changes: 88 additions & 0 deletions test/acceptance/docker-token.test.ts
Expand Up @@ -120,6 +120,94 @@ test('`snyk test` without docker flag - docker token and no api key', async (t)
}
});

test('`snyk test` with docker flag - displays CTA', async (t) => {
stubDockerPluginResponse(
plugins,
{
plugin: {
packageManager: 'deb',
},
package: {
name: 'docker-image',
dependencies: {
'apt/libapt-pkg5.0': {
version: '1.6.3ubuntu0.1',
dependencies: {
'bzip2/libbz2-1.0': {
version: '1.0.6-8.1',
},
},
},
'bzip2/libbz2-1.0': {
version: '1.0.6-8.1',
},
},
},
},
t,
);
const vulns = require('./fixtures/docker/find-result.json');
server.setNextResponse(vulns);

try {
await cli.test('foo:latest', {
docker: true,
});
} catch (err) {
const msg = err.message;
t.match(
msg,
'For more free scans that keep your images secure, sign up to Snyk at https://dockr.ly/3ePqVcp',
'displays docker CTA for scan with vulns',
);
}
});

test('`snyk test` with docker flag - does not display CTA', async (t) => {
stubDockerPluginResponse(
plugins,
{
plugin: {
packageManager: 'deb',
},
package: {
name: 'docker-image',
dependencies: {
'apt/libapt-pkg5.0': {
version: '1.6.3ubuntu0.1',
dependencies: {
'bzip2/libbz2-1.0': {
version: '1.0.6-8.1',
},
},
},
'bzip2/libbz2-1.0': {
version: '1.0.6-8.1',
},
},
},
},
t,
);
const vulns = require('./fixtures/docker/find-result.json');
server.setNextResponse(vulns);
await cli.config('set', 'api=' + apiKey);
try {
await cli.test('foo:latest', {
docker: true,
});
} catch (err) {
const msg = err.message;
t.notMatch(
msg,
'For more free scans that keep your images secure, sign up to Snyk at https://dockr.ly/3ePqVcp',
'does not display docker CTA if API key was used',
);
}
await cli.config('unset', 'api');
t.end();
});

test('teardown', async (t) => {
t.plan(4);

Expand Down

0 comments on commit 4f16863

Please sign in to comment.