diff --git a/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Check.java b/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Check.java index d69b3ecbe..05bab0aae 100644 --- a/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Check.java +++ b/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Check.java @@ -940,16 +940,7 @@ public class Check extends Update { throw new BuildException(ex); } } - 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); + engine.writeReports(getProjectName(),new File(reportOutputDirectory), reportFormat); if (this.failBuildOnCVSS <= 10) { checkForFailure(engine.getDependencies()); diff --git a/dependency-check-cli/src/main/java/org/owasp/dependencycheck/App.java b/dependency-check-cli/src/main/java/org/owasp/dependencycheck/App.java index 399dd15b3..8b7b709f3 100644 --- a/dependency-check-cli/src/main/java/org/owasp/dependencycheck/App.java +++ b/dependency-check-cli/src/main/java/org/owasp/dependencycheck/App.java @@ -281,18 +281,9 @@ public class App { } exCol = ex; } - final List 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 { - report.generateReports(reportDirectory, outputFormat); + engine.writeReports(applicationName, new File(reportDirectory), outputFormat); } catch (ReportException ex) { if (exCol != null) { exCol.addException(ex); @@ -306,7 +297,7 @@ public class App { } //Set the exit code based on whether we found a high enough vulnerability - for (Dependency dep : dependencies) { + for (Dependency dep : engine.getDependencies()) { if (!dep.getVulnerabilities().isEmpty()) { for (Vulnerability vuln : dep.getVulnerabilities()) { LOGGER.debug("VULNERABILITY FOUND " + dep.getDisplayFileName()); @@ -316,7 +307,6 @@ public class App { } } } - return retCode; } finally { if (engine != null) { diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java index bfbc066c8..e50d625aa 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java @@ -54,6 +54,9 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; 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 @@ -796,4 +799,42 @@ public class Engine implements FileFilter { exceptions.add(throwable); 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); + } } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/agent/DependencyCheckScanAgent.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/agent/DependencyCheckScanAgent.java index 2ee63b1f6..c862d0fc1 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/agent/DependencyCheckScanAgent.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/agent/DependencyCheckScanAgent.java @@ -840,21 +840,15 @@ public class DependencyCheckScanAgent { * * @param engine a dependency-check engine * @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) { - 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); + private void generateExternalReports(Engine engine, File outDirectory) throws ScanAgentException { try { - r.generateReports(outDirectory.getCanonicalPath(), this.reportFormat.name()); - } catch (IOException | ReportException ex) { - LOGGER.error("Unexpected exception occurred during analysis; please see the verbose error log for more details."); - LOGGER.debug("", ex); + engine.writeReports(applicationName, outDirectory, this.reportFormat.name()); + } catch (ReportException ex) { + LOGGER.debug("Unexpected exception occurred during analysis; please see the verbose error log for more details.", ex); + throw new ScanAgentException("Error generating the report", ex); } } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/ReportGenerator.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/ReportGenerator.java index b8acd2557..8b1229a98 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/ReportGenerator.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/ReportGenerator.java @@ -107,29 +107,8 @@ public class ReportGenerator { */ public ReportGenerator(String applicationName, List dependencies, List analyzers, DatabaseProperties properties) { velocityEngine = createVelocityEngine(); - context = createContext(); - velocityEngine.init(); - 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")); + context = createContext(applicationName, dependencies, analyzers, properties); } /** @@ -148,9 +127,15 @@ public class ReportGenerator { List dependencies, List analyzers, DatabaseProperties properties) { this(applicationName, dependencies, analyzers, properties); - context.put("applicationVersion", version); - context.put("artifactID", artifactID); - context.put("groupID", groupID); + if (version != null) { + context.put("applicationVersion", version); + } + if (artifactID != null) { + context.put("artifactID", artifactID); + } + if (groupID != null) { + context.put("groupID", groupID); + } } /** @@ -166,67 +151,235 @@ public class ReportGenerator { } /** - * Creates a new Velocity Context. + * Constructs the velocity context used to generate the dependency-check + * reports. * - * @return a Velocity Context + * @param applicationName the application name being analyzed + * @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 Context createContext() { - return new VelocityContext(); + private VelocityContext createContext(String applicationName, List dependencies, List analyzers, DatabaseProperties properties) { + 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 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; } /** - * Generates the Dependency Reports for the identified dependencies. + * Writes the dependency-check report to the given output location. * - * @param outputStream the OutputStream to send the generated report to - * @param format the format the report should be written in - * @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 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 + * @param outputLocation the path where the reports should be written + * @param format the format the report should be written in (XML, HTML, + * JSON, CSV, ALL) or even the path to a custom velocity template (either + * fully qualified or the template name on the class path). + * @throws ReportException is thrown if there is an error creating out the * reports */ - public void generateReports(String outputDir, Format format) throws ReportException { - if (format == Format.XML || format == Format.ALL) { - generateReport("XmlReport", outputDir + File.separator + "dependency-check-report.xml"); + public void write(String outputLocation, String format) throws ReportException { + Format reportFormat = null; + try { + reportFormat = Format.valueOf(format.toUpperCase()); + } catch (IllegalArgumentException ex) { + LOGGER.trace("ignore this exception", ex); } - if (format == Format.JSON || format == Format.ALL) { - generateReport("JsonReport", outputDir + File.separator + "dependency-check-report.json"); - pretifyJson(outputDir + File.separator + "dependency-check-report.json"); + + if (reportFormat != null) { + write(outputLocation, reportFormat); + } 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) { - generateReport("HtmlReport", outputDir + File.separator + "dependency-check-report.html"); - } - if (format == Format.VULN || format == Format.ALL) { - generateReport("VulnerabilityReport", outputDir + File.separator + "dependency-check-vulnerability.html"); + + } + + /** + * Writes the dependency-check report(s). + * + * @param outputLocation the path where the reports should be written + * @param format 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 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. * @@ -311,139 +464,4 @@ 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); - } - } } diff --git a/dependency-check-core/src/main/resources/templates/CsvReport.vsl b/dependency-check-core/src/main/resources/templates/csvReport.vsl similarity index 100% rename from dependency-check-core/src/main/resources/templates/CsvReport.vsl rename to dependency-check-core/src/main/resources/templates/csvReport.vsl diff --git a/dependency-check-core/src/main/resources/templates/HtmlReport.vsl b/dependency-check-core/src/main/resources/templates/htmlReport.vsl similarity index 100% rename from dependency-check-core/src/main/resources/templates/HtmlReport.vsl rename to dependency-check-core/src/main/resources/templates/htmlReport.vsl diff --git a/dependency-check-core/src/main/resources/templates/JsonReport.vsl b/dependency-check-core/src/main/resources/templates/jsonReport.vsl similarity index 100% rename from dependency-check-core/src/main/resources/templates/JsonReport.vsl rename to dependency-check-core/src/main/resources/templates/jsonReport.vsl diff --git a/dependency-check-core/src/main/resources/templates/VulnerabilityReport.vsl b/dependency-check-core/src/main/resources/templates/vulnReport.vsl similarity index 100% rename from dependency-check-core/src/main/resources/templates/VulnerabilityReport.vsl rename to dependency-check-core/src/main/resources/templates/vulnReport.vsl diff --git a/dependency-check-core/src/main/resources/templates/XmlReport.vsl b/dependency-check-core/src/main/resources/templates/xmlReport.vsl similarity index 100% rename from dependency-check-core/src/main/resources/templates/XmlReport.vsl rename to dependency-check-core/src/main/resources/templates/xmlReport.vsl diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIT.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIT.java index dd81bf828..a85d34793 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIT.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIT.java @@ -17,6 +17,7 @@ */ package org.owasp.dependencycheck; +import java.io.File; import java.io.IOException; import static org.junit.Assert.assertTrue; @@ -72,12 +73,7 @@ public class EngineIT extends BaseDBTestCase { throw ex; } } - 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.writeReports("dependency-check sample", new File("./target/"), "ALL"); instance.cleanup(); } } diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/reporting/ReportGeneratorIT.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/reporting/ReportGeneratorIT.java index e472c1e63..c0392df31 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/reporting/ReportGeneratorIT.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/reporting/ReportGeneratorIT.java @@ -25,15 +25,12 @@ import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import javax.xml.validation.Validator; -import static org.junit.Assert.fail; import org.junit.Test; import org.owasp.dependencycheck.BaseDBTestCase; import org.owasp.dependencycheck.BaseTest; 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.DatabaseProperties; import org.owasp.dependencycheck.exception.ExceptionCollection; import org.owasp.dependencycheck.exception.ReportException; import org.owasp.dependencycheck.utils.InvalidSettingException; @@ -47,67 +44,6 @@ import static org.junit.Assert.fail; */ 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 properties = new HashMap(); -// Dependency d = new Dependency(); -// d.setFileName("FileName.jar"); -// d.setActualFilePath("lib/FileName.jar"); -// d.addCPEentry("cpe://a:/some:cpe:1.0"); -// -// List dependencies = new ArrayList(); -// d.getProductEvidence().addEvidence("jar","filename","test", Confidence.HIGH); -// d.getProductEvidence().addEvidence("manifest","vendor","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 * data and validates the generated XML document against the XSD. @@ -115,7 +51,7 @@ public class ReportGeneratorIT extends BaseDBTestCase { * @throws Exception */ @Test - public void testGenerateXMLReport() { + public void testGenerateReport() { try { String templateName = "XmlReport"; @@ -123,7 +59,7 @@ public class ReportGeneratorIT extends BaseDBTestCase { if (!f.exists()) { f.mkdir(); } - String writeTo = "target/test-reports/Report.xml"; + File writeTo = new File("target/test-reports/Report.xml"); File suppressionFile = BaseTest.getResourceAsFile(this, "incorrectSuppressions.xml"); Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppressionFile.getAbsolutePath()); @@ -135,29 +71,20 @@ public class ReportGeneratorIT extends BaseDBTestCase { //File jetty = new File(this.getClass().getClassLoader().getResource("org.mortbay.jetty.jar").getPath()); File jetty = BaseTest.getResourceAsFile(this, "org.mortbay.jetty.jar"); - boolean autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE); Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false); Engine engine = new Engine(); - Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate); engine.scan(struts); engine.scan(axis); engine.scan(jetty); engine.analyzeDependencies(); - - 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.writeReports("Test Report", "org.owasp", "dependency-check-core", "1.4.7", writeTo, "XML"); engine.cleanup(); InputStream xsdStream = ReportGenerator.class.getClassLoader().getResourceAsStream("schema/dependency-check.1.5.xsd"); StreamSource xsdSource = new StreamSource(xsdStream); - StreamSource xmlSource = new StreamSource(new File(writeTo)); + StreamSource xmlSource = new StreamSource(writeTo); SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema schema = sf.newSchema(xsdSource); Validator validator = schema.newValidator(); diff --git a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/AggregateMojo.java b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/AggregateMojo.java index 62c333efe..7a0c0b6d5 100644 --- a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/AggregateMojo.java +++ b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/AggregateMojo.java @@ -123,7 +123,8 @@ public class AggregateMojo extends BaseDependencyCheckMojo { outputDir = new File(this.getProject().getBuild().getDirectory()); } try { - writeReports(engine, this.getProject(), outputDir); + final MavenProject p = this.getProject(); + engine.writeReports(p.getName(), p.getGroupId(), p.getArtifactId(), p.getVersion(), outputDir, getFormat()); } catch (ReportException ex) { if (exCol == null) { exCol = new ExceptionCollection("Error writing aggregate report", ex); diff --git a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java index 99b3a401f..e7cf5f937 100644 --- a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java +++ b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java @@ -1069,35 +1069,6 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma 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); - } - - } - // /** * Checks to see if a vulnerability has been identified with a CVSS score diff --git a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/CheckMojo.java b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/CheckMojo.java index cb95628db..1b6a30d55 100644 --- a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/CheckMojo.java +++ b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/CheckMojo.java @@ -25,6 +25,7 @@ import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; +import org.apache.maven.project.MavenProject; import org.owasp.dependencycheck.Engine; import org.owasp.dependencycheck.data.nvdcve.DatabaseException; import org.owasp.dependencycheck.exception.ExceptionCollection; @@ -99,19 +100,19 @@ public class CheckMojo extends BaseDependencyCheckMojo { ExceptionCollection exCol = scanArtifacts(getProject(), engine); if (engine.getDependencies().isEmpty()) { getLog().info("No dependencies were identified that could be analyzed by dependency-check"); - } else { - try { - engine.analyzeDependencies(); - } catch (ExceptionCollection ex) { - if (this.isFailOnError() && ex.isFatal()) { - throw new MojoExecutionException("One or more exceptions occurred during analysis", ex); - } - exCol = ex; + } + try { + engine.analyzeDependencies(); + } catch (ExceptionCollection ex) { + if (this.isFailOnError() && ex.isFatal()) { + throw new MojoExecutionException("One or more exceptions occurred during analysis", ex); } + exCol = ex; } if (exCol == null || !exCol.isFatal()) { try { - writeReports(engine, getProject(), getCorrectOutputDirectory()); + final MavenProject p = this.getProject(); + engine.writeReports(p.getName(), p.getGroupId(), p.getArtifactId(), p.getVersion(), getCorrectOutputDirectory(), getFormat()); } catch (ReportException ex) { if (this.isFailOnError()) { if (exCol != null) {