mirror of
https://github.com/ysoftdevs/DependencyCheck.git
synced 2026-01-14 15:53:36 +01:00
Compare commits
2 Commits
reportGene
...
cvedb-cach
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3bdc6988b3 | ||
|
|
e86225c1e1 |
@@ -940,7 +940,16 @@ public class Check extends Update {
|
|||||||
throw new BuildException(ex);
|
throw new BuildException(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
engine.writeReports(getProjectName(),new File(reportOutputDirectory), reportFormat);
|
DatabaseProperties prop = null;
|
||||||
|
try (CveDB cve = CveDB.getInstance()) {
|
||||||
|
prop = cve.getDatabaseProperties();
|
||||||
|
} catch (DatabaseException ex) {
|
||||||
|
//TODO shouldn't this be a fatal exception
|
||||||
|
log("Unable to retrieve DB Properties", ex, Project.MSG_DEBUG);
|
||||||
|
}
|
||||||
|
|
||||||
|
final ReportGenerator reporter = new ReportGenerator(getProjectName(), engine.getDependencies(), engine.getAnalyzers(), prop);
|
||||||
|
reporter.generateReports(reportOutputDirectory, reportFormat);
|
||||||
|
|
||||||
if (this.failBuildOnCVSS <= 10) {
|
if (this.failBuildOnCVSS <= 10) {
|
||||||
checkForFailure(engine.getDependencies());
|
checkForFailure(engine.getDependencies());
|
||||||
|
|||||||
@@ -281,9 +281,18 @@ public class App {
|
|||||||
}
|
}
|
||||||
exCol = ex;
|
exCol = ex;
|
||||||
}
|
}
|
||||||
|
final List<Dependency> dependencies = engine.getDependencies();
|
||||||
|
DatabaseProperties prop = null;
|
||||||
|
try (CveDB cve = CveDB.getInstance()) {
|
||||||
|
prop = cve.getDatabaseProperties();
|
||||||
|
} catch (DatabaseException ex) {
|
||||||
|
//TODO shouldn't this be a fatal exception
|
||||||
|
LOGGER.debug("Unable to retrieve DB Properties", ex);
|
||||||
|
}
|
||||||
|
final ReportGenerator report = new ReportGenerator(applicationName, dependencies, engine.getAnalyzers(), prop);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
engine.writeReports(applicationName, new File(reportDirectory), outputFormat);
|
report.generateReports(reportDirectory, outputFormat);
|
||||||
} catch (ReportException ex) {
|
} catch (ReportException ex) {
|
||||||
if (exCol != null) {
|
if (exCol != null) {
|
||||||
exCol.addException(ex);
|
exCol.addException(ex);
|
||||||
@@ -297,7 +306,7 @@ public class App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Set the exit code based on whether we found a high enough vulnerability
|
//Set the exit code based on whether we found a high enough vulnerability
|
||||||
for (Dependency dep : engine.getDependencies()) {
|
for (Dependency dep : dependencies) {
|
||||||
if (!dep.getVulnerabilities().isEmpty()) {
|
if (!dep.getVulnerabilities().isEmpty()) {
|
||||||
for (Vulnerability vuln : dep.getVulnerabilities()) {
|
for (Vulnerability vuln : dep.getVulnerabilities()) {
|
||||||
LOGGER.debug("VULNERABILITY FOUND " + dep.getDisplayFileName());
|
LOGGER.debug("VULNERABILITY FOUND " + dep.getDisplayFileName());
|
||||||
@@ -307,6 +316,7 @@ public class App {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return retCode;
|
return retCode;
|
||||||
} finally {
|
} finally {
|
||||||
if (engine != null) {
|
if (engine != null) {
|
||||||
|
|||||||
@@ -54,9 +54,6 @@ import java.util.concurrent.ExecutorService;
|
|||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
|
|
||||||
import org.owasp.dependencycheck.exception.ReportException;
|
|
||||||
import org.owasp.dependencycheck.reporting.ReportGenerator;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scans files, directories, etc. for Dependencies. Analyzers are loaded and
|
* Scans files, directories, etc. for Dependencies. Analyzers are loaded and
|
||||||
@@ -799,42 +796,4 @@ public class Engine implements FileFilter {
|
|||||||
exceptions.add(throwable);
|
exceptions.add(throwable);
|
||||||
throw new ExceptionCollection(message, exceptions, true);
|
throw new ExceptionCollection(message, exceptions, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes the report to the given output directory.
|
|
||||||
*
|
|
||||||
* @param applicationName the name of the application/project
|
|
||||||
* @param groupId the Maven groupId
|
|
||||||
* @param artifactId the Maven artifactId
|
|
||||||
* @param version the Maven version
|
|
||||||
* @param outputDir the path to the output directory (can include the full
|
|
||||||
* file name if the format is not ALL)
|
|
||||||
* @param format the report format (ALL, HTML, CSV, JSON, etc.)
|
|
||||||
* @throws ReportException thrown if there is an error generating the report
|
|
||||||
*/
|
|
||||||
public void writeReports(String applicationName, String groupId, String artifactId,
|
|
||||||
String version, File outputDir, String format) throws ReportException {
|
|
||||||
|
|
||||||
DatabaseProperties prop = database.getDatabaseProperties();
|
|
||||||
final ReportGenerator r = new ReportGenerator(applicationName, groupId, artifactId, version, dependencies, getAnalyzers(), prop);
|
|
||||||
try {
|
|
||||||
r.write(outputDir.getAbsolutePath(), format);
|
|
||||||
} catch (ReportException ex) {
|
|
||||||
final String msg = String.format("Error generating the report for %s", applicationName);
|
|
||||||
throw new ReportException(msg, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes the report to the given output directory.
|
|
||||||
*
|
|
||||||
* @param applicationName the name of the application/project
|
|
||||||
* @param outputDir the path to the output directory (can include the full
|
|
||||||
* file name if the format is not ALL)
|
|
||||||
* @param format the report format (ALL, HTML, CSV, JSON, etc.)
|
|
||||||
* @throws ReportException thrown if there is an error generating the report
|
|
||||||
*/
|
|
||||||
public void writeReports(String applicationName, File outputDir, String format) throws ReportException {
|
|
||||||
writeReports(applicationName, null, null, null, outputDir, format);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -840,15 +840,21 @@ public class DependencyCheckScanAgent {
|
|||||||
*
|
*
|
||||||
* @param engine a dependency-check engine
|
* @param engine a dependency-check engine
|
||||||
* @param outDirectory the directory to write the reports to
|
* @param outDirectory the directory to write the reports to
|
||||||
* @throw ScanAgentException thrown if there is an error generating the
|
|
||||||
* report
|
|
||||||
*/
|
*/
|
||||||
private void generateExternalReports(Engine engine, File outDirectory) throws ScanAgentException {
|
private void generateExternalReports(Engine engine, File outDirectory) {
|
||||||
|
DatabaseProperties prop = null;
|
||||||
|
try (CveDB cve = CveDB.getInstance()) {
|
||||||
|
prop = cve.getDatabaseProperties();
|
||||||
|
} catch (DatabaseException ex) {
|
||||||
|
//TODO shouldn't this be a fatal exception
|
||||||
|
LOGGER.debug("Unable to retrieve DB Properties", ex);
|
||||||
|
}
|
||||||
|
final ReportGenerator r = new ReportGenerator(this.applicationName, engine.getDependencies(), engine.getAnalyzers(), prop);
|
||||||
try {
|
try {
|
||||||
engine.writeReports(applicationName, outDirectory, this.reportFormat.name());
|
r.generateReports(outDirectory.getCanonicalPath(), this.reportFormat.name());
|
||||||
} catch (ReportException ex) {
|
} catch (IOException | ReportException ex) {
|
||||||
LOGGER.debug("Unexpected exception occurred during analysis; please see the verbose error log for more details.", ex);
|
LOGGER.error("Unexpected exception occurred during analysis; please see the verbose error log for more details.");
|
||||||
throw new ScanAgentException("Error generating the report", ex);
|
LOGGER.debug("", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import java.sql.PreparedStatement;
|
|||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.EnumMap;
|
import java.util.EnumMap;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@@ -36,6 +37,7 @@ import java.util.Properties;
|
|||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.annotation.concurrent.ThreadSafe;
|
import javax.annotation.concurrent.ThreadSafe;
|
||||||
|
import org.apache.commons.collections.map.ReferenceMap;
|
||||||
import org.owasp.dependencycheck.data.cwe.CweDB;
|
import org.owasp.dependencycheck.data.cwe.CweDB;
|
||||||
import org.owasp.dependencycheck.dependency.Reference;
|
import org.owasp.dependencycheck.dependency.Reference;
|
||||||
import org.owasp.dependencycheck.dependency.Vulnerability;
|
import org.owasp.dependencycheck.dependency.Vulnerability;
|
||||||
@@ -48,6 +50,8 @@ import org.owasp.dependencycheck.utils.Settings;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import static org.apache.commons.collections.map.AbstractReferenceMap.HARD;
|
||||||
|
import static org.apache.commons.collections.map.AbstractReferenceMap.SOFT;
|
||||||
import static org.owasp.dependencycheck.data.nvdcve.CveDB.PreparedStatementCveDb.*;
|
import static org.owasp.dependencycheck.data.nvdcve.CveDB.PreparedStatementCveDb.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -91,6 +95,9 @@ public final class CveDB implements AutoCloseable {
|
|||||||
*/
|
*/
|
||||||
private final EnumMap<PreparedStatementCveDb, PreparedStatement> preparedStatements = new EnumMap<>(PreparedStatementCveDb.class);
|
private final EnumMap<PreparedStatementCveDb, PreparedStatement> preparedStatements = new EnumMap<>(PreparedStatementCveDb.class);
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private final Map<String, List<Vulnerability>> vulnerabilitiesForCpeCache = Collections.synchronizedMap(new ReferenceMap(HARD, SOFT));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The enum value names must match the keys of the statements in the
|
* The enum value names must match the keys of the statements in the
|
||||||
* statement bundles "dbStatements*.properties".
|
* statement bundles "dbStatements*.properties".
|
||||||
@@ -269,6 +276,7 @@ public final class CveDB implements AutoCloseable {
|
|||||||
instance.usageCount -= 1;
|
instance.usageCount -= 1;
|
||||||
if (instance.usageCount <= 0 && instance.isOpen()) {
|
if (instance.usageCount <= 0 && instance.isOpen()) {
|
||||||
instance.usageCount = 0;
|
instance.usageCount = 0;
|
||||||
|
clearCache();
|
||||||
instance.closeStatements();
|
instance.closeStatements();
|
||||||
try {
|
try {
|
||||||
instance.connection.close();
|
instance.connection.close();
|
||||||
@@ -474,6 +482,7 @@ public final class CveDB implements AutoCloseable {
|
|||||||
* @param value the property value
|
* @param value the property value
|
||||||
*/
|
*/
|
||||||
public synchronized void saveProperty(String key, String value) {
|
public synchronized void saveProperty(String key, String value) {
|
||||||
|
clearCache();
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
final PreparedStatement mergeProperty = getPreparedStatement(MERGE_PROPERTY);
|
final PreparedStatement mergeProperty = getPreparedStatement(MERGE_PROPERTY);
|
||||||
@@ -498,6 +507,17 @@ public final class CveDB implements AutoCloseable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears cache. Should be called whenever something is modified. While this is not the optimal cache eviction
|
||||||
|
* strategy, this is good enough for typical usage (update DB and then only read) and it is easier to maintain
|
||||||
|
* the code.
|
||||||
|
*
|
||||||
|
* It should be also called when DB is closed.
|
||||||
|
*/
|
||||||
|
private void clearCache() {
|
||||||
|
vulnerabilitiesForCpeCache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the vulnerabilities associated with the specified CPE.
|
* Retrieves the vulnerabilities associated with the specified CPE.
|
||||||
*
|
*
|
||||||
@@ -506,6 +526,13 @@ public final class CveDB implements AutoCloseable {
|
|||||||
* @throws DatabaseException thrown if there is an exception retrieving data
|
* @throws DatabaseException thrown if there is an exception retrieving data
|
||||||
*/
|
*/
|
||||||
public synchronized List<Vulnerability> getVulnerabilities(String cpeStr) throws DatabaseException {
|
public synchronized List<Vulnerability> getVulnerabilities(String cpeStr) throws DatabaseException {
|
||||||
|
final List<Vulnerability> cachedVulnerabilities = vulnerabilitiesForCpeCache.get(cpeStr);
|
||||||
|
if (cachedVulnerabilities != null) {
|
||||||
|
LOGGER.debug("Cache hit for {}", cpeStr);
|
||||||
|
return cachedVulnerabilities;
|
||||||
|
} else {
|
||||||
|
LOGGER.debug("Cache miss for {}", cpeStr);
|
||||||
|
}
|
||||||
final VulnerableSoftware cpe = new VulnerableSoftware();
|
final VulnerableSoftware cpe = new VulnerableSoftware();
|
||||||
try {
|
try {
|
||||||
cpe.parseName(cpeStr);
|
cpe.parseName(cpeStr);
|
||||||
@@ -554,6 +581,7 @@ public final class CveDB implements AutoCloseable {
|
|||||||
} finally {
|
} finally {
|
||||||
DBUtils.closeResultSet(rs);
|
DBUtils.closeResultSet(rs);
|
||||||
}
|
}
|
||||||
|
vulnerabilitiesForCpeCache.put(cpeStr, vulnerabilities);
|
||||||
return vulnerabilities;
|
return vulnerabilities;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -633,6 +661,7 @@ public final class CveDB implements AutoCloseable {
|
|||||||
* @throws DatabaseException is thrown if the database
|
* @throws DatabaseException is thrown if the database
|
||||||
*/
|
*/
|
||||||
public synchronized void updateVulnerability(Vulnerability vuln) throws DatabaseException {
|
public synchronized void updateVulnerability(Vulnerability vuln) throws DatabaseException {
|
||||||
|
clearCache();
|
||||||
try {
|
try {
|
||||||
int vulnerabilityId = 0;
|
int vulnerabilityId = 0;
|
||||||
final PreparedStatement selectVulnerabilityId = getPreparedStatement(SELECT_VULNERABILITY_ID);
|
final PreparedStatement selectVulnerabilityId = getPreparedStatement(SELECT_VULNERABILITY_ID);
|
||||||
@@ -799,6 +828,7 @@ public final class CveDB implements AutoCloseable {
|
|||||||
* ensure orphan entries are removed.
|
* ensure orphan entries are removed.
|
||||||
*/
|
*/
|
||||||
public synchronized void cleanupDatabase() {
|
public synchronized void cleanupDatabase() {
|
||||||
|
clearCache();
|
||||||
try {
|
try {
|
||||||
final PreparedStatement ps = getPreparedStatement(CLEANUP_ORPHANS);
|
final PreparedStatement ps = getPreparedStatement(CLEANUP_ORPHANS);
|
||||||
if (ps != null) {
|
if (ps != null) {
|
||||||
@@ -934,6 +964,7 @@ public final class CveDB implements AutoCloseable {
|
|||||||
* Deletes unused dictionary entries from the database.
|
* Deletes unused dictionary entries from the database.
|
||||||
*/
|
*/
|
||||||
public synchronized void deleteUnusedCpe() {
|
public synchronized void deleteUnusedCpe() {
|
||||||
|
clearCache();
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
try {
|
try {
|
||||||
ps = connection.prepareStatement(statementBundle.getString("DELETE_UNUSED_DICT_CPE"));
|
ps = connection.prepareStatement(statementBundle.getString("DELETE_UNUSED_DICT_CPE"));
|
||||||
@@ -956,6 +987,7 @@ public final class CveDB implements AutoCloseable {
|
|||||||
* @param product the CPE product
|
* @param product the CPE product
|
||||||
*/
|
*/
|
||||||
public synchronized void addCpe(String cpe, String vendor, String product) {
|
public synchronized void addCpe(String cpe, String vendor, String product) {
|
||||||
|
clearCache();
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
try {
|
try {
|
||||||
ps = connection.prepareStatement(statementBundle.getString("ADD_DICT_CPE"));
|
ps = connection.prepareStatement(statementBundle.getString("ADD_DICT_CPE"));
|
||||||
|
|||||||
@@ -107,8 +107,29 @@ public class ReportGenerator {
|
|||||||
*/
|
*/
|
||||||
public ReportGenerator(String applicationName, List<Dependency> dependencies, List<Analyzer> analyzers, DatabaseProperties properties) {
|
public ReportGenerator(String applicationName, List<Dependency> dependencies, List<Analyzer> analyzers, DatabaseProperties properties) {
|
||||||
velocityEngine = createVelocityEngine();
|
velocityEngine = createVelocityEngine();
|
||||||
|
context = createContext();
|
||||||
|
|
||||||
velocityEngine.init();
|
velocityEngine.init();
|
||||||
context = createContext(applicationName, dependencies, analyzers, properties);
|
final EscapeTool enc = new EscapeTool();
|
||||||
|
|
||||||
|
final DateTime dt = new DateTime();
|
||||||
|
final DateTimeFormatter dateFormat = DateTimeFormat.forPattern("MMM d, yyyy 'at' HH:mm:ss z");
|
||||||
|
final DateTimeFormatter dateFormatXML = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
|
||||||
|
|
||||||
|
// final Date d = new Date();
|
||||||
|
// final DateFormat dateFormat = new SimpleDateFormat("MMM d, yyyy 'at' HH:mm:ss z");
|
||||||
|
// final DateFormat dateFormatXML = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
|
||||||
|
final String scanDate = dateFormat.print(dt);
|
||||||
|
final String scanDateXML = dateFormatXML.print(dt);
|
||||||
|
|
||||||
|
context.put("applicationName", applicationName);
|
||||||
|
context.put("dependencies", dependencies);
|
||||||
|
context.put("analyzers", analyzers);
|
||||||
|
context.put("properties", properties);
|
||||||
|
context.put("scanDate", scanDate);
|
||||||
|
context.put("scanDateXML", scanDateXML);
|
||||||
|
context.put("enc", enc);
|
||||||
|
context.put("version", Settings.getString(Settings.KEYS.APPLICATION_VERSION, "Unknown"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -127,15 +148,9 @@ public class ReportGenerator {
|
|||||||
List<Dependency> dependencies, List<Analyzer> analyzers, DatabaseProperties properties) {
|
List<Dependency> dependencies, List<Analyzer> analyzers, DatabaseProperties properties) {
|
||||||
|
|
||||||
this(applicationName, dependencies, analyzers, properties);
|
this(applicationName, dependencies, analyzers, properties);
|
||||||
if (version != null) {
|
context.put("applicationVersion", version);
|
||||||
context.put("applicationVersion", version);
|
context.put("artifactID", artifactID);
|
||||||
}
|
context.put("groupID", groupID);
|
||||||
if (artifactID != null) {
|
|
||||||
context.put("artifactID", artifactID);
|
|
||||||
}
|
|
||||||
if (groupID != null) {
|
|
||||||
context.put("groupID", groupID);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -151,235 +166,67 @@ public class ReportGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs the velocity context used to generate the dependency-check
|
* Creates a new Velocity Context.
|
||||||
* reports.
|
|
||||||
*
|
*
|
||||||
* @param applicationName the application name being analyzed
|
* @return a Velocity Context
|
||||||
* @param dependencies the list of dependencies
|
|
||||||
* @param analyzers the list of analyzers used
|
|
||||||
* @param properties the database properties (containing timestamps of the
|
|
||||||
* NVD CVE data)
|
|
||||||
* @return the velocity context
|
|
||||||
*/
|
*/
|
||||||
private VelocityContext createContext(String applicationName, List<Dependency> dependencies, List<Analyzer> analyzers, DatabaseProperties properties) {
|
private Context createContext() {
|
||||||
final DateTime dt = new DateTime();
|
return new VelocityContext();
|
||||||
final DateTimeFormatter dateFormat = DateTimeFormat.forPattern("MMM d, yyyy 'at' HH:mm:ss z");
|
|
||||||
final DateTimeFormatter dateFormatXML = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
|
|
||||||
|
|
||||||
final String scanDate = dateFormat.print(dt);
|
|
||||||
final String scanDateXML = dateFormatXML.print(dt);
|
|
||||||
|
|
||||||
VelocityContext ctxt = new VelocityContext();
|
|
||||||
ctxt.put("applicationName", applicationName);
|
|
||||||
ctxt.put("dependencies", dependencies);
|
|
||||||
ctxt.put("analyzers", analyzers);
|
|
||||||
ctxt.put("properties", properties);
|
|
||||||
ctxt.put("scanDate", scanDate);
|
|
||||||
ctxt.put("scanDateXML", scanDateXML);
|
|
||||||
ctxt.put("enc", new EscapeTool());
|
|
||||||
ctxt.put("version", Settings.getString(Settings.KEYS.APPLICATION_VERSION, "Unknown"));
|
|
||||||
return ctxt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes the dependency-check report to the given output location.
|
* Generates the Dependency Reports for the identified dependencies.
|
||||||
*
|
*
|
||||||
* @param outputLocation the path where the reports should be written
|
* @param outputStream the OutputStream to send the generated report to
|
||||||
* @param format the format the report should be written in (XML, HTML,
|
* @param format the format the report should be written in
|
||||||
* JSON, CSV, ALL) or even the path to a custom velocity template (either
|
* @throws IOException is thrown when the template file does not exist
|
||||||
* fully qualified or the template name on the class path).
|
* @throws Exception is thrown if there is an error writing out the reports
|
||||||
* @throws ReportException is thrown if there is an error creating out the
|
*/
|
||||||
|
public void generateReports(OutputStream outputStream, Format format) throws IOException, Exception {
|
||||||
|
if (format == Format.XML || format == Format.ALL) {
|
||||||
|
generateReport("XmlReport", outputStream);
|
||||||
|
}
|
||||||
|
if (format == Format.HTML || format == Format.ALL) {
|
||||||
|
generateReport("HtmlReport", outputStream);
|
||||||
|
}
|
||||||
|
if (format == Format.VULN || format == Format.ALL) {
|
||||||
|
generateReport("VulnerabilityReport", outputStream);
|
||||||
|
}
|
||||||
|
if (format == Format.JSON || format == Format.ALL) {
|
||||||
|
generateReport("JsonReport", outputStream);
|
||||||
|
}
|
||||||
|
if (format == Format.CSV || format == Format.ALL) {
|
||||||
|
generateReport("CsvReport", outputStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the Dependency Reports for the identified dependencies.
|
||||||
|
*
|
||||||
|
* @param outputDir the path where the reports should be written
|
||||||
|
* @param format the format the report should be written in
|
||||||
|
* @throws ReportException is thrown if there is an error writing out the
|
||||||
* reports
|
* reports
|
||||||
*/
|
*/
|
||||||
public void write(String outputLocation, String format) throws ReportException {
|
public void generateReports(String outputDir, Format format) throws ReportException {
|
||||||
Format reportFormat = null;
|
if (format == Format.XML || format == Format.ALL) {
|
||||||
try {
|
generateReport("XmlReport", outputDir + File.separator + "dependency-check-report.xml");
|
||||||
reportFormat = Format.valueOf(format.toUpperCase());
|
|
||||||
} catch (IllegalArgumentException ex) {
|
|
||||||
LOGGER.trace("ignore this exception", ex);
|
|
||||||
}
|
}
|
||||||
|
if (format == Format.JSON || format == Format.ALL) {
|
||||||
if (reportFormat != null) {
|
generateReport("JsonReport", outputDir + File.separator + "dependency-check-report.json");
|
||||||
write(outputLocation, reportFormat);
|
pretifyJson(outputDir + File.separator + "dependency-check-report.json");
|
||||||
} else {
|
|
||||||
File out = getReportFile(outputLocation, null);
|
|
||||||
if (out.isDirectory()) {
|
|
||||||
throw new ReportException("Unable to write non-standard VSL output to a directory, please specify a file name");
|
|
||||||
}
|
|
||||||
processTemplate(format, out);
|
|
||||||
}
|
}
|
||||||
|
if (format == Format.CSV || format == Format.ALL) {
|
||||||
}
|
generateReport("CsvReport", outputDir + File.separator + "dependency-check-report.csv");
|
||||||
|
}
|
||||||
/**
|
if (format == Format.HTML || format == Format.ALL) {
|
||||||
* Writes the dependency-check report(s).
|
generateReport("HtmlReport", outputDir + File.separator + "dependency-check-report.html");
|
||||||
*
|
}
|
||||||
* @param outputLocation the path where the reports should be written
|
if (format == Format.VULN || format == Format.ALL) {
|
||||||
* @param format the format the report should be written in (XML, HTML, ALL)
|
generateReport("VulnerabilityReport", outputDir + File.separator + "dependency-check-vulnerability.html");
|
||||||
* @throws ReportException is thrown if there is an error creating out the
|
|
||||||
* reports
|
|
||||||
*/
|
|
||||||
public void write(String outputLocation, Format format) throws ReportException {
|
|
||||||
if (format == Format.ALL) {
|
|
||||||
for (Format f : Format.values()) {
|
|
||||||
if (f != Format.ALL) {
|
|
||||||
write(outputLocation, f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
final File out = getReportFile(outputLocation, format);
|
|
||||||
final String templateName = format.toString().toLowerCase() + "Report";
|
|
||||||
processTemplate(templateName, out);
|
|
||||||
if (format == Format.JSON) {
|
|
||||||
pretifyJson(out.getPath());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// /**
|
|
||||||
// * Writes the dependency-check report(s).
|
|
||||||
// *
|
|
||||||
// * @param outputStream the OutputStream to send the generated report to
|
|
||||||
// * @param format the format the report should be written in
|
|
||||||
// * @throws ReportException thrown if the report format is ALL
|
|
||||||
// * @throws IOException is thrown when the template file does not exist
|
|
||||||
// * @throws Exception is thrown if there is an error writing out the reports
|
|
||||||
// */
|
|
||||||
// public void write(OutputStream outputStream, Format format) throws ReportException, IOException, Exception {
|
|
||||||
// if (format == Format.ALL) {
|
|
||||||
// throw new ReportException("Unable to write ALL reports to a single output stream, please check the API");
|
|
||||||
// }
|
|
||||||
// final String templateName = format.toString().toLowerCase() + "Report";
|
|
||||||
// processTemplate(templateName, outputStream);
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines the report file name based on the give output location and
|
|
||||||
* format. If the output location contains a full file name that has the
|
|
||||||
* correct extension for the given report type then the output location is
|
|
||||||
* returned. However, if the output location is a directory, this method
|
|
||||||
* will generate the correct name for the given output format.
|
|
||||||
*
|
|
||||||
* @param outputLocation the specified output location
|
|
||||||
* @param format the report format
|
|
||||||
* @return the report File
|
|
||||||
*/
|
|
||||||
protected File getReportFile(String outputLocation, Format format) {
|
|
||||||
File outFile = new File(outputLocation);
|
|
||||||
if (outFile.getParentFile() == null) {
|
|
||||||
outFile = new File(".", outputLocation);
|
|
||||||
}
|
|
||||||
final String pathToCheck = outputLocation.toLowerCase();
|
|
||||||
if (format == Format.XML && !pathToCheck.endsWith(".xml")) {
|
|
||||||
return new File(outFile, "dependency-check-report.xml");
|
|
||||||
}
|
|
||||||
if (format == Format.HTML && !pathToCheck.endsWith(".html") && !pathToCheck.endsWith(".htm")) {
|
|
||||||
return new File(outFile, "dependency-check-report.html");
|
|
||||||
}
|
|
||||||
if (format == Format.VULN && !pathToCheck.endsWith(".html") && !pathToCheck.endsWith(".htm")) {
|
|
||||||
return new File(outFile, "dependency-check-vulnerability.html");
|
|
||||||
}
|
|
||||||
if (format == Format.JSON && !pathToCheck.endsWith(".json")) {
|
|
||||||
return new File(outFile, "dependency-check-report.json");
|
|
||||||
}
|
|
||||||
if (format == Format.CSV && !pathToCheck.endsWith(".csv")) {
|
|
||||||
return new File(outFile, "dependency-check-report.csv");
|
|
||||||
}
|
|
||||||
return outFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a report from a given Velocity Template. The template name
|
|
||||||
* provided can be the name of a template contained in the jar file, such as
|
|
||||||
* 'XmlReport' or 'HtmlReport', or the template name can be the path to a
|
|
||||||
* template file.
|
|
||||||
*
|
|
||||||
* @param template the name of the template to load
|
|
||||||
* @param file the output file to write the report to
|
|
||||||
* @throws ReportException is thrown when the report cannot be generated
|
|
||||||
*/
|
|
||||||
protected void processTemplate(String template, File file) throws ReportException {
|
|
||||||
ensureParentDirectoryExists(file);
|
|
||||||
try (OutputStream output = new FileOutputStream(file)) {
|
|
||||||
processTemplate(template, output);
|
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new ReportException(String.format("Unable to write to file: %s", file), ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a report from a given Velocity Template. The template name
|
|
||||||
* provided can be the name of a template contained in the jar file, such as
|
|
||||||
* 'XmlReport' or 'HtmlReport', or the template name can be the path to a
|
|
||||||
* template file.
|
|
||||||
*
|
|
||||||
* @param templateName the name of the template to load
|
|
||||||
* @param outputStream the OutputStream to write the report to
|
|
||||||
* @throws ReportException is thrown when an exception occurs
|
|
||||||
*/
|
|
||||||
protected void processTemplate(String templateName, OutputStream outputStream) throws ReportException {
|
|
||||||
InputStream input = null;
|
|
||||||
String logTag = null;
|
|
||||||
final File f = new File(templateName);
|
|
||||||
try {
|
|
||||||
if (f.isFile()) {
|
|
||||||
try {
|
|
||||||
logTag = templateName;
|
|
||||||
input = new FileInputStream(f);
|
|
||||||
} catch (FileNotFoundException ex) {
|
|
||||||
throw new ReportException("Unable to locate template file: " + templateName, ex);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
logTag = "templates/" + templateName + ".vsl";
|
|
||||||
input = this.getClass().getClassLoader().getResourceAsStream(logTag);
|
|
||||||
}
|
|
||||||
if (input == null) {
|
|
||||||
logTag = templateName;
|
|
||||||
input = this.getClass().getClassLoader().getResourceAsStream(templateName);
|
|
||||||
}
|
|
||||||
if (input == null) {
|
|
||||||
throw new ReportException("Template file doesn't exist: " + logTag);
|
|
||||||
}
|
|
||||||
|
|
||||||
try (InputStreamReader reader = new InputStreamReader(input, "UTF-8");
|
|
||||||
OutputStreamWriter writer = new OutputStreamWriter(outputStream, "UTF-8")) {
|
|
||||||
if (!velocityEngine.evaluate(context, writer, logTag, reader)) {
|
|
||||||
throw new ReportException("Failed to convert the template into html.");
|
|
||||||
}
|
|
||||||
writer.flush();
|
|
||||||
} catch (UnsupportedEncodingException ex) {
|
|
||||||
throw new ReportException("Unable to generate the report using UTF-8", ex);
|
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new ReportException("Unable to write the report", ex);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (input != null) {
|
|
||||||
try {
|
|
||||||
input.close();
|
|
||||||
} catch (IOException ex) {
|
|
||||||
LOGGER.trace("Error closing input", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Validates that the given file's parent directory exists. If the directory
|
|
||||||
* does not exist an attempt to create the necessary path is made; if that
|
|
||||||
* fails a ReportException will be raised.
|
|
||||||
*
|
|
||||||
* @param file the file or directory directory
|
|
||||||
* @throws ReportException thrown if the parent directory does not exist and
|
|
||||||
* cannot be created
|
|
||||||
*/
|
|
||||||
private void ensureParentDirectoryExists(File file) throws ReportException {
|
|
||||||
if (!file.getParentFile().exists()) {
|
|
||||||
final boolean created = file.getParentFile().mkdirs();
|
|
||||||
if (!created) {
|
|
||||||
final String msg = String.format("Unable to create directory '%s'.", file.getParentFile().getAbsolutePath());
|
|
||||||
throw new ReportException(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Reformats the given JSON file.
|
* Reformats the given JSON file.
|
||||||
*
|
*
|
||||||
@@ -464,4 +311,139 @@ public class ReportGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the Dependency Reports for the identified dependencies.
|
||||||
|
*
|
||||||
|
* @param outputDir the path where the reports should be written
|
||||||
|
* @param outputFormat the format the report should be written in (XML,
|
||||||
|
* HTML, ALL)
|
||||||
|
* @throws ReportException is thrown if there is an error creating out the
|
||||||
|
* reports
|
||||||
|
*/
|
||||||
|
public void generateReports(String outputDir, String outputFormat) throws ReportException {
|
||||||
|
final String format = outputFormat.toUpperCase();
|
||||||
|
final String pathToCheck = outputDir.toLowerCase();
|
||||||
|
if (format.matches("^(XML|HTML|VULN|JSON|ALL)$")) {
|
||||||
|
if ("XML".equalsIgnoreCase(format)) {
|
||||||
|
if (pathToCheck.endsWith(".xml")) {
|
||||||
|
generateReport("XmlReport", outputDir);
|
||||||
|
} else {
|
||||||
|
generateReports(outputDir, Format.XML);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ("HTML".equalsIgnoreCase(format)) {
|
||||||
|
if (pathToCheck.endsWith(".html") || pathToCheck.endsWith(".htm")) {
|
||||||
|
generateReport("HtmlReport", outputDir);
|
||||||
|
} else {
|
||||||
|
generateReports(outputDir, Format.HTML);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ("VULN".equalsIgnoreCase(format)) {
|
||||||
|
if (pathToCheck.endsWith(".html") || pathToCheck.endsWith(".htm")) {
|
||||||
|
generateReport("VulnReport", outputDir);
|
||||||
|
} else {
|
||||||
|
generateReports(outputDir, Format.VULN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ("JSON".equalsIgnoreCase(format)) {
|
||||||
|
if (pathToCheck.endsWith(".json")) {
|
||||||
|
generateReport("JsonReport", outputDir);
|
||||||
|
pretifyJson(outputDir);
|
||||||
|
} else {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a report from a given Velocity Template. The template name
|
||||||
|
* provided can be the name of a template contained in the jar file, such as
|
||||||
|
* 'XmlReport' or 'HtmlReport', or the template name can be the path to a
|
||||||
|
* template file.
|
||||||
|
*
|
||||||
|
* @param templateName the name of the template to load
|
||||||
|
* @param outputStream the OutputStream to write the report to
|
||||||
|
* @throws ReportException is thrown when an exception occurs
|
||||||
|
*/
|
||||||
|
protected void generateReport(String templateName, OutputStream outputStream) throws ReportException {
|
||||||
|
InputStream input = null;
|
||||||
|
String templatePath = null;
|
||||||
|
final File f = new File(templateName);
|
||||||
|
try {
|
||||||
|
if (f.exists() && f.isFile()) {
|
||||||
|
try {
|
||||||
|
templatePath = templateName;
|
||||||
|
input = new FileInputStream(f);
|
||||||
|
} catch (FileNotFoundException ex) {
|
||||||
|
throw new ReportException("Unable to locate template file: " + templateName, ex);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
templatePath = "templates/" + templateName + ".vsl";
|
||||||
|
input = this.getClass().getClassLoader().getResourceAsStream(templatePath);
|
||||||
|
}
|
||||||
|
if (input == null) {
|
||||||
|
throw new ReportException("Template file doesn't exist: " + templatePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
try (InputStreamReader reader = new InputStreamReader(input, "UTF-8");
|
||||||
|
OutputStreamWriter writer = new OutputStreamWriter(outputStream, "UTF-8")) {
|
||||||
|
if (!velocityEngine.evaluate(context, writer, templatePath, reader)) {
|
||||||
|
throw new ReportException("Failed to convert the template into html.");
|
||||||
|
}
|
||||||
|
writer.flush();
|
||||||
|
} catch (UnsupportedEncodingException ex) {
|
||||||
|
throw new ReportException("Unable to generate the report using UTF-8", ex);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new ReportException("Unable to write the report", ex);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (input != null) {
|
||||||
|
try {
|
||||||
|
input.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LOGGER.trace("Error closing input", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a report from a given Velocity Template. The template name
|
||||||
|
* provided can be the name of a template contained in the jar file, such as
|
||||||
|
* 'XmlReport' or 'HtmlReport', or the template name can be the path to a
|
||||||
|
* template file.
|
||||||
|
*
|
||||||
|
* @param templateName the name of the template to load
|
||||||
|
* @param outFileName the filename and path to write the report to
|
||||||
|
* @throws ReportException is thrown when the report cannot be generated
|
||||||
|
*/
|
||||||
|
protected void generateReport(String templateName, String outFileName) throws ReportException {
|
||||||
|
File outFile = new File(outFileName);
|
||||||
|
if (outFile.getParentFile() == null) {
|
||||||
|
outFile = new File(".", outFileName);
|
||||||
|
}
|
||||||
|
if (!outFile.getParentFile().exists()) {
|
||||||
|
final boolean created = outFile.getParentFile().mkdirs();
|
||||||
|
if (!created) {
|
||||||
|
throw new ReportException("Unable to create directory '" + outFile.getParentFile().getAbsolutePath() + "'.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try (OutputStream outputSteam = new FileOutputStream(outFile)) {
|
||||||
|
generateReport(templateName, outputSteam);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new ReportException("Unable to write to file: " + outFile, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.owasp.dependencycheck;
|
package org.owasp.dependencycheck;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
@@ -73,7 +72,12 @@ public class EngineIT extends BaseDBTestCase {
|
|||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
instance.writeReports("dependency-check sample", new File("./target/"), "ALL");
|
DatabaseProperties prop = null;
|
||||||
|
try (CveDB cve = CveDB.getInstance()) {
|
||||||
|
prop = cve.getDatabaseProperties();
|
||||||
|
}
|
||||||
|
ReportGenerator rg = new ReportGenerator("DependencyCheck", instance.getDependencies(), instance.getAnalyzers(), prop);
|
||||||
|
rg.generateReports("./target/", "ALL");
|
||||||
instance.cleanup();
|
instance.cleanup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,12 +25,15 @@ import javax.xml.transform.stream.StreamSource;
|
|||||||
import javax.xml.validation.Schema;
|
import javax.xml.validation.Schema;
|
||||||
import javax.xml.validation.SchemaFactory;
|
import javax.xml.validation.SchemaFactory;
|
||||||
import javax.xml.validation.Validator;
|
import javax.xml.validation.Validator;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.owasp.dependencycheck.BaseDBTestCase;
|
import org.owasp.dependencycheck.BaseDBTestCase;
|
||||||
import org.owasp.dependencycheck.BaseTest;
|
import org.owasp.dependencycheck.BaseTest;
|
||||||
import org.owasp.dependencycheck.Engine;
|
import org.owasp.dependencycheck.Engine;
|
||||||
|
import org.owasp.dependencycheck.data.nvdcve.CveDB;
|
||||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||||
|
import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
|
||||||
import org.owasp.dependencycheck.exception.ExceptionCollection;
|
import org.owasp.dependencycheck.exception.ExceptionCollection;
|
||||||
import org.owasp.dependencycheck.exception.ReportException;
|
import org.owasp.dependencycheck.exception.ReportException;
|
||||||
import org.owasp.dependencycheck.utils.InvalidSettingException;
|
import org.owasp.dependencycheck.utils.InvalidSettingException;
|
||||||
@@ -44,6 +47,67 @@ import static org.junit.Assert.fail;
|
|||||||
*/
|
*/
|
||||||
public class ReportGeneratorIT extends BaseDBTestCase {
|
public class ReportGeneratorIT extends BaseDBTestCase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of generateReport method, of class ReportGenerator.
|
||||||
|
*
|
||||||
|
* @throws Exception is thrown when an exception occurs.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testGenerateReport() throws Exception {
|
||||||
|
// String templateName = "HtmlReport";
|
||||||
|
// File f = new File("target/test-reports");
|
||||||
|
// if (!f.exists()) {
|
||||||
|
// f.mkdir();
|
||||||
|
// }
|
||||||
|
// String writeTo = "target/test-reports/Report.html";
|
||||||
|
// Map<String, Object> properties = new HashMap<String, Object>();
|
||||||
|
// Dependency d = new Dependency();
|
||||||
|
// d.setFileName("FileName.jar");
|
||||||
|
// d.setActualFilePath("lib/FileName.jar");
|
||||||
|
// d.addCPEentry("cpe://a:/some:cpe:1.0");
|
||||||
|
//
|
||||||
|
// List<Dependency> dependencies = new ArrayList<Dependency>();
|
||||||
|
// d.getProductEvidence().addEvidence("jar","filename","<test>test", Confidence.HIGH);
|
||||||
|
// d.getProductEvidence().addEvidence("manifest","vendor","<test>test", Confidence.HIGH);
|
||||||
|
//
|
||||||
|
// for (Evidence e : d.getProductEvidence().iterator(Confidence.HIGH)) {
|
||||||
|
// String t = e.getValue();
|
||||||
|
// }
|
||||||
|
// dependencies.add(d);
|
||||||
|
//
|
||||||
|
// Dependency d2 = new Dependency();
|
||||||
|
// d2.setFileName("Another.jar");
|
||||||
|
// d2.setActualFilePath("lib/Another.jar");
|
||||||
|
// d2.addCPEentry("cpe://a:/another:cpe:1.0");
|
||||||
|
// d2.addCPEentry("cpe://a:/another:cpe:1.1");
|
||||||
|
// d2.addCPEentry("cpe://a:/another:cpe:1.2");
|
||||||
|
// d2.getProductEvidence().addEvidence("jar","filename","another.jar", Confidence.HIGH);
|
||||||
|
// d2.getProductEvidence().addEvidence("manifest","vendor","Company A", Confidence.MEDIUM);
|
||||||
|
//
|
||||||
|
// for (Evidence e : d2.getProductEvidence().iterator(Confidence.HIGH)) {
|
||||||
|
// String t = e.getValue();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// dependencies.add(d2);
|
||||||
|
//
|
||||||
|
// Dependency d3 = new Dependency();
|
||||||
|
// d3.setFileName("Third.jar");
|
||||||
|
// d3.setActualFilePath("lib/Third.jar");
|
||||||
|
// d3.getProductEvidence().addEvidence("jar","filename","third.jar", Confidence.HIGH);
|
||||||
|
//
|
||||||
|
// for (Evidence e : d3.getProductEvidence().iterator(Confidence.HIGH)) {
|
||||||
|
// String t = e.getValue();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// dependencies.add(d3);
|
||||||
|
//
|
||||||
|
// properties.put("dependencies",dependencies);
|
||||||
|
//
|
||||||
|
// ReportGenerator instance = new ReportGenerator();
|
||||||
|
// instance.generateReport(templateName, writeTo, properties);
|
||||||
|
//assertTrue("need to add a real check here", false);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates an XML report containing known vulnerabilities and realistic
|
* Generates an XML report containing known vulnerabilities and realistic
|
||||||
* data and validates the generated XML document against the XSD.
|
* data and validates the generated XML document against the XSD.
|
||||||
@@ -51,7 +115,7 @@ public class ReportGeneratorIT extends BaseDBTestCase {
|
|||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testGenerateReport() {
|
public void testGenerateXMLReport() {
|
||||||
try {
|
try {
|
||||||
String templateName = "XmlReport";
|
String templateName = "XmlReport";
|
||||||
|
|
||||||
@@ -59,7 +123,7 @@ public class ReportGeneratorIT extends BaseDBTestCase {
|
|||||||
if (!f.exists()) {
|
if (!f.exists()) {
|
||||||
f.mkdir();
|
f.mkdir();
|
||||||
}
|
}
|
||||||
File writeTo = new File("target/test-reports/Report.xml");
|
String writeTo = "target/test-reports/Report.xml";
|
||||||
File suppressionFile = BaseTest.getResourceAsFile(this, "incorrectSuppressions.xml");
|
File suppressionFile = BaseTest.getResourceAsFile(this, "incorrectSuppressions.xml");
|
||||||
|
|
||||||
Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppressionFile.getAbsolutePath());
|
Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppressionFile.getAbsolutePath());
|
||||||
@@ -71,20 +135,29 @@ public class ReportGeneratorIT extends BaseDBTestCase {
|
|||||||
//File jetty = new File(this.getClass().getClassLoader().getResource("org.mortbay.jetty.jar").getPath());
|
//File jetty = new File(this.getClass().getClassLoader().getResource("org.mortbay.jetty.jar").getPath());
|
||||||
File jetty = BaseTest.getResourceAsFile(this, "org.mortbay.jetty.jar");
|
File jetty = BaseTest.getResourceAsFile(this, "org.mortbay.jetty.jar");
|
||||||
|
|
||||||
|
boolean autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE);
|
||||||
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
|
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
|
||||||
Engine engine = new Engine();
|
Engine engine = new Engine();
|
||||||
|
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
|
||||||
|
|
||||||
engine.scan(struts);
|
engine.scan(struts);
|
||||||
engine.scan(axis);
|
engine.scan(axis);
|
||||||
engine.scan(jetty);
|
engine.scan(jetty);
|
||||||
engine.analyzeDependencies();
|
engine.analyzeDependencies();
|
||||||
engine.writeReports("Test Report", "org.owasp", "dependency-check-core", "1.4.7", writeTo, "XML");
|
|
||||||
|
CveDB cveDB = CveDB.getInstance();
|
||||||
|
DatabaseProperties dbProp = cveDB.getDatabaseProperties();
|
||||||
|
|
||||||
|
ReportGenerator generator = new ReportGenerator("Test Report", "org.owasp", "dependency-check-core", "1.4.7",
|
||||||
|
engine.getDependencies(), engine.getAnalyzers(), dbProp);
|
||||||
|
generator.generateReport(templateName, writeTo);
|
||||||
|
cveDB.close();
|
||||||
|
|
||||||
engine.cleanup();
|
engine.cleanup();
|
||||||
|
|
||||||
InputStream xsdStream = ReportGenerator.class.getClassLoader().getResourceAsStream("schema/dependency-check.1.5.xsd");
|
InputStream xsdStream = ReportGenerator.class.getClassLoader().getResourceAsStream("schema/dependency-check.1.5.xsd");
|
||||||
StreamSource xsdSource = new StreamSource(xsdStream);
|
StreamSource xsdSource = new StreamSource(xsdStream);
|
||||||
StreamSource xmlSource = new StreamSource(writeTo);
|
StreamSource xmlSource = new StreamSource(new File(writeTo));
|
||||||
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
|
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
|
||||||
Schema schema = sf.newSchema(xsdSource);
|
Schema schema = sf.newSchema(xsdSource);
|
||||||
Validator validator = schema.newValidator();
|
Validator validator = schema.newValidator();
|
||||||
|
|||||||
@@ -123,8 +123,7 @@ public class AggregateMojo extends BaseDependencyCheckMojo {
|
|||||||
outputDir = new File(this.getProject().getBuild().getDirectory());
|
outputDir = new File(this.getProject().getBuild().getDirectory());
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
final MavenProject p = this.getProject();
|
writeReports(engine, this.getProject(), outputDir);
|
||||||
engine.writeReports(p.getName(), p.getGroupId(), p.getArtifactId(), p.getVersion(), outputDir, getFormat());
|
|
||||||
} catch (ReportException ex) {
|
} catch (ReportException ex) {
|
||||||
if (exCol == null) {
|
if (exCol == null) {
|
||||||
exCol = new ExceptionCollection("Error writing aggregate report", ex);
|
exCol = new ExceptionCollection("Error writing aggregate report", ex);
|
||||||
|
|||||||
@@ -1069,6 +1069,35 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
|
|||||||
return format;
|
return format;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the reports for a given dependency-check engine.
|
||||||
|
*
|
||||||
|
* @param engine a dependency-check engine
|
||||||
|
* @param p the Maven project
|
||||||
|
* @param outputDir the directory path to write the report(s)
|
||||||
|
* @throws ReportException thrown if there is an error writing the report
|
||||||
|
*/
|
||||||
|
protected void writeReports(Engine engine, MavenProject p, File outputDir) throws ReportException {
|
||||||
|
DatabaseProperties prop = null;
|
||||||
|
try (CveDB cve = CveDB.getInstance()) {
|
||||||
|
prop = cve.getDatabaseProperties();
|
||||||
|
} catch (DatabaseException ex) {
|
||||||
|
//TODO shouldn't this throw an exception?
|
||||||
|
if (getLog().isDebugEnabled()) {
|
||||||
|
getLog().debug("Unable to retrieve DB Properties", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final ReportGenerator r = new ReportGenerator(p.getName(), p.getGroupId(), p.getArtifactId(), p.getVersion(),
|
||||||
|
engine.getDependencies(), engine.getAnalyzers(), prop);
|
||||||
|
try {
|
||||||
|
r.generateReports(outputDir.getAbsolutePath(), format);
|
||||||
|
} catch (ReportException ex) {
|
||||||
|
final String msg = String.format("Error generating the report for %s", p.getName());
|
||||||
|
throw new ReportException(msg, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
//<editor-fold defaultstate="collapsed" desc="Methods to fail build or show summary">
|
//<editor-fold defaultstate="collapsed" desc="Methods to fail build or show summary">
|
||||||
/**
|
/**
|
||||||
* Checks to see if a vulnerability has been identified with a CVSS score
|
* Checks to see if a vulnerability has been identified with a CVSS score
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ import org.apache.maven.plugins.annotations.LifecyclePhase;
|
|||||||
import org.apache.maven.plugins.annotations.Mojo;
|
import org.apache.maven.plugins.annotations.Mojo;
|
||||||
import org.apache.maven.plugins.annotations.Parameter;
|
import org.apache.maven.plugins.annotations.Parameter;
|
||||||
import org.apache.maven.plugins.annotations.ResolutionScope;
|
import org.apache.maven.plugins.annotations.ResolutionScope;
|
||||||
import org.apache.maven.project.MavenProject;
|
|
||||||
import org.owasp.dependencycheck.Engine;
|
import org.owasp.dependencycheck.Engine;
|
||||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||||
import org.owasp.dependencycheck.exception.ExceptionCollection;
|
import org.owasp.dependencycheck.exception.ExceptionCollection;
|
||||||
@@ -100,19 +99,19 @@ public class CheckMojo extends BaseDependencyCheckMojo {
|
|||||||
ExceptionCollection exCol = scanArtifacts(getProject(), engine);
|
ExceptionCollection exCol = scanArtifacts(getProject(), engine);
|
||||||
if (engine.getDependencies().isEmpty()) {
|
if (engine.getDependencies().isEmpty()) {
|
||||||
getLog().info("No dependencies were identified that could be analyzed by dependency-check");
|
getLog().info("No dependencies were identified that could be analyzed by dependency-check");
|
||||||
}
|
} else {
|
||||||
try {
|
try {
|
||||||
engine.analyzeDependencies();
|
engine.analyzeDependencies();
|
||||||
} catch (ExceptionCollection ex) {
|
} catch (ExceptionCollection ex) {
|
||||||
if (this.isFailOnError() && ex.isFatal()) {
|
if (this.isFailOnError() && ex.isFatal()) {
|
||||||
throw new MojoExecutionException("One or more exceptions occurred during analysis", ex);
|
throw new MojoExecutionException("One or more exceptions occurred during analysis", ex);
|
||||||
|
}
|
||||||
|
exCol = ex;
|
||||||
}
|
}
|
||||||
exCol = ex;
|
|
||||||
}
|
}
|
||||||
if (exCol == null || !exCol.isFatal()) {
|
if (exCol == null || !exCol.isFatal()) {
|
||||||
try {
|
try {
|
||||||
final MavenProject p = this.getProject();
|
writeReports(engine, getProject(), getCorrectOutputDirectory());
|
||||||
engine.writeReports(p.getName(), p.getGroupId(), p.getArtifactId(), p.getVersion(), getCorrectOutputDirectory(), getFormat());
|
|
||||||
} catch (ReportException ex) {
|
} catch (ReportException ex) {
|
||||||
if (this.isFailOnError()) {
|
if (this.isFailOnError()) {
|
||||||
if (exCol != null) {
|
if (exCol != null) {
|
||||||
|
|||||||
Reference in New Issue
Block a user