mirror of
https://github.com/ysoftdevs/DependencyCheck.git
synced 2026-01-14 15:53:36 +01:00
Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc2953d6a3 | ||
|
|
c888019068 | ||
|
|
56639d3965 | ||
|
|
09ff99823e | ||
|
|
5078e32dc7 | ||
|
|
ecaadff0d8 | ||
|
|
f2ad8cc7d1 | ||
|
|
c8d77eb213 | ||
|
|
fe3d9e8bf6 | ||
|
|
6c4171be75 | ||
|
|
4bbb466e43 | ||
|
|
c478415667 | ||
|
|
fc832b67c5 | ||
|
|
943a9ea97e | ||
|
|
2c7ab297d7 | ||
|
|
d8299f7db1 | ||
|
|
4deeb33f08 | ||
|
|
3bf4cf8c85 | ||
|
|
e0217fc6c3 | ||
|
|
62a3efa23a | ||
|
|
cc7ebe6d52 | ||
|
|
5d920e4b44 | ||
|
|
1264ea54a1 | ||
|
|
caa1d77d23 | ||
|
|
20a55b3342 | ||
|
|
8bfe67fc60 | ||
|
|
d42a1c6ab1 | ||
|
|
80a89ef6d1 | ||
|
|
1a0e605f0c | ||
|
|
573c8eb509 | ||
|
|
e676e3a14b | ||
|
|
af8c807ee0 | ||
|
|
dfaa5df965 | ||
|
|
32055ecdcc | ||
|
|
9db71c5f0c | ||
|
|
99856bf285 | ||
|
|
4d006b3e05 | ||
|
|
4e37165ba6 | ||
|
|
38a5834785 | ||
|
|
d6e1352869 | ||
|
|
bf1b7bd7a2 | ||
|
|
2306327057 | ||
|
|
2d389ba73f | ||
|
|
ce8d5bc635 | ||
|
|
8fdc2007e0 |
@@ -20,7 +20,7 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
|
||||
<parent>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-parent</artifactId>
|
||||
<version>1.2.7</version>
|
||||
<version>1.2.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>dependency-check-ant</artifactId>
|
||||
|
||||
@@ -559,6 +559,28 @@ public class DependencyCheckTask extends Task {
|
||||
public void setNuspecAnalyzerEnabled(boolean nuspecAnalyzerEnabled) {
|
||||
this.nuspecAnalyzerEnabled = nuspecAnalyzerEnabled;
|
||||
}
|
||||
/**
|
||||
* Whether or not the central analyzer is enabled.
|
||||
*/
|
||||
private boolean centralAnalyzerEnabled = false;
|
||||
|
||||
/**
|
||||
* Get the value of centralAnalyzerEnabled
|
||||
*
|
||||
* @return the value of centralAnalyzerEnabled
|
||||
*/
|
||||
public boolean isCentralAnalyzerEnabled() {
|
||||
return centralAnalyzerEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of centralAnalyzerEnabled
|
||||
*
|
||||
* @param centralAnalyzerEnabled new value of centralAnalyzerEnabled
|
||||
*/
|
||||
public void setCentralAnalyzerEnabled(boolean centralAnalyzerEnabled) {
|
||||
this.centralAnalyzerEnabled = centralAnalyzerEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the nexus analyzer is enabled.
|
||||
@@ -1015,6 +1037,8 @@ public class DependencyCheckTask extends Task {
|
||||
Settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED, jarAnalyzerEnabled);
|
||||
//NUSPEC ANALYZER
|
||||
Settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, nuspecAnalyzerEnabled);
|
||||
//CENTRAL ANALYZER
|
||||
Settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled);
|
||||
//NEXUS ANALYZER
|
||||
Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled);
|
||||
if (nexusUrl != null && !nexusUrl.isEmpty()) {
|
||||
|
||||
@@ -50,8 +50,9 @@ Property | Description
|
||||
------------------------|---------------------------------------------------------------------------|------------------
|
||||
archiveAnalyzerEnabled | Sets whether the Archive Analyzer will be used. | true
|
||||
zipExtensions | A comma-separated list of additional file extensions to be treated like a ZIP file, the contents will be extracted and analyzed. |
|
||||
jarAnalyzer | Sets whether Jar Analyzer will be used. | true
|
||||
nexusAnalyzerEnabled | Sets whether Nexus Analyzer will be used. | true
|
||||
jarAnalyzer | Sets whether the Jar Analyzer will be used. | true
|
||||
centralAnalyzerEnabled | Sets whether the Central Analyzer will be used. If this analyzer is being disabled there is a good chance you also want to disable the Nexus Analyzer (see below). | true
|
||||
nexusAnalyzerEnabled | Sets whether Nexus Analyzer will be used. This analyzer is superceded by the Central Analyzer; however, you can configure this to run against a Nexus Pro installation. | true
|
||||
nexusUrl | Defines the Nexus Pro URL. If not set the Nexus Analyzer will be disabled. |
|
||||
nexusUsesProxy | Whether or not the defined proxy should be used when connecting to Nexus. | true
|
||||
nuspecAnalyzerEnabled | Sets whether or not the .NET Nuget Nuspec Analyzer will be used. | true
|
||||
|
||||
@@ -20,7 +20,7 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
|
||||
<parent>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-parent</artifactId>
|
||||
<version>1.2.7</version>
|
||||
<version>1.2.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>dependency-check-cli</artifactId>
|
||||
|
||||
@@ -233,6 +233,7 @@ public class App {
|
||||
final boolean archiveDisabled = cli.isArchiveDisabled();
|
||||
final boolean assemblyDisabled = cli.isAssemblyDisabled();
|
||||
final boolean nuspecDisabled = cli.isNuspecDisabled();
|
||||
final boolean centralDisabled = cli.isCentralDisabled();
|
||||
final boolean nexusDisabled = cli.isNexusDisabled();
|
||||
final String nexusUrl = cli.getNexusUrl();
|
||||
final String databaseDriverName = cli.getDatabaseDriverName();
|
||||
@@ -298,6 +299,7 @@ public class App {
|
||||
Settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, !nuspecDisabled);
|
||||
Settings.setBoolean(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, !assemblyDisabled);
|
||||
|
||||
Settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, !centralDisabled);
|
||||
Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, !nexusDisabled);
|
||||
if (nexusUrl != null && !nexusUrl.isEmpty()) {
|
||||
Settings.setString(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
|
||||
|
||||
@@ -323,6 +323,10 @@ public final class CliParser {
|
||||
.withDescription("Disable the .NET Assembly Analyzer.")
|
||||
.create();
|
||||
|
||||
final Option disableCentralAnalyzer = OptionBuilder.withLongOpt(ARGUMENT.DISABLE_CENTRAL)
|
||||
.withDescription("Disable the Central Analyzer. If this analyzer is disabled it is likely you also want to disable the Nexus Analyzer.")
|
||||
.create();
|
||||
|
||||
final Option disableNexusAnalyzer = OptionBuilder.withLongOpt(ARGUMENT.DISABLE_NEXUS)
|
||||
.withDescription("Disable the Nexus Analyzer.")
|
||||
.create();
|
||||
@@ -360,6 +364,7 @@ public final class CliParser {
|
||||
.addOption(disableArchiveAnalyzer)
|
||||
.addOption(disableAssemblyAnalyzer)
|
||||
.addOption(disableNuspecAnalyzer)
|
||||
.addOption(disableCentralAnalyzer)
|
||||
.addOption(disableNexusAnalyzer)
|
||||
.addOption(nexusUrl)
|
||||
.addOption(nexusUsesProxy)
|
||||
@@ -456,6 +461,15 @@ public final class CliParser {
|
||||
return (line != null) && line.hasOption(ARGUMENT.DISABLE_NEXUS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the disableCentral command line argument was specified.
|
||||
*
|
||||
* @return true if the disableCentral command line argument was specified; otherwise false
|
||||
*/
|
||||
public boolean isCentralDisabled() {
|
||||
return (line != null) && line.hasOption(ARGUMENT.DISABLE_CENTRAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the url to the nexus server if one was specified.
|
||||
*
|
||||
@@ -876,6 +890,10 @@ public final class CliParser {
|
||||
* Disables the Nuspec Analyzer.
|
||||
*/
|
||||
public static final String DISABLE_NUSPEC = "disableNuspec";
|
||||
/**
|
||||
* Disables the Central Analyzer.
|
||||
*/
|
||||
public static final String DISABLE_CENTRAL = "disableCentral";
|
||||
/**
|
||||
* Disables the Nexus Analyzer.
|
||||
*/
|
||||
|
||||
@@ -23,8 +23,9 @@ Short | Argument Name | Paramete
|
||||
-------|-----------------------|-----------------|-----------------------------------------------------------------------------|---------------
|
||||
| \-\-disableArchive | | Sets whether the Archive Analyzer will be used. | false
|
||||
| \-\-zipExtensions | \<strings\> | A comma-separated list of additional file extensions to be treated like a ZIP file, the contents will be extracted and analyzed. |
|
||||
| \-\-disableJar | | Sets whether Jar Analyzer will be used. | false
|
||||
| \-\-disableNexus | | Sets whether Nexus Analyzer will be used. | false
|
||||
| \-\-disableJar | | Sets whether the Jar Analyzer will be used. | false
|
||||
| \-\-disableCentral | | Sets whether the Central Analyzer will be used. If this analyzer is being disabled there is a good chance you also want to disable the Nexus Analyzer. | false
|
||||
| \-\-disableNexus | | Sets whether the Nexus Analyzer will be used. Note, this has been superceded by the Central Analyzer. However, you can configure the Nexus URL to utilize an internally hosted Nexus Pro server. | false
|
||||
| \-\-nexus | \<url\> | The url to the Nexus Pro Server. If not set the Nexus Analyzer will be disabled. |
|
||||
| \-\-nexusUsesProxy | \<true\|false\> | Whether or not the defined proxy should be used when connecting to Nexus. | true
|
||||
| \-\-disableNuspec | | Sets whether or not the .NET Nuget Nuspec Analyzer will be used. | false
|
||||
|
||||
@@ -20,7 +20,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||
<parent>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-parent</artifactId>
|
||||
<version>1.2.7</version>
|
||||
<version>1.2.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>dependency-check-core</artifactId>
|
||||
|
||||
@@ -153,6 +153,11 @@ public class Engine {
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the dependencies.
|
||||
*
|
||||
* @param dependencies the dependencies
|
||||
*/
|
||||
public void setDependencies(List<Dependency> dependencies) {
|
||||
this.dependencies = dependencies;
|
||||
}
|
||||
@@ -323,7 +328,7 @@ public class Engine {
|
||||
}
|
||||
} else {
|
||||
final String msg = String.format("No file extension found on file '%s'. The file was not analyzed.", file.toString());
|
||||
LOGGER.log(Level.FINEST, msg);
|
||||
LOGGER.log(Level.FINE, msg);
|
||||
}
|
||||
return dependency;
|
||||
}
|
||||
@@ -513,6 +518,15 @@ public class Engine {
|
||||
return scan;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of file type analyzers.
|
||||
*
|
||||
* @return the set of file type analyzers
|
||||
*/
|
||||
public Set<FileTypeAnalyzer> getFileTypeAnalyzers() {
|
||||
return this.fileTypeAnalyzers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the CPE Index to ensure documents exists. If none exist a NoDataException is thrown.
|
||||
*
|
||||
|
||||
@@ -41,16 +41,7 @@ public abstract class AbstractFileTypeAnalyzer extends AbstractAnalyzer implemen
|
||||
* enabled.
|
||||
*/
|
||||
public AbstractFileTypeAnalyzer() {
|
||||
final String key = getAnalyzerEnabledSettingKey();
|
||||
try {
|
||||
enabled = Settings.getBoolean(key, true);
|
||||
} catch (InvalidSettingException ex) {
|
||||
String msg = String.format("Invalid setting for property '%s'", key);
|
||||
LOGGER.log(Level.WARNING, msg);
|
||||
LOGGER.log(Level.FINE, "", ex);
|
||||
msg = String.format("%s has been disabled", getName());
|
||||
LOGGER.log(Level.WARNING, msg);
|
||||
}
|
||||
reset();
|
||||
}
|
||||
//</editor-fold>
|
||||
|
||||
@@ -164,6 +155,23 @@ public abstract class AbstractFileTypeAnalyzer extends AbstractAnalyzer implemen
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the enabled flag on the analyzer.
|
||||
*/
|
||||
@Override
|
||||
public final void reset() {
|
||||
final String key = getAnalyzerEnabledSettingKey();
|
||||
try {
|
||||
enabled = Settings.getBoolean(key, true);
|
||||
} catch (InvalidSettingException ex) {
|
||||
String msg = String.format("Invalid setting for property '%s'", key);
|
||||
LOGGER.log(Level.WARNING, msg);
|
||||
LOGGER.log(Level.FINE, "", ex);
|
||||
msg = String.format("%s has been disabled", getName());
|
||||
LOGGER.log(Level.WARNING, msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyzes a given dependency. If the dependency is an archive, such as a WAR or EAR, the contents are extracted,
|
||||
* scanned, and added to the list of dependencies within the engine.
|
||||
|
||||
@@ -31,4 +31,9 @@ public interface FileTypeAnalyzer extends Analyzer {
|
||||
* @return whether or not the specified file extension is supported by this analyzer.
|
||||
*/
|
||||
boolean supportsExtension(String extension);
|
||||
|
||||
/**
|
||||
* Resets the analyzers state.
|
||||
*/
|
||||
void reset();
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ public final class CpeMemoryIndex {
|
||||
/**
|
||||
* singleton instance.
|
||||
*/
|
||||
private static CpeMemoryIndex instance = new CpeMemoryIndex();
|
||||
private static final CpeMemoryIndex INSTANCE = new CpeMemoryIndex();
|
||||
|
||||
/**
|
||||
* private constructor for singleton.
|
||||
@@ -76,7 +76,7 @@ public final class CpeMemoryIndex {
|
||||
* @return the instance of the CpeMemoryIndex
|
||||
*/
|
||||
public static CpeMemoryIndex getInstance() {
|
||||
return instance;
|
||||
return INSTANCE;
|
||||
}
|
||||
/**
|
||||
* The in memory Lucene index.
|
||||
@@ -114,18 +114,20 @@ public final class CpeMemoryIndex {
|
||||
* @throws IndexException thrown if there is an error creating the index
|
||||
*/
|
||||
public void open(CveDB cve) throws IndexException {
|
||||
if (!openState) {
|
||||
index = new RAMDirectory();
|
||||
buildIndex(cve);
|
||||
try {
|
||||
indexReader = DirectoryReader.open(index);
|
||||
} catch (IOException ex) {
|
||||
throw new IndexException(ex);
|
||||
synchronized (INSTANCE) {
|
||||
if (!openState) {
|
||||
index = new RAMDirectory();
|
||||
buildIndex(cve);
|
||||
try {
|
||||
indexReader = DirectoryReader.open(index);
|
||||
} catch (IOException ex) {
|
||||
throw new IndexException(ex);
|
||||
}
|
||||
indexSearcher = new IndexSearcher(indexReader);
|
||||
searchingAnalyzer = createSearchingAnalyzer();
|
||||
queryParser = new QueryParser(LuceneUtils.CURRENT_VERSION, Fields.DOCUMENT_KEY, searchingAnalyzer);
|
||||
openState = true;
|
||||
}
|
||||
indexSearcher = new IndexSearcher(indexReader);
|
||||
searchingAnalyzer = createSearchingAnalyzer();
|
||||
queryParser = new QueryParser(LuceneUtils.CURRENT_VERSION, Fields.DOCUMENT_KEY, searchingAnalyzer);
|
||||
openState = true;
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
||||
@@ -261,7 +261,7 @@ public class DownloadTask implements Callable<Future<ProcessTask>> {
|
||||
*/
|
||||
private void extractGzip(File file) throws FileNotFoundException, IOException {
|
||||
final String originalPath = file.getPath();
|
||||
File gzip = new File(originalPath + ".gz");
|
||||
final File gzip = new File(originalPath + ".gz");
|
||||
if (gzip.isFile() && !gzip.delete()) {
|
||||
gzip.deleteOnExit();
|
||||
}
|
||||
|
||||
@@ -610,7 +610,14 @@ public class Dependency implements Serializable, Comparable<Dependency> {
|
||||
* @param dependency a reference to the related dependency
|
||||
*/
|
||||
public void addRelatedDependency(Dependency dependency) {
|
||||
relatedDependencies.add(dependency);
|
||||
if (this == dependency) {
|
||||
LOGGER.warning("Attempted to add a circular reference - please post the log file to issue #172 here "
|
||||
+ "https://github.com/jeremylong/DependencyCheck/issues/172 ");
|
||||
LOGGER.log(Level.FINE, "this: {0}", this.toString());
|
||||
LOGGER.log(Level.FINE, "dependency: {0}", dependency.toString());
|
||||
} else {
|
||||
relatedDependencies.add(dependency);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.util.Properties;
|
||||
import mockit.Mock;
|
||||
import mockit.MockUp;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import org.junit.Test;
|
||||
import org.owasp.dependencycheck.BaseTest;
|
||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
|
||||
@@ -136,9 +137,9 @@ public class EngineVersionCheckTest extends BaseTest {
|
||||
@Test
|
||||
public void testGetCurrentReleaseVersion() {
|
||||
EngineVersionCheck instance = new EngineVersionCheck();
|
||||
DependencyVersion expResult = new DependencyVersion("1.2.6");
|
||||
DependencyVersion minExpResult = new DependencyVersion("1.2.6");
|
||||
String release = instance.getCurrentReleaseVersion();
|
||||
DependencyVersion result = new DependencyVersion(release);
|
||||
assertEquals(expResult, result);
|
||||
assertTrue(minExpResult.compareTo(result) <= 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-parent</artifactId>
|
||||
<version>1.2.7</version>
|
||||
<version>1.2.8</version>
|
||||
</parent>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-jenkins</artifactId>
|
||||
|
||||
@@ -22,7 +22,7 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
|
||||
<parent>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-parent</artifactId>
|
||||
<version>1.2.7</version>
|
||||
<version>1.2.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>dependency-check-maven</artifactId>
|
||||
@@ -86,6 +86,23 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.16</version>
|
||||
<configuration>
|
||||
<systemProperties>
|
||||
<property>
|
||||
<name>data.directory</name>
|
||||
<value>${project.build.directory}/dependency-check-data</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>temp.directory</name>
|
||||
<value>${project.build.directory}/temp</value>
|
||||
</property>
|
||||
</systemProperties>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<inherited>true</inherited>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
@@ -315,6 +332,12 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
|
||||
<artifactId>maven-reporting-api</artifactId>
|
||||
<version>3.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jmockit</groupId>
|
||||
<artifactId>jmockit</artifactId>
|
||||
<version>1.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
|
||||
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* This file is part of dependency-check-maven.
|
||||
*
|
||||
* 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) 2013 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.maven;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.plugin.MojoFailureException;
|
||||
import org.apache.maven.plugins.annotations.LifecyclePhase;
|
||||
import org.apache.maven.plugins.annotations.Mojo;
|
||||
import org.apache.maven.plugins.annotations.ResolutionScope;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.owasp.dependencycheck.analyzer.DependencyBundlingAnalyzer;
|
||||
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||
import org.owasp.dependencycheck.dependency.Dependency;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
|
||||
/**
|
||||
* Maven Plugin that checks project dependencies and the dependencies of all child modules to see if they have any known
|
||||
* published vulnerabilities.
|
||||
*
|
||||
* @author Jeremy Long <jeremy.long@owasp.org>
|
||||
*/
|
||||
@Mojo(
|
||||
name = "aggregate",
|
||||
defaultPhase = LifecyclePhase.SITE,
|
||||
aggregator = true,
|
||||
threadSafe = true,
|
||||
requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME,
|
||||
requiresOnline = true
|
||||
)
|
||||
public class AggregateMojo extends BaseDependencyCheckMojo {
|
||||
|
||||
/**
|
||||
* Logger field reference.
|
||||
*/
|
||||
private static final Logger LOGGER = Logger.getLogger(AggregateMojo.class.getName());
|
||||
|
||||
/**
|
||||
* Executes the aggregate dependency-check goal. This runs dependency-check and generates the subsequent reports.
|
||||
*
|
||||
* @throws MojoExecutionException thrown if there is ane exception running the mojo
|
||||
* @throws MojoFailureException thrown if dependency-check is configured to fail the build
|
||||
*/
|
||||
@Override
|
||||
public void runCheck() throws MojoExecutionException, MojoFailureException {
|
||||
final Engine engine = generateDataFile();
|
||||
|
||||
if (getProject() == getReactorProjects().get(getReactorProjects().size() - 1)) {
|
||||
final Map<MavenProject, Set<MavenProject>> children = buildAggregateInfo();
|
||||
boolean hasOrchestration = false;
|
||||
for (MavenProject current : getReactorProjects()) {
|
||||
final List<Dependency> dependencies = readDataFile(current);
|
||||
final List<MavenProject> childProjects = getAllChildren(current, children);
|
||||
//check for orchestration build - execution root with no children or dependencies
|
||||
if ((dependencies == null || dependencies.isEmpty()) && childProjects.isEmpty() && current.isExecutionRoot()) {
|
||||
hasOrchestration = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (MavenProject current : getReactorProjects()) {
|
||||
List<Dependency> dependencies = readDataFile(current);
|
||||
final List<MavenProject> childProjects = getAllChildren(current, children);
|
||||
//check for orchestration build - execution root with no children or dependencies
|
||||
if ((dependencies == null || dependencies.isEmpty()) && childProjects.isEmpty() && current.isExecutionRoot()) {
|
||||
engine.resetFileTypeAnalyzers();
|
||||
for (MavenProject mod : getReactorProjects()) {
|
||||
scanArtifacts(mod, engine);
|
||||
}
|
||||
engine.analyzeDependencies();
|
||||
} else {
|
||||
if (dependencies == null) {
|
||||
dependencies = new ArrayList<Dependency>();
|
||||
}
|
||||
for (MavenProject reportOn : childProjects) {
|
||||
final List<Dependency> childDeps = readDataFile(reportOn);
|
||||
if (childDeps != null && !childDeps.isEmpty()) {
|
||||
dependencies.addAll(childDeps);
|
||||
}
|
||||
}
|
||||
engine.getDependencies().clear();
|
||||
engine.getDependencies().addAll(dependencies);
|
||||
final DependencyBundlingAnalyzer bundler = new DependencyBundlingAnalyzer();
|
||||
try {
|
||||
bundler.analyze(null, engine);
|
||||
} catch (AnalysisException ex) {
|
||||
LOGGER.log(Level.WARNING, "An error occured grouping the dependencies; duplicate entries may exist in the report", ex);
|
||||
LOGGER.log(Level.FINE, "Bundling Exception", ex);
|
||||
}
|
||||
}
|
||||
try {
|
||||
final File outputDir = getCorrectOutputDirectory(current);
|
||||
writeReports(engine, current, outputDir);
|
||||
} catch (MojoExecutionException ex) {
|
||||
if (!hasOrchestration) {
|
||||
throw ex;
|
||||
} // else ignore this
|
||||
}
|
||||
}
|
||||
}
|
||||
engine.cleanup();
|
||||
Settings.cleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list containing all the recursive, non-pom children of the given project, never <code>null</code>.
|
||||
*
|
||||
* @param project the parent project to collect the child project references
|
||||
* @param childMap a map of the parent-child relationships
|
||||
* @return a list of child projects
|
||||
*/
|
||||
protected List<MavenProject> getAllChildren(MavenProject project, Map<MavenProject, Set<MavenProject>> childMap) {
|
||||
final Set<MavenProject> children = childMap.get(project);
|
||||
if (children == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
final List<MavenProject> result = new ArrayList<MavenProject>();
|
||||
for (MavenProject child : children) {
|
||||
if (isMultiModule(child)) {
|
||||
result.addAll(getAllChildren(child, childMap));
|
||||
} else {
|
||||
result.add(child);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the project has pom packaging
|
||||
*
|
||||
* @param mavenProject Project to test
|
||||
* @return <code>true</code> if it has a pom packaging; otherwise <code>false</code>
|
||||
*/
|
||||
protected boolean isMultiModule(MavenProject mavenProject) {
|
||||
return "pom".equals(mavenProject.getPackaging());
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the parent-child map.
|
||||
*
|
||||
* @return a map of the parent/child relationships
|
||||
*/
|
||||
private Map<MavenProject, Set<MavenProject>> buildAggregateInfo() {
|
||||
final Map<MavenProject, Set<MavenProject>> parentChildMap = new HashMap<MavenProject, Set<MavenProject>>();
|
||||
for (MavenProject proj : getReactorProjects()) {
|
||||
Set<MavenProject> depList = parentChildMap.get(proj.getParent());
|
||||
if (depList == null) {
|
||||
depList = new HashSet<MavenProject>();
|
||||
parentChildMap.put(proj.getParent(), depList);
|
||||
}
|
||||
depList.add(proj);
|
||||
}
|
||||
return parentChildMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs dependency-check's Engine and writes the serialized dependencies to disk.
|
||||
*
|
||||
* @return the Engine used to execute dependency-check
|
||||
* @throws MojoExecutionException thrown if there is an exception running the mojo
|
||||
* @throws MojoFailureException thrown if dependency-check is configured to fail the build if severe CVEs are
|
||||
* identified.
|
||||
*/
|
||||
protected Engine generateDataFile() throws MojoExecutionException, MojoFailureException {
|
||||
final Engine engine;
|
||||
try {
|
||||
engine = initializeEngine();
|
||||
} catch (DatabaseException ex) {
|
||||
LOGGER.log(Level.FINE, "Database connection error", ex);
|
||||
throw new MojoExecutionException("An exception occured connecting to the local database. Please see the log file for more details.", ex);
|
||||
}
|
||||
scanArtifacts(getProject(), engine);
|
||||
engine.analyzeDependencies();
|
||||
writeDataFile(engine.getDependencies());
|
||||
showSummary(engine.getDependencies());
|
||||
checkForFailure(engine.getDependencies());
|
||||
return engine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canGenerateReport() {
|
||||
return true; //aggregate always returns true for now - we can look at a more complicated/acurate solution later
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the report name.
|
||||
*
|
||||
* @param locale the location
|
||||
* @return the report name
|
||||
*/
|
||||
public String getName(Locale locale) {
|
||||
return "dependency-check:aggregate";
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the description of the Dependency-Check report to be displayed in the Maven Generated Reports page.
|
||||
*
|
||||
* @param locale The Locale to get the description for
|
||||
* @return the description
|
||||
*/
|
||||
public String getDescription(Locale locale) {
|
||||
return "Generates an aggregate report of all child Maven projects providing details on any "
|
||||
+ "published vulnerabilities within project dependencies. This report is a best "
|
||||
+ "effort and may contain false positives and false negatives.";
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright (c) 2013 Jeremy Long. All Rights Reserved.
|
||||
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.maven;
|
||||
|
||||
@@ -29,50 +29,42 @@ import java.io.ObjectOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.apache.maven.artifact.Artifact;
|
||||
import org.apache.maven.doxia.sink.Sink;
|
||||
import org.apache.maven.plugin.AbstractMojo;
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.plugin.MojoFailureException;
|
||||
import org.apache.maven.plugins.annotations.LifecyclePhase;
|
||||
import org.apache.maven.plugins.annotations.Mojo;
|
||||
import org.apache.maven.plugins.annotations.Component;
|
||||
import org.apache.maven.plugins.annotations.Parameter;
|
||||
import org.apache.maven.plugins.annotations.ResolutionScope;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.apache.maven.reporting.MavenReport;
|
||||
import org.apache.maven.reporting.MavenReportException;
|
||||
import org.apache.maven.settings.Proxy;
|
||||
import org.owasp.dependencycheck.analyzer.DependencyBundlingAnalyzer;
|
||||
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
||||
import org.owasp.dependencycheck.data.nexus.MavenArtifact;
|
||||
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.dependency.Confidence;
|
||||
import org.owasp.dependencycheck.dependency.Dependency;
|
||||
import org.owasp.dependencycheck.dependency.Identifier;
|
||||
import org.owasp.dependencycheck.dependency.Vulnerability;
|
||||
import org.owasp.dependencycheck.reporting.ReportGenerator;
|
||||
import org.owasp.dependencycheck.utils.LogUtils;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
|
||||
/**
|
||||
* Maven Plugin that checks project dependencies to see if they have any known published vulnerabilities.
|
||||
*
|
||||
* @author Jeremy Long <jeremy.long@owasp.org>
|
||||
*/
|
||||
@Mojo(
|
||||
name = "check",
|
||||
defaultPhase = LifecyclePhase.COMPILE,
|
||||
threadSafe = true,
|
||||
requiresDependencyResolution = ResolutionScope.RUNTIME_PLUS_SYSTEM,
|
||||
requiresOnline = true
|
||||
)
|
||||
public class DependencyCheckMojo extends ReportAggregationMojo {
|
||||
public abstract class BaseDependencyCheckMojo extends AbstractMojo implements MavenReport {
|
||||
|
||||
//<editor-fold defaultstate="collapsed" desc="Private fields">
|
||||
/**
|
||||
* Logger field reference.
|
||||
*/
|
||||
private static final Logger LOGGER = Logger.getLogger(DependencyCheckMojo.class.getName());
|
||||
private static final Logger LOGGER = Logger.getLogger(BaseDependencyCheckMojo.class.getName());
|
||||
/**
|
||||
* The properties file location.
|
||||
*/
|
||||
@@ -86,12 +78,23 @@ public class DependencyCheckMojo extends ReportAggregationMojo {
|
||||
*/
|
||||
private static final String NEW_LINE = System.getProperty("line.separator", "\n").intern();
|
||||
/**
|
||||
* The dependency-check engine used to scan the project.
|
||||
* Sets whether or not the external report format should be used.
|
||||
*/
|
||||
private Engine engine = null;
|
||||
//</editor-fold>
|
||||
@Parameter(property = "metaFileName", defaultValue = "dependency-check.ser", required = true)
|
||||
private String dataFileName;
|
||||
|
||||
//</editor-fold>
|
||||
// <editor-fold defaultstate="collapsed" desc="Maven bound parameters and components">
|
||||
/**
|
||||
* The Maven Project Object.
|
||||
*/
|
||||
@Component
|
||||
private MavenProject project;
|
||||
/**
|
||||
* List of Maven project of the current build
|
||||
*/
|
||||
@Parameter(readonly = true, required = true, property = "reactorProjects")
|
||||
private List<MavenProject> reactorProjects;
|
||||
/**
|
||||
* The path to the verbose log.
|
||||
*/
|
||||
@@ -117,6 +120,14 @@ public class DependencyCheckMojo extends ReportAggregationMojo {
|
||||
@SuppressWarnings("CanBeFinal")
|
||||
@Parameter(property = "autoupdate", defaultValue = "true", required = true)
|
||||
private boolean autoUpdate = true;
|
||||
/**
|
||||
* Generate aggregate reports in multi-module projects.
|
||||
*
|
||||
* @deprecated use the aggregate goal instead
|
||||
*/
|
||||
@Parameter(property = "aggregate", defaultValue = "false")
|
||||
@Deprecated
|
||||
private boolean aggregate;
|
||||
/**
|
||||
* The report format to be generated (HTML, XML, VULN, ALL). This configuration option has no affect if using this
|
||||
* within the Site plug-in unless the externalReport is set to true. Default is HTML.
|
||||
@@ -184,14 +195,22 @@ public class DependencyCheckMojo extends ReportAggregationMojo {
|
||||
@Parameter(property = "nuspecAnalyzerEnabled", defaultValue = "true", required = false)
|
||||
private boolean nuspecAnalyzerEnabled = true;
|
||||
|
||||
/**
|
||||
* Whether or not the Central Analyzer is enabled.
|
||||
*/
|
||||
@SuppressWarnings("CanBeFinal")
|
||||
@Parameter(property = "centralAnalyzerEnabled", defaultValue = "true", required = false)
|
||||
private boolean centralAnalyzerEnabled = true;
|
||||
|
||||
/**
|
||||
* Whether or not the Nexus Analyzer is enabled.
|
||||
*/
|
||||
@SuppressWarnings("CanBeFinal")
|
||||
@Parameter(property = "nexusAnalyzerEnabled", defaultValue = "true", required = false)
|
||||
private boolean nexusAnalyzerEnabled = true;
|
||||
|
||||
/**
|
||||
* Whether or not the Nexus Analyzer is enabled.
|
||||
* The URL of a Nexus Pro server.
|
||||
*/
|
||||
@Parameter(property = "nexusUrl", defaultValue = "", required = false)
|
||||
private String nexusUrl;
|
||||
@@ -299,38 +318,116 @@ public class DependencyCheckMojo extends ReportAggregationMojo {
|
||||
@Deprecated
|
||||
private String externalReport = null;
|
||||
|
||||
// </editor-fold>
|
||||
/**
|
||||
* Executes the Dependency-Check on the dependent libraries.
|
||||
*
|
||||
* @return the Engine used to scan the dependencies.
|
||||
* @throws DatabaseException thrown if there is an exception connecting to the database
|
||||
* Specifies the destination directory for the generated Dependency-Check report. This generally maps to
|
||||
* "target/site".
|
||||
*/
|
||||
private Engine executeDependencyCheck() throws DatabaseException {
|
||||
return executeDependencyCheck(getProject());
|
||||
@Parameter(property = "reportOutputDirectory", defaultValue = "${project.reporting.outputDirectory}", required = true)
|
||||
private File reportOutputDirectory;
|
||||
// </editor-fold>
|
||||
//<editor-fold defaultstate="collapsed" desc="Base Maven implementation">
|
||||
|
||||
/**
|
||||
* Executes dependency-check.
|
||||
*
|
||||
* @throws MojoExecutionException thrown if there is an exception executing the mojo
|
||||
* @throws MojoFailureException thrown if dependency-check failed the build
|
||||
*/
|
||||
@Override
|
||||
public void execute() throws MojoExecutionException, MojoFailureException {
|
||||
validateAggregate();
|
||||
project.setContextValue(getOutputDirectoryContextKey(), this.outputDirectory);
|
||||
runCheck();
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the Dependency-Check on the dependent libraries.
|
||||
* Checks if the aggregate configuration parameter has been set to true. If it has a MojoExecutionException is
|
||||
* thrown because the aggregate configuration parameter is no longer supported.
|
||||
*
|
||||
* @param project the project to run dependency-check on
|
||||
* @return the Engine used to scan the dependencies.
|
||||
* @throws DatabaseException thrown if there is an exception connecting to the database
|
||||
* @throws MojoExecutionException thrown if aggregate is set to true
|
||||
*/
|
||||
private Engine executeDependencyCheck(MavenProject project) throws DatabaseException {
|
||||
final Engine localEngine;
|
||||
if (engine == null) {
|
||||
localEngine = initializeEngine(project);
|
||||
} else {
|
||||
localEngine = engine;
|
||||
private void validateAggregate() throws MojoExecutionException {
|
||||
if (aggregate) {
|
||||
final String msg = "Aggregate configuration detected - as of dependency-check 1.2.8 this no longer supported. "
|
||||
+ "Please use the aggregate goal instead.";
|
||||
throw new MojoExecutionException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
final Set<Artifact> artifacts = project.getArtifacts();
|
||||
for (Artifact a : artifacts) {
|
||||
/**
|
||||
* Generates the Dependency-Check Site Report.
|
||||
*
|
||||
* @param sink the sink to write the report to
|
||||
* @param locale the locale to use when generating the report
|
||||
* @throws MavenReportException if a maven report exception occurs
|
||||
* @deprecated use {@link #generate(org.apache.maven.doxia.sink.Sink, java.util.Locale) instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public final void generate(@SuppressWarnings("deprecation") org.codehaus.doxia.sink.Sink sink, Locale locale) throws MavenReportException {
|
||||
generate((Sink) sink, locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the Dependency-Check Site Report.
|
||||
*
|
||||
* @param sink the sink to write the report to
|
||||
* @param locale the locale to use when generating the report
|
||||
* @throws MavenReportException if a maven report exception occurs
|
||||
*/
|
||||
public void generate(Sink sink, Locale locale) throws MavenReportException {
|
||||
try {
|
||||
validateAggregate();
|
||||
} catch (MojoExecutionException ex) {
|
||||
throw new MavenReportException(ex.getMessage());
|
||||
}
|
||||
project.setContextValue(getOutputDirectoryContextKey(), getReportOutputDirectory());
|
||||
try {
|
||||
runCheck();
|
||||
} catch (MojoExecutionException ex) {
|
||||
throw new MavenReportException(ex.getMessage(), ex);
|
||||
} catch (MojoFailureException ex) {
|
||||
LOGGER.warning("Vulnerabilities were identifies that exceed the CVSS threshold for failing the build");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the correct output directory depending on if a site is being executed or not.
|
||||
*
|
||||
* @return the directory to write the report(s)
|
||||
* @throws MojoExecutionException thrown if there is an error loading the file path
|
||||
*/
|
||||
protected File getCorrectOutputDirectory() throws MojoExecutionException {
|
||||
return getCorrectOutputDirectory(this.project);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the correct output directory depending on if a site is being executed or not.
|
||||
*
|
||||
* @param current the Maven project to get the output directory from
|
||||
* @return the directory to write the report(s)
|
||||
* @throws MojoExecutionException thrown if there is an error loading the file path
|
||||
*/
|
||||
protected File getCorrectOutputDirectory(MavenProject current) throws MojoExecutionException {
|
||||
final Object obj = current.getContextValue(getOutputDirectoryContextKey());
|
||||
if (obj != null && obj instanceof File) {
|
||||
return (File) obj;
|
||||
} else {
|
||||
throw new MojoExecutionException(String.format("Unable to determine output directory for '%s'", current.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans the project's artifacts and adds them to the engine's dependency list.
|
||||
*
|
||||
* @param project the project to scan the dependencies of
|
||||
* @param engine the engine to use to scan the dependencies
|
||||
*/
|
||||
protected void scanArtifacts(MavenProject project, Engine engine) {
|
||||
for (Artifact a : project.getArtifacts()) {
|
||||
if (excludeFromScan(a)) {
|
||||
continue;
|
||||
}
|
||||
final List<Dependency> deps = localEngine.scan(a.getFile().getAbsoluteFile());
|
||||
final List<Dependency> deps = engine.scan(a.getFile().getAbsoluteFile());
|
||||
if (deps != null) {
|
||||
if (deps.size() == 1) {
|
||||
final Dependency d = deps.get(0);
|
||||
@@ -345,44 +442,96 @@ public class DependencyCheckMojo extends ReportAggregationMojo {
|
||||
}
|
||||
}
|
||||
}
|
||||
localEngine.analyzeDependencies();
|
||||
|
||||
return localEngine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the dependency-check scan and generates the necassary report.
|
||||
*
|
||||
* @throws MojoExecutionException thrown if there is an exception running the scan
|
||||
* @throws MojoFailureException thrown if dependency-check is configured to fail the build
|
||||
*/
|
||||
public abstract void runCheck() throws MojoExecutionException, MojoFailureException;
|
||||
|
||||
/**
|
||||
* Sets the Reporting output directory.
|
||||
*
|
||||
* @param directory the output directory
|
||||
*/
|
||||
@Override
|
||||
public void setReportOutputDirectory(File directory) {
|
||||
reportOutputDirectory = directory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the report output directory.
|
||||
*
|
||||
* @return the report output directory
|
||||
*/
|
||||
@Override
|
||||
public File getReportOutputDirectory() {
|
||||
return reportOutputDirectory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the output directory.
|
||||
*
|
||||
* @return the output directory
|
||||
*/
|
||||
public File getOutputDirectory() {
|
||||
return outputDirectory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this is an external report. This method always returns true.
|
||||
*
|
||||
* @return <code>true</code>
|
||||
*/
|
||||
@Override
|
||||
public final boolean isExternalReport() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the output name.
|
||||
*
|
||||
* @return the output name
|
||||
*/
|
||||
public String getOutputName() {
|
||||
if ("HTML".equalsIgnoreCase(this.format) || "ALL".equalsIgnoreCase(this.format)) {
|
||||
return "dependency-check-report";
|
||||
} else if ("XML".equalsIgnoreCase(this.format)) {
|
||||
return "dependency-check-report.xml#";
|
||||
} else if ("VULN".equalsIgnoreCase(this.format)) {
|
||||
return "dependency-check-vulnerability";
|
||||
} else {
|
||||
LOGGER.log(Level.WARNING, "Unknown report format used during site generation.");
|
||||
return "dependency-check-report";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the category name.
|
||||
*
|
||||
* @return the category name
|
||||
*/
|
||||
public String getCategoryName() {
|
||||
return MavenReport.CATEGORY_PROJECT_REPORTS;
|
||||
}
|
||||
//</editor-fold>
|
||||
|
||||
/**
|
||||
* Initializes a new <code>Engine</code> that can be used for scanning.
|
||||
*
|
||||
* @param project the current MavenProject
|
||||
* @return a newly instantiated <code>Engine</code>
|
||||
* @throws DatabaseException thrown if there is a database exception
|
||||
*/
|
||||
private Engine initializeEngine(MavenProject project) throws DatabaseException {
|
||||
protected Engine initializeEngine() throws DatabaseException {
|
||||
final InputStream in = BaseDependencyCheckMojo.class.getClassLoader().getResourceAsStream(LOG_PROPERTIES_FILE);
|
||||
LogUtils.prepareLogger(in, logFile);
|
||||
populateSettings();
|
||||
final Engine localEngine = new Engine(project);
|
||||
return localEngine;
|
||||
return new Engine(this.project, this.reactorProjects);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests is the artifact should be included in the scan (i.e. is the dependency in a scope that is being scanned).
|
||||
*
|
||||
* @param a the Artifact to test
|
||||
* @return <code>true</code> if the artifact is in an excluded scope; otherwise <code>false</code>
|
||||
*/
|
||||
private boolean excludeFromScan(Artifact a) {
|
||||
if (skipTestScope && Artifact.SCOPE_TEST.equals(a.getScope())) {
|
||||
return true;
|
||||
}
|
||||
if (skipProvidedScope && Artifact.SCOPE_PROVIDED.equals(a.getScope())) {
|
||||
return true;
|
||||
}
|
||||
if (skipRuntimeScope && !Artifact.SCOPE_RUNTIME.equals(a.getScope())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//<editor-fold defaultstate="collapsed" desc="Methods to populate global settings">
|
||||
/**
|
||||
* Takes the properties supplied and updates the dependency-check settings. Additionally, this sets the system
|
||||
* properties required to change the proxy url, port, and connection timeout.
|
||||
@@ -443,6 +592,8 @@ public class DependencyCheckMojo extends ReportAggregationMojo {
|
||||
//NUSPEC ANALYZER
|
||||
Settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, nuspecAnalyzerEnabled);
|
||||
//NEXUS ANALYZER
|
||||
Settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled);
|
||||
//NEXUS ANALYZER
|
||||
Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled);
|
||||
if (nexusUrl != null && !nexusUrl.isEmpty()) {
|
||||
Settings.setString(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
|
||||
@@ -527,248 +678,90 @@ public class DependencyCheckMojo extends ReportAggregationMojo {
|
||||
return null;
|
||||
}
|
||||
|
||||
//</editor-fold>
|
||||
/**
|
||||
* Initialize the mojo.
|
||||
*/
|
||||
@Override
|
||||
protected void initialize() {
|
||||
final InputStream in = DependencyCheckMojo.class.getClassLoader().getResourceAsStream(LOG_PROPERTIES_FILE);
|
||||
LogUtils.prepareLogger(in, logFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the dependency-check and generates the report.
|
||||
* Tests is the artifact should be included in the scan (i.e. is the dependency in a scope that is being scanned).
|
||||
*
|
||||
* @throws MojoExecutionException if a maven exception occurs
|
||||
* @throws MojoFailureException thrown if a CVSS score is found that is higher then the configured level
|
||||
* @param a the Artifact to test
|
||||
* @return <code>true</code> if the artifact is in an excluded scope; otherwise <code>false</code>
|
||||
*/
|
||||
@Override
|
||||
protected void performExecute() throws MojoExecutionException, MojoFailureException {
|
||||
try {
|
||||
engine = executeDependencyCheck();
|
||||
ReportingUtil.generateExternalReports(engine, outputDirectory, getProject().getName(), format);
|
||||
if (this.showSummary) {
|
||||
showSummary(engine.getDependencies());
|
||||
}
|
||||
if (this.failBuildOnCVSS <= 10) {
|
||||
checkForFailure(engine.getDependencies());
|
||||
}
|
||||
} catch (DatabaseException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Unable to connect to the dependency-check database; analysis has stopped");
|
||||
LOGGER.log(Level.FINE, "", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postExecute() throws MojoExecutionException, MojoFailureException {
|
||||
try {
|
||||
super.postExecute();
|
||||
} finally {
|
||||
cleanupEngine();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postGenerate() throws MavenReportException {
|
||||
try {
|
||||
super.postGenerate();
|
||||
} finally {
|
||||
cleanupEngine();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls <code>engine.cleanup()</code> to release resources.
|
||||
*/
|
||||
private void cleanupEngine() {
|
||||
if (engine != null) {
|
||||
engine.cleanup();
|
||||
engine = null;
|
||||
}
|
||||
Settings.cleanup(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the Dependency-Check Site Report.
|
||||
*
|
||||
* @param locale the locale to use when generating the report
|
||||
* @throws MavenReportException if a maven report exception occurs
|
||||
*/
|
||||
@Override
|
||||
protected void executeNonAggregateReport(Locale locale) throws MavenReportException {
|
||||
final List<Dependency> deps = readDataFile();
|
||||
if (deps != null) {
|
||||
try {
|
||||
if (engine != null) {
|
||||
engine = initializeEngine(getProject());
|
||||
}
|
||||
engine.getDependencies().addAll(deps);
|
||||
} catch (DatabaseException ex) {
|
||||
final String msg = String.format("An unrecoverable exception with the dependency-check initialization occured while scanning %s",
|
||||
getProject().getName());
|
||||
throw new MavenReportException(msg, ex);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
engine = executeDependencyCheck();
|
||||
} catch (DatabaseException ex) {
|
||||
final String msg = String.format("An unrecoverable exception with the dependency-check scan occured while scanning %s",
|
||||
getProject().getName());
|
||||
throw new MavenReportException(msg, ex);
|
||||
}
|
||||
}
|
||||
ReportingUtil.generateExternalReports(engine, getReportOutputDirectory(), getProject().getName(), format);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void executeAggregateReport(MavenProject project, Locale locale) throws MavenReportException {
|
||||
List<Dependency> deps = readDataFile(project);
|
||||
if (deps != null) {
|
||||
try {
|
||||
if (engine != null) {
|
||||
engine = initializeEngine(project);
|
||||
}
|
||||
engine.getDependencies().addAll(deps);
|
||||
} catch (DatabaseException ex) {
|
||||
final String msg = String.format("An unrecoverable exception with the dependency-check initialization occured while scanning %s",
|
||||
project.getName());
|
||||
throw new MavenReportException(msg, ex);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
engine = executeDependencyCheck(project);
|
||||
} catch (DatabaseException ex) {
|
||||
final String msg = String.format("An unrecoverable exception with the dependency-check scan occured while scanning %s",
|
||||
project.getName());
|
||||
throw new MavenReportException(msg, ex);
|
||||
}
|
||||
}
|
||||
for (MavenProject child : getAllChildren(project)) {
|
||||
deps = readDataFile(child);
|
||||
if (deps == null) {
|
||||
final String msg = String.format("Unable to include information on %s in the dependency-check aggregate report",
|
||||
child.getName());
|
||||
LOGGER.severe(msg);
|
||||
} else {
|
||||
engine.getDependencies().addAll(deps);
|
||||
}
|
||||
}
|
||||
final DependencyBundlingAnalyzer bundler = new DependencyBundlingAnalyzer();
|
||||
try {
|
||||
bundler.analyze(null, engine);
|
||||
} catch (AnalysisException ex) {
|
||||
LOGGER.log(Level.WARNING, "An error occured grouping the dependencies; duplicate entries may exist in the report", ex);
|
||||
LOGGER.log(Level.FINE, "Bundling Exception", ex);
|
||||
}
|
||||
final File outputDir = getReportOutputDirectory(project);
|
||||
if (outputDir != null) {
|
||||
ReportingUtil.generateExternalReports(engine, outputDir, project.getName(), format);
|
||||
}
|
||||
}
|
||||
|
||||
// <editor-fold defaultstate="collapsed" desc="Mojo interface/abstract required setter/getter methods">
|
||||
/**
|
||||
* Returns the output name.
|
||||
*
|
||||
* @return the output name
|
||||
*/
|
||||
public String getOutputName() {
|
||||
if ("HTML".equalsIgnoreCase(this.format) || "ALL".equalsIgnoreCase(this.format)) {
|
||||
return "dependency-check-report";
|
||||
} else if ("XML".equalsIgnoreCase(this.format)) {
|
||||
return "dependency-check-report.xml#";
|
||||
} else if ("VULN".equalsIgnoreCase(this.format)) {
|
||||
return "dependency-check-vulnerability";
|
||||
} else {
|
||||
LOGGER.log(Level.WARNING, "Unknown report format used during site generation.");
|
||||
return "dependency-check-report";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the category name.
|
||||
*
|
||||
* @return the category name
|
||||
*/
|
||||
public String getCategoryName() {
|
||||
return MavenReport.CATEGORY_PROJECT_REPORTS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the report name.
|
||||
*
|
||||
* @param locale the location
|
||||
* @return the report name
|
||||
*/
|
||||
public String getName(Locale locale) {
|
||||
return "dependency-check";
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the description of the Dependency-Check report to be displayed in the Maven Generated Reports page.
|
||||
*
|
||||
* @param locale The Locale to get the description for
|
||||
* @return the description
|
||||
*/
|
||||
public String getDescription(Locale locale) {
|
||||
return "A report providing details on any published "
|
||||
+ "vulnerabilities within project dependencies. This report is a best effort but may contain "
|
||||
+ "false positives and false negatives.";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not a report can be generated.
|
||||
*
|
||||
* @return <code>true</code> if a report can be generated; otherwise <code>false</code>
|
||||
*/
|
||||
public boolean canGenerateReport() {
|
||||
if (canGenerateAggregateReport() || (isAggregate() && isMultiModule())) {
|
||||
protected boolean excludeFromScan(Artifact a) {
|
||||
if (skipTestScope && Artifact.SCOPE_TEST.equals(a.getScope())) {
|
||||
return true;
|
||||
}
|
||||
if (canGenerateNonAggregateReport()) {
|
||||
if (skipProvidedScope && Artifact.SCOPE_PROVIDED.equals(a.getScope())) {
|
||||
return true;
|
||||
}
|
||||
if (skipRuntimeScope && !Artifact.SCOPE_RUNTIME.equals(a.getScope())) {
|
||||
return true;
|
||||
} else {
|
||||
final String msg;
|
||||
if (getProject().getArtifacts().size() > 0) {
|
||||
msg = "No project dependencies exist in the included scope - dependency-check:check is unable to generate a report.";
|
||||
} else {
|
||||
msg = "No project dependencies exist - dependency-check:check is unable to generate a report.";
|
||||
}
|
||||
LOGGER.warning(msg);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not a non-aggregate report can be generated.
|
||||
* Returns a reference to the current project. This method is used instead of auto-binding the project via component
|
||||
* annotation in concrete implementations of this. If the child has a <code>@Component MavenProject project;</code>
|
||||
* defined then the abstract class (i.e. this class) will not have access to the current project (just the way Maven
|
||||
* works with the binding).
|
||||
*
|
||||
* @return <code>true</code> if a non-aggregate report can be generated; otherwise <code>false</code>
|
||||
* @return returns a reference to the current project
|
||||
*/
|
||||
@Override
|
||||
protected boolean canGenerateNonAggregateReport() {
|
||||
boolean ability = false;
|
||||
for (Artifact a : getProject().getArtifacts()) {
|
||||
if (!excludeFromScan(a)) {
|
||||
ability = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ability;
|
||||
protected MavenProject getProject() {
|
||||
return project;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not an aggregate report can be generated.
|
||||
* Returns the list of Maven Projects in this build.
|
||||
*
|
||||
* @return <code>true</code> if an aggregate report can be generated; otherwise <code>false</code>
|
||||
* @return the list of Maven Projects in this build
|
||||
*/
|
||||
@Override
|
||||
protected boolean canGenerateAggregateReport() {
|
||||
return isAggregate() && isLastProject();
|
||||
protected List<MavenProject> getReactorProjects() {
|
||||
return reactorProjects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the report format.
|
||||
*
|
||||
* @return the report format
|
||||
*/
|
||||
protected String getFormat() {
|
||||
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).
|
||||
*/
|
||||
protected void writeReports(Engine engine, MavenProject p, File outputDir) {
|
||||
DatabaseProperties prop = null;
|
||||
CveDB cve = null;
|
||||
try {
|
||||
cve = new CveDB();
|
||||
cve.open();
|
||||
prop = cve.getDatabaseProperties();
|
||||
} catch (DatabaseException ex) {
|
||||
LOGGER.log(Level.FINE, "Unable to retrieve DB Properties", ex);
|
||||
} finally {
|
||||
if (cve != null) {
|
||||
cve.close();
|
||||
}
|
||||
}
|
||||
final ReportGenerator r = new ReportGenerator(p.getName(), engine.getDependencies(), engine.getAnalyzers(), prop);
|
||||
try {
|
||||
r.generateReports(outputDir.getAbsolutePath(), format);
|
||||
} catch (IOException ex) {
|
||||
LOGGER.log(Level.SEVERE,
|
||||
"Unexpected exception occurred during analysis; please see the verbose error log for more details.");
|
||||
LOGGER.log(Level.FINE, null, ex);
|
||||
} catch (Throwable ex) {
|
||||
LOGGER.log(Level.SEVERE,
|
||||
"Unexpected exception occurred during analysis; please see the verbose error log for more details.");
|
||||
LOGGER.log(Level.FINE, null, ex);
|
||||
}
|
||||
}
|
||||
|
||||
// </editor-fold>
|
||||
//<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 that is above the threshold set in the
|
||||
@@ -777,27 +770,29 @@ public class DependencyCheckMojo extends ReportAggregationMojo {
|
||||
* @param dependencies the list of dependency objects
|
||||
* @throws MojoFailureException thrown if a CVSS score is found that is higher then the threshold set
|
||||
*/
|
||||
private void checkForFailure(List<Dependency> dependencies) throws MojoFailureException {
|
||||
final StringBuilder ids = new StringBuilder();
|
||||
for (Dependency d : dependencies) {
|
||||
boolean addName = true;
|
||||
for (Vulnerability v : d.getVulnerabilities()) {
|
||||
if (v.getCvssScore() >= failBuildOnCVSS) {
|
||||
if (addName) {
|
||||
addName = false;
|
||||
ids.append(NEW_LINE).append(d.getFileName()).append(": ");
|
||||
ids.append(v.getName());
|
||||
} else {
|
||||
ids.append(", ").append(v.getName());
|
||||
protected void checkForFailure(List<Dependency> dependencies) throws MojoFailureException {
|
||||
if (failBuildOnCVSS <= 10) {
|
||||
final StringBuilder ids = new StringBuilder();
|
||||
for (Dependency d : dependencies) {
|
||||
boolean addName = true;
|
||||
for (Vulnerability v : d.getVulnerabilities()) {
|
||||
if (v.getCvssScore() >= failBuildOnCVSS) {
|
||||
if (addName) {
|
||||
addName = false;
|
||||
ids.append(NEW_LINE).append(d.getFileName()).append(": ");
|
||||
ids.append(v.getName());
|
||||
} else {
|
||||
ids.append(", ").append(v.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ids.length() > 0) {
|
||||
final String msg = String.format("%n%nDependency-Check Failure:%n"
|
||||
+ "One or more dependencies were identified with vulnerabilities that have a CVSS score greater then '%.1f': %s%n"
|
||||
+ "See the dependency-check report for more details.%n%n", failBuildOnCVSS, ids.toString());
|
||||
throw new MojoFailureException(msg);
|
||||
if (ids.length() > 0) {
|
||||
final String msg = String.format("%n%nDependency-Check Failure:%n"
|
||||
+ "One or more dependencies were identified with vulnerabilities that have a CVSS score greater then '%.1f': %s%n"
|
||||
+ "See the dependency-check report for more details.%n%n", failBuildOnCVSS, ids.toString());
|
||||
throw new MojoFailureException(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -806,52 +801,73 @@ public class DependencyCheckMojo extends ReportAggregationMojo {
|
||||
*
|
||||
* @param dependencies a list of dependency objects
|
||||
*/
|
||||
private void showSummary(List<Dependency> dependencies) {
|
||||
final StringBuilder summary = new StringBuilder();
|
||||
for (Dependency d : dependencies) {
|
||||
boolean firstEntry = true;
|
||||
final StringBuilder ids = new StringBuilder();
|
||||
for (Vulnerability v : d.getVulnerabilities()) {
|
||||
if (firstEntry) {
|
||||
firstEntry = false;
|
||||
} else {
|
||||
ids.append(", ");
|
||||
}
|
||||
ids.append(v.getName());
|
||||
}
|
||||
if (ids.length() > 0) {
|
||||
summary.append(d.getFileName()).append(" (");
|
||||
firstEntry = true;
|
||||
for (Identifier id : d.getIdentifiers()) {
|
||||
protected void showSummary(List<Dependency> dependencies) {
|
||||
if (showSummary) {
|
||||
final StringBuilder summary = new StringBuilder();
|
||||
for (Dependency d : dependencies) {
|
||||
boolean firstEntry = true;
|
||||
final StringBuilder ids = new StringBuilder();
|
||||
for (Vulnerability v : d.getVulnerabilities()) {
|
||||
if (firstEntry) {
|
||||
firstEntry = false;
|
||||
} else {
|
||||
summary.append(", ");
|
||||
ids.append(", ");
|
||||
}
|
||||
summary.append(id.getValue());
|
||||
ids.append(v.getName());
|
||||
}
|
||||
if (ids.length() > 0) {
|
||||
summary.append(d.getFileName()).append(" (");
|
||||
firstEntry = true;
|
||||
for (Identifier id : d.getIdentifiers()) {
|
||||
if (firstEntry) {
|
||||
firstEntry = false;
|
||||
} else {
|
||||
summary.append(", ");
|
||||
}
|
||||
summary.append(id.getValue());
|
||||
}
|
||||
summary.append(") : ").append(ids).append(NEW_LINE);
|
||||
}
|
||||
summary.append(") : ").append(ids).append(NEW_LINE);
|
||||
}
|
||||
}
|
||||
if (summary.length() > 0) {
|
||||
final String msg = String.format("%n%n" + "One or more dependencies were identified with known vulnerabilities:%n%n%s"
|
||||
+ "%n%nSee the dependency-check report for more details.%n%n", summary.toString());
|
||||
LOGGER.log(Level.WARNING, msg);
|
||||
if (summary.length() > 0) {
|
||||
final String msg = String.format("%n%n" + "One or more dependencies were identified with known vulnerabilities:%n%n%s"
|
||||
+ "%n%nSee the dependency-check report for more details.%n%n", summary.toString());
|
||||
LOGGER.log(Level.WARNING, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//</editor-fold>
|
||||
//<editor-fold defaultstate="collapsed" desc="Methods to read/write the serialized data file">
|
||||
/**
|
||||
* Returns the key used to store the path to the data file that is saved by <code>writeDataFile()</code>. This key
|
||||
* is used in the <code>MavenProject.(set|get)ContextValue</code>.
|
||||
*
|
||||
* @return the key used to store the path to the data file
|
||||
*/
|
||||
protected String getDataFileContextKey() {
|
||||
return "dependency-check-path-" + dataFileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key used to store the path to the output directory. When generating the report in the
|
||||
* <code>executeAggregateReport()</code> the output directory should be obtained by using this key.
|
||||
*
|
||||
* @return the key used to store the path to the output directory
|
||||
*/
|
||||
protected String getOutputDirectoryContextKey() {
|
||||
return "dependency-output-dir-" + dataFileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the scan data to disk. This is used to serialize the scan data between the "check" and "aggregate" phase.
|
||||
*
|
||||
* @return the File object referencing the data file that was written
|
||||
* @param dependencies the list of dependencies to serialize
|
||||
*/
|
||||
@Override
|
||||
protected File writeDataFile() {
|
||||
protected void writeDataFile(List<Dependency> dependencies) {
|
||||
File file = null;
|
||||
if (engine != null && getProject().getContextValue(this.getDataFileContextKey()) == null) {
|
||||
file = new File(getProject().getBuild().getDirectory(), getDataFileName());
|
||||
if (dependencies != null && project.getContextValue(this.getDataFileContextKey()) == null) {
|
||||
file = new File(project.getBuild().getDirectory(), dataFileName);
|
||||
OutputStream os = null;
|
||||
OutputStream bos = null;
|
||||
ObjectOutputStream out = null;
|
||||
@@ -859,13 +875,14 @@ public class DependencyCheckMojo extends ReportAggregationMojo {
|
||||
os = new FileOutputStream(file);
|
||||
bos = new BufferedOutputStream(os);
|
||||
out = new ObjectOutputStream(bos);
|
||||
out.writeObject(engine.getDependencies());
|
||||
out.writeObject(dependencies);
|
||||
out.flush();
|
||||
|
||||
//call reset to prevent resource leaks per
|
||||
//https://www.securecoding.cert.org/confluence/display/java/SER10-J.+Avoid+memory+and+resource+leaks+during+serialization
|
||||
out.reset();
|
||||
|
||||
project.setContextValue(this.getDataFileContextKey(), file.getAbsolutePath());
|
||||
LOGGER.fine(String.format("Serialized data file written to '%s'", file.getAbsolutePath()));
|
||||
} catch (IOException ex) {
|
||||
LOGGER.log(Level.WARNING, "Unable to create data file used for report aggregation; "
|
||||
+ "if report aggregation is being used the results may be incomplete.");
|
||||
@@ -894,18 +911,6 @@ public class DependencyCheckMojo extends ReportAggregationMojo {
|
||||
}
|
||||
}
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the serialized scan data from disk. This is used to serialize the scan data between the "check" and
|
||||
* "aggregate" phase.
|
||||
*
|
||||
* @return a <code>Engine</code> object populated with dependencies if the serialized data file exists; otherwise
|
||||
* <code>null</code> is returned
|
||||
*/
|
||||
protected List<Dependency> readDataFile() {
|
||||
return readDataFile(getProject());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -946,5 +951,4 @@ public class DependencyCheckMojo extends ReportAggregationMojo {
|
||||
return ret;
|
||||
}
|
||||
//</editor-fold>
|
||||
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* This file is part of dependency-check-maven.
|
||||
*
|
||||
* 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) 2013 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.maven;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.apache.maven.artifact.Artifact;
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.plugin.MojoFailureException;
|
||||
import org.apache.maven.plugins.annotations.LifecyclePhase;
|
||||
import org.apache.maven.plugins.annotations.Mojo;
|
||||
import org.apache.maven.plugins.annotations.ResolutionScope;
|
||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
|
||||
/**
|
||||
* Maven Plugin that checks the project dependencies to see if they have any known published vulnerabilities.
|
||||
*
|
||||
* @author Jeremy Long <jeremy.long@owasp.org>
|
||||
*/
|
||||
@Mojo(
|
||||
name = "check",
|
||||
defaultPhase = LifecyclePhase.COMPILE,
|
||||
threadSafe = true,
|
||||
requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME,
|
||||
requiresOnline = true
|
||||
)
|
||||
public class CheckMojo extends BaseDependencyCheckMojo {
|
||||
|
||||
/**
|
||||
* Logger field reference.
|
||||
*/
|
||||
private static final Logger LOGGER = Logger.getLogger(CheckMojo.class.getName());
|
||||
|
||||
/**
|
||||
* Returns whether or not a the report can be generated.
|
||||
*
|
||||
* @return <code>true</code> if the report can be generated; otherwise <code>false</code>
|
||||
*/
|
||||
@Override
|
||||
public boolean canGenerateReport() {
|
||||
boolean isCapable = false;
|
||||
for (Artifact a : getProject().getArtifacts()) {
|
||||
if (!excludeFromScan(a)) {
|
||||
isCapable = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return isCapable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the dependency-check engine on the project's dependencies and generates the report.
|
||||
*
|
||||
* @throws MojoExecutionException thrown if there is an exception executing the goal
|
||||
* @throws MojoFailureException thrown if dependency-check is configured to fail the build
|
||||
*/
|
||||
@Override
|
||||
public void runCheck() throws MojoExecutionException, MojoFailureException {
|
||||
final Engine engine;
|
||||
try {
|
||||
engine = initializeEngine();
|
||||
} catch (DatabaseException ex) {
|
||||
LOGGER.log(Level.FINE, "Database connection error", ex);
|
||||
throw new MojoExecutionException("An exception occured connecting to the local database. Please see the log file for more details.", ex);
|
||||
}
|
||||
scanArtifacts(getProject(), engine);
|
||||
if (engine.getDependencies().isEmpty()) {
|
||||
LOGGER.info("No dependencies were identified that could be analyzed by dependency-check");
|
||||
} else {
|
||||
engine.analyzeDependencies();
|
||||
writeReports(engine, getProject(), getCorrectOutputDirectory());
|
||||
writeDataFile(engine.getDependencies());
|
||||
showSummary(engine.getDependencies());
|
||||
checkForFailure(engine.getDependencies());
|
||||
}
|
||||
engine.cleanup();
|
||||
Settings.cleanup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the report name.
|
||||
*
|
||||
* @param locale the location
|
||||
* @return the report name
|
||||
*/
|
||||
public String getName(Locale locale) {
|
||||
return "dependency-check";
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the description of the Dependency-Check report to be displayed in the Maven Generated Reports page.
|
||||
*
|
||||
* @param locale The Locale to get the description for
|
||||
* @return the description
|
||||
*/
|
||||
public String getDescription(Locale locale) {
|
||||
return "Generates a report providing details on any published vulnerabilities within project dependencies. "
|
||||
+ "This report is a best effort and may contain false positives and false negatives.";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,10 +17,12 @@
|
||||
*/
|
||||
package org.owasp.dependencycheck.maven;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.owasp.dependencycheck.analyzer.Analyzer;
|
||||
import org.owasp.dependencycheck.analyzer.CPEAnalyzer;
|
||||
import org.owasp.dependencycheck.analyzer.FileTypeAnalyzer;
|
||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
|
||||
@@ -44,22 +46,37 @@ public class Engine extends org.owasp.dependencycheck.Engine {
|
||||
* The current MavenProject.
|
||||
*/
|
||||
private MavenProject currentProject;
|
||||
/**
|
||||
* The list of MavenProjects that are part of the current build.
|
||||
*/
|
||||
private List<MavenProject> reactorProjects;
|
||||
/**
|
||||
* Key used in the MavenProject context values to note whether or not an update has been executed.
|
||||
*/
|
||||
public static final String UPDATE_EXECUTED_FLAG = "dependency-check-update-executed";
|
||||
|
||||
/**
|
||||
* Creates a new Engine to perform anyalsis on dependencies.
|
||||
*
|
||||
* @param project the current Maven project
|
||||
* @param reactorProjects the reactor projects for the current Maven execution
|
||||
* @throws DatabaseException thrown if there is an issue connecting to the database
|
||||
*/
|
||||
public Engine(MavenProject project) throws DatabaseException {
|
||||
public Engine(MavenProject project, List<MavenProject> reactorProjects) throws DatabaseException {
|
||||
this.currentProject = project;
|
||||
final MavenProject parent = getRootParent();
|
||||
if (parent != null && parent.getContextValue("dependency-check-data-was-updated") != null) {
|
||||
this.reactorProjects = reactorProjects;
|
||||
final MavenProject root = getExecutionRoot();
|
||||
if (root != null) {
|
||||
LOGGER.fine(String.format("Checking root project, %s, if updates have already been completed", root.getArtifactId()));
|
||||
} else {
|
||||
LOGGER.fine("Checking root project, null, if updates have already been completed");
|
||||
}
|
||||
if (root != null && root.getContextValue(UPDATE_EXECUTED_FLAG) != null) {
|
||||
System.setProperty(Settings.KEYS.AUTO_UPDATE, Boolean.FALSE.toString());
|
||||
}
|
||||
initializeEngine();
|
||||
if (parent != null) {
|
||||
parent.setContextValue("dependency-check-data-was-updated", Boolean.valueOf(true));
|
||||
if (root != null) {
|
||||
root.setContextValue(UPDATE_EXECUTED_FLAG, Boolean.TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +98,7 @@ public class Engine extends org.owasp.dependencycheck.Engine {
|
||||
@Override
|
||||
protected Analyzer initializeAnalyzer(Analyzer analyzer) {
|
||||
if ((analyzer instanceof CPEAnalyzer)) {
|
||||
CPEAnalyzer cpe = getPreviouslyLoadedAnalyzer();
|
||||
CPEAnalyzer cpe = getPreviouslyLoadedCPEAnalyzer();
|
||||
if (cpe != null) {
|
||||
return cpe;
|
||||
}
|
||||
@@ -91,6 +108,23 @@ public class Engine extends org.owasp.dependencycheck.Engine {
|
||||
return super.initializeAnalyzer(analyzer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases resources used by the analyzers by calling close() on each analyzer.
|
||||
*/
|
||||
@Override
|
||||
public void cleanup() {
|
||||
super.cleanup();
|
||||
if (currentProject == null || reactorProjects == null) {
|
||||
return;
|
||||
}
|
||||
if (this.currentProject == reactorProjects.get(reactorProjects.size() - 1)) {
|
||||
final CPEAnalyzer cpe = getPreviouslyLoadedCPEAnalyzer();
|
||||
if (cpe != null) {
|
||||
cpe.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the given analyzer. This skips closing the CPEAnalyzer.
|
||||
*
|
||||
@@ -99,7 +133,7 @@ public class Engine extends org.owasp.dependencycheck.Engine {
|
||||
@Override
|
||||
protected void closeAnalyzer(Analyzer analyzer) {
|
||||
if ((analyzer instanceof CPEAnalyzer)) {
|
||||
if (getPreviouslyLoadedAnalyzer() == null) {
|
||||
if (getPreviouslyLoadedCPEAnalyzer() == null) {
|
||||
super.closeAnalyzer(analyzer);
|
||||
}
|
||||
} else {
|
||||
@@ -107,26 +141,19 @@ public class Engine extends org.owasp.dependencycheck.Engine {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the CPEAnalyzer if it has been created and persisted in the root parent MavenProject context.
|
||||
*/
|
||||
public void cleanupFinal() {
|
||||
final CPEAnalyzer cpe = getPreviouslyLoadedAnalyzer();
|
||||
if (cpe != null) {
|
||||
cpe.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the CPEAnalyzer from the root Maven Project.
|
||||
*
|
||||
* @return an initialized CPEAnalyzer
|
||||
*/
|
||||
private CPEAnalyzer getPreviouslyLoadedAnalyzer() {
|
||||
private CPEAnalyzer getPreviouslyLoadedCPEAnalyzer() {
|
||||
CPEAnalyzer cpe = null;
|
||||
final MavenProject project = getRootParent();
|
||||
final MavenProject project = getExecutionRoot();
|
||||
if (project != null) {
|
||||
cpe = (CPEAnalyzer) project.getContextValue(CPE_ANALYZER_KEY);
|
||||
final Object obj = project.getContextValue(CPE_ANALYZER_KEY);
|
||||
if (obj != null && obj instanceof CPEAnalyzer) {
|
||||
cpe = (CPEAnalyzer) project.getContextValue(CPE_ANALYZER_KEY);
|
||||
}
|
||||
}
|
||||
return cpe;
|
||||
}
|
||||
@@ -137,7 +164,7 @@ public class Engine extends org.owasp.dependencycheck.Engine {
|
||||
* @param cpe the CPEAnalyzer to store
|
||||
*/
|
||||
private void storeCPEAnalyzer(CPEAnalyzer cpe) {
|
||||
final MavenProject p = getRootParent();
|
||||
final MavenProject p = getExecutionRoot();
|
||||
if (p != null) {
|
||||
p.setContextValue(CPE_ANALYZER_KEY, cpe);
|
||||
}
|
||||
@@ -148,7 +175,16 @@ public class Engine extends org.owasp.dependencycheck.Engine {
|
||||
*
|
||||
* @return the root Maven Project
|
||||
*/
|
||||
private MavenProject getRootParent() {
|
||||
private MavenProject getExecutionRoot() {
|
||||
if (reactorProjects == null) {
|
||||
return null;
|
||||
}
|
||||
for (MavenProject p : reactorProjects) {
|
||||
if (p.isExecutionRoot()) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
//the following should never run, but leaving it as a failsafe.
|
||||
if (this.currentProject == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -158,4 +194,15 @@ public class Engine extends org.owasp.dependencycheck.Engine {
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the file type analyzers so that they can be re-used to scan additional directories. Without the reset the
|
||||
* analyzer might be disabled because the first scan/analyze did not identify any files that could be processed by
|
||||
* the analyzer.
|
||||
*/
|
||||
public void resetFileTypeAnalyzers() {
|
||||
for (FileTypeAnalyzer a : getFileTypeAnalyzers()) {
|
||||
a.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,468 +0,0 @@
|
||||
/*
|
||||
* This file is part of dependency-check-maven.
|
||||
*
|
||||
* 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) 2014 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.maven;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Logger;
|
||||
import org.apache.maven.doxia.sink.Sink;
|
||||
import org.apache.maven.plugin.AbstractMojo;
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.plugin.MojoFailureException;
|
||||
import org.apache.maven.plugins.annotations.Component;
|
||||
import org.apache.maven.plugins.annotations.Parameter;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.apache.maven.reporting.MavenReport;
|
||||
import org.apache.maven.reporting.MavenReportException;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This is an abstract reporting mojo that enables report aggregation. Some of the code in the this class was copied
|
||||
* from the CoberturaReportMojo (http://mojo.codehaus.org/cobertura-maven-plugin/, version 2.6). The authors of the
|
||||
* CoberturaReportMojo were <a href="will.gwaltney@sas.com">Will Gwaltney</a> and
|
||||
* <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>. There working example of how to do report aggregation was
|
||||
* invaluable.</p>
|
||||
* <p>
|
||||
* An important point about using this abstract class is that it is intended for one to write some form of serialized
|
||||
* data (via the {@link org.owasp.dependencycheck.maven.ReportAggregationMojo#writeDataFile() }; note that the
|
||||
* <code>writeDataFile()</code> function is called automatically after either {@link org.owasp.dependencycheck.maven.ReportAggregationMojo#executeNonAggregateReport(org.apache.maven.doxia.sink.Sink,
|
||||
* org.apache.maven.doxia.sink.SinkFactory, java.util.Locale)
|
||||
* } or {@link org.owasp.dependencycheck.maven.ReportAggregationMojo#executeAggregateReport(org.apache.maven.doxia.sink.Sink,
|
||||
* org.apache.maven.doxia.sink.SinkFactory, java.util.Locale)
|
||||
* } are called. When <code>executeAggregateReport()</code> is implemented, one can call {@link org.owasp.dependencycheck.maven.ReportAggregationMojo#getChildDataFiles()
|
||||
* } to obtain a list of the data files to aggregate.</p>
|
||||
*
|
||||
*
|
||||
* @author Jeremy Long <jeremy.long@owasp.org>
|
||||
*/
|
||||
public abstract class ReportAggregationMojo extends AbstractMojo implements MavenReport {
|
||||
|
||||
/**
|
||||
* The Maven Project Object.
|
||||
*/
|
||||
@Component
|
||||
private MavenProject project;
|
||||
|
||||
/**
|
||||
* Logger field reference.
|
||||
*/
|
||||
private static final Logger LOGGER = Logger.getLogger(ReportAggregationMojo.class.getName());
|
||||
|
||||
/**
|
||||
* List of Maven project of the current build
|
||||
*/
|
||||
@Parameter(readonly = true, required = true, property = "reactorProjects")
|
||||
private List<MavenProject> reactorProjects;
|
||||
|
||||
/**
|
||||
* Generate aggregate reports in multi-module projects.
|
||||
*/
|
||||
@Parameter(property = "aggregate", defaultValue = "false")
|
||||
private boolean aggregate;
|
||||
|
||||
/**
|
||||
* Sets whether or not the external report format should be used.
|
||||
*/
|
||||
@Parameter(property = "metaFileName", defaultValue = "dependency-check.ser", required = true)
|
||||
private String dataFileName;
|
||||
/**
|
||||
* Specifies the destination directory for the generated Dependency-Check report. This generally maps to
|
||||
* "target/site".
|
||||
*/
|
||||
@Parameter(property = "reportOutputDirectory", defaultValue = "${project.reporting.outputDirectory}", required = true)
|
||||
private File reportOutputDirectory;
|
||||
|
||||
/**
|
||||
* Sets the Reporting output directory.
|
||||
*
|
||||
* @param directory the output directory
|
||||
*/
|
||||
@Override
|
||||
public void setReportOutputDirectory(File directory) {
|
||||
reportOutputDirectory = directory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the output directory.
|
||||
*
|
||||
* @return the output directory
|
||||
*/
|
||||
@Override
|
||||
public File getReportOutputDirectory() {
|
||||
return reportOutputDirectory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the output directory for the given project.
|
||||
*
|
||||
* @param project the Maven project to get the output directory for
|
||||
* @return the output directory for the given project
|
||||
*/
|
||||
public File getReportOutputDirectory(MavenProject project) {
|
||||
final Object o = project.getContextValue(getOutputDirectoryContextKey());
|
||||
if (o != null && o instanceof File) {
|
||||
return (File) o;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this is an external report. This method always returns true.
|
||||
*
|
||||
* @return <code>true</code>
|
||||
*/
|
||||
@Override
|
||||
public final boolean isExternalReport() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the mojo.
|
||||
*/
|
||||
protected abstract void initialize();
|
||||
|
||||
/**
|
||||
* The collection of child projects.
|
||||
*/
|
||||
private final Map<MavenProject, Set<MavenProject>> projectChildren = new HashMap<MavenProject, Set<MavenProject>>();
|
||||
|
||||
/**
|
||||
* Called before execute; allows for any setup that is needed. If this is overridden you must call
|
||||
* </code>super.preExecute()</code>.
|
||||
*
|
||||
* @throws MojoExecutionException thrown if there is an issue executing the mojo
|
||||
* @throws MojoFailureException thrown if there is an issue executing the mojo
|
||||
*/
|
||||
protected void preExecute() throws MojoExecutionException, MojoFailureException {
|
||||
buildAggregateInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the mojo is being executed.
|
||||
*
|
||||
* @throws MojoExecutionException thrown if there is an issue executing the mojo
|
||||
* @throws MojoFailureException thrown if there is an issue executing the mojo
|
||||
*/
|
||||
protected abstract void performExecute() throws MojoExecutionException, MojoFailureException;
|
||||
|
||||
/**
|
||||
* Runs after the mojo has executed. This implementation will call <code>writeDataFile()</code>. As such, it is
|
||||
* important that if this method is overriden that <code>super.postExecute()</code> is called.
|
||||
*
|
||||
* @throws MojoExecutionException thrown if there is an issue executing the mojo
|
||||
* @throws MojoFailureException thrown if there is an issue executing the mojo
|
||||
*/
|
||||
protected void postExecute() throws MojoExecutionException, MojoFailureException {
|
||||
final File written = writeDataFile();
|
||||
if (written != null) {
|
||||
project.setContextValue(getDataFileContextKey(), written.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key used to store the path to the data file that is saved by <code>writeDataFile()</code>. This key
|
||||
* is used in the <code>MavenProject.(set|get)ContextValue</code>.
|
||||
*
|
||||
* @return the key used to store the path to the data file
|
||||
*/
|
||||
protected String getDataFileContextKey() {
|
||||
return "dependency-check-path-" + this.getDataFileName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key used to store the path to the output directory. When generating the report in the
|
||||
* <code>executeAggregateReport()</code> the output directory should be obtained by using this key.
|
||||
*
|
||||
* @return the key used to store the path to the output directory
|
||||
*/
|
||||
protected String getOutputDirectoryContextKey() {
|
||||
return "dependency-output-dir-" + this.getDataFileName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is called by Maven to execute the mojo.
|
||||
*
|
||||
* @throws MojoExecutionException thrown if there is an issue executing the mojo
|
||||
* @throws MojoFailureException thrown if there is an issue executing the mojo
|
||||
*/
|
||||
public final void execute() throws MojoExecutionException, MojoFailureException {
|
||||
try {
|
||||
initialize();
|
||||
preExecute();
|
||||
performExecute();
|
||||
} finally {
|
||||
postExecute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs prior to the site report generation.
|
||||
*
|
||||
* @throws MavenReportException if a maven report exception occurs
|
||||
*/
|
||||
protected void preGenerate() throws MavenReportException {
|
||||
buildAggregateInfo();
|
||||
|
||||
project.setContextValue(getOutputDirectoryContextKey(), getReportOutputDirectory());
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes after the site report has been generated.
|
||||
*
|
||||
* @throws MavenReportException if a maven report exception occurs
|
||||
*/
|
||||
protected void postGenerate() throws MavenReportException {
|
||||
final File written = writeDataFile();
|
||||
if (written != null) {
|
||||
project.setContextValue(getDataFileContextKey(), written.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the non aggregate report.
|
||||
*
|
||||
* @param locale the locale to use when generating the report
|
||||
* @throws MavenReportException if a maven report exception occurs
|
||||
*/
|
||||
protected abstract void executeNonAggregateReport(Locale locale) throws MavenReportException;
|
||||
|
||||
/**
|
||||
* Generates the aggregate Site Report.
|
||||
*
|
||||
* @param project the maven project used to generate the aggregate report
|
||||
* @param locale the locale to use when generating the report
|
||||
* @throws MavenReportException if a maven report exception occurs
|
||||
*/
|
||||
protected abstract void executeAggregateReport(MavenProject project, Locale locale) throws MavenReportException;
|
||||
|
||||
/**
|
||||
* Generates the Dependency-Check Site Report.
|
||||
*
|
||||
* @param sink the sink to write the report to
|
||||
* @param locale the locale to use when generating the report
|
||||
* @throws MavenReportException if a maven report exception occurs
|
||||
* @deprecated use {@link #generate(org.apache.maven.doxia.sink.Sink, java.util.Locale) instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public final void generate(@SuppressWarnings("deprecation") org.codehaus.doxia.sink.Sink sink, Locale locale) throws MavenReportException {
|
||||
generate((Sink) sink, locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the Dependency-Check Site Report.
|
||||
*
|
||||
* @param sink the sink to write the report to
|
||||
* @param locale the locale to use when generating the report
|
||||
* @throws MavenReportException if a maven report exception occurs
|
||||
*/
|
||||
public final void generate(Sink sink, Locale locale) throws MavenReportException {
|
||||
try {
|
||||
initialize();
|
||||
preGenerate();
|
||||
if (canGenerateNonAggregateReport()) {
|
||||
executeNonAggregateReport(locale);
|
||||
}
|
||||
} finally {
|
||||
postGenerate();
|
||||
}
|
||||
if (canGenerateAggregateReport()) {
|
||||
for (MavenProject proj : reactorProjects) {
|
||||
if (!isMultiModule(proj)) {
|
||||
continue;
|
||||
}
|
||||
executeAggregateReport(proj, locale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the mojo can generate a non-aggregate report for this project.
|
||||
*
|
||||
* @return <code>true</code> if a non-aggregate report can be generated, otherwise <code>false</code>
|
||||
*/
|
||||
protected abstract boolean canGenerateNonAggregateReport();
|
||||
|
||||
/**
|
||||
* Returns whether or not we can generate any aggregate reports at this time.
|
||||
*
|
||||
* @return <code>true</code> if an aggregate report can be generated, otherwise <code>false</code>
|
||||
*/
|
||||
protected abstract boolean canGenerateAggregateReport();
|
||||
|
||||
/**
|
||||
* Returns the name of the data file that contains the serialized data.
|
||||
*
|
||||
* @return the name of the data file that contains the serialized data
|
||||
*/
|
||||
protected String getDataFileName() {
|
||||
return dataFileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the data file to disk in the target directory.
|
||||
*
|
||||
* @return the File object referencing the data file that was written
|
||||
*/
|
||||
protected abstract File writeDataFile();
|
||||
|
||||
/**
|
||||
* Collects the information needed for building aggregate reports.
|
||||
*/
|
||||
private void buildAggregateInfo() {
|
||||
// build parent-child map
|
||||
for (MavenProject proj : reactorProjects) {
|
||||
Set<MavenProject> depList = projectChildren.get(proj.getParent());
|
||||
if (depList == null) {
|
||||
depList = new HashSet<MavenProject>();
|
||||
projectChildren.put(proj.getParent(), depList);
|
||||
}
|
||||
depList.add(proj);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list containing all the recursive, non-pom children of the given project, never <code>null</code>.
|
||||
*
|
||||
* @return a list of child projects
|
||||
*/
|
||||
protected List<MavenProject> getAllChildren() {
|
||||
return getAllChildren(project);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list containing all the recursive, non-pom children of the given project, never <code>null</code>.
|
||||
*
|
||||
* @param parentProject the parent project to collect the child project references
|
||||
* @return a list of child projects
|
||||
*/
|
||||
protected List<MavenProject> getAllChildren(MavenProject parentProject) {
|
||||
final Set<MavenProject> children = projectChildren.get(parentProject);
|
||||
if (children == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final List<MavenProject> result = new ArrayList<MavenProject>();
|
||||
for (MavenProject child : children) {
|
||||
if (isMultiModule(child)) {
|
||||
result.addAll(getAllChildren(child));
|
||||
} else {
|
||||
result.add(child);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of data files that were produced by the direct children of the given MavenProject.
|
||||
*
|
||||
* @param project the Maven project to obtain the child data files from
|
||||
* @return a list of the data files
|
||||
*/
|
||||
protected List<File> getAllChildDataFiles(MavenProject project) {
|
||||
final List<MavenProject> children = getAllChildren(project);
|
||||
return getDataFiles(children);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns any existing output files from the given list of projects.
|
||||
*
|
||||
* @param projects the list of projects to obtain the output files from
|
||||
* @return a list of output files
|
||||
*/
|
||||
protected List<File> getDataFiles(List<MavenProject> projects) {
|
||||
final List<File> files = new ArrayList<File>();
|
||||
for (MavenProject proj : projects) {
|
||||
final Object path = project.getContextValue(getDataFileContextKey());
|
||||
if (path == null) {
|
||||
final String msg = String.format("Unable to aggregate data for '%s' - aggregate data file was not generated",
|
||||
proj.getName());
|
||||
LOGGER.warning(msg);
|
||||
} else {
|
||||
final File outputFile = new File((String) path);
|
||||
if (outputFile.exists()) {
|
||||
files.add(outputFile);
|
||||
} else {
|
||||
if (!isMultiModule(project)) {
|
||||
final String msg = String.format("Unable to aggregate data for '%s' - missing data file '%s'",
|
||||
proj.getName(), outputFile.getPath());
|
||||
LOGGER.warning(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the project has pom packaging
|
||||
*
|
||||
* @param mavenProject Project to test
|
||||
* @return <code>true</code> if it has a pom packaging; otherwise <code>false</code>
|
||||
*/
|
||||
protected boolean isMultiModule(MavenProject mavenProject) {
|
||||
return "pom".equals(mavenProject.getPackaging());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the current project has pom packaging
|
||||
*
|
||||
* @return <code>true</code> if it has a pom packaging; otherwise <code>false</code>
|
||||
*/
|
||||
protected boolean isMultiModule() {
|
||||
return isMultiModule(project);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the current project is the last project in a multi-module build. If the maven build is not a
|
||||
* multi-module project then this will always return true.
|
||||
*
|
||||
* @return <code>true</code> if the current project is the last project in a multi-module build; otherwise
|
||||
* <code>false</code>
|
||||
*/
|
||||
protected boolean isLastProject() {
|
||||
return project.equals(reactorProjects.get(reactorProjects.size() - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the mojo is configured to perform report aggregation.
|
||||
*
|
||||
* @return <code>true</code> if report aggregation is enabled; otherwise <code>false</code>
|
||||
*/
|
||||
public boolean isAggregate() {
|
||||
return aggregate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the current project. This method is used instead of auto-binding the project via component
|
||||
* annotation in concrete implementations of this. If the child has a <code>@Component MavenProject project;</code>
|
||||
* defined then the abstract class (i.e. this class) will not have access to the current project (just the way Maven
|
||||
* works with the binding).
|
||||
*
|
||||
* @return returns a reference to the current project
|
||||
*/
|
||||
protected MavenProject getProject() {
|
||||
return project;
|
||||
}
|
||||
}
|
||||
@@ -1,455 +0,0 @@
|
||||
/*
|
||||
* This file is part of dependency-check-maven.
|
||||
*
|
||||
* 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) 2014 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.maven;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.text.DateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.apache.maven.doxia.sink.Sink;
|
||||
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.dependency.Dependency;
|
||||
import org.owasp.dependencycheck.dependency.Evidence;
|
||||
import org.owasp.dependencycheck.dependency.Identifier;
|
||||
import org.owasp.dependencycheck.dependency.Reference;
|
||||
import org.owasp.dependencycheck.dependency.Vulnerability;
|
||||
import org.owasp.dependencycheck.dependency.VulnerableSoftware;
|
||||
import org.owasp.dependencycheck.reporting.ReportGenerator;
|
||||
|
||||
/**
|
||||
* A utility class that encapsulates the report generation for dependency-check-maven.
|
||||
*
|
||||
* @author Jeremy Long <jeremy.long@owasp.org>
|
||||
*/
|
||||
final class ReportingUtil {
|
||||
|
||||
/**
|
||||
* Logger field reference.
|
||||
*/
|
||||
private static final Logger LOGGER = Logger.getLogger(ReportingUtil.class.getName());
|
||||
|
||||
/**
|
||||
* Empty private constructor for this utility class.
|
||||
*/
|
||||
private ReportingUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the reports for a given dependency-check engine.
|
||||
*
|
||||
* @param engine a dependency-check engine
|
||||
* @param outDirectory the directory to write the reports to
|
||||
* @param projectName the name of the project that a report is being generated for
|
||||
* @param format the format of the report to generate
|
||||
*/
|
||||
static void generateExternalReports(Engine engine, File outDirectory, String projectName, String format) {
|
||||
DatabaseProperties prop = null;
|
||||
CveDB cve = null;
|
||||
try {
|
||||
cve = new CveDB();
|
||||
cve.open();
|
||||
prop = cve.getDatabaseProperties();
|
||||
} catch (DatabaseException ex) {
|
||||
LOGGER.log(Level.FINE, "Unable to retrieve DB Properties", ex);
|
||||
} finally {
|
||||
if (cve != null) {
|
||||
cve.close();
|
||||
}
|
||||
}
|
||||
final ReportGenerator r = new ReportGenerator(projectName, engine.getDependencies(), engine.getAnalyzers(), prop);
|
||||
try {
|
||||
r.generateReports(outDirectory.getCanonicalPath(), format);
|
||||
} catch (IOException ex) {
|
||||
LOGGER.log(Level.SEVERE,
|
||||
"Unexpected exception occurred during analysis; please see the verbose error log for more details.");
|
||||
LOGGER.log(Level.FINE, null, ex);
|
||||
} catch (Throwable ex) {
|
||||
LOGGER.log(Level.SEVERE,
|
||||
"Unexpected exception occurred during analysis; please see the verbose error log for more details.");
|
||||
LOGGER.log(Level.FINE, null, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a dependency-check report using the Maven Site format.
|
||||
*
|
||||
* @param engine the engine used to scan the dependencies
|
||||
* @param sink the sink to write the data to
|
||||
* @param projectName the name of the project
|
||||
*/
|
||||
static void generateMavenSiteReport(final Engine engine, Sink sink, String projectName) {
|
||||
final List<Dependency> dependencies = engine.getDependencies();
|
||||
|
||||
writeSiteReportHeader(sink, projectName);
|
||||
writeSiteReportTOC(sink, dependencies);
|
||||
|
||||
int cnt = 0;
|
||||
for (Dependency d : dependencies) {
|
||||
writeSiteReportDependencyHeader(sink, d);
|
||||
cnt = writeSiteReportDependencyEvidenceUsed(d, cnt, sink);
|
||||
cnt = writeSiteReportDependencyRelatedDependencies(d, cnt, sink);
|
||||
writeSiteReportDependencyIdentifiers(d, sink);
|
||||
writeSiteReportDependencyVulnerabilities(d, sink, cnt);
|
||||
}
|
||||
sink.body_();
|
||||
}
|
||||
|
||||
// <editor-fold defaultstate="collapsed" desc="various writeXXXXX methods to generate the Site Report">
|
||||
/**
|
||||
* Writes the vulnerabilities to the site report.
|
||||
*
|
||||
* @param d the dependency
|
||||
* @param sink the sink to write the data to
|
||||
* @param collapsibleHeaderCount the collapsible header count
|
||||
*/
|
||||
private static void writeSiteReportDependencyVulnerabilities(Dependency d, Sink sink, int collapsibleHeaderCount) {
|
||||
int cnt = collapsibleHeaderCount;
|
||||
if (d.getVulnerabilities() != null && !d.getVulnerabilities().isEmpty()) {
|
||||
for (Vulnerability v : d.getVulnerabilities()) {
|
||||
|
||||
sink.paragraph();
|
||||
sink.bold();
|
||||
try {
|
||||
sink.link("http://web.nvd.nist.gov/view/vuln/detail?vulnId=" + URLEncoder.encode(v.getName(), "US-ASCII"));
|
||||
sink.text(v.getName());
|
||||
sink.link_();
|
||||
sink.bold_();
|
||||
} catch (UnsupportedEncodingException ex) {
|
||||
sink.text(v.getName());
|
||||
sink.bold_();
|
||||
sink.lineBreak();
|
||||
sink.text("http://web.nvd.nist.gov/view/vuln/detail?vulnId=" + v.getName());
|
||||
}
|
||||
sink.paragraph_();
|
||||
sink.paragraph();
|
||||
sink.text("Severity: ");
|
||||
if (v.getCvssScore() < 4.0) {
|
||||
sink.text("Low");
|
||||
} else {
|
||||
if (v.getCvssScore() >= 7.0) {
|
||||
sink.text("High");
|
||||
} else {
|
||||
sink.text("Medium");
|
||||
}
|
||||
}
|
||||
sink.lineBreak();
|
||||
sink.text("CVSS Score: " + v.getCvssScore());
|
||||
if (v.getCwe() != null && !v.getCwe().isEmpty()) {
|
||||
sink.lineBreak();
|
||||
sink.text("CWE: ");
|
||||
sink.text(v.getCwe());
|
||||
}
|
||||
sink.paragraph_();
|
||||
sink.paragraph();
|
||||
sink.text(v.getDescription());
|
||||
if (v.getReferences() != null && !v.getReferences().isEmpty()) {
|
||||
sink.list();
|
||||
for (Reference ref : v.getReferences()) {
|
||||
sink.listItem();
|
||||
sink.text(ref.getSource());
|
||||
sink.text(" - ");
|
||||
sink.link(ref.getUrl());
|
||||
sink.text(ref.getName());
|
||||
sink.link_();
|
||||
sink.listItem_();
|
||||
}
|
||||
sink.list_();
|
||||
}
|
||||
sink.paragraph_();
|
||||
if (v.getVulnerableSoftware() != null && !v.getVulnerableSoftware().isEmpty()) {
|
||||
sink.paragraph();
|
||||
|
||||
cnt += 1;
|
||||
sink.rawText("Vulnerable Software <a href=\"javascript:toggleElement(this, 'vulnSoft" + cnt + "')\">[-]</a>");
|
||||
sink.rawText("<div id=\"vulnSoft" + cnt + "\" style=\"display:block\">");
|
||||
sink.list();
|
||||
for (VulnerableSoftware vs : v.getVulnerableSoftware()) {
|
||||
sink.listItem();
|
||||
try {
|
||||
sink.link("http://web.nvd.nist.gov/view/vuln/search-results?cpe=" + URLEncoder.encode(vs.getName(), "US-ASCII"));
|
||||
sink.text(vs.getName());
|
||||
sink.link_();
|
||||
if (vs.hasPreviousVersion()) {
|
||||
sink.text(" and all previous versions.");
|
||||
}
|
||||
} catch (UnsupportedEncodingException ex) {
|
||||
sink.text(vs.getName());
|
||||
if (vs.hasPreviousVersion()) {
|
||||
sink.text(" and all previous versions.");
|
||||
}
|
||||
sink.text(" (http://web.nvd.nist.gov/view/vuln/search-results?cpe=" + vs.getName() + ")");
|
||||
}
|
||||
|
||||
sink.listItem_();
|
||||
}
|
||||
sink.list_();
|
||||
sink.rawText("</div>");
|
||||
sink.paragraph_();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the identifiers to the site report.
|
||||
*
|
||||
* @param d the dependency
|
||||
* @param sink the sink to write the data to
|
||||
*/
|
||||
private static void writeSiteReportDependencyIdentifiers(Dependency d, Sink sink) {
|
||||
if (d.getIdentifiers() != null && !d.getIdentifiers().isEmpty()) {
|
||||
sink.sectionTitle4();
|
||||
sink.text("Identifiers");
|
||||
sink.sectionTitle4_();
|
||||
sink.list();
|
||||
for (Identifier i : d.getIdentifiers()) {
|
||||
sink.listItem();
|
||||
sink.text(i.getType());
|
||||
sink.text(": ");
|
||||
if (i.getUrl() != null && i.getUrl().length() > 0) {
|
||||
sink.link(i.getUrl());
|
||||
sink.text(i.getValue());
|
||||
sink.link_();
|
||||
} else {
|
||||
sink.text(i.getValue());
|
||||
}
|
||||
if (i.getDescription() != null && i.getDescription().length() > 0) {
|
||||
sink.lineBreak();
|
||||
sink.text(i.getDescription());
|
||||
}
|
||||
sink.listItem_();
|
||||
}
|
||||
sink.list_();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the related dependencies to the site report.
|
||||
*
|
||||
* @param d the dependency
|
||||
* @param sink the sink to write the data to
|
||||
* @param collapsibleHeaderCount the collapsible header count
|
||||
* @return the collapsible header count
|
||||
*/
|
||||
private static int writeSiteReportDependencyRelatedDependencies(Dependency d, int collapsibleHeaderCount, Sink sink) {
|
||||
int cnt = collapsibleHeaderCount;
|
||||
if (d.getRelatedDependencies() != null && !d.getRelatedDependencies().isEmpty()) {
|
||||
cnt += 1;
|
||||
sink.sectionTitle4();
|
||||
sink.rawText("Related Dependencies <a href=\"javascript:toggleElement(this, 'related" + cnt + "')\">[+]</a>");
|
||||
sink.sectionTitle4_();
|
||||
sink.rawText("<div id=\"related" + cnt + "\" style=\"display:none\">");
|
||||
sink.list();
|
||||
for (Dependency r : d.getRelatedDependencies()) {
|
||||
sink.listItem();
|
||||
sink.text(r.getFileName());
|
||||
sink.list();
|
||||
writeListItem(sink, "File Path: " + r.getFilePath());
|
||||
writeListItem(sink, "SHA1: " + r.getSha1sum());
|
||||
writeListItem(sink, "MD5: " + r.getMd5sum());
|
||||
sink.list_();
|
||||
sink.listItem_();
|
||||
}
|
||||
sink.list_();
|
||||
sink.rawText("</div>");
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the evidence used to the site report.
|
||||
*
|
||||
* @param d the dependency
|
||||
* @param sink the sink to write the data to
|
||||
* @param collapsibleHeaderCount the collapsible header count
|
||||
* @return the collapsible header count
|
||||
*/
|
||||
private static int writeSiteReportDependencyEvidenceUsed(Dependency d, int collapsibleHeaderCount, Sink sink) {
|
||||
int cnt = collapsibleHeaderCount;
|
||||
final Set<Evidence> evidence = d.getEvidenceForDisplay();
|
||||
if (evidence != null && evidence.size() > 0) {
|
||||
cnt += 1;
|
||||
sink.sectionTitle4();
|
||||
sink.rawText("Evidence Collected <a href=\"javascript:toggleElement(this, 'evidence" + cnt + "')\">[+]</a>");
|
||||
sink.sectionTitle4_();
|
||||
sink.rawText("<div id=\"evidence" + cnt + "\" style=\"display:none\">");
|
||||
sink.table();
|
||||
sink.tableRow();
|
||||
writeTableHeaderCell(sink, "Source");
|
||||
writeTableHeaderCell(sink, "Name");
|
||||
writeTableHeaderCell(sink, "Value");
|
||||
sink.tableRow_();
|
||||
for (Evidence e : evidence) {
|
||||
sink.tableRow();
|
||||
writeTableCell(sink, e.getSource());
|
||||
writeTableCell(sink, e.getName());
|
||||
writeTableCell(sink, e.getValue());
|
||||
sink.tableRow_();
|
||||
}
|
||||
sink.table_();
|
||||
sink.rawText("</div>");
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the dependency header to the site report.
|
||||
*
|
||||
* @param d the dependency
|
||||
* @param sink the sink to write the data to
|
||||
*/
|
||||
private static void writeSiteReportDependencyHeader(Sink sink, Dependency d) {
|
||||
sink.sectionTitle2();
|
||||
sink.anchor("sha1" + d.getSha1sum());
|
||||
sink.text(d.getFileName());
|
||||
sink.anchor_();
|
||||
sink.sectionTitle2_();
|
||||
if (d.getDescription() != null && d.getDescription().length() > 0) {
|
||||
sink.paragraph();
|
||||
sink.bold();
|
||||
sink.text("Description: ");
|
||||
sink.bold_();
|
||||
sink.text(d.getDescription());
|
||||
sink.paragraph_();
|
||||
}
|
||||
if (d.getLicense() != null && d.getLicense().length() > 0) {
|
||||
sink.paragraph();
|
||||
sink.bold();
|
||||
sink.text("License: ");
|
||||
sink.bold_();
|
||||
if (d.getLicense().startsWith("http://") && !d.getLicense().contains(" ")) {
|
||||
sink.link(d.getLicense());
|
||||
sink.text(d.getLicense());
|
||||
sink.link_();
|
||||
} else {
|
||||
sink.text(d.getLicense());
|
||||
}
|
||||
sink.paragraph_();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a list item to the site report.
|
||||
*
|
||||
* @param sink the sink to write the data to
|
||||
* @param text the text to write
|
||||
*/
|
||||
private static void writeListItem(Sink sink, String text) {
|
||||
sink.listItem();
|
||||
sink.text(text);
|
||||
sink.listItem_();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a table cell to the site report.
|
||||
*
|
||||
* @param sink the sink to write the data to
|
||||
* @param text the text to write
|
||||
*/
|
||||
private static void writeTableCell(Sink sink, String text) {
|
||||
sink.tableCell();
|
||||
sink.text(text);
|
||||
sink.tableCell_();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a table header cell to the site report.
|
||||
*
|
||||
* @param sink the sink to write the data to
|
||||
* @param text the text to write
|
||||
*/
|
||||
private static void writeTableHeaderCell(Sink sink, String text) {
|
||||
sink.tableHeaderCell();
|
||||
sink.text(text);
|
||||
sink.tableHeaderCell_();
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the TOC for the site report.
|
||||
*
|
||||
* @param sink the sink to write the data to
|
||||
* @param dependencies the dependencies that are being reported on
|
||||
*/
|
||||
private static void writeSiteReportTOC(Sink sink, final List<Dependency> dependencies) {
|
||||
sink.list();
|
||||
for (Dependency d : dependencies) {
|
||||
sink.listItem();
|
||||
sink.link("#sha1" + d.getSha1sum());
|
||||
sink.text(d.getFileName());
|
||||
sink.link_();
|
||||
if (!d.getVulnerabilities().isEmpty()) {
|
||||
sink.rawText(" <font style=\"color:red\">•</font>");
|
||||
}
|
||||
if (!d.getRelatedDependencies().isEmpty()) {
|
||||
sink.list();
|
||||
for (Dependency r : d.getRelatedDependencies()) {
|
||||
writeListItem(sink, r.getFileName());
|
||||
}
|
||||
sink.list_();
|
||||
}
|
||||
sink.listItem_();
|
||||
}
|
||||
sink.list_();
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the site report header.
|
||||
*
|
||||
* @param sink the sink to write the data to
|
||||
* @param projectName the name of the project
|
||||
*/
|
||||
private static void writeSiteReportHeader(Sink sink, String projectName) {
|
||||
sink.head();
|
||||
sink.title();
|
||||
sink.text("Dependency-Check Report: " + projectName);
|
||||
sink.title_();
|
||||
sink.head_();
|
||||
sink.body();
|
||||
sink.rawText("<script type=\"text/javascript\">");
|
||||
sink.rawText("function toggleElement(el, targetId) {");
|
||||
sink.rawText("if (el.innerText == '[+]') {");
|
||||
sink.rawText(" el.innerText = '[-]';");
|
||||
sink.rawText(" document.getElementById(targetId).style.display='block';");
|
||||
sink.rawText("} else {");
|
||||
sink.rawText(" el.innerText = '[+]';");
|
||||
sink.rawText(" document.getElementById(targetId).style.display='none';");
|
||||
sink.rawText("}");
|
||||
|
||||
sink.rawText("}");
|
||||
sink.rawText("</script>");
|
||||
sink.section1();
|
||||
sink.sectionTitle1();
|
||||
sink.text("Project: " + projectName);
|
||||
sink.sectionTitle1_();
|
||||
sink.date();
|
||||
final Date now = new Date();
|
||||
sink.text(DateFormat.getDateTimeInstance().format(now));
|
||||
sink.date_();
|
||||
sink.section1_();
|
||||
}
|
||||
// </editor-fold>
|
||||
|
||||
}
|
||||
@@ -1,10 +1,18 @@
|
||||
Goals
|
||||
====================
|
||||
|
||||
Goal | Description
|
||||
-----------|-----------------------
|
||||
aggregate | Runs dependency-check against the child projects and aggregates the results into a single report.
|
||||
check | Runs dependency-check against the project and generates a report.
|
||||
|
||||
Configuration
|
||||
====================
|
||||
The following properties can be set on the dependency-check-maven plugin.
|
||||
|
||||
Property | Description | Default Value
|
||||
---------------------|------------------------------------|------------------
|
||||
aggregate | Sets whether report aggregation will be performed for multi-module site reports. This option only affects the report generation when configured within the reporting section. | false
|
||||
aggregate | Deprecated - use the aggregate goal instead. |
|
||||
autoUpdate | Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to false. | true
|
||||
outputDirectory | The location to write the report(s). Note, this is not used if generating the report as part of a `mvn site` build | 'target'
|
||||
failBuildOnCVSS | Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11 which means since the CVSS scores are 0-10, by default the build will never fail. | 11
|
||||
@@ -28,7 +36,8 @@ Property | Description
|
||||
archiveAnalyzerEnabled | Sets whether the Archive Analyzer will be used. | true
|
||||
zipExtensions | A comma-separated list of additional file extensions to be treated like a ZIP file, the contents will be extracted and analyzed. |
|
||||
jarAnalyzer | Sets whether Jar Analyzer will be used. | true
|
||||
nexusAnalyzerEnabled | Sets whether Nexus Analyzer will be used. | true
|
||||
centralAnalyzerEnabled | Sets whether Central Analyzer will be used. If this analyzer is being disabled there is a good chance you also want to disable the Nexus Analyzer (see below). | true
|
||||
nexusAnalyzerEnabled | Sets whether Nexus Analyzer will be used. This analyzer is superceded by the Central Analyzer; however, you can configure this to run against a Nexus Pro installation. | true
|
||||
nexusUrl | Defines the Nexus Pro Server URL. If not set the Nexus Analyzer will be disabled. |
|
||||
nexusUsesProxy | Whether or not the defined proxy should be used when connecting to Nexus. | true
|
||||
nuspecAnalyzerEnabled | Sets whether or not the .NET Nuget Nuspec Analyzer will be used. | true
|
||||
|
||||
@@ -13,7 +13,7 @@ seven days the update will only take a few seconds.
|
||||
#set( $H = '#' )
|
||||
|
||||
$H$H$H Example 1:
|
||||
Create the DependencyCheck-report.html in the target directory
|
||||
Create the DependencyCheck-report.html in the target directory.
|
||||
|
||||
```xml
|
||||
<project>
|
||||
@@ -43,7 +43,7 @@ Create the DependencyCheck-report.html in the target directory
|
||||
```
|
||||
|
||||
$H$H$H Example 2:
|
||||
Create an aggregated dependency-check report within the site
|
||||
Create an aggregated dependency-check report within the site.
|
||||
|
||||
```xml
|
||||
<project>
|
||||
@@ -57,13 +57,10 @@ Create an aggregated dependency-check report within the site
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-maven</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<configuration>
|
||||
<aggregate>true</aggregate>
|
||||
</configuration>
|
||||
<reportSets>
|
||||
<reportSet>
|
||||
<reports>
|
||||
<report>check</report>
|
||||
<report>aggregate</report>
|
||||
</reports>
|
||||
</reportSet>
|
||||
</reportSets>
|
||||
@@ -78,7 +75,7 @@ Create an aggregated dependency-check report within the site
|
||||
```
|
||||
|
||||
$H$H$H Example 3:
|
||||
Create the DependencyCheck-report.html and fail the build for CVSS greater then 8
|
||||
Create the DependencyCheck-report.html and fail the build for CVSS greater then 8.
|
||||
|
||||
```xml
|
||||
<project>
|
||||
@@ -111,7 +108,7 @@ Create the DependencyCheck-report.html and fail the build for CVSS greater then
|
||||
```
|
||||
|
||||
$H$H$H Example 4:
|
||||
Create the DependencyCheck-report.html and skip artifacts not bundled in distribution (Provided and Runtime scope)
|
||||
Create the DependencyCheck-report.html and skip artifacts not bundled in distribution (Provided and Runtime scope).
|
||||
|
||||
```xml
|
||||
<project>
|
||||
@@ -145,7 +142,7 @@ Create the DependencyCheck-report.html and skip artifacts not bundled in distrib
|
||||
```
|
||||
|
||||
$H$H$H Example 5:
|
||||
Create the DependencyCheck-report.html and use internal mirroring of CVE contents
|
||||
Create the DependencyCheck-report.html and use internal mirroring of CVE contents.
|
||||
|
||||
```xml
|
||||
<project>
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* This file is part of dependency-check-maven.
|
||||
*
|
||||
* 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) 2014 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.maven;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import mockit.Mock;
|
||||
import mockit.MockUp;
|
||||
import org.apache.maven.artifact.Artifact;
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.plugin.MojoFailureException;
|
||||
import org.apache.maven.plugin.testing.stubs.ArtifactStub;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import org.junit.Test;
|
||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||
import org.owasp.dependencycheck.utils.InvalidSettingException;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jeremy Long <jeremy.long@owasp.org>
|
||||
*/
|
||||
public class BaseDependencyCheckMojoTest extends BaseTest {
|
||||
|
||||
/**
|
||||
* Test of scanArtifacts method, of class BaseDependencyCheckMojo.
|
||||
*/
|
||||
@Test
|
||||
public void testScanArtifacts() throws DatabaseException, InvalidSettingException {
|
||||
MavenProject project = new MockUp<MavenProject>() {
|
||||
@Mock
|
||||
public Set<Artifact> getArtifacts() {
|
||||
Set<Artifact> artifacts = new HashSet<Artifact>();
|
||||
Artifact a = new ArtifactStub();
|
||||
try {
|
||||
File file = new File(Test.class.getProtectionDomain().getCodeSource().getLocation().toURI());
|
||||
a.setFile(file);
|
||||
artifacts.add(a);
|
||||
} catch (URISyntaxException ex) {
|
||||
Logger.getLogger(BaseDependencyCheckMojoTest.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
//File file = new File(this.getClass().getClassLoader().getResource("daytrader-ear-2.1.7.ear").getPath());
|
||||
|
||||
return artifacts;
|
||||
}
|
||||
}.getMockInstance();
|
||||
|
||||
boolean autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE);
|
||||
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
|
||||
Engine engine = new Engine(null, null);
|
||||
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
|
||||
|
||||
assertTrue(engine.getDependencies().isEmpty());
|
||||
BaseDependencyCheckMojoImpl instance = new BaseDependencyCheckMojoImpl();
|
||||
instance.scanArtifacts(project, engine);
|
||||
assertFalse(engine.getDependencies().isEmpty());
|
||||
engine.cleanup();
|
||||
}
|
||||
|
||||
public class BaseDependencyCheckMojoImpl extends BaseDependencyCheckMojo {
|
||||
|
||||
@Override
|
||||
public void runCheck() throws MojoExecutionException, MojoFailureException {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(Locale locale) {
|
||||
return "test implementation";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription(Locale locale) {
|
||||
return "test implementation";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canGenerateReport() {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* This file is part of dependency-check-maven.
|
||||
*
|
||||
* 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) 2014 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.maven;
|
||||
|
||||
import java.io.InputStream;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jeremy Long <jeremy.long@owasp.org>
|
||||
*/
|
||||
public class BaseTest {
|
||||
|
||||
/**
|
||||
* The properties file location.
|
||||
*/
|
||||
public static final String PROPERTIES_FILE = "mojo.properties";
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() throws Exception {
|
||||
Settings.initialize();
|
||||
InputStream mojoProperties = BaseTest.class.getClassLoader().getResourceAsStream(BaseTest.PROPERTIES_FILE);
|
||||
Settings.mergeProperties(mojoProperties);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() throws Exception {
|
||||
Settings.cleanup(true);
|
||||
}
|
||||
}
|
||||
@@ -1,210 +0,0 @@
|
||||
/*
|
||||
* This file is part of dependency-check-maven.
|
||||
*
|
||||
* 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) 2013 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.maven;
|
||||
|
||||
import org.apache.maven.plugin.testing.AbstractMojoTestCase;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* TODO - figure out how to get the test harness to work. ATM no tests are running.
|
||||
*
|
||||
* @author Jeremy Long <jeremy.long@owasp.org>
|
||||
*/
|
||||
public class DependencyCheckMojoTest extends AbstractMojoTestCase {
|
||||
|
||||
public DependencyCheckMojoTest() {
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() throws Exception {
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() throws Exception {
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
}
|
||||
//
|
||||
// /**
|
||||
// * Test of execute method, of class DependencyCheckMojo.
|
||||
// */
|
||||
// @Test
|
||||
// public void testExecute() throws Exception {
|
||||
// System.out.println("execute");
|
||||
// DependencyCheckMojo instance = new DependencyCheckMojo();
|
||||
// instance.execute();
|
||||
// // TODO review the generated test code and remove the default call to fail.
|
||||
// fail("The test case is a prototype.");
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Test of generate method, of class DependencyCheckMojo.
|
||||
// */
|
||||
// @Test
|
||||
// public void testGenerate_Sink_Locale() throws Exception {
|
||||
// System.out.println("generate");
|
||||
// org.codehaus.doxia.sink.Sink sink = null;
|
||||
// Locale locale = null;
|
||||
// DependencyCheckMojo instance = new DependencyCheckMojo();
|
||||
// instance.generate(sink, locale);
|
||||
// // TODO review the generated test code and remove the default call to fail.
|
||||
// fail("The test case is a prototype.");
|
||||
// }
|
||||
|
||||
/**
|
||||
* Test of generate method, of class DependencyCheckMojo.
|
||||
*/
|
||||
@Test
|
||||
public void testGenerate_Sink_SinkFactory_Locale() throws Exception {
|
||||
//can't get the test-harness to work.
|
||||
// File samplePom = new File(this.getClass().getClassLoader().getResource("sample.xml").toURI());
|
||||
// DependencyCheckMojo mojo = (DependencyCheckMojo) lookupMojo("check", samplePom);
|
||||
// assertNotNull("Unable to load mojo", mojo);
|
||||
//
|
||||
// File out = mojo.getReportOutputDirectory();
|
||||
// OutputStream os = new FileOutputStream(out);
|
||||
// MySink sink = new MySink(os);
|
||||
// Locale locale = new Locale("en");
|
||||
//
|
||||
//
|
||||
// mojo.generate(sink, null, locale);
|
||||
// sink.close();
|
||||
}
|
||||
// /**
|
||||
// * Test of getOutputName method, of class DependencyCheckMojo.
|
||||
// */
|
||||
// @Test
|
||||
// public void testGetOutputName() {
|
||||
// System.out.println("getOutputName");
|
||||
// DependencyCheckMojo instance = new DependencyCheckMojo();
|
||||
// String expResult = "";
|
||||
// String result = instance.getOutputName();
|
||||
// assertEquals(expResult, result);
|
||||
// // TODO review the generated test code and remove the default call to fail.
|
||||
// fail("The test case is a prototype.");
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Test of getCategoryName method, of class DependencyCheckMojo.
|
||||
// */
|
||||
// @Test
|
||||
// public void testGetCategoryName() {
|
||||
// System.out.println("getCategoryName");
|
||||
// DependencyCheckMojo instance = new DependencyCheckMojo();
|
||||
// String expResult = "";
|
||||
// String result = instance.getCategoryName();
|
||||
// assertEquals(expResult, result);
|
||||
// // TODO review the generated test code and remove the default call to fail.
|
||||
// fail("The test case is a prototype.");
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Test of getName method, of class DependencyCheckMojo.
|
||||
// */
|
||||
// @Test
|
||||
// public void testGetName() {
|
||||
// System.out.println("getName");
|
||||
// Locale locale = null;
|
||||
// DependencyCheckMojo instance = new DependencyCheckMojo();
|
||||
// String expResult = "";
|
||||
// String result = instance.getName(locale);
|
||||
// assertEquals(expResult, result);
|
||||
// // TODO review the generated test code and remove the default call to fail.
|
||||
// fail("The test case is a prototype.");
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Test of setReportOutputDirectory method, of class DependencyCheckMojo.
|
||||
// */
|
||||
// @Test
|
||||
// public void testSetReportOutputDirectory() {
|
||||
// System.out.println("setReportOutputDirectory");
|
||||
// File directory = null;
|
||||
// DependencyCheckMojo instance = new DependencyCheckMojo();
|
||||
// instance.setReportOutputDirectory(directory);
|
||||
// // TODO review the generated test code and remove the default call to fail.
|
||||
// fail("The test case is a prototype.");
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Test of getReportOutputDirectory method, of class DependencyCheckMojo.
|
||||
// */
|
||||
// @Test
|
||||
// public void testGetReportOutputDirectory() {
|
||||
// System.out.println("getReportOutputDirectory");
|
||||
// DependencyCheckMojo instance = new DependencyCheckMojo();
|
||||
// File expResult = null;
|
||||
// File result = instance.getReportOutputDirectory();
|
||||
// assertEquals(expResult, result);
|
||||
// // TODO review the generated test code and remove the default call to fail.
|
||||
// fail("The test case is a prototype.");
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Test of getDescription method, of class DependencyCheckMojo.
|
||||
// */
|
||||
// @Test
|
||||
// public void testGetDescription() {
|
||||
// System.out.println("getDescription");
|
||||
// Locale locale = null;
|
||||
// DependencyCheckMojo instance = new DependencyCheckMojo();
|
||||
// String expResult = "";
|
||||
// String result = instance.getDescription(locale);
|
||||
// assertEquals(expResult, result);
|
||||
// // TODO review the generated test code and remove the default call to fail.
|
||||
// fail("The test case is a prototype.");
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Test of isExternalReport method, of class DependencyCheckMojo.
|
||||
// */
|
||||
// @Test
|
||||
// public void testIsExternalReport() {
|
||||
// System.out.println("isExternalReport");
|
||||
// DependencyCheckMojo instance = new DependencyCheckMojo();
|
||||
// boolean expResult = false;
|
||||
// boolean result = instance.isExternalReport();
|
||||
// assertEquals(expResult, result);
|
||||
// // TODO review the generated test code and remove the default call to fail.
|
||||
// fail("The test case is a prototype.");
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Test of canGenerateReport method, of class DependencyCheckMojo.
|
||||
// */
|
||||
// @Test
|
||||
// public void testCanGenerateReport() {
|
||||
// System.out.println("canGenerateReport");
|
||||
// DependencyCheckMojo instance = new DependencyCheckMojo();
|
||||
// boolean expResult = false;
|
||||
// boolean result = instance.canGenerateReport();
|
||||
// assertEquals(expResult, result);
|
||||
// // TODO review the generated test code and remove the default call to fail.
|
||||
// fail("The test case is a prototype.");
|
||||
// }
|
||||
}
|
||||
@@ -1,601 +0,0 @@
|
||||
/*
|
||||
* This file is part of dependency-check-maven.
|
||||
*
|
||||
* 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) 2013 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.maven;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.apache.maven.doxia.logging.Log;
|
||||
import org.apache.maven.doxia.sink.Sink;
|
||||
import org.apache.maven.doxia.sink.SinkEventAttributes;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jeremy Long <jeremy.long@owasp.org>
|
||||
*/
|
||||
public class MySink implements Sink {
|
||||
|
||||
private OutputStreamWriter out = null;
|
||||
|
||||
public MySink(OutputStream os) {
|
||||
out = new OutputStreamWriter(os);
|
||||
|
||||
}
|
||||
|
||||
private void writeTag(String tag) {
|
||||
try {
|
||||
out.write(tag);
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(MySink.class.getName()).log(Level.SEVERE, "Error writing a tag; unable to generate the report");
|
||||
Logger.getLogger(MySink.class.getName()).log(Level.FINE, null, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void head() {
|
||||
writeTag("<head>");
|
||||
}
|
||||
|
||||
public void head_() {
|
||||
writeTag("</head>");
|
||||
}
|
||||
|
||||
public void title() {
|
||||
writeTag("<title>");
|
||||
}
|
||||
|
||||
public void title_() {
|
||||
writeTag("</title>");
|
||||
}
|
||||
|
||||
public void author() {
|
||||
writeTag("<author>");
|
||||
}
|
||||
|
||||
public void author_() {
|
||||
writeTag("</author>");
|
||||
}
|
||||
|
||||
public void date() {
|
||||
writeTag("<time>");
|
||||
}
|
||||
|
||||
public void date_() {
|
||||
writeTag("</time>");
|
||||
}
|
||||
|
||||
public void body() {
|
||||
writeTag("<body>");
|
||||
}
|
||||
|
||||
public void body_() {
|
||||
writeTag("</body>");
|
||||
}
|
||||
|
||||
public void sectionTitle() {
|
||||
writeTag("<h1>");
|
||||
}
|
||||
|
||||
public void sectionTitle_() {
|
||||
writeTag("</h1>");
|
||||
}
|
||||
|
||||
public void section1() {
|
||||
writeTag("<div>");
|
||||
}
|
||||
|
||||
public void section1_() {
|
||||
writeTag("</div>");
|
||||
}
|
||||
|
||||
public void sectionTitle1() {
|
||||
writeTag("<h2>");
|
||||
}
|
||||
|
||||
public void sectionTitle1_() {
|
||||
writeTag("</h2>");
|
||||
}
|
||||
|
||||
public void section2() {
|
||||
writeTag("<div>");
|
||||
}
|
||||
|
||||
public void section2_() {
|
||||
writeTag("</div>");
|
||||
}
|
||||
|
||||
public void sectionTitle2() {
|
||||
writeTag("<h3>");
|
||||
}
|
||||
|
||||
public void sectionTitle2_() {
|
||||
writeTag("</h3>");
|
||||
}
|
||||
|
||||
public void section3() {
|
||||
writeTag("<div>");
|
||||
}
|
||||
|
||||
public void section3_() {
|
||||
writeTag("</div>");
|
||||
}
|
||||
|
||||
public void sectionTitle3() {
|
||||
writeTag("<h4>");
|
||||
}
|
||||
|
||||
public void sectionTitle3_() {
|
||||
writeTag("</h4>");
|
||||
}
|
||||
|
||||
public void section4() {
|
||||
writeTag("<div>");
|
||||
}
|
||||
|
||||
public void section4_() {
|
||||
writeTag("</div>");
|
||||
}
|
||||
|
||||
public void sectionTitle4() {
|
||||
writeTag("<h5>");
|
||||
}
|
||||
|
||||
public void sectionTitle4_() {
|
||||
writeTag("</h5>");
|
||||
}
|
||||
|
||||
public void section5() {
|
||||
writeTag("<div>");
|
||||
}
|
||||
|
||||
public void section5_() {
|
||||
writeTag("</div>");
|
||||
}
|
||||
|
||||
public void sectionTitle5() {
|
||||
writeTag("<h6>");
|
||||
}
|
||||
|
||||
public void sectionTitle5_() {
|
||||
writeTag("</h6>");
|
||||
}
|
||||
|
||||
public void list() {
|
||||
writeTag("<ul>");
|
||||
}
|
||||
|
||||
public void list_() {
|
||||
writeTag("</ul>");
|
||||
}
|
||||
|
||||
public void listItem() {
|
||||
writeTag("<li>");
|
||||
}
|
||||
|
||||
public void listItem_() {
|
||||
writeTag("</li>");
|
||||
}
|
||||
|
||||
public void numberedList(int numbering) {
|
||||
writeTag("<ol>");
|
||||
}
|
||||
|
||||
public void numberedList_() {
|
||||
writeTag("</ol>");
|
||||
}
|
||||
|
||||
public void numberedListItem() {
|
||||
writeTag("<li>");
|
||||
}
|
||||
|
||||
public void numberedListItem_() {
|
||||
writeTag("</li>");
|
||||
}
|
||||
|
||||
public void definitionList() {
|
||||
writeTag("<dl>");
|
||||
}
|
||||
|
||||
public void definitionList_() {
|
||||
writeTag("</dl>");
|
||||
}
|
||||
|
||||
public void definitionListItem() {
|
||||
writeTag("<dt>");
|
||||
}
|
||||
|
||||
public void definitionListItem_() {
|
||||
writeTag("</dt>");
|
||||
}
|
||||
|
||||
public void definition() {
|
||||
writeTag("<dd>");
|
||||
}
|
||||
|
||||
public void definition_() {
|
||||
writeTag("</dd>");
|
||||
}
|
||||
|
||||
public void definedTerm() {
|
||||
writeTag("<dt>");
|
||||
}
|
||||
|
||||
public void definedTerm_() {
|
||||
writeTag("</dt>");
|
||||
}
|
||||
|
||||
public void figure() {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
public void figure_() {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
public void figureCaption() {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
public void figureCaption_() {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
public void figureGraphics(String name) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
public void table() {
|
||||
writeTag("<table>");
|
||||
}
|
||||
|
||||
public void table_() {
|
||||
writeTag("</table>");
|
||||
}
|
||||
|
||||
public void tableRows(int[] justification, boolean grid) {
|
||||
writeTag("<tr>");
|
||||
}
|
||||
|
||||
public void tableRows_() {
|
||||
writeTag("</tr>");
|
||||
}
|
||||
|
||||
public void tableRow() {
|
||||
writeTag("<tr>");
|
||||
}
|
||||
|
||||
public void tableRow_() {
|
||||
writeTag("</tr>");
|
||||
}
|
||||
|
||||
public void tableCell() {
|
||||
writeTag("<td>");
|
||||
}
|
||||
|
||||
public void tableCell(String width) {
|
||||
writeTag("<td>");
|
||||
}
|
||||
|
||||
public void tableCell_() {
|
||||
writeTag("</td>");
|
||||
}
|
||||
|
||||
public void tableHeaderCell() {
|
||||
writeTag("<th>");
|
||||
}
|
||||
|
||||
public void tableHeaderCell(String width) {
|
||||
writeTag("<th>");
|
||||
}
|
||||
|
||||
public void tableHeaderCell_() {
|
||||
writeTag("</th>");
|
||||
}
|
||||
|
||||
public void tableCaption() {
|
||||
writeTag("<caption>");
|
||||
}
|
||||
|
||||
public void tableCaption_() {
|
||||
writeTag("</caption>");
|
||||
}
|
||||
|
||||
public void paragraph() {
|
||||
writeTag("<p>");
|
||||
}
|
||||
|
||||
public void paragraph_() {
|
||||
writeTag("</p>");
|
||||
}
|
||||
|
||||
public void verbatim(boolean boxed) {
|
||||
writeTag("<pre>");
|
||||
}
|
||||
|
||||
public void verbatim_() {
|
||||
writeTag("</pre>");
|
||||
}
|
||||
|
||||
public void horizontalRule() {
|
||||
writeTag("<hr/>");
|
||||
}
|
||||
|
||||
public void pageBreak() {
|
||||
writeTag("<br/>");
|
||||
}
|
||||
|
||||
public void anchor(String name) {
|
||||
writeTag("<a href=\"" + name + "\">");
|
||||
}
|
||||
|
||||
public void anchor_() {
|
||||
writeTag("</a>");
|
||||
}
|
||||
|
||||
public void link(String name) {
|
||||
writeTag("<link href=\"" + name + "\">");
|
||||
}
|
||||
|
||||
public void link_() {
|
||||
writeTag("</link>");
|
||||
}
|
||||
|
||||
public void italic() {
|
||||
writeTag("<i>");
|
||||
}
|
||||
|
||||
public void italic_() {
|
||||
writeTag("</i>");
|
||||
}
|
||||
|
||||
public void bold() {
|
||||
writeTag("<b>");
|
||||
}
|
||||
|
||||
public void bold_() {
|
||||
writeTag("</b>");
|
||||
}
|
||||
|
||||
public void monospaced() {
|
||||
writeTag("<pre>");
|
||||
}
|
||||
|
||||
public void monospaced_() {
|
||||
writeTag("</pre>");
|
||||
}
|
||||
|
||||
public void lineBreak() {
|
||||
writeTag("<br>");
|
||||
}
|
||||
|
||||
public void nonBreakingSpace() {
|
||||
writeTag(" ");
|
||||
}
|
||||
|
||||
public void text(String text) {
|
||||
try {
|
||||
//TODO add HTML Encoding - or figure out how to get the doxia xhtmlsink to work.
|
||||
out.write(text);
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(MySink.class.getName()).log(Level.SEVERE, "Error writing a text; unable to generate the report");
|
||||
Logger.getLogger(MySink.class.getName()).log(Level.FINE, null, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void rawText(String text) {
|
||||
try {
|
||||
out.write(text);
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(MySink.class.getName()).log(Level.SEVERE, "Error writing raw text; unable to generate the report");
|
||||
Logger.getLogger(MySink.class.getName()).log(Level.FINE, null, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
try {
|
||||
out.flush();
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(MySink.class.getName()).log(Level.FINEST, null, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
flush();
|
||||
try {
|
||||
out.close();
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(MySink.class.getName()).log(Level.FINEST, null, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void head(SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void title(SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void author(SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void date(SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void body(SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void section(int i, SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void section_(int i) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sectionTitle(int i, SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sectionTitle_(int i) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void list(SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void listItem(SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void numberedList(int i, SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void numberedListItem(SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void definitionList(SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void definitionListItem(SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void definition(SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void definedTerm(SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void figure(SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void figureCaption(SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void figureGraphics(String string, SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void table(SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tableRow(SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tableCell(SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tableHeaderCell(SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tableCaption(SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paragraph(SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void verbatim(SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void horizontalRule(SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void anchor(String string, SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void link(String string, SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lineBreak(SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void text(String string, SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void comment(String string) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unknown(String string, Object[] os, SinkEventAttributes sea) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableLogging(Log log) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
# the path to the data directory
|
||||
data.directory=[JAR]/dependency-check-data
|
||||
@@ -21,7 +21,7 @@ Copyright (c) 2014 - Jeremy Long. All Rights Reserved.
|
||||
<parent>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-parent</artifactId>
|
||||
<version>1.2.7</version>
|
||||
<version>1.2.8</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>dependency-check-utils</artifactId>
|
||||
|
||||
@@ -80,11 +80,11 @@ public final class Downloader {
|
||||
try {
|
||||
org.apache.commons.io.FileUtils.copyFile(file, outputPath);
|
||||
} catch (IOException ex) {
|
||||
final String msg = String.format("Download failed, unable to copy '%s'", url.toString());
|
||||
final String msg = String.format("Download failed, unable to copy '%s' to '%s'", url.toString(), outputPath.getAbsolutePath());
|
||||
throw new DownloadFailedException(msg);
|
||||
}
|
||||
} else {
|
||||
final String msg = String.format("Download failed, file does not exist '%s'", url.toString());
|
||||
final String msg = String.format("Download failed, file ('%s') does not exist", url.toString());
|
||||
throw new DownloadFailedException(msg);
|
||||
}
|
||||
} else {
|
||||
@@ -101,7 +101,8 @@ public final class Downloader {
|
||||
} finally {
|
||||
conn = null;
|
||||
}
|
||||
throw new DownloadFailedException("Error downloading file.", ex);
|
||||
final String msg = String.format("Error downloading file %s; unable to connect.", url.toString());
|
||||
throw new DownloadFailedException(msg, ex);
|
||||
}
|
||||
final String encoding = conn.getContentEncoding();
|
||||
|
||||
@@ -122,13 +123,19 @@ public final class Downloader {
|
||||
while ((bytesRead = reader.read(buffer)) > 0) {
|
||||
writer.write(buffer, 0, bytesRead);
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
final String msg = String.format("Error saving '%s' to file '%s'%nConnection Timeout: %d%nEncoding: %s%n",
|
||||
url.toString(), outputPath.getAbsolutePath(), conn.getConnectTimeout(), encoding);
|
||||
throw new DownloadFailedException(msg, ex);
|
||||
} catch (Throwable ex) {
|
||||
throw new DownloadFailedException("Error saving downloaded file.", ex);
|
||||
final String msg = String.format("Unexpected exception saving '%s' to file '%s'%nConnection Timeout: %d%nEncoding: %s%n",
|
||||
url.toString(), outputPath.getAbsolutePath(), conn.getConnectTimeout(), encoding);
|
||||
throw new DownloadFailedException(msg, ex);
|
||||
} finally {
|
||||
if (writer != null) {
|
||||
try {
|
||||
writer.close();
|
||||
} catch (Throwable ex) {
|
||||
} catch (IOException ex) {
|
||||
LOGGER.log(Level.FINEST,
|
||||
"Error closing the writer in Downloader.", ex);
|
||||
}
|
||||
@@ -136,7 +143,7 @@ public final class Downloader {
|
||||
if (reader != null) {
|
||||
try {
|
||||
reader.close();
|
||||
} catch (Throwable ex) {
|
||||
} catch (IOException ex) {
|
||||
LOGGER.log(Level.FINEST,
|
||||
"Error closing the reader in Downloader.", ex);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
package org.owasp.dependencycheck.utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.logging.FileHandler;
|
||||
@@ -57,6 +58,13 @@ public final class LogUtils {
|
||||
if (verboseLogFile != null && !verboseLogFile.isEmpty()) {
|
||||
verboseLoggingEnabled = true;
|
||||
final Logger logger = Logger.getLogger("");
|
||||
final File logFile = new File(verboseLogFile);
|
||||
final File logDir = logFile.getParentFile();
|
||||
if (logDir != null && !logDir.isDirectory() && !logDir.mkdirs()) {
|
||||
final String msg = String.format("Unable to create directory '%s', verbose logging will be disabled.",
|
||||
logDir.getAbsolutePath());
|
||||
throw new IOException(msg);
|
||||
}
|
||||
final FileHandler fileHandler = new FileHandler(verboseLogFile, true);
|
||||
fileHandler.setFormatter(new SimpleFormatter());
|
||||
fileHandler.setLevel(Level.FINE);
|
||||
|
||||
2
pom.xml
2
pom.xml
@@ -20,7 +20,7 @@ Copyright (c) 2012 - Jeremy Long
|
||||
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-parent</artifactId>
|
||||
<version>1.2.7</version>
|
||||
<version>1.2.8</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
|
||||
11
src/site/markdown/central-analyzer.md
Normal file
11
src/site/markdown/central-analyzer.md
Normal file
@@ -0,0 +1,11 @@
|
||||
Central Analyzer
|
||||
==============
|
||||
|
||||
Dependency-check includes an analyzer that will check for the Maven GAV
|
||||
(Group/Artifact/Version) information for artifacts in the scanned area. By
|
||||
default the information comes from [Maven Central][1]. If the artifact's hash
|
||||
is found in the configured Nexus repository, its GAV is recorded as an Identifier
|
||||
and the Group is collected as Vendor evidence, the Artifact is collected as Product
|
||||
evidence, and the Version is collected as Version evidence.
|
||||
|
||||
[1]: http://search.maven.org/ "Maven Central"
|
||||
@@ -1,54 +1,17 @@
|
||||
Nexus Analyzer
|
||||
==============
|
||||
|
||||
Dependency-check includes an analyzer that will check for the Maven GAV
|
||||
(Group/Artifact/Version) information for artifacts in the scanned area. By
|
||||
default the information comes from [Maven Central][1], but can be configured to
|
||||
use a local repository if necessary. If the artifact's hash is found in the
|
||||
configured Nexus repository, its GAV is recorded as an Identifier and the Group
|
||||
is collected as Vendor evidence, the Artifact is collected as Product evidence,
|
||||
and the Version is collected as Version evidence.
|
||||
The Nexus Analyzer has been superceded by the Central Analyzer. If both the
|
||||
Central Analyzer and Nexus Analyzer are enabled and the Nexus URL has not
|
||||
been configured to point to an instance of Nexus Pro the Nexus Analyzer will
|
||||
disable itself.
|
||||
|
||||
Default Configuration
|
||||
---------------------
|
||||
|
||||
By default, the Nexus analyzer uses the [Sonatype Nexus Repository][2] to search
|
||||
for SHA-1 hashes of dependencies. If the proxy is configured for Dependency
|
||||
Check, that proxy is used in order to connect to the Nexus Central repository.
|
||||
So if you're using `--proxyurl` on the command-line, the `proxyUrl` setting in
|
||||
the Maven plugin, or the `proxyUrl` attribute in the Ant task, that proxy will
|
||||
be used by default. Also, the proxy port, user, and password configured globally
|
||||
are used as well.
|
||||
|
||||
Overriding Defaults
|
||||
-------------------
|
||||
|
||||
If you have an internal Nexus repository you want to use, Dependency Check can
|
||||
be configured to use this repository rather than Sonatype. This needs to be a
|
||||
Nexus repository (support for Artifactory is planned). For a normal installation
|
||||
of Nexus, you would append `/service/local/` to the root of the URL to your
|
||||
Nexus repository. This URL can be set as:
|
||||
|
||||
* `analyzer.nexus.url` in `dependencycheck.properties`
|
||||
* `--nexus <url>` in the CLI
|
||||
* The `nexusUrl` property in the Maven plugin
|
||||
* The `nexusUrl` attribute in the Ant task
|
||||
|
||||
If this repository is internal and should not use the proxy, you can disable the
|
||||
proxy for just the Nexus analyzer. Setting this makes no difference if a proxy
|
||||
is not configured.
|
||||
|
||||
* `analyzer.nexus.proxy=false` in `dependencycheck.properties`
|
||||
* `--nexusUsesProxy false` in the CLI
|
||||
* The `nexusUsesProxy` property in the Maven plugin
|
||||
* The `nexusUsesProxy` attribute in the Ant task
|
||||
|
||||
Finally, the Nexus analyzer can be disabled altogether.
|
||||
|
||||
* `analyzer.nexus.enabled=false` in `dependencycheck.properties`
|
||||
* `--disableNexus` in the CLI
|
||||
* `nexusAnalyzerEnabled` property in the Maven plugin
|
||||
* `nexusAnalyzerEnabled` attribute in the Ant task
|
||||
The Nexus Analyzer will check for the Maven GAV (Group/Artifact/Version) information
|
||||
for artifacts in the scanned area. This is done by determining if an artifact exists
|
||||
in a Nexus Pro installation using the SHA-1 hash of the artifact scanned. If the
|
||||
artifact's hash is found in the configured Nexus repository, its GAV is recorded as
|
||||
an Identifier and the Group is collected as Vendor evidence, the Artifact is
|
||||
collected as Product evidence, and the Version is collected as Version evidence.
|
||||
|
||||
Logging
|
||||
-------
|
||||
@@ -60,9 +23,9 @@ You may see a log message similar to the following during analysis:
|
||||
|
||||
At the beginning of analysis, a check is made by the Nexus analyzer to see if it
|
||||
is able to reach the configured Nexus service, and if it cannot be reached, the
|
||||
analyzer will be disabled. If you see this message, you can use the
|
||||
configuration settings described above to resolve the issue, or disable the
|
||||
analyzer altogether.
|
||||
analyzer will be disabled. If you see this message, you can use the configuration
|
||||
settings described in either the CLI, Ant, Maven, or Jenkins plugins to resolve
|
||||
the issue, or disable the analyzer altogether.
|
||||
|
||||
[1]: http://search.maven.org/ "Maven Central"
|
||||
[2]: https://repository.sonatype.org/ "Sonatype Nexus Repository"
|
||||
|
||||
@@ -98,6 +98,9 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
|
||||
<item name="Jar Analyzer" href="./jar-analyzer.html">
|
||||
<description>Jar Analyzer</description>
|
||||
</item>
|
||||
<item name="Central Analyzer" href="./central-analyzer.html">
|
||||
<description>Central Analyzer</description>
|
||||
</item>
|
||||
<item name="Nexus Analyzer" href="./nexus-analyzer.html">
|
||||
<description>Nexus Analyzer</description>
|
||||
</item>
|
||||
|
||||
Reference in New Issue
Block a user