Skip to content
This repository has been archived by the owner on Aug 2, 2023. It is now read-only.

Commit

Permalink
Specify Trivy version in workflow file (version 2) (#130) (#138)
Browse files Browse the repository at this point in the history
* specify trivy version

* Trivy version logging

* Fix wrongly assigned variable for trivyversion.

* Updated readme with new parameter.

* Rename variable for Trivy version.

* Build JS

* Update src/trivyHelper.ts

Co-authored-by: Koushik Dey <[email protected]>

* build trivyhelper.js - change debug message

* Fix failing tests and add new test

Co-authored-by: Koushik Dey <[email protected]>

Co-authored-by: Randi Øyri <[email protected]>
  • Loading branch information
koushdey and oyri authored Mar 28, 2022
1 parent 74375b0 commit f9af925
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 23 deletions.
3 changes: 2 additions & 1 deletion __mocks__/@actions/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ let __mockInputValues = {
'username': 'username',
'password': 'password',
'severit-threshold': 'HIGH',
'run-quality-checks': 'true'
'run-quality-checks': 'true',
'trivy-version': 'latest'
};

function __setMockInputValues(mockObject) {
Expand Down
68 changes: 54 additions & 14 deletions __tests__/trivyHelper.test.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,37 @@

jest.mock('fs');
jest.mock('os');



describe('Run Trivy', () => {
const mockedFs = require('fs');
const mockedOs = require('os');
const mockedToolCache = require('@actions/tool-cache');
const mockedFileHelper = require('../src/fileHelper');
mockedFileHelper.getContainerScanDirectory = jest.fn().mockImplementation(() =>{
return 'test/_temp/containerscan_123';
});

let mockFile = {
'releaseDownloadedPath': JSON.stringify({ tag_name: 'v1.1.1' })
};
let cachedTools = {
'trivy': true,
'dockle': true
};
mockedFs.__setMockFiles(mockFile);
function setupFileMock() {
const mockedFileHelper = require('../src/fileHelper');
mockedFileHelper.getContainerScanDirectory = jest.fn().mockImplementation(() => {
return 'test/_temp/containerscan_123';
});

return {
'releaseDownloadedPath': JSON.stringify({tag_name: 'v1.1.1'})
};
}
mockedFs.__setMockFiles(setupFileMock());

function toolCache() {
const mockedToolCache = require('@actions/tool-cache');
let cachedTools = {
'trivy': true,
'dockle': true
};
return {mockedToolCache, cachedTools};
}
let {mockedToolCache, cachedTools} = toolCache();
mockedToolCache.__setToolCached(cachedTools);


afterAll(() => {
jest.clearAllMocks();
jest.resetModules();
Expand All @@ -36,7 +48,7 @@ describe('Run Trivy', () => {
expect(mockedToolCache.downloadTool).toHaveBeenCalledTimes(1);
});

test('Trivy binaries are not present in the cache', async () => {
test('Trivy binaries are not present in the cache', async () => {
cachedTools['trivy'] = false;
mockedToolCache.__setToolCached(cachedTools);
const runner = require('../src/trivyHelper');
Expand All @@ -48,4 +60,32 @@ describe('Run Trivy', () => {
expect(mockedToolCache.find).toHaveReturnedWith(undefined);
expect(mockedToolCache.downloadTool).toHaveBeenCalledTimes(2);
});

test('Trivy binaries are not present in the cache and not use latest version', async () => {
jest.resetModules();
const mockedFs = require('fs');
const mockedOs = require('os');
mockedFs.__setMockFiles(setupFileMock());
let {mockedToolCache, cachedTools} = toolCache();
cachedTools['trivy'] = false;
mockedToolCache.__setToolCached(cachedTools);
jest.mock('../src/inputHelper', () => {
const inputHelper = jest.requireActual('../src/inputHelper');
return {
__esModule: true,
...inputHelper,
trivyVersion: '0.23.0',
};
});

const runner = require('../src/trivyHelper');
const trivyResult = await runner.runTrivy();
expect(trivyResult).toHaveProperty('status', 0);
expect(trivyResult).toHaveProperty('timestamp');
expect(mockedOs.type).toHaveBeenCalledTimes(1);
expect(mockedToolCache.find).toHaveReturnedWith(undefined);
expect(mockedToolCache.downloadTool).toHaveBeenCalledTimes(1);
});


});
4 changes: 4 additions & 0 deletions action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ inputs:
description: 'Github token'
default: ${{ github.token }}
required: true
trivy-version:
description: 'Version of Trivy to run'
default: 'latest'
required: false
run-quality-checks:
description: 'Add additional checks to ensure the image is secure and follows best practices and CIS standards'
default: 'true'
Expand Down
1 change: 1 addition & 0 deletions lib/inputHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ exports.imageName = core.getInput("image-name");
exports.githubToken = core.getInput("token");
exports.username = core.getInput("username");
exports.password = core.getInput("password");
exports.trivyVersion = core.getInput("trivy-version");
exports.severityThreshold = core.getInput("severity-threshold");
exports.runQualityChecks = core.getInput("run-quality-checks");
function isRunQualityChecksEnabled() {
Expand Down
12 changes: 8 additions & 4 deletions lib/trivyHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,15 @@ function runTrivy() {
exports.runTrivy = runTrivy;
function getTrivy() {
return __awaiter(this, void 0, void 0, function* () {
const latestTrivyVersion = yield getLatestTrivyVersion();
let cachedToolPath = toolCache.find(exports.trivyToolName, latestTrivyVersion);
let version = inputHelper.trivyVersion;
if (version == 'latest') {
version = yield getLatestTrivyVersion();
}
core.debug(util.format('Use Trivy version: %s', version));
let cachedToolPath = toolCache.find(exports.trivyToolName, version);
if (!cachedToolPath) {
let trivyDownloadPath;
const trivyDownloadUrl = getTrivyDownloadUrl(latestTrivyVersion);
const trivyDownloadUrl = getTrivyDownloadUrl(version);
const trivyDownloadDir = `${process.env['GITHUB_WORKSPACE']}/_temp/tools/trivy`;
core.debug(util.format("Could not find trivy in cache, downloading from %s", trivyDownloadUrl));
try {
Expand All @@ -85,7 +89,7 @@ function getTrivy() {
throw new Error(util.format("Failed to download trivy from %s: %s", trivyDownloadUrl, error.toString()));
}
const untarredTrivyPath = yield toolCache.extractTar(trivyDownloadPath);
cachedToolPath = yield toolCache.cacheDir(untarredTrivyPath, exports.trivyToolName, latestTrivyVersion);
cachedToolPath = yield toolCache.cacheDir(untarredTrivyPath, exports.trivyToolName, version);
}
const trivyToolPath = cachedToolPath + "/" + exports.trivyToolName;
fs.chmodSync(trivyToolPath, "777");
Expand Down
1 change: 1 addition & 0 deletions src/inputHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export const imageName = core.getInput("image-name");
export const githubToken = core.getInput("token");
export const username = core.getInput("username");
export const password = core.getInput("password");
export const trivyVersion = core.getInput("trivy-version");
export const severityThreshold = core.getInput("severity-threshold");
export const runQualityChecks = core.getInput("run-quality-checks");

Expand Down
13 changes: 9 additions & 4 deletions src/trivyHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export async function runTrivy(): Promise<TrivyResult> {
const trivyCommand = "image";

const imageName = inputHelper.imageName;

const trivyOptions: ExecOptions = await getTrivyExecOptions();
console.log(`Scanning for vulnerabilties in image: ${imageName}`);
const trivyToolRunner = new ToolRunner(trivyPath, [trivyCommand, imageName], trivyOptions);
Expand All @@ -58,12 +59,16 @@ export async function runTrivy(): Promise<TrivyResult> {
}

export async function getTrivy(): Promise<string> {
const latestTrivyVersion = await getLatestTrivyVersion();

let cachedToolPath = toolCache.find(trivyToolName, latestTrivyVersion);
let version = inputHelper.trivyVersion;
if(version == 'latest'){
version = await getLatestTrivyVersion();
}
core.debug(util.format('Use Trivy version: %s', version));
let cachedToolPath = toolCache.find(trivyToolName, version);
if (!cachedToolPath) {
let trivyDownloadPath;
const trivyDownloadUrl = getTrivyDownloadUrl(latestTrivyVersion);
const trivyDownloadUrl = getTrivyDownloadUrl(version);
const trivyDownloadDir = `${process.env['GITHUB_WORKSPACE']}/_temp/tools/trivy`;
core.debug(util.format("Could not find trivy in cache, downloading from %s", trivyDownloadUrl));

Expand All @@ -74,7 +79,7 @@ export async function getTrivy(): Promise<string> {
}

const untarredTrivyPath = await toolCache.extractTar(trivyDownloadPath);
cachedToolPath = await toolCache.cacheDir(untarredTrivyPath, trivyToolName, latestTrivyVersion);
cachedToolPath = await toolCache.cacheDir(untarredTrivyPath, trivyToolName, version);
}

const trivyToolPath = cachedToolPath + "/" + trivyToolName;
Expand Down

0 comments on commit f9af925

Please sign in to comment.