Skip to content

Commit

Permalink
Merge pull request #30 from homoluctus/feature/issue_option
Browse files Browse the repository at this point in the history
Creating issue is optional
  • Loading branch information
homoluctus authored Nov 27, 2019
2 parents 1d7e70b + d334820 commit 3e6fbfb
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 48 deletions.
50 changes: 32 additions & 18 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,6 @@ env:
IMAGE_NAME: alpine:3.10.1

jobs:
jest:
name: Test with jest
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v1

- uses: actions/setup-node@v1
with:
node-version: '12.x'

- name: Install dependencies
run: npm install

- name: Jest
run: npm run test

test1:
name: Test for with parameter
runs-on: ubuntu-18.04
Expand Down Expand Up @@ -58,7 +42,7 @@ jobs:
if: always()
with:
type: ${{ job.status }}
job_name: ':ts: *test gitrivy*'
job_name: ':ts: *test gitrivy (test1)*'
channel: '#develop'
url: ${{ secrets.SLACK_WEBHOOK }}

Expand Down Expand Up @@ -91,6 +75,36 @@ jobs:
if: always()
with:
type: ${{ job.status }}
job_name: ':ts: *test gitrivy*'
job_name: ':ts: *test gitrivy (test2)*'
channel: '#develop'
url: ${{ secrets.SLACK_WEBHOOK }}

test3:
name: Test not to create issue
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v1

- name: Install dependencies
run: npm install

# - name: Test
# run: npm run test

- name: Build
run: npm run build

- name: Pull docker image
run: docker pull alpine:3.10.3

- uses: ./
with:
issue: 'false'

- uses: homoluctus/[email protected]
if: always()
with:
type: ${{ job.status }}
job_name: ':ts: *test gitrivy (test3)*'
channel: '#develop'
url: ${{ secrets.SLACK_WEBHOOK }}
26 changes: 26 additions & 0 deletions .github/workflows/unittest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Unit Test

on:
pull_request:
paths:
- 'src/**'
- 'dist/**'
- tsconfig.json
- package*

jobs:
jest:
name: Test with jest
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v1

- uses: actions/setup-node@v1
with:
node-version: '12.x'

- name: Install dependencies
run: npm install

- name: Jest
run: npm run test
34 changes: 32 additions & 2 deletions __tests__/trivy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,26 +128,55 @@ describe('Scan', () => {
severity: 'HIGH,CRITICAL',
vulnType: 'os,library',
ignoreUnfixed: true,
format: 'json',
};
const result: Vulnerability[] = Trivy.scan(trivyPath, image, options);
const result: Vulnerability[] | string = Trivy.scan(
trivyPath,
image,
options
);
expect(result.length).toBeGreaterThanOrEqual(1);
expect(result).toBeInstanceOf(Object);
});

test('without ignoreUnfixed', () => {
const options: TrivyOption = {
severity: 'HIGH,CRITICAL',
vulnType: 'os,library',
ignoreUnfixed: false,
format: 'json',
};
const result: Vulnerability[] = Trivy.scan(trivyPath, image, options);
const result: Vulnerability[] | string = Trivy.scan(
trivyPath,
image,
options
);
expect(result.length).toBeGreaterThanOrEqual(1);
expect(result).toBeInstanceOf(Object);
});

test('with table format', () => {
const options: TrivyOption = {
severity: 'HIGH,CRITICAL',
vulnType: 'os,library',
ignoreUnfixed: false,
format: 'table',
};
const result: Vulnerability[] | string = Trivy.scan(
trivyPath,
image,
options
);
expect(result.length).toBeGreaterThanOrEqual(1);
expect(result).toMatch(/alpine:3\.10/);
});

test('with invalid severity', () => {
const invalidOption: TrivyOption = {
severity: 'INVALID',
vulnType: 'os,library',
ignoreUnfixed: true,
format: 'json',
};
expect(() => {
Trivy.scan(trivyPath, image, invalidOption);
Expand All @@ -159,6 +188,7 @@ describe('Scan', () => {
severity: 'HIGH',
vulnType: 'INVALID',
ignoreUnfixed: true,
format: 'json',
};
expect(() => {
Trivy.scan(trivyPath, image, invalidOption);
Expand Down
10 changes: 7 additions & 3 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@ name: 'Trivy Action'
description: 'Scan docker image vulnerability using Trivy and create GitHub Issue'
author: 'homoluctus'
inputs:
token:
description: 'GitHub access token'
required: true
trivy_version:
description: 'Trivy version'
default: 'latest'
Expand All @@ -24,6 +21,13 @@ inputs:
description: 'Ignore unfixed vulnerabilities [true, false]'
default: 'false'
required: false
issue:
description: 'Decide whether to create a issue when vulnerabilities are found [true, false]'
default: 'true'
required: false
token:
description: 'GitHub access token used to create a issue'
required: false
issue_title:
description: 'Issue title'
default: 'Security Alert'
Expand Down
26 changes: 16 additions & 10 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6572,28 +6572,35 @@ const issue_1 = __webpack_require__(163);
function run() {
return __awaiter(this, void 0, void 0, function* () {
try {
const token = core.getInput('token', { required: true });
const trivyVersion = core
.getInput('trivy_version')
.replace(/^v/, '');
const image = core.getInput('image') || process.env.IMAGE_NAME;
const issueFlag = core.getInput('issue').toLowerCase() == 'true';
if (image === undefined || image === '') {
throw new Error('Please specify scan target image name');
}
const trivyOptions = {
const trivyOption = {
severity: core.getInput('severity').replace(/\s+/g, ''),
vulnType: core.getInput('vuln_type').replace(/\s+/g, ''),
ignoreUnfixed: core.getInput('ignore_unfixed').toLowerCase() === 'true',
format: issueFlag ? 'json' : 'table',
};
const downloader = new trivy_1.Downloader();
const trivyCmdPath = yield downloader.download(trivyVersion);
const result = trivy_1.Trivy.scan(trivyCmdPath, image, trivyOptions);
const result = trivy_1.Trivy.scan(trivyCmdPath, image, trivyOption);
if (!issueFlag) {
core.info(`Not create a issue because issue parameter is false.
Vulnerabilities:
${result}`);
return;
}
const issueContent = trivy_1.Trivy.parse(result);
if (issueContent === '') {
core.info('Vulnerabilities were not found.\nYour maintenance looks good 👍');
return;
}
const issueOptions = {
const issueOption = {
title: core.getInput('issue_title'),
body: issueContent,
labels: core
Expand All @@ -6605,7 +6612,8 @@ function run() {
.replace(/\s+/g, '')
.split(','),
};
const output = yield issue_1.createIssue(token, issueOptions);
const token = core.getInput('token', { required: true });
const output = yield issue_1.createIssue(token, issueOption);
core.setOutput('html_url', output.htmlUrl);
core.setOutput('issue_number', output.issueNumber.toString());
}
Expand Down Expand Up @@ -13315,19 +13323,18 @@ class Trivy {
'--vuln-type',
option.vulnType,
'--format',
'json',
option.format,
'--quiet',
'--no-progress',
];
if (option.ignoreUnfixed) {
if (option.ignoreUnfixed)
args.push('--ignore-unfixed');
}
args.push(image);
const result = child_process_1.spawnSync(trivyPath, args, {
encoding: 'utf-8',
});
if (result.stdout && result.stdout.length > 0) {
const vulnerabilities = JSON.parse(result.stdout);
const vulnerabilities = option.format === 'json' ? JSON.parse(result.stdout) : result.stdout;
if (vulnerabilities.length > 0) {
return vulnerabilities;
}
Expand Down Expand Up @@ -13359,7 +13366,6 @@ class Trivy {
}
issueContent += `${vulnTable}\n\n`;
}
console.debug(issueContent);
return issueContent;
}
static validateOption(option) {
Expand Down
26 changes: 19 additions & 7 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,42 @@ import {

async function run() {
try {
const token: string = core.getInput('token', { required: true });
const trivyVersion: string = core
.getInput('trivy_version')
.replace(/^v/, '');
const image: string | undefined =
core.getInput('image') || process.env.IMAGE_NAME;
const issueFlag: boolean = core.getInput('issue').toLowerCase() == 'true';

if (image === undefined || image === '') {
throw new Error('Please specify scan target image name');
}

const trivyOptions: TrivyOption = {
const trivyOption: TrivyOption = {
severity: core.getInput('severity').replace(/\s+/g, ''),
vulnType: core.getInput('vuln_type').replace(/\s+/g, ''),
ignoreUnfixed: core.getInput('ignore_unfixed').toLowerCase() === 'true',
format: issueFlag ? 'json' : 'table',
};

const downloader = new Downloader();
const trivyCmdPath: string = await downloader.download(trivyVersion);
const result: Vulnerability[] = Trivy.scan(
const result: Vulnerability[] | string = Trivy.scan(
trivyCmdPath,
image,
trivyOptions
trivyOption
);
const issueContent: string = Trivy.parse(result);

if (!issueFlag) {
core.info(
`Not create a issue because issue parameter is false.
Vulnerabilities:
${result}`
);
return;
}

const issueContent: string = Trivy.parse(result as Vulnerability[]);

if (issueContent === '') {
core.info(
Expand All @@ -43,7 +54,7 @@ async function run() {
return;
}

const issueOptions: IssueOption = {
const issueOption: IssueOption = {
title: core.getInput('issue_title'),
body: issueContent,
labels: core
Expand All @@ -55,7 +66,8 @@ async function run() {
.replace(/\s+/g, '')
.split(','),
};
const output: IssueResponse = await createIssue(token, issueOptions);
const token: string = core.getInput('token', { required: true });
const output: IssueResponse = await createIssue(token, issueOption);
core.setOutput('html_url', output.htmlUrl);
core.setOutput('issue_number', output.issueNumber.toString());
} catch (error) {
Expand Down
1 change: 1 addition & 0 deletions src/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export interface TrivyOption {
severity: string;
vulnType: string;
ignoreUnfixed: boolean;
format: string;
}

export interface Vulnerability {
Expand Down
14 changes: 6 additions & 8 deletions src/trivy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ export class Trivy {
trivyPath: string,
image: string,
option: TrivyOption
): Vulnerability[] {
): Vulnerability[] | string {
Trivy.validateOption(option);

const args: string[] = [
Expand All @@ -132,22 +132,21 @@ export class Trivy {
'--vuln-type',
option.vulnType,
'--format',
'json',
option.format,
'--quiet',
'--no-progress',
];

if (option.ignoreUnfixed) {
args.push('--ignore-unfixed');
}

if (option.ignoreUnfixed) args.push('--ignore-unfixed');
args.push(image);

const result: SpawnSyncReturns<string> = spawnSync(trivyPath, args, {
encoding: 'utf-8',
});

if (result.stdout && result.stdout.length > 0) {
const vulnerabilities: Vulnerability[] = JSON.parse(result.stdout);
const vulnerabilities: Vulnerability[] | string =
option.format === 'json' ? JSON.parse(result.stdout) : result.stdout;
if (vulnerabilities.length > 0) {
return vulnerabilities;
}
Expand Down Expand Up @@ -185,7 +184,6 @@ export class Trivy {
}
issueContent += `${vulnTable}\n\n`;
}
console.debug(issueContent);
return issueContent;
}

Expand Down

0 comments on commit 3e6fbfb

Please sign in to comment.