Skip to content

Commit

Permalink
fix: Junit xml format output (#130)
Browse files Browse the repository at this point in the history
💥
  • Loading branch information
DarthHater committed Jan 23, 2020
1 parent 5384d02 commit 7e26c6c
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 4 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ Options:
--quiet, -q Only print out vulnerable dependencies [boolean]
--verbose, -V Set console logging level to verbose [boolean]
--json, -j Set output to JSON [boolean]
--xml, -x Set output to JUnit XML format [boolean]
--whitelist, -w Set path to whitelist file [string]
```

Expand Down
5 changes: 5 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
"ora": "^4.0.3",
"read-installed": "~4.0.3",
"winston": "^3.2.1",
"xmlbuilder": "^13.0.2",
"yargs": "^15.0.2"
}
}
2 changes: 1 addition & 1 deletion src/Application/Application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ export class Application {

this.spinner.maybeCreateMessageForSpinner('Auditing your results from Sonatype OSS Index');
logMessage('Instantiating OSS Index Request Service, with quiet option', DEBUG, { quiet: args.quiet });
let auditOSSIndex = new AuditOSSIndex((args.quiet) ? true : false, (args.json) ? true : false);
let auditOSSIndex = new AuditOSSIndex((args.quiet) ? true : false, (args.json) ? true : false, (args.xml) ? true : false);
this.spinner.maybeStop();

logMessage('Attempting to audit results', DEBUG);
Expand Down
56 changes: 54 additions & 2 deletions src/Audit/AuditOSSIndex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,24 @@
*/
import { OssIndexServerResult, Vulnerability } from "../Types/OssIndexServerResult";
import chalk from 'chalk';
import * as builder from 'xmlbuilder';

export class AuditOSSIndex {

constructor(
readonly quiet: boolean = false,
readonly json: boolean = false)
readonly json: boolean = false,
readonly xml: boolean = false)
{}

public auditResults(results: Array<OssIndexServerResult>): boolean {
if (this.json) {
return this.printJson(results);
}
if (this.xml) {
return this.printJUnitXML(results);
}

let total = results.length;
results = results.sort((a, b) => {
return (a.coordinates < b.coordinates ? -1 : 1);
Expand Down Expand Up @@ -56,12 +62,58 @@ export class AuditOSSIndex {
private printJson(results: Array<OssIndexServerResult>): boolean {
console.log(JSON.stringify(results, null, 2));

if (results.filter((x) => { return (x.vulnerabilities && x.vulnerabilities?.length > 0) }).length > 0) {
if (this.getNumberOfVulnerablePackagesFromResults(results) > 0) {
return true;
}
return false;
}

private printJUnitXML(results: Array<OssIndexServerResult>): boolean {
let testsuite = builder.create('testsuite');
testsuite.att('tests', results.length);
testsuite.att('timestamp', new Date().toISOString());
testsuite.att('failures', this.getNumberOfVulnerablePackagesFromResults(results));

for(let i: number = 0; i < results.length; i++) {
let testcase = testsuite.ele("testcase", {"classname": results[i].coordinates, "name": results[i].coordinates});
let vulns = results[i].vulnerabilities;

if (vulns) {
if (vulns.length > 0) {
for (let j: number = 0; j < vulns.length; j++) {
let failure = testcase.ele("failure", { "type": vulns[j].title }, this.getVulnerabilityForXmlBlock(vulns[j]));
}
}
}
}

let xml = testsuite.end({ pretty: true });

console.log(xml);

if (this.getNumberOfVulnerablePackagesFromResults(results) > 0) {
return true;
}
return false;
}

private getNumberOfVulnerablePackagesFromResults(results: Array<OssIndexServerResult>): number {
return results.filter((x) => { return (x.vulnerabilities && x.vulnerabilities?.length > 0) }).length;
}

private getVulnerabilityForXmlBlock(vuln: Vulnerability): string {
let vulnBlock = "";
vulnBlock += `Vulnerability Title: ${vuln.title}\n`;
vulnBlock += `ID: ${vuln.id}\n`;
vulnBlock += `Description: ${vuln.description}\n`;
vulnBlock += `CVSS Score: ${vuln.cvssScore}\n`;
vulnBlock += `CVSS Vector: ${vuln.cvssVector}\n`;
vulnBlock += `CVE: ${vuln.cve}\n`;
vulnBlock += `Reference: ${vuln.reference}\n`;

return vulnBlock;
}

private getColorFromMaxScore(maxScore: number, defaultColor: string = 'darkblue'): string {
if (maxScore > 8) {
defaultColor = 'red';
Expand Down
8 changes: 7 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,12 @@ let argv = yargs
description: 'Set output to JSON',
demandOption: false
},
xml: {
alias: 'x',
type: 'boolean',
description: 'Set output to JUnit XML format',
demandOption: false
},
whitelist: {
alias: 'w',
type: 'string',
Expand Down Expand Up @@ -156,7 +162,7 @@ if (argv) {
throw new Error(e);
});
} else {
let silence = (argv.json || argv.quiet) ? true : false;
let silence = (argv.json || argv.quiet || argv.xml) ? true : false;
let artie = (argv.artie) ? true : false;

if (argv.server) {
Expand Down

0 comments on commit 7e26c6c

Please sign in to comment.