implemented CSV reports per #675

This commit is contained in:
Jeremy Long
2017-05-08 07:43:39 -04:00
parent 4c15993a44
commit e721dac389
7 changed files with 356 additions and 4 deletions

View File

@@ -19,7 +19,9 @@ package org.owasp.dependencycheck.reporting;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Set;
import org.apache.commons.lang3.StringEscapeUtils;
import org.owasp.dependencycheck.dependency.Identifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -94,4 +96,71 @@ public class EscapeTool {
}
return StringEscapeUtils.escapeJson(text);
}
/**
* Formats text for CSV format. This includes trimming whitespace, replace
* line breaks with spaces, and if necessary quotes the text and/or escapes
* contained quotes.
*
* @param text the text to escape and quote
* @return the escaped and quoted text
*/
public String csv(String text) {
if (text == null || text.isEmpty()) {
return text;
}
return StringEscapeUtils.escapeCsv(text.trim().replace("\n", " "));
}
/**
* Takes a set of Identifiers, filters them to none CPE, and formats them
* for display in a CSV.
*
* @param ids the set of identifiers
* @return the formated list of none CPE identifiers
*/
public String csvIdentifiers(Set<Identifier> ids) {
if (ids == null || ids.isEmpty()) {
return "";
}
boolean addComma = false;
StringBuilder sb = new StringBuilder();
for (Identifier id : ids) {
if (!"cpe".equals(id.getType())) {
if (addComma) {
sb.append(", ");
} else {
addComma = true;
}
sb.append(id.getValue());
}
}
return StringEscapeUtils.escapeCsv(sb.toString());
}
/**
* Takes a set of Identifiers, filters them to just CPEs, and formats them
* for display in a CSV.
*
* @param ids the set of identifiers
* @return the formated list of CPE identifiers
*/
public String csvCpe(Set<Identifier> ids) {
if (ids == null || ids.isEmpty()) {
return "";
}
boolean addComma = false;
StringBuilder sb = new StringBuilder();
for (Identifier id : ids) {
if ("cpe".equals(id.getType())) {
if (addComma) {
sb.append(", ");
} else {
addComma = true;
}
sb.append(id.getValue());
}
}
return StringEscapeUtils.escapeCsv(sb.toString());
}
}

View File

@@ -81,7 +81,11 @@ public class ReportGenerator {
/**
* Generate JSON report.
*/
JSON
JSON,
/**
* Generate CSV report.
*/
CSV
}
/**
* The Velocity Engine.
@@ -191,6 +195,9 @@ public class ReportGenerator {
if (format == Format.JSON || format == Format.ALL) {
generateReport("JsonReport", outputStream);
}
if (format == Format.CSV || format == Format.ALL) {
generateReport("CsvReport", outputStream);
}
}
/**
@@ -209,6 +216,9 @@ public class ReportGenerator {
generateReport("JsonReport", outputDir + File.separator + "dependency-check-report.json");
pretifyJson(outputDir + File.separator + "dependency-check-report.json");
}
if (format == Format.CSV || format == Format.ALL) {
generateReport("CsvReport", outputDir + File.separator + "dependency-check-report.csv");
}
if (format == Format.HTML || format == Format.ALL) {
generateReport("HtmlReport", outputDir + File.separator + "dependency-check-report.html");
}
@@ -344,6 +354,13 @@ public class ReportGenerator {
generateReports(outputDir, Format.JSON);
}
}
if ("CSV".equalsIgnoreCase(format)) {
if (pathToCheck.endsWith(".csv")) {
generateReport("CsvReport", outputDir);
} else {
generateReports(outputDir, Format.JSON);
}
}
if ("ALL".equalsIgnoreCase(format)) {
generateReports(outputDir, Format.ALL);
}

View File

@@ -0,0 +1,27 @@
#**
This file is part of Dependency-Check.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Copyright (c) 2017 Jeremy Long. All Rights Reserved.
@author Jeremy Long <jeremy.long@owasp.org>
@version 1 *###
"Project","ScanDate","DependencyName","DependencyPath","Description","License","Md5","Sha1","Identifiers","CPE","CVE","CWE","Vulnerability","Severity","CVSSv2"
#macro(writeSev $score)#if($score<4.0)"Low"#elseif($score>=7.0)"High"#else"Medium"#end#end
#foreach($dependency in $dependencies)#if($dependency.getVulnerabilities().size()>0)
#foreach($vuln in $dependency.getVulnerabilities())
$enc.csv($applicationName),$enc.csv($scanDate),$enc.csv($dependency.DisplayFileName),#if($dependency.FilePath)$enc.csv($dependency.FilePath)#end,#if($dependency.description)$enc.csv($dependency.description)#end,#if($dependency.license)$enc.csv($dependency.license)#end,#if($dependency.Md5sum)$enc.csv($dependency.Md5sum)#end,#if($dependency.Sha1sum)$enc.csv($dependency.Sha1sum)#end,#if($dependency.identifiers)$enc.csvIdentifiers($dependency.identifiers)#end,#if($dependency.identifiers)$enc.csvCpe($dependency.identifiers)#end,#if($vuln.name)$enc.csv($vuln.name)#end,#if($dependency.cwe)$enc.csv($vuln.cwe)#end,#if($vuln.description)$enc.csv($vuln.description)#end,#writeSev($vuln.cvssScore),$vuln.cvssScore
#end
#end
#end