Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,8 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
* The id of a server defined in the settings.xml to authenticate Sonatype
* OSS Index requests and profit from higher rate limits. Provide the OSS
* account email address as username and password or API token as password.
* Is potentially overwritten by {@link #ossIndexPasswordEnvironmentVariable}
* or {@link #ossIndexPassword}.
*/
@SuppressWarnings("CanBeFinal")
@Parameter(property = "ossIndexServerId")
Expand All @@ -794,12 +796,27 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
* OSS password or API token as an alternative to the indirection through
* the ossIndexServerId (see above). Both ossIndexUsername and
* ossIndexPassword must be set to use this approach instead of the server
* ID.
* ID. The parameters {@link #ossIndexPasswordEnvironmentVariable} or
* {@link #ossIndexServerId} should be used instead otherwise Maven debug
* logging could expose the password. This takes precedence over
* {@link #ossIndexServerId} and {@link #ossIndexPasswordEnvironmentVariable}.
*/
@SuppressWarnings("CanBeFinal")
@Parameter(property = "ossIndexPassword")
private String ossIndexPassword;

/**
* The environment variable from which to retrieve the Sonatype Guide
* personal access token (or legacy OSS Index API token); used together
* with ossIndexUsername when that is set. Takes precedence over
* {@link #ossIndexServerId} but is potentially overwritten by
* {@link #ossIndexPassword}. This is the recommended option to pass the
* token in CI builds.
*/
@SuppressWarnings("CanBeFinal")
@Parameter(property = "ossIndexPasswordEnvironmentVariable")
private String ossIndexPasswordEnvironmentVariable;

/**
* Whether we should only warn about Sonatype OSS Index remote errors
* instead of failing the goal completely.
Expand Down Expand Up @@ -2483,7 +2500,13 @@ protected void populateSettings() throws MojoFailureException, MojoExecutionExce
settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_OSSINDEX_ENABLED, ossIndexAnalyzerEnabled);
settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_OSSINDEX_URL, ossIndexAnalyzerUrl);
if (StringUtils.isEmpty(ossIndexPassword)) {
configureServerCredentialsUserPassOrApiKey(ossIndexServerId, Settings.KEYS.ANALYZER_OSSINDEX_USER, Settings.KEYS.ANALYZER_OSSINDEX_PASSWORD);
if (ossIndexPasswordEnvironmentVariable != null) {
settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_OSSINDEX_USER, ossIndexUsername);
settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_OSSINDEX_PASSWORD, System.getenv(ossIndexPasswordEnvironmentVariable));
getLog().debug("Using OSS Index password from environment variable " + ossIndexPasswordEnvironmentVariable);
} else {
configureServerCredentialsUserPassOrApiKey(ossIndexServerId, Settings.KEYS.ANALYZER_OSSINDEX_USER, Settings.KEYS.ANALYZER_OSSINDEX_PASSWORD);
}
} else {
settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_OSSINDEX_USER, ossIndexUsername);
settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_OSSINDEX_PASSWORD, ossIndexPassword);
Expand Down
4 changes: 3 additions & 1 deletion maven/src/site/markdown/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ be needed.
| ossIndexAnalyzerUrl | Alternative base URL for the OSS Index API. If not set the public Sonatype OSS Index API on Sonatype Guide will be used. *Deprecated alias: `ossindexAnalyzerUrl`* | https://api.guide.sonatype.com |
| ossIndexServerId | The id of [a server](https://maven.apache.org/settings.html#Servers) defined in the `settings.xml` to authenticate Sonatype OSS Index API requests. Provide a Sonatype Guide personal access token alone as `password` OR for legacy OSS Index API tokens provide `username` = account email address and `password` = legacy API token (deprecated). |   |
| ossIndexUsername | *(deprecated)* Sets the OSS Index API username for use with legacy OSS Index API tokens (as an alternative to the indirection through the `ossIndexServerId` noted above). Username is not required after migration to using Sonatype Guide personal access token as password. |   |
| ossIndexPassword | Sets the OSS Index API token (deprecated) or Sonatype Guide personal access token (as an alternative to the indirection through the `ossIndexServerId` noted above). |   |
| ossIndexPassword | Sets the OSS Index API token (deprecated) or Sonatype Guide personal access token (as an alternative to the indirection through the `ossIndexServerId` noted above). Be aware that if you use -X the secret will be written to the standard out; prefer `ossIndexServerId` or `ossIndexPasswordEnvironmentVariable`. |   |
| ossIndexPasswordEnvironmentVariable | The name of the environment variable from which to retrieve the value for `ossIndexPassword`; the recommended option to pass the token in CI builds. Takes precedence over `ossIndexServerId` but is overridden by `ossIndexPassword`. |   |
| ossIndexWarnOnlyOnRemoteErrors | Sets whether remote errors from the OSS Index (e.g. BAD GATEWAY, RATE LIMIT EXCEEDED) will result in warnings only instead of failing execution. | false |
| nexusAnalyzerEnabled | Sets whether Nexus Analyzer will be used. This analyzer is an alternative to the Central or Artifactory Analyzers, allowing retrieval from Sonatype Nexus installations. | false |
| nexusUrl | Sets the Nexus Repository v3 API base URL (example https://domain.enterprise/nexus/). If not set the Nexus Analyzer will be disabled. |   |
Expand Down Expand Up @@ -151,6 +152,7 @@ Note that any passwords in the below configuration could be exposed if you use `
| Property | Description | Default Value |
|---------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------|
| nvdApiServerId | The id of a server defined in the settings.xml that configures the credentials (password is used as ApiKey) for accessing the NVD API; obtained from https://nvd.nist.gov/developers/request-an-api-key. |   |
| nvdApiKeyEnvironmentVariable | The name of the environment variable from which to retrieve the NVD API Key; the recommended option to pass the API Key in CI builds. Takes precedence over `nvdApiServerId` but is overridden by `nvdApiKey`. |   |
| nvdApiKey | If you don't want register token as password in settings.xml, you can specify Bearer token for accessing the NVD API, but be aware that if you use -X the secret will be written to the standard out. |   |
| nvdApiEndpoint | The NVD API endpoint URL; setting this is uncommon. | https://services.nvd.nist.gov/rest/json/cves/2.0 |
| nvdMaxRetryCount | The maximum number of retry requests for a single call to the NVD API. | 10 |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

import io.github.jeremylong.openvulnerability.client.nvd.CvssV2;
import io.github.jeremylong.openvulnerability.client.nvd.CvssV2Data;
import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.junit.jupiter.api.Test;
Expand All @@ -30,13 +32,15 @@
import org.owasp.dependencycheck.dependency.Vulnerability;
import org.owasp.dependencycheck.exception.ExceptionCollection;
import org.owasp.dependencycheck.utils.CvssUtil;
import org.owasp.dependencycheck.utils.Settings;

import java.io.File;
import java.lang.reflect.Field;
import java.util.Locale;

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
Expand All @@ -49,6 +53,12 @@
@ExtendWith(MockitoExtension.class)
class BaseDependencyCheckMojoTest extends BaseTest {

/**
* A test cannot set environment variables for its own JVM; PATH is present on every platform
* and stands in for the variable that would hold the secret.
*/
private static final String SECRET_ENVIRONMENT_VARIABLE = "PATH";

@Spy
MavenProject project;

Expand Down Expand Up @@ -176,6 +186,72 @@ private static BaseDependencyCheckMojo mojoWithThreshold(float threshold) throws
return mojo;
}

/**
* The OSS Index password can be read from an environment variable.
*
* See https://github.com/dependency-check/DependencyCheck/issues/7642
*/
@Test
void should_read_the_ossIndex_password_from_the_environment_variable() throws Exception {
assertNotNull(System.getenv(SECRET_ENVIRONMENT_VARIABLE));
final BaseDependencyCheckMojo mojo = mojoReadyToPopulateSettings();
setField(mojo, "ossIndexUsername", "user@example.com");
setField(mojo, "ossIndexPasswordEnvironmentVariable", SECRET_ENVIRONMENT_VARIABLE);

mojo.populateSettings();

assertEquals("user@example.com", mojo.getSettings().getString(Settings.KEYS.ANALYZER_OSSINDEX_USER));
assertEquals(System.getenv(SECRET_ENVIRONMENT_VARIABLE), mojo.getSettings().getString(Settings.KEYS.ANALYZER_OSSINDEX_PASSWORD));
}

/**
* As with the NVD API key, the environment variable takes precedence over the server id. The
* settings.xml is empty, so the server id alone would leave the password unset.
*/
@Test
void should_prefer_the_environment_variable_over_the_ossIndex_server_id() throws Exception {
assertNotNull(System.getenv(SECRET_ENVIRONMENT_VARIABLE));
final BaseDependencyCheckMojo mojo = mojoReadyToPopulateSettings();
setField(mojo, "settingsXml", new org.apache.maven.settings.Settings());
setField(mojo, "ossIndexServerId", "ossindex");
setField(mojo, "ossIndexPasswordEnvironmentVariable", SECRET_ENVIRONMENT_VARIABLE);

mojo.populateSettings();

assertEquals(System.getenv(SECRET_ENVIRONMENT_VARIABLE), mojo.getSettings().getString(Settings.KEYS.ANALYZER_OSSINDEX_PASSWORD));
}

/**
* As with the NVD API key, a password configured directly takes precedence over the environment variable.
*/
@Test
void should_prefer_the_configured_ossIndex_password_over_the_environment_variable() throws Exception {
final BaseDependencyCheckMojo mojo = mojoReadyToPopulateSettings();
setField(mojo, "ossIndexPassword", "configured-token");
setField(mojo, "ossIndexPasswordEnvironmentVariable", SECRET_ENVIRONMENT_VARIABLE);

mojo.populateSettings();

assertEquals("configured-token", mojo.getSettings().getString(Settings.KEYS.ANALYZER_OSSINDEX_PASSWORD));
}

/**
* Creates a mojo with just enough of the Maven context injected for {@code populateSettings()} to run.
*/
private static BaseDependencyCheckMojo mojoReadyToPopulateSettings() throws Exception {
final BaseDependencyCheckMojo mojo = new BaseDependencyCheckMojoImpl();
setField(mojo, "project", new MavenProject());
setField(mojo, "mojoExecution", new MojoExecution(new Plugin(), "check", null));
setField(mojo, "mavenSettings", new org.apache.maven.settings.Settings());
return mojo;
}

private static void setField(BaseDependencyCheckMojo mojo, String name, Object value) throws Exception {
final Field field = BaseDependencyCheckMojo.class.getDeclaredField(name);
field.setAccessible(true);
field.set(mojo, value);
}

/**
* Implementation of ODC Mojo for testing.
*/
Expand Down
Loading