diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NexusAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NexusAnalyzer.java
index 8990af8f7..4d15c708a 100644
--- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NexusAnalyzer.java
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NexusAnalyzer.java
@@ -93,6 +93,10 @@ public class NexusAnalyzer extends AbstractAnalyzer {
LOGGER.fine(String.format("Nexus Analyzer URL: %s", searchUrl));
try {
searcher = new NexusSearch(new URL(searchUrl));
+ if (! searcher.preflightRequest()) {
+ LOGGER.warning("There was an issue getting Nexus status. Disabling analyzer.");
+ enabled = false;
+ }
} catch (MalformedURLException mue) {
// I know that initialize can throw an exception, but we'll
// just disable the analyzer if the URL isn't valid
diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/NexusSearch.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/NexusSearch.java
index 5e8e67139..3580d0dc2 100644
--- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/NexusSearch.java
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/NexusSearch.java
@@ -19,18 +19,24 @@ package org.owasp.dependencycheck.data.nexus;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.logging.Logger;
+
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathFactory;
+
+import org.owasp.dependencycheck.utils.Downloader;
+import org.owasp.dependencycheck.utils.InvalidSettingException;
+import org.owasp.dependencycheck.utils.Settings;
import org.w3c.dom.Document;
/**
* Class of methods to search Nexus repositories.
- *
+ *
* @author colezlaw
*/
public class NexusSearch {
@@ -40,40 +46,71 @@ public class NexusSearch {
*/
private final URL rootURL;
+ /**
+ * Whether to use the Proxy when making requests
+ */
+ private boolean useProxy;
+
/**
* Used for logging.
*/
- private static final Logger LOGGER = Logger.getLogger(NexusSearch.class.getName());
+ private static final Logger LOGGER = Logger.getLogger(NexusSearch.class
+ .getName());
/**
* Creates a NexusSearch for the given repository URL.
- *
- * @param rootURL the root URL of the repository on which searches should execute. full URL's are calculated
- * relative to this URL, so it should end with a /
+ *
+ * @param rootURL
+ * the root URL of the repository on which searches should
+ * execute. full URL's are calculated relative to this URL, so it
+ * should end with a /
*/
public NexusSearch(URL rootURL) {
this.rootURL = rootURL;
+ try {
+ if (null != Settings.getString(Settings.KEYS.PROXY_URL)
+ && Settings.getBoolean(Settings.KEYS.ANALYZER_NEXUS_PROXY)) {
+ useProxy = true;
+ LOGGER.fine("Using proxy");
+ } else {
+ useProxy = false;
+ LOGGER.fine("Not using proxy");
+ }
+ } catch (InvalidSettingException ise) {
+ useProxy = false;
+ }
}
/**
- * Searches the configured Nexus repository for the given sha1 hash. If the artifact is found, a
- * MavenArtifact is populated with the coordinate information.
- *
- * @param sha1 The SHA-1 hash string for which to search
+ * Searches the configured Nexus repository for the given sha1 hash. If the
+ * artifact is found, a MavenArtifact is populated with the
+ * coordinate information.
+ *
+ * @param sha1
+ * The SHA-1 hash string for which to search
* @return the populated Maven coordinates
- * @throws IOException if it's unable to connect to the specified repositor or if the specified artifact is not
- * found.
+ * @throws IOException
+ * if it's unable to connect to the specified repositor or if
+ * the specified artifact is not found.
*/
public MavenArtifact searchSha1(String sha1) throws IOException {
if (null == sha1 || !sha1.matches("^[0-9A-Fa-f]{40}$")) {
throw new IllegalArgumentException("Invalid SHA1 format");
}
- final URL url = new URL(rootURL, String.format("identify/sha1/%s", sha1.toLowerCase()));
+ final URL url = new URL(rootURL, String.format("identify/sha1/%s",
+ sha1.toLowerCase()));
LOGGER.fine(String.format("Searching Nexus url %s", url.toString()));
- final URLConnection conn = url.openConnection();
+ // Determine if we need to use a proxy. The rules:
+ // 1) If the proxy is set, AND the setting is set to true, use the proxy
+ // 2) Otherwise, don't use the proxy (either the proxy isn't configured,
+ // or proxy is specifically
+ // set to false
+ URLConnection conn = null;
+ conn = Downloader.getConnection(url, useProxy);
+
conn.setDoOutput(true);
// JSON would be more elegant, but there's not currently a dependency
@@ -82,23 +119,65 @@ public class NexusSearch {
conn.connect();
try {
- final DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ final DocumentBuilder builder = DocumentBuilderFactory
+ .newInstance().newDocumentBuilder();
final Document doc = builder.parse(conn.getInputStream());
final XPath xpath = XPathFactory.newInstance().newXPath();
- final String groupId = xpath.evaluate("/org.sonatype.nexus.rest.model.NexusArtifact/groupId", doc);
- final String artifactId = xpath.evaluate("/org.sonatype.nexus.rest.model.NexusArtifact/artifactId", doc);
- final String version = xpath.evaluate("/org.sonatype.nexus.rest.model.NexusArtifact/version", doc);
- final String link = xpath.evaluate("/org.sonatype.nexus.rest.model.NexusArtifact/artifactLink", doc);
+ final String groupId = xpath
+ .evaluate(
+ "/org.sonatype.nexus.rest.model.NexusArtifact/groupId",
+ doc);
+ final String artifactId = xpath.evaluate(
+ "/org.sonatype.nexus.rest.model.NexusArtifact/artifactId",
+ doc);
+ final String version = xpath
+ .evaluate(
+ "/org.sonatype.nexus.rest.model.NexusArtifact/version",
+ doc);
+ final String link = xpath
+ .evaluate(
+ "/org.sonatype.nexus.rest.model.NexusArtifact/artifactLink",
+ doc);
return new MavenArtifact(groupId, artifactId, version, link);
} catch (FileNotFoundException fnfe) {
- // This is what we get when the SHA1 they sent doesn't exist in Nexus. This
+ // This is what we get when the SHA1 they sent doesn't exist in
+ // Nexus. This
// is useful upstream for recovery, so we just re-throw it
throw fnfe;
} catch (Exception e) {
- // Anything else is jacked-up XML stuff that we really can't recover from well
+ // Anything else is jacked-up XML stuff that we really can't recover
+ // from well
throw new IOException(e.getMessage(), e);
}
}
+
+ /**
+ * Do a preflight request to see if the repository is actually working.
+ *
+ * @return whether the repository is listening and returns the /status URL
+ * correctly
+ */
+ public boolean preflightRequest() {
+ try {
+ HttpURLConnection conn = Downloader.getConnection(new URL(rootURL, "status"));
+ conn.addRequestProperty("Accept", "application/xml");
+ conn.connect();
+ if (conn.getResponseCode() != 200) {
+ LOGGER.warning("Expected 200 result from Nexus, got " + conn.getResponseCode());
+ return false;
+ }
+ final DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ final Document doc = builder.parse(conn.getInputStream());
+ if (doc.getDocumentElement().getNodeName() != "status") {
+ LOGGER.warning("Expected root node name of status, got " + doc.getDocumentElement().getNodeName());
+ return false;
+ }
+ } catch (Exception e) {
+ return false;
+ }
+
+ return true;
+ }
}
// vim: cc=120:sw=4:ts=4:sts=4
diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/Downloader.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/Downloader.java
index e8cbc0466..c7816b124 100644
--- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/Downloader.java
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/Downloader.java
@@ -176,7 +176,7 @@ public final class Downloader {
* @return an HttpURLConnection
* @throws DownloadFailedException thrown if there is an exception
*/
- private static HttpURLConnection getConnection(URL url) throws DownloadFailedException {
+ public static HttpURLConnection getConnection(URL url) throws DownloadFailedException {
HttpURLConnection conn = null;
Proxy proxy = null;
final String proxyUrl = Settings.getString(Settings.KEYS.PROXY_URL);
@@ -219,4 +219,28 @@ public final class Downloader {
}
return conn;
}
+
+ /**
+ * Utility method to get an HttpURLConnection. The use of a proxy here is optional as there
+ * may be cases where a proxy is configured but we don't want to use it (for example, if there's
+ * an internal repository configured)
+ *
+ * @param url the url to connect to
+ * @parem proxy whether to use the proxy (if configured)
+ * @throws DownloadFailedException thrown if there is an exception
+ */
+ public static HttpURLConnection getConnection(URL url, boolean proxy) throws DownloadFailedException {
+ if (proxy) {
+ return getConnection(url);
+ }
+ HttpURLConnection conn = null;
+ try {
+ conn = (HttpURLConnection)url.openConnection();
+ final int timeout = Settings.getInt(Settings.KEYS.CONNECTION_TIMEOUT, 60000);
+ conn.setConnectTimeout(timeout);
+ } catch (IOException ioe) {
+ throw new DownloadFailedException("Error getting connection.", ioe);
+ }
+ return conn;
+ }
}
diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/Settings.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/Settings.java
index 0a54a5ed9..01d876fb5 100644
--- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/Settings.java
+++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/Settings.java
@@ -145,6 +145,10 @@ public final class Settings {
* The properties key for the Nexus search URL.
*/
public static final String ANALYZER_NEXUS_URL = "analyzer.nexus.url";
+ /**
+ * The properties key for using the proxy to reach Nexus
+ */
+ public static final String ANALYZER_NEXUS_PROXY = "analyzer.nexus.proxy";
/**
* The path to mono, if available.
*/
diff --git a/dependency-check-core/src/main/resources/dependencycheck.properties b/dependency-check-core/src/main/resources/dependencycheck.properties
index b4a09d5d1..837c7c91f 100644
--- a/dependency-check-core/src/main/resources/dependencycheck.properties
+++ b/dependency-check-core/src/main/resources/dependencycheck.properties
@@ -45,4 +45,6 @@ cve.url-1.2.base=http://nvd.nist.gov/download/nvdcve-%d.xml
# the URL for searching Nexus for SHA-1 hashes and whether it's enabled
analyzer.nexus.enabled=true
analyzer.nexus.url=http://repository.sonatype.org/service/local/
-
+# If set to true, the proxy will still ONLY be used if the proxy properties (proxy.url, proxy.port)
+# are configured
+analyzer.nexus.proxy=true
diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nexus/NexusSearchTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nexus/NexusSearchTest.java
index c83d06701..9904cc847 100644
--- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nexus/NexusSearchTest.java
+++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nexus/NexusSearchTest.java
@@ -17,13 +17,15 @@
*/
package org.owasp.dependencycheck.data.nexus;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
import java.io.FileNotFoundException;
import java.net.URL;
import java.util.logging.Logger;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
+
+import org.junit.Assume;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.owasp.dependencycheck.utils.Settings;
@@ -37,6 +39,7 @@ public class NexusSearchTest {
String nexusUrl = Settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL);
LOGGER.fine(nexusUrl);
searcher = new NexusSearch(new URL(nexusUrl));
+ Assume.assumeTrue(searcher.preflightRequest());
}
@Test(expected = IllegalArgumentException.class)
@@ -52,7 +55,6 @@ public class NexusSearchTest {
// This test does generate network traffic and communicates with a host
// you may not be able to reach. Remove the @Ignore annotation if you want to
// test it anyway
- @Ignore
@Test
public void testValidSha1() throws Exception {
MavenArtifact ma = searcher.searchSha1("9977a8d04e75609cf01badc4eb6a9c7198c4c5ea");
@@ -65,7 +67,6 @@ public class NexusSearchTest {
// This test does generate network traffic and communicates with a host
// you may not be able to reach. Remove the @Ignore annotation if you want to
// test it anyway
- @Ignore
@Test(expected = FileNotFoundException.class)
public void testMissingSha1() throws Exception {
searcher.searchSha1("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
diff --git a/dependency-check-core/src/test/resources/dependencycheck.properties b/dependency-check-core/src/test/resources/dependencycheck.properties
index f7a395ed4..6db3dc947 100644
--- a/dependency-check-core/src/test/resources/dependencycheck.properties
+++ b/dependency-check-core/src/test/resources/dependencycheck.properties
@@ -50,3 +50,6 @@ cve.url-1.2.base=http://nvd.nist.gov/download/nvdcve-%d.xml
# the URL for searching Nexus for SHA-1 hashes and whether it's enabled
analyzer.nexus.enabled=true
analyzer.nexus.url=http://repository.sonatype.org/service/local/
+# If set to true, the proxy will still ONLY be used if the proxy properties (proxy.url, proxy.port)
+# are configured
+analyzer.nexus.proxy=true