diff --git a/README.md b/README.md index 865442a1..36ad36ed 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,11 @@ Please checkout [Trivy](https://github.com/aquasecurity/trivy/blob/main/LICENSE) (Optional) Password to authenticate to the Docker registry. This is only required when you're trying to pull an image from your private registry '' + + allowed-list + (Optional) File path for the allowedlist + .github/containerscan/allowedlist.yaml + ## Action output @@ -95,7 +100,7 @@ Here is a sample scan report: ``` ## Ignoring vulnerabilities -In case you would like the action to ignore any vulnerabilities and best practice checks, create an allowedlist file at the path `.github/containerscan/allowedlist.yaml` in your repo. Here's an example allowedlist.yaml file. +In case you would like the action to ignore any vulnerabilities and best practice checks, create an allowedlist file (default `.github/containerscan/allowedlist.yaml`) in your repo. Here's an example allowedlist.yaml file. ```yaml general: diff --git a/__tests__/allowedlistHandler.test.ts b/__tests__/allowedlistHandler.test.ts index 74eba31f..5620bac9 100644 --- a/__tests__/allowedlistHandler.test.ts +++ b/__tests__/allowedlistHandler.test.ts @@ -26,7 +26,7 @@ describe('Initialize allowedlist file', () => { test('No allowedlist file is given', () => { const allowedlistHandler = require('../src/allowedlistHandler'); - expect(allowedlistHandler.init).not.toThrow(); + expect(() => allowedlistHandler.init(".github/containerscan/allowedlist.yaml")).not.toThrow(); expect(mockedFs.existsSync).not.toReturnWith(true); expect(mockedFs.existsSync).toHaveBeenCalledTimes(2); }); @@ -38,7 +38,7 @@ describe('Initialize allowedlist file', () => { mockedFs.__setMockFiles(mockFile); const allowedlistHandler = require('../src/allowedlistHandler'); - expect(allowedlistHandler.init).not.toThrow(); + expect(() => allowedlistHandler.init(".github/containerscan/allowedlist.yaml")).not.toThrow(); expect(mockedFs.existsSync).toReturnWith(true); expect(mockedFs.existsSync).toHaveBeenCalledTimes(1); expect(mockedFs.writeFileSync).toHaveBeenCalledTimes(2); @@ -50,7 +50,19 @@ describe('Initialize allowedlist file', () => { }; mockedFs.__setMockFiles(mockFile); const allowedlistHandler = require('../src/allowedlistHandler'); - expect(allowedlistHandler.init).not.toThrow(); + expect(() => allowedlistHandler.init(".github/containerscan/allowedlist.yaml")).not.toThrow(); + expect(mockedFs.existsSync).toReturnWith(true); + expect(mockedFs.existsSync).toHaveBeenCalledTimes(2); + expect(mockedFs.writeFileSync).toHaveBeenCalledTimes(2); + }); + + test('different file name is given', () => { + let mockFile = { + 'test/.github/path/file.yml': '{general: {vulnerabilities: [CVE-2003-1307, CVE-2007-0086], bestPracticeViolations: [CIS-DI-0005, DKL-LI-0003]}}' + }; + mockedFs.__setMockFiles(mockFile); + const allowedlistHandler = require('../src/allowedlistHandler'); + expect(() => allowedlistHandler.init(".github/path/file.yaml")).not.toThrow(); expect(mockedFs.existsSync).toReturnWith(true); expect(mockedFs.existsSync).toHaveBeenCalledTimes(2); expect(mockedFs.writeFileSync).toHaveBeenCalledTimes(2); @@ -62,7 +74,7 @@ describe('Initialize allowedlist file', () => { }; mockedFs.__setMockFiles(mockFile); const allowedlistHandler = require('../src/allowedlistHandler'); - expect(allowedlistHandler.init).toThrow(); + expect(() => allowedlistHandler.init(".github/containerscan/allowedlist.yaml")).toThrow(); expect(mockedFs.writeFileSync).toHaveBeenCalledTimes(0); }); @@ -72,7 +84,7 @@ describe('Initialize allowedlist file', () => { }; mockedFs.__setMockFiles(mockFile); const allowedlistHandler = require('../src/allowedlistHandler'); - expect(allowedlistHandler.init).not.toThrow(); + expect(() => allowedlistHandler.init(".github/containerscan/allowedlist.yaml")).not.toThrow(); expect(mockedFs.writeFileSync).toHaveBeenCalledTimes(1); }); }); diff --git a/action.yaml b/action.yaml index 9b31296a..4a9577ea 100644 --- a/action.yaml +++ b/action.yaml @@ -18,6 +18,10 @@ inputs: description: 'Github token' default: ${{ github.token }} required: true + allowed-list: + description: 'File path for the allowedlist' + default: '.github/containerscan/allowedlist.yaml' + required: false run-quality-checks: description: 'Add additional checks to ensure the image is secure and follows best practices and CIS standards' default: 'true' diff --git a/lib/allowedlistHandler.js b/lib/allowedlistHandler.js index 12078b47..89923e3e 100644 --- a/lib/allowedlistHandler.js +++ b/lib/allowedlistHandler.js @@ -27,10 +27,10 @@ function initializeDockleAllowedlistPath() { //Dockle expects .dockleignore file at the root of the repo dockleAllowedlistPath = `${process.env['GITHUB_WORKSPACE']}/.dockleignore`; } -function init() { - let allowedlistFilePath = `${process.env['GITHUB_WORKSPACE']}/.github/containerscan/allowedlist.yaml`; +function init(allowedlistInput) { + let allowedlistFilePath = `${process.env['GITHUB_WORKSPACE']}/${allowedlistInput.replace(/.yml$/, ".yaml")}`; if (!fs.existsSync(allowedlistFilePath)) { - allowedlistFilePath = `${process.env['GITHUB_WORKSPACE']}/.github/containerscan/allowedlist.yml`; + allowedlistFilePath = allowedlistFilePath.replace(/.yaml$/, ".yml"); if (!fs.existsSync(allowedlistFilePath)) { console.log("Could not find allowedlist file."); return; diff --git a/lib/inputHelper.js b/lib/inputHelper.js index 7fec74a3..70b4f433 100644 --- a/lib/inputHelper.js +++ b/lib/inputHelper.js @@ -14,6 +14,7 @@ exports.username = core.getInput("username"); exports.password = core.getInput("password"); exports.severityThreshold = core.getInput("severity-threshold"); exports.runQualityChecks = core.getInput("run-quality-checks"); +exports.allowedList = core.getInput("allowed-list"); function isRunQualityChecksEnabled() { return exports.runQualityChecks.toLowerCase() === "true"; } diff --git a/lib/main.js b/lib/main.js index fdcf84a7..cb357f22 100644 --- a/lib/main.js +++ b/lib/main.js @@ -25,7 +25,7 @@ const utils = __importStar(require("./utils")); function run() { return __awaiter(this, void 0, void 0, function* () { inputHelper.validateRequiredInputs(); - allowedlistHandler.init(); + allowedlistHandler.init(inputHelper.allowedList); const trivyResult = yield trivyHelper.runTrivy(); const trivyStatus = trivyResult.status; if (trivyStatus === trivyHelper.TRIVY_EXIT_CODE) { @@ -36,11 +36,10 @@ function run() { } else { const errors = utils.extractErrorsFromLogs(trivyHelper.getTrivyLogPath(), trivyHelper.trivyToolName); - errors.forEach(err => { core.error(err); }); - throw new Error(`An error occurred while scanning container image: ${imageName} for vulnerabilities.`); + throw new Error(`An error occurred while scanning container image: ${inputHelper.imageName} for vulnerabilities.`); } let dockleStatus; if (inputHelper.isRunQualityChecksEnabled()) { diff --git a/lib/utils.js b/lib/utils.js index 4eb951e8..25773b8a 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -169,4 +169,4 @@ function getCheckText(trivyStatus, dockleStatus) { text = `${text}\n${separator}\n${dockleText}`; } return text; -} \ No newline at end of file +} diff --git a/src/allowedlistHandler.ts b/src/allowedlistHandler.ts index 313b3f69..258e705f 100644 --- a/src/allowedlistHandler.ts +++ b/src/allowedlistHandler.ts @@ -22,10 +22,11 @@ function initializeDockleAllowedlistPath() { dockleAllowedlistPath = `${process.env['GITHUB_WORKSPACE']}/.dockleignore`; } -export function init() { - let allowedlistFilePath = `${process.env['GITHUB_WORKSPACE']}/.github/containerscan/allowedlist.yaml`; +export function init(allowedlistInput) { + let allowedlistFilePath = `${process.env['GITHUB_WORKSPACE']}/${allowedlistInput.replace(/.yml$/, ".yaml")}` + if (!fs.existsSync(allowedlistFilePath)) { - allowedlistFilePath = `${process.env['GITHUB_WORKSPACE']}/.github/containerscan/allowedlist.yml`; + allowedlistFilePath = allowedlistFilePath.replace(/.yaml$/, ".yml") if (!fs.existsSync(allowedlistFilePath)) { console.log("Could not find allowedlist file."); return; diff --git a/src/inputHelper.ts b/src/inputHelper.ts index 03bcece4..06c8e365 100644 --- a/src/inputHelper.ts +++ b/src/inputHelper.ts @@ -6,6 +6,7 @@ export const username = core.getInput("username"); export const password = core.getInput("password"); export const severityThreshold = core.getInput("severity-threshold"); export const runQualityChecks = core.getInput("run-quality-checks"); +export const allowedList = core.getInput("allowed-list"); export function isRunQualityChecksEnabled(): boolean { return runQualityChecks.toLowerCase() === "true"; diff --git a/src/main.ts b/src/main.ts index e0f70f5e..d4d24895 100644 --- a/src/main.ts +++ b/src/main.ts @@ -7,7 +7,7 @@ import * as utils from './utils'; export async function run(): Promise { inputHelper.validateRequiredInputs(); - allowedlistHandler.init(); + allowedlistHandler.init(inputHelper.allowedList); const trivyResult = await trivyHelper.runTrivy(); const trivyStatus = trivyResult.status;