Merge pull request #1355 from DataDog/mar-kolya/new-api-key-option

Introduce to API key config option
This commit is contained in:
Nikolay Martynov 2020-04-06 14:52:33 -04:00 committed by GitHub
commit 71f1611f10
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 157 additions and 76 deletions

View File

@ -122,7 +122,7 @@ public final class RecordingUploader {
public RecordingUploader(final Config config) { public RecordingUploader(final Config config) {
url = config.getFinalProfilingUrl(); url = config.getFinalProfilingUrl();
apiKey = config.getProfilingApiKey(); apiKey = config.getApiKey();
/* /*
FIXME: currently `Config` class cannot get access to some pieces of information we need here: FIXME: currently `Config` class cannot get access to some pieces of information we need here:

View File

@ -68,7 +68,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class) @ExtendWith(MockitoExtension.class)
public class RecordingUploaderTest { public class RecordingUploaderTest {
private static final String APIKEY_VALUE = "testkey"; private static final String API_KEY_VALUE = "testkey";
private static final String URL_PATH = "/lalala"; private static final String URL_PATH = "/lalala";
private static final String RECORDING_RESOURCE = "test-recording.jfr"; private static final String RECORDING_RESOURCE = "test-recording.jfr";
private static final String RECODING_NAME_PREFIX = "test-recording-"; private static final String RECODING_NAME_PREFIX = "test-recording-";
@ -121,7 +121,7 @@ public class RecordingUploaderTest {
url = server.url(URL_PATH); url = server.url(URL_PATH);
when(config.getFinalProfilingUrl()).thenReturn(server.url(URL_PATH).toString()); when(config.getFinalProfilingUrl()).thenReturn(server.url(URL_PATH).toString());
when(config.getProfilingApiKey()).thenReturn(APIKEY_VALUE); when(config.getApiKey()).thenReturn(API_KEY_VALUE);
when(config.getMergedProfilingTags()).thenReturn(TAGS); when(config.getMergedProfilingTags()).thenReturn(TAGS);
when(config.getProfilingUploadTimeout()).thenReturn((int) REQUEST_TIMEOUT.getSeconds()); when(config.getProfilingUploadTimeout()).thenReturn((int) REQUEST_TIMEOUT.getSeconds());
@ -152,7 +152,7 @@ public class RecordingUploaderTest {
final RecordedRequest recordedRequest = server.takeRequest(5, TimeUnit.SECONDS); final RecordedRequest recordedRequest = server.takeRequest(5, TimeUnit.SECONDS);
assertEquals(url, recordedRequest.getRequestUrl()); assertEquals(url, recordedRequest.getRequestUrl());
assertEquals(APIKEY_VALUE, recordedRequest.getHeader("DD-API-KEY")); assertEquals(API_KEY_VALUE, recordedRequest.getHeader("DD-API-KEY"));
final Multimap<String, Object> parameters = final Multimap<String, Object> parameters =
ProfilingTestUtils.parseProfilingRequestParameters(recordedRequest); ProfilingTestUtils.parseProfilingRequestParameters(recordedRequest);
@ -215,7 +215,7 @@ public class RecordingUploaderTest {
final RecordedRequest recordedFirstRequest = server.takeRequest(5, TimeUnit.SECONDS); final RecordedRequest recordedFirstRequest = server.takeRequest(5, TimeUnit.SECONDS);
assertEquals(server.url(""), recordedFirstRequest.getRequestUrl()); assertEquals(server.url(""), recordedFirstRequest.getRequestUrl());
assertEquals(APIKEY_VALUE, recordedFirstRequest.getHeader("DD-API-KEY")); assertEquals(API_KEY_VALUE, recordedFirstRequest.getHeader("DD-API-KEY"));
assertNull(recordedFirstRequest.getHeader("Proxy-Authorization")); assertNull(recordedFirstRequest.getHeader("Proxy-Authorization"));
assertEquals(backendHost, recordedFirstRequest.getHeader("Host")); assertEquals(backendHost, recordedFirstRequest.getHeader("Host"));
assertEquals( assertEquals(
@ -223,7 +223,7 @@ public class RecordingUploaderTest {
final RecordedRequest recordedSecondRequest = server.takeRequest(5, TimeUnit.SECONDS); final RecordedRequest recordedSecondRequest = server.takeRequest(5, TimeUnit.SECONDS);
assertEquals(server.url(""), recordedSecondRequest.getRequestUrl()); assertEquals(server.url(""), recordedSecondRequest.getRequestUrl());
assertEquals(APIKEY_VALUE, recordedSecondRequest.getHeader("DD-API-KEY")); assertEquals(API_KEY_VALUE, recordedSecondRequest.getHeader("DD-API-KEY"));
assertEquals( assertEquals(
Credentials.basic("username", "password"), Credentials.basic("username", "password"),
recordedSecondRequest.getHeader("Proxy-Authorization")); recordedSecondRequest.getHeader("Proxy-Authorization"));

View File

@ -34,7 +34,7 @@ public class ProfilingAgent {
log.info("Profiling: disabled"); log.info("Profiling: disabled");
return; return;
} }
if (config.getProfilingApiKey() == null) { if (config.getApiKey() == null) {
log.info("Profiling: no API key, profiling disabled"); log.info("Profiling: no API key, profiling disabled");
return; return;
} }
@ -80,6 +80,7 @@ public class ProfilingAgent {
} }
private static class ShutdownHook extends Thread { private static class ShutdownHook extends Thread {
private final WeakReference<ProfilingSystem> profilerRef; private final WeakReference<ProfilingSystem> profilerRef;
private final WeakReference<RecordingUploader> uploaderRef; private final WeakReference<RecordingUploader> uploaderRef;

View File

@ -12,7 +12,7 @@ import spock.lang.Timeout
class CustomLogManagerTest extends Specification { class CustomLogManagerTest extends Specification {
private static final String DEFAULT_LOG_LEVEL = "debug" private static final String DEFAULT_LOG_LEVEL = "debug"
private static final String PROFILING_API_KEY = "some-api-key" private static final String API_KEY = "some-api-key"
// Run all tests using forked jvm because groovy has already set the global log manager // Run all tests using forked jvm because groovy has already set the global log manager
def "agent services starts up in premain with no custom log manager set"() { def "agent services starts up in premain with no custom log manager set"() {
@ -20,7 +20,7 @@ class CustomLogManagerTest extends Specification {
IntegrationTestUtils.runOnSeparateJvm(LogManagerSetter.getName() IntegrationTestUtils.runOnSeparateJvm(LogManagerSetter.getName()
, ["-Ddd.jmxfetch.enabled=true", "-Ddd.jmxfetch.refresh-beans-period=1", "-Ddd.profiling.enabled=true", "-Ddatadog.slf4j.simpleLogger.defaultLogLevel=$DEFAULT_LOG_LEVEL"] as String[] , ["-Ddd.jmxfetch.enabled=true", "-Ddd.jmxfetch.refresh-beans-period=1", "-Ddd.profiling.enabled=true", "-Ddatadog.slf4j.simpleLogger.defaultLogLevel=$DEFAULT_LOG_LEVEL"] as String[]
, "" as String[] , "" as String[]
, ["DD_PROFILING_APIKEY": PROFILING_API_KEY] , ["DD_API_KEY": API_KEY]
, true) == 0 , true) == 0
} }
@ -29,7 +29,7 @@ class CustomLogManagerTest extends Specification {
IntegrationTestUtils.runOnSeparateJvm(LogManagerSetter.getName() IntegrationTestUtils.runOnSeparateJvm(LogManagerSetter.getName()
, ["-Ddd.jmxfetch.enabled=true", "-Ddd.jmxfetch.refresh-beans-period=1", "-Ddd.profiling.enabled=true", "-Ddatadog.slf4j.simpleLogger.defaultLogLevel=$DEFAULT_LOG_LEVEL", "-Djava.util.logging.manager=jvmbootstraptest.CustomLogManager"] as String[] , ["-Ddd.jmxfetch.enabled=true", "-Ddd.jmxfetch.refresh-beans-period=1", "-Ddd.profiling.enabled=true", "-Ddatadog.slf4j.simpleLogger.defaultLogLevel=$DEFAULT_LOG_LEVEL", "-Djava.util.logging.manager=jvmbootstraptest.CustomLogManager"] as String[]
, "" as String[] , "" as String[]
, ["DD_PROFILING_APIKEY": PROFILING_API_KEY] , ["DD_API_KEY": API_KEY]
, true) == 0 , true) == 0
} }
@ -38,7 +38,7 @@ class CustomLogManagerTest extends Specification {
IntegrationTestUtils.runOnSeparateJvm(LogManagerSetter.getName() IntegrationTestUtils.runOnSeparateJvm(LogManagerSetter.getName()
, ["-Ddd.jmxfetch.enabled=true", "-Ddd.jmxfetch.refresh-beans-period=1", "-Ddd.profiling.enabled=true", "-Ddatadog.slf4j.simpleLogger.defaultLogLevel=$DEFAULT_LOG_LEVEL", "-Djava.util.logging.manager=jvmbootstraptest.MissingLogManager"] as String[] , ["-Ddd.jmxfetch.enabled=true", "-Ddd.jmxfetch.refresh-beans-period=1", "-Ddd.profiling.enabled=true", "-Ddatadog.slf4j.simpleLogger.defaultLogLevel=$DEFAULT_LOG_LEVEL", "-Djava.util.logging.manager=jvmbootstraptest.MissingLogManager"] as String[]
, "" as String[] , "" as String[]
, ["DD_PROFILING_APIKEY": PROFILING_API_KEY] , ["DD_API_KEY": API_KEY]
, true) == 0 , true) == 0
} }
@ -47,7 +47,7 @@ class CustomLogManagerTest extends Specification {
IntegrationTestUtils.runOnSeparateJvm(LogManagerSetter.getName() IntegrationTestUtils.runOnSeparateJvm(LogManagerSetter.getName()
, ["-Ddd.jmxfetch.enabled=true", "-Ddd.jmxfetch.refresh-beans-period=1", "-Ddd.profiling.enabled=true", "-Ddatadog.slf4j.simpleLogger.defaultLogLevel=$DEFAULT_LOG_LEVEL", "-Ddd.app.customlogmanager=true"] as String[] , ["-Ddd.jmxfetch.enabled=true", "-Ddd.jmxfetch.refresh-beans-period=1", "-Ddd.profiling.enabled=true", "-Ddatadog.slf4j.simpleLogger.defaultLogLevel=$DEFAULT_LOG_LEVEL", "-Ddd.app.customlogmanager=true"] as String[]
, "" as String[] , "" as String[]
, ["DD_PROFILING_APIKEY": PROFILING_API_KEY] , ["DD_API_KEY": API_KEY]
, true) == 0 , true) == 0
} }
@ -56,7 +56,7 @@ class CustomLogManagerTest extends Specification {
IntegrationTestUtils.runOnSeparateJvm(LogManagerSetter.getName() IntegrationTestUtils.runOnSeparateJvm(LogManagerSetter.getName()
, ["-Ddd.jmxfetch.enabled=true", "-Ddd.jmxfetch.refresh-beans-period=1", "-Ddd.profiling.enabled=true", "-Ddatadog.slf4j.simpleLogger.defaultLogLevel=$DEFAULT_LOG_LEVEL"] as String[] , ["-Ddd.jmxfetch.enabled=true", "-Ddd.jmxfetch.refresh-beans-period=1", "-Ddd.profiling.enabled=true", "-Ddatadog.slf4j.simpleLogger.defaultLogLevel=$DEFAULT_LOG_LEVEL"] as String[]
, "" as String[] , "" as String[]
, ["JBOSS_HOME": "/", "DD_PROFILING_APIKEY": PROFILING_API_KEY] , ["JBOSS_HOME": "/", "DD_API_KEY": API_KEY]
, true) == 0 , true) == 0
} }
@ -65,7 +65,7 @@ class CustomLogManagerTest extends Specification {
IntegrationTestUtils.runOnSeparateJvm(LogManagerSetter.getName() IntegrationTestUtils.runOnSeparateJvm(LogManagerSetter.getName()
, ["-Ddd.jmxfetch.enabled=true", "-Ddd.jmxfetch.refresh-beans-period=1", "-Ddd.profiling.enabled=true", "-Ddatadog.slf4j.simpleLogger.defaultLogLevel=$DEFAULT_LOG_LEVEL", "-Ddd.app.customlogmanager=false", "-Djava.util.logging.manager=jvmbootstraptest.CustomLogManager"] as String[] , ["-Ddd.jmxfetch.enabled=true", "-Ddd.jmxfetch.refresh-beans-period=1", "-Ddd.profiling.enabled=true", "-Ddatadog.slf4j.simpleLogger.defaultLogLevel=$DEFAULT_LOG_LEVEL", "-Ddd.app.customlogmanager=false", "-Djava.util.logging.manager=jvmbootstraptest.CustomLogManager"] as String[]
, "" as String[] , "" as String[]
, ["JBOSS_HOME": "/", "DD_PROFILING_APIKEY": PROFILING_API_KEY] , ["JBOSS_HOME": "/", "DD_API_KEY": API_KEY]
, true) == 0 , true) == 0
} }
} }

View File

@ -57,7 +57,7 @@ class ProfilingIntegrationContinuousProfilesTest extends AbstractSmokeTest {
then: then:
firstRequest.getRequestUrl().toString() == profilingUrl firstRequest.getRequestUrl().toString() == profilingUrl
firstRequest.getHeader("DD-API-KEY") == PROFILING_API_KEY firstRequest.getHeader("DD-API-KEY") == API_KEY
firstRequestParameters.get("recording-name").get(0) == 'dd-profiling' firstRequestParameters.get("recording-name").get(0) == 'dd-profiling'
firstRequestParameters.get("format").get(0) == "jfr" firstRequestParameters.get("format").get(0) == "jfr"
@ -87,7 +87,7 @@ class ProfilingIntegrationContinuousProfilesTest extends AbstractSmokeTest {
then: then:
secondRequest.getRequestUrl().toString() == profilingUrl secondRequest.getRequestUrl().toString() == profilingUrl
secondRequest.getHeader("DD-API-KEY") == PROFILING_API_KEY secondRequest.getHeader("DD-API-KEY") == API_KEY
secondRequestParameters.get("recording-name").get(0) == 'dd-profiling' secondRequestParameters.get("recording-name").get(0) == 'dd-profiling'
def secondStartTime = Instant.parse(secondRequestParameters.get("recording-start").get(0)) def secondStartTime = Instant.parse(secondRequestParameters.get("recording-start").get(0))

View File

@ -6,7 +6,7 @@ import spock.lang.Specification
abstract class AbstractSmokeTest extends Specification { abstract class AbstractSmokeTest extends Specification {
public static final PROFILING_API_KEY = "org2_api_key" public static final API_KEY = "some-api-key"
public static final PROFILING_START_DELAY_SECONDS = 1 public static final PROFILING_START_DELAY_SECONDS = 1
public static final int PROFILING_RECORDING_UPLOAD_PERIOD_SECONDS = 5 public static final int PROFILING_RECORDING_UPLOAD_PERIOD_SECONDS = 5
@ -49,7 +49,7 @@ abstract class AbstractSmokeTest extends Specification {
ProcessBuilder processBuilder = createProcessBuilder() ProcessBuilder processBuilder = createProcessBuilder()
processBuilder.environment().put("JAVA_HOME", System.getProperty("java.home")) processBuilder.environment().put("JAVA_HOME", System.getProperty("java.home"))
processBuilder.environment().put("DD_PROFILING_APIKEY", PROFILING_API_KEY) processBuilder.environment().put("DD_API_KEY", API_KEY)
processBuilder.redirectErrorStream(true) processBuilder.redirectErrorStream(true)
File log = new File("${buildDirectory}/reports/testProcess.${this.getClass().getName()}.log") File log = new File("${buildDirectory}/reports/testProcess.${this.getClass().getName()}.log")

View File

@ -49,6 +49,8 @@ public class Config {
private static final Pattern ENV_REPLACEMENT = Pattern.compile("[^a-zA-Z0-9_]"); private static final Pattern ENV_REPLACEMENT = Pattern.compile("[^a-zA-Z0-9_]");
public static final String CONFIGURATION_FILE = "trace.config"; public static final String CONFIGURATION_FILE = "trace.config";
public static final String API_KEY = "api-key";
public static final String API_KEY_FILE = "api-key-file";
public static final String SITE = "site"; public static final String SITE = "site";
public static final String SERVICE_NAME = "service.name"; public static final String SERVICE_NAME = "service.name";
public static final String TRACE_ENABLED = "trace.enabled"; public static final String TRACE_ENABLED = "trace.enabled";
@ -112,10 +114,14 @@ public class Config {
public static final String PROFILING_ENABLED = "profiling.enabled"; public static final String PROFILING_ENABLED = "profiling.enabled";
@Deprecated // Use dd.site instead @Deprecated // Use dd.site instead
public static final String PROFILING_URL = "profiling.url"; public static final String PROFILING_URL = "profiling.url";
public static final String PROFILING_API_KEY = "profiling.api-key"; @Deprecated // Use dd.api-key instead
public static final String PROFILING_API_KEY_FILE = "profiling.api-key-file"; public static final String PROFILING_API_KEY_OLD = "profiling.api-key";
public static final String PROFILING_API_KEY_OLD = "profiling.apikey"; @Deprecated // Use dd.api-key-file instead
public static final String PROFILING_API_KEY_FILE_OLD = "profiling.apikey.file"; public static final String PROFILING_API_KEY_FILE_OLD = "profiling.api-key-file";
@Deprecated // Use dd.api-key instead
public static final String PROFILING_API_KEY_VERY_OLD = "profiling.apikey";
@Deprecated // Use dd.api-key-file instead
public static final String PROFILING_API_KEY_FILE_VERY_OLD = "profiling.apikey.file";
public static final String PROFILING_TAGS = "profiling.tags"; public static final String PROFILING_TAGS = "profiling.tags";
public static final String PROFILING_START_DELAY = "profiling.start-delay"; public static final String PROFILING_START_DELAY = "profiling.start-delay";
// DANGEROUS! May lead on sigsegv on JVMs before 14 // DANGEROUS! May lead on sigsegv on JVMs before 14
@ -206,9 +212,9 @@ public class Config {
private static final String INTERNAL_HOST_NAME = "_dd.hostname"; private static final String INTERNAL_HOST_NAME = "_dd.hostname";
/** Used for masking sensitive information when doing toString */ /** Used for masking sensitive information when doing toString */
@ToString.Include(name = "profilingApiKey") @ToString.Include(name = "apiKey")
private String profilingApiKeyMasker() { private String profilingApiKeyMasker() {
return profilingApiKey != null ? "****" : null; return apiKey != null ? "****" : null;
} }
/** Used for masking sensitive information when doing toString */ /** Used for masking sensitive information when doing toString */
@ -223,6 +229,11 @@ public class Config {
*/ */
@Getter private final String runtimeId; @Getter private final String runtimeId;
/**
* Note: this has effect only on profiling site. Traces are sent to Datadog agent and are not
* affected by this setting.
*/
@Getter private final String apiKey;
/** /**
* Note: this has effect only on profiling site. Traces are sent to Datadog agent and are not * Note: this has effect only on profiling site. Traces are sent to Datadog agent and are not
* affected by this setting. * affected by this setting.
@ -291,7 +302,6 @@ public class Config {
@Getter private final boolean profilingEnabled; @Getter private final boolean profilingEnabled;
@Deprecated private final String profilingUrl; @Deprecated private final String profilingUrl;
@Getter private final String profilingApiKey;
private final Map<String, String> profilingTags; private final Map<String, String> profilingTags;
@Getter private final int profilingStartDelay; @Getter private final int profilingStartDelay;
@Getter private final boolean profilingStartForceFirst; @Getter private final boolean profilingStartForceFirst;
@ -314,6 +324,19 @@ public class Config {
runtimeId = UUID.randomUUID().toString(); runtimeId = UUID.randomUUID().toString();
// Note: We do not want APiKey to be loaded from property for security reasons
// Note: we do not use defined default here
// FIXME: We should use better authentication mechanism
final String apiKeyFile = getSettingFromEnvironment(API_KEY_FILE, null);
String tmpApiKey = System.getenv(propertyNameToEnvironmentVariableName(API_KEY));
if (apiKeyFile != null) {
try {
tmpApiKey =
new String(Files.readAllBytes(Paths.get(apiKeyFile)), StandardCharsets.UTF_8).trim();
} catch (final IOException e) {
log.error("Cannot read API key from file {}, skipping", apiKeyFile, e);
}
}
site = getSettingFromEnvironment(SITE, DEFAULT_SITE); site = getSettingFromEnvironment(SITE, DEFAULT_SITE);
serviceName = getSettingFromEnvironment(SERVICE_NAME, DEFAULT_SERVICE_NAME); serviceName = getSettingFromEnvironment(SERVICE_NAME, DEFAULT_SERVICE_NAME);
@ -438,38 +461,38 @@ public class Config {
profilingEnabled = profilingEnabled =
getBooleanSettingFromEnvironment(PROFILING_ENABLED, DEFAULT_PROFILING_ENABLED); getBooleanSettingFromEnvironment(PROFILING_ENABLED, DEFAULT_PROFILING_ENABLED);
profilingUrl = getSettingFromEnvironment(PROFILING_URL, null); profilingUrl = getSettingFromEnvironment(PROFILING_URL, null);
// Note: We do not want APiKey to be loaded from property for security reasons
// Note: we do not use defined default here if (tmpApiKey == null) {
// FIXME: We should use better authentication mechanism
final String profilingApiKeyFile = getSettingFromEnvironment(PROFILING_API_KEY_FILE, null);
String tmpProfilingApiKey =
System.getenv(propertyNameToEnvironmentVariableName(PROFILING_API_KEY));
if (profilingApiKeyFile != null) {
try {
tmpProfilingApiKey =
new String(Files.readAllBytes(Paths.get(profilingApiKeyFile)), StandardCharsets.UTF_8)
.trim();
} catch (final IOException e) {
log.error("Cannot read API key from file {}, skipping", profilingApiKeyFile, e);
}
}
if (tmpProfilingApiKey == null) {
final String oldProfilingApiKeyFile = final String oldProfilingApiKeyFile =
getSettingFromEnvironment(PROFILING_API_KEY_FILE_OLD, null); getSettingFromEnvironment(PROFILING_API_KEY_FILE_OLD, null);
tmpProfilingApiKey = tmpApiKey = System.getenv(propertyNameToEnvironmentVariableName(PROFILING_API_KEY_OLD));
System.getenv(propertyNameToEnvironmentVariableName(PROFILING_API_KEY_OLD));
if (oldProfilingApiKeyFile != null) { if (oldProfilingApiKeyFile != null) {
try { try {
tmpProfilingApiKey = tmpApiKey =
new String( new String(
Files.readAllBytes(Paths.get(oldProfilingApiKeyFile)), StandardCharsets.UTF_8) Files.readAllBytes(Paths.get(oldProfilingApiKeyFile)), StandardCharsets.UTF_8)
.trim(); .trim();
} catch (final IOException e) { } catch (final IOException e) {
log.error("Cannot read API key from file {}, skipping", profilingApiKeyFile, e); log.error("Cannot read API key from file {}, skipping", oldProfilingApiKeyFile, e);
}
}
}
if (tmpApiKey == null) {
final String veryOldProfilingApiKeyFile =
getSettingFromEnvironment(PROFILING_API_KEY_FILE_VERY_OLD, null);
tmpApiKey = System.getenv(propertyNameToEnvironmentVariableName(PROFILING_API_KEY_VERY_OLD));
if (veryOldProfilingApiKeyFile != null) {
try {
tmpApiKey =
new String(
Files.readAllBytes(Paths.get(veryOldProfilingApiKeyFile)),
StandardCharsets.UTF_8)
.trim();
} catch (final IOException e) {
log.error("Cannot read API key from file {}, skipping", veryOldProfilingApiKeyFile, e);
} }
} }
} }
profilingApiKey = tmpProfilingApiKey;
profilingTags = getMapSettingFromEnvironment(PROFILING_TAGS, null); profilingTags = getMapSettingFromEnvironment(PROFILING_TAGS, null);
profilingStartDelay = profilingStartDelay =
@ -493,6 +516,9 @@ public class Config {
profilingProxyUsername = getSettingFromEnvironment(PROFILING_PROXY_USERNAME, null); profilingProxyUsername = getSettingFromEnvironment(PROFILING_PROXY_USERNAME, null);
profilingProxyPassword = getSettingFromEnvironment(PROFILING_PROXY_PASSWORD, null); profilingProxyPassword = getSettingFromEnvironment(PROFILING_PROXY_PASSWORD, null);
// Setting this last because we have a few places where this can come from
apiKey = tmpApiKey;
log.debug("New instance: {}", this); log.debug("New instance: {}", this);
} }
@ -500,6 +526,7 @@ public class Config {
private Config(final Properties properties, final Config parent) { private Config(final Properties properties, final Config parent) {
runtimeId = parent.runtimeId; runtimeId = parent.runtimeId;
apiKey = properties.getProperty(API_KEY, parent.apiKey);
site = properties.getProperty(SITE, parent.site); site = properties.getProperty(SITE, parent.site);
serviceName = properties.getProperty(SERVICE_NAME, parent.serviceName); serviceName = properties.getProperty(SERVICE_NAME, parent.serviceName);
@ -633,7 +660,6 @@ public class Config {
profilingEnabled = profilingEnabled =
getPropertyBooleanValue(properties, PROFILING_ENABLED, parent.profilingEnabled); getPropertyBooleanValue(properties, PROFILING_ENABLED, parent.profilingEnabled);
profilingUrl = properties.getProperty(PROFILING_URL, parent.profilingUrl); profilingUrl = properties.getProperty(PROFILING_URL, parent.profilingUrl);
profilingApiKey = properties.getProperty(PROFILING_API_KEY, parent.profilingApiKey);
profilingTags = getPropertyMapValue(properties, PROFILING_TAGS, parent.profilingTags); profilingTags = getPropertyMapValue(properties, PROFILING_TAGS, parent.profilingTags);
profilingStartDelay = profilingStartDelay =
getPropertyIntegerValue(properties, PROFILING_START_DELAY, parent.profilingStartDelay); getPropertyIntegerValue(properties, PROFILING_START_DELAY, parent.profilingStartDelay);

View File

@ -8,6 +8,8 @@ import org.junit.contrib.java.lang.system.RestoreSystemProperties
import static datadog.trace.api.Config.AGENT_HOST import static datadog.trace.api.Config.AGENT_HOST
import static datadog.trace.api.Config.AGENT_PORT_LEGACY import static datadog.trace.api.Config.AGENT_PORT_LEGACY
import static datadog.trace.api.Config.AGENT_UNIX_DOMAIN_SOCKET import static datadog.trace.api.Config.AGENT_UNIX_DOMAIN_SOCKET
import static datadog.trace.api.Config.API_KEY
import static datadog.trace.api.Config.API_KEY_FILE
import static datadog.trace.api.Config.CONFIGURATION_FILE import static datadog.trace.api.Config.CONFIGURATION_FILE
import static datadog.trace.api.Config.DB_CLIENT_HOST_SPLIT_BY_INSTANCE import static datadog.trace.api.Config.DB_CLIENT_HOST_SPLIT_BY_INSTANCE
import static datadog.trace.api.Config.DEFAULT_JMX_FETCH_STATSD_PORT import static datadog.trace.api.Config.DEFAULT_JMX_FETCH_STATSD_PORT
@ -32,9 +34,8 @@ import static datadog.trace.api.Config.LANGUAGE_TAG_VALUE
import static datadog.trace.api.Config.PARTIAL_FLUSH_MIN_SPANS import static datadog.trace.api.Config.PARTIAL_FLUSH_MIN_SPANS
import static datadog.trace.api.Config.PREFIX import static datadog.trace.api.Config.PREFIX
import static datadog.trace.api.Config.PRIORITY_SAMPLING import static datadog.trace.api.Config.PRIORITY_SAMPLING
import static datadog.trace.api.Config.PROFILING_API_KEY
import static datadog.trace.api.Config.PROFILING_API_KEY_FILE
import static datadog.trace.api.Config.PROFILING_API_KEY_FILE_OLD import static datadog.trace.api.Config.PROFILING_API_KEY_FILE_OLD
import static datadog.trace.api.Config.PROFILING_API_KEY_FILE_VERY_OLD
import static datadog.trace.api.Config.PROFILING_ENABLED import static datadog.trace.api.Config.PROFILING_ENABLED
import static datadog.trace.api.Config.PROFILING_PROXY_HOST import static datadog.trace.api.Config.PROFILING_PROXY_HOST
import static datadog.trace.api.Config.PROFILING_PROXY_PASSWORD import static datadog.trace.api.Config.PROFILING_PROXY_PASSWORD
@ -75,6 +76,7 @@ class ConfigTest extends DDSpecification {
@Rule @Rule
public final EnvironmentVariables environmentVariables = new EnvironmentVariables() public final EnvironmentVariables environmentVariables = new EnvironmentVariables()
private static final DD_API_KEY_ENV = "DD_API_KEY"
private static final DD_SERVICE_NAME_ENV = "DD_SERVICE_NAME" private static final DD_SERVICE_NAME_ENV = "DD_SERVICE_NAME"
private static final DD_TRACE_ENABLED_ENV = "DD_TRACE_ENABLED" private static final DD_TRACE_ENABLED_ENV = "DD_TRACE_ENABLED"
private static final DD_WRITER_TYPE_ENV = "DD_WRITER_TYPE" private static final DD_WRITER_TYPE_ENV = "DD_WRITER_TYPE"
@ -91,8 +93,8 @@ class ConfigTest extends DDSpecification {
private static final DD_AGENT_PORT_LEGACY_ENV = "DD_AGENT_PORT" private static final DD_AGENT_PORT_LEGACY_ENV = "DD_AGENT_PORT"
private static final DD_TRACE_REPORT_HOSTNAME = "DD_TRACE_REPORT_HOSTNAME" private static final DD_TRACE_REPORT_HOSTNAME = "DD_TRACE_REPORT_HOSTNAME"
private static final DD_PROFILING_API_KEY_ENV = "DD_PROFILING_API_KEY" private static final DD_PROFILING_API_KEY_OLD_ENV = "DD_PROFILING_API_KEY"
private static final DD_PROFILING_API_KEY_OLD_ENV = "DD_PROFILING_APIKEY" private static final DD_PROFILING_API_KEY_VERY_OLD_ENV = "DD_PROFILING_APIKEY"
private static final DD_PROFILING_TAGS_ENV = "DD_PROFILING_TAGS" private static final DD_PROFILING_TAGS_ENV = "DD_PROFILING_TAGS"
private static final DD_PROFILING_PROXY_PASSWORD_ENV = "DD_PROFILING_PROXY_PASSWORD" private static final DD_PROFILING_PROXY_PASSWORD_ENV = "DD_PROFILING_PROXY_PASSWORD"
@ -101,6 +103,8 @@ class ConfigTest extends DDSpecification {
Config config = provider() Config config = provider()
then: then:
config.apiKey == null
config.site == Config.DEFAULT_SITE
config.serviceName == "unnamed-java-app" config.serviceName == "unnamed-java-app"
config.traceEnabled == true config.traceEnabled == true
config.writerType == "DDAgentWriter" config.writerType == "DDAgentWriter"
@ -135,9 +139,7 @@ class ConfigTest extends DDSpecification {
config.healthMetricsStatsdPort == null config.healthMetricsStatsdPort == null
config.profilingEnabled == false config.profilingEnabled == false
config.site == Config.DEFAULT_SITE
config.profilingUrl == null config.profilingUrl == null
config.profilingApiKey == null
config.mergedProfilingTags == [(HOST_TAG): config.getHostName(), (RUNTIME_ID_TAG): config.getRuntimeId(), (SERVICE_TAG): config.serviceName, (LANGUAGE_TAG_KEY): LANGUAGE_TAG_VALUE] config.mergedProfilingTags == [(HOST_TAG): config.getHostName(), (RUNTIME_ID_TAG): config.getRuntimeId(), (SERVICE_TAG): config.serviceName, (LANGUAGE_TAG_KEY): LANGUAGE_TAG_VALUE]
config.profilingStartDelay == 10 config.profilingStartDelay == 10
config.profilingStartForceFirst == false config.profilingStartForceFirst == false
@ -162,6 +164,8 @@ class ConfigTest extends DDSpecification {
def "specify overrides via properties"() { def "specify overrides via properties"() {
setup: setup:
def prop = new Properties() def prop = new Properties()
prop.setProperty(API_KEY, "new api key")
prop.setProperty(SITE, "new site")
prop.setProperty(SERVICE_NAME, "something else") prop.setProperty(SERVICE_NAME, "something else")
prop.setProperty(TRACE_ENABLED, "false") prop.setProperty(TRACE_ENABLED, "false")
prop.setProperty(WRITER_TYPE, "LoggingWriter") prop.setProperty(WRITER_TYPE, "LoggingWriter")
@ -201,9 +205,7 @@ class ConfigTest extends DDSpecification {
prop.setProperty(TRACE_RATE_LIMIT, "200") prop.setProperty(TRACE_RATE_LIMIT, "200")
prop.setProperty(PROFILING_ENABLED, "true") prop.setProperty(PROFILING_ENABLED, "true")
prop.setProperty(SITE, "new site")
prop.setProperty(PROFILING_URL, "new url") prop.setProperty(PROFILING_URL, "new url")
prop.setProperty(PROFILING_API_KEY, "new api key")
prop.setProperty(PROFILING_TAGS, "f:6,host:test-host") prop.setProperty(PROFILING_TAGS, "f:6,host:test-host")
prop.setProperty(PROFILING_START_DELAY, "1111") prop.setProperty(PROFILING_START_DELAY, "1111")
prop.setProperty(PROFILING_START_FORCE_FIRST, "true") prop.setProperty(PROFILING_START_FORCE_FIRST, "true")
@ -220,6 +222,8 @@ class ConfigTest extends DDSpecification {
Config config = Config.get(prop) Config config = Config.get(prop)
then: then:
config.apiKey == "new api key" // we can still override via internal properties object
config.site == "new site"
config.serviceName == "something else" config.serviceName == "something else"
config.traceEnabled == false config.traceEnabled == false
config.writerType == "LoggingWriter" config.writerType == "LoggingWriter"
@ -258,9 +262,7 @@ class ConfigTest extends DDSpecification {
config.traceRateLimit == 200 config.traceRateLimit == 200
config.profilingEnabled == true config.profilingEnabled == true
config.site == "new site"
config.profilingUrl == "new url" config.profilingUrl == "new url"
config.profilingApiKey == "new api key" // we can still override via internal properties object
config.mergedProfilingTags == [b: "2", f: "6", (HOST_TAG): "test-host", (RUNTIME_ID_TAG): config.getRuntimeId(), (SERVICE_TAG): config.serviceName, (LANGUAGE_TAG_KEY): LANGUAGE_TAG_VALUE] config.mergedProfilingTags == [b: "2", f: "6", (HOST_TAG): "test-host", (RUNTIME_ID_TAG): config.getRuntimeId(), (SERVICE_TAG): config.serviceName, (LANGUAGE_TAG_KEY): LANGUAGE_TAG_VALUE]
config.profilingStartDelay == 1111 config.profilingStartDelay == 1111
config.profilingStartForceFirst == true config.profilingStartForceFirst == true
@ -276,6 +278,8 @@ class ConfigTest extends DDSpecification {
def "specify overrides via system properties"() { def "specify overrides via system properties"() {
setup: setup:
System.setProperty(PREFIX + API_KEY, "new api key")
System.setProperty(PREFIX + SITE, "new site")
System.setProperty(PREFIX + SERVICE_NAME, "something else") System.setProperty(PREFIX + SERVICE_NAME, "something else")
System.setProperty(PREFIX + TRACE_ENABLED, "false") System.setProperty(PREFIX + TRACE_ENABLED, "false")
System.setProperty(PREFIX + WRITER_TYPE, "LoggingWriter") System.setProperty(PREFIX + WRITER_TYPE, "LoggingWriter")
@ -315,9 +319,7 @@ class ConfigTest extends DDSpecification {
System.setProperty(PREFIX + TRACE_RATE_LIMIT, "200") System.setProperty(PREFIX + TRACE_RATE_LIMIT, "200")
System.setProperty(PREFIX + PROFILING_ENABLED, "true") System.setProperty(PREFIX + PROFILING_ENABLED, "true")
System.setProperty(PREFIX + SITE, "new site")
System.setProperty(PREFIX + PROFILING_URL, "new url") System.setProperty(PREFIX + PROFILING_URL, "new url")
System.setProperty(PREFIX + PROFILING_API_KEY, "new api key")
System.setProperty(PREFIX + PROFILING_TAGS, "f:6,host:test-host") System.setProperty(PREFIX + PROFILING_TAGS, "f:6,host:test-host")
System.setProperty(PREFIX + PROFILING_START_DELAY, "1111") System.setProperty(PREFIX + PROFILING_START_DELAY, "1111")
System.setProperty(PREFIX + PROFILING_START_FORCE_FIRST, "true") System.setProperty(PREFIX + PROFILING_START_FORCE_FIRST, "true")
@ -334,6 +336,8 @@ class ConfigTest extends DDSpecification {
Config config = new Config() Config config = new Config()
then: then:
config.apiKey == null // system properties cannot be used to provide a key
config.site == "new site"
config.serviceName == "something else" config.serviceName == "something else"
config.traceEnabled == false config.traceEnabled == false
config.writerType == "LoggingWriter" config.writerType == "LoggingWriter"
@ -372,9 +376,7 @@ class ConfigTest extends DDSpecification {
config.traceRateLimit == 200 config.traceRateLimit == 200
config.profilingEnabled == true config.profilingEnabled == true
config.site == "new site"
config.profilingUrl == "new url" config.profilingUrl == "new url"
config.profilingApiKey == null // system properties cannot be used to provide a key
config.mergedProfilingTags == [b: "2", f: "6", (HOST_TAG): "test-host", (RUNTIME_ID_TAG): config.getRuntimeId(), (SERVICE_TAG): config.serviceName, (LANGUAGE_TAG_KEY): LANGUAGE_TAG_VALUE] config.mergedProfilingTags == [b: "2", f: "6", (HOST_TAG): "test-host", (RUNTIME_ID_TAG): config.getRuntimeId(), (SERVICE_TAG): config.serviceName, (LANGUAGE_TAG_KEY): LANGUAGE_TAG_VALUE]
config.profilingStartDelay == 1111 config.profilingStartDelay == 1111
config.profilingStartForceFirst == true config.profilingStartForceFirst == true
@ -390,6 +392,7 @@ class ConfigTest extends DDSpecification {
def "specify overrides via env vars"() { def "specify overrides via env vars"() {
setup: setup:
environmentVariables.set(DD_API_KEY_ENV, "test-api-key")
environmentVariables.set(DD_SERVICE_NAME_ENV, "still something else") environmentVariables.set(DD_SERVICE_NAME_ENV, "still something else")
environmentVariables.set(DD_TRACE_ENABLED_ENV, "false") environmentVariables.set(DD_TRACE_ENABLED_ENV, "false")
environmentVariables.set(DD_WRITER_TYPE_ENV, "LoggingWriter") environmentVariables.set(DD_WRITER_TYPE_ENV, "LoggingWriter")
@ -397,12 +400,12 @@ class ConfigTest extends DDSpecification {
environmentVariables.set(DD_PROPAGATION_STYLE_INJECT, "Datadog B3") environmentVariables.set(DD_PROPAGATION_STYLE_INJECT, "Datadog B3")
environmentVariables.set(DD_JMXFETCH_METRICS_CONFIGS_ENV, "some/file") environmentVariables.set(DD_JMXFETCH_METRICS_CONFIGS_ENV, "some/file")
environmentVariables.set(DD_TRACE_REPORT_HOSTNAME, "true") environmentVariables.set(DD_TRACE_REPORT_HOSTNAME, "true")
environmentVariables.set(DD_PROFILING_API_KEY_ENV, "test-api-key")
when: when:
def config = new Config() def config = new Config()
then: then:
config.apiKey == "test-api-key"
config.serviceName == "still something else" config.serviceName == "still something else"
config.traceEnabled == false config.traceEnabled == false
config.writerType == "LoggingWriter" config.writerType == "LoggingWriter"
@ -410,7 +413,6 @@ class ConfigTest extends DDSpecification {
config.propagationStylesToInject.toList() == [Config.PropagationStyle.DATADOG, Config.PropagationStyle.B3] config.propagationStylesToInject.toList() == [Config.PropagationStyle.DATADOG, Config.PropagationStyle.B3]
config.jmxFetchMetricsConfigs == ["some/file"] config.jmxFetchMetricsConfigs == ["some/file"]
config.reportHostName == true config.reportHostName == true
config.profilingApiKey == "test-api-key"
} }
def "sys props override env vars"() { def "sys props override env vars"() {
@ -1008,14 +1010,14 @@ class ConfigTest extends DDSpecification {
def "verify api key loaded from file: #path"() { def "verify api key loaded from file: #path"() {
setup: setup:
environmentVariables.set(DD_PROFILING_API_KEY_ENV, "default-api-key") environmentVariables.set(DD_API_KEY_ENV, "default-api-key")
System.setProperty(PREFIX + PROFILING_API_KEY_FILE, path) System.setProperty(PREFIX + API_KEY_FILE, path)
when: when:
def config = new Config() def config = new Config()
then: then:
config.profilingApiKey == expectedKey config.apiKey == expectedKey
where: where:
path | expectedKey path | expectedKey
@ -1023,6 +1025,17 @@ class ConfigTest extends DDSpecification {
"/path/that/doesnt/exist" | "default-api-key" "/path/that/doesnt/exist" | "default-api-key"
} }
def "verify api key loaded from old option name"() {
setup:
environmentVariables.set(DD_PROFILING_API_KEY_OLD_ENV, "old-api-key")
when:
def config = new Config()
then:
config.apiKey == "old-api-key"
}
def "verify api key loaded from file for old option name: #path"() { def "verify api key loaded from file for old option name: #path"() {
setup: setup:
environmentVariables.set(DD_PROFILING_API_KEY_OLD_ENV, "default-api-key") environmentVariables.set(DD_PROFILING_API_KEY_OLD_ENV, "default-api-key")
@ -1032,7 +1045,7 @@ class ConfigTest extends DDSpecification {
def config = new Config() def config = new Config()
then: then:
config.profilingApiKey == expectedKey config.apiKey == expectedKey
where: where:
path | expectedKey path | expectedKey
@ -1040,16 +1053,56 @@ class ConfigTest extends DDSpecification {
"/path/that/doesnt/exist" | "default-api-key" "/path/that/doesnt/exist" | "default-api-key"
} }
def "verify api key loaded from new option when both new and old are set"() { def "verify api key loaded from very old option name"() {
setup: setup:
System.setProperty(PREFIX + PROFILING_API_KEY_FILE_OLD, getClass().getClassLoader().getResource("apikey.old").getFile()) environmentVariables.set(DD_PROFILING_API_KEY_VERY_OLD_ENV, "very-old-api-key")
System.setProperty(PREFIX + PROFILING_API_KEY_FILE, getClass().getClassLoader().getResource("apikey").getFile())
when: when:
def config = new Config() def config = new Config()
then: then:
config.profilingApiKey == "test-api-key" config.apiKey == "very-old-api-key"
}
def "verify api key loaded from file for very old option name: #path"() {
setup:
environmentVariables.set(DD_PROFILING_API_KEY_VERY_OLD_ENV, "default-api-key")
System.setProperty(PREFIX + PROFILING_API_KEY_FILE_VERY_OLD, path)
when:
def config = new Config()
then:
config.apiKey == expectedKey
where:
path | expectedKey
getClass().getClassLoader().getResource("apikey.very-old").getFile() | "test-api-key-very-old"
"/path/that/doesnt/exist" | "default-api-key"
}
def "verify api key loaded from new option when both new and old are set"() {
setup:
System.setProperty(PREFIX + API_KEY_FILE, getClass().getClassLoader().getResource("apikey").getFile())
System.setProperty(PREFIX + PROFILING_API_KEY_FILE_OLD, getClass().getClassLoader().getResource("apikey.old").getFile())
when:
def config = new Config()
then:
config.apiKey == "test-api-key"
}
def "verify api key loaded from new option when both old and very old are set"() {
setup:
System.setProperty(PREFIX + PROFILING_API_KEY_FILE_OLD, getClass().getClassLoader().getResource("apikey.old").getFile())
System.setProperty(PREFIX + PROFILING_API_KEY_FILE_VERY_OLD, getClass().getClassLoader().getResource("apikey.very-old").getFile())
when:
def config = new Config()
then:
config.apiKey == "test-api-key-old"
} }
def "verify dd.tags overrides global tags in properties"() { def "verify dd.tags overrides global tags in properties"() {
@ -1112,30 +1165,30 @@ class ConfigTest extends DDSpecification {
config.mergedProfilingTags == [a: "1", f: "6", (HOST_TAG): config.getHostName(), (RUNTIME_ID_TAG): config.getRuntimeId(), (SERVICE_TAG): config.serviceName, (LANGUAGE_TAG_KEY): LANGUAGE_TAG_VALUE] config.mergedProfilingTags == [a: "1", f: "6", (HOST_TAG): config.getHostName(), (RUNTIME_ID_TAG): config.getRuntimeId(), (SERVICE_TAG): config.serviceName, (LANGUAGE_TAG_KEY): LANGUAGE_TAG_VALUE]
} }
def "toString works when passwords are empty"() { def "toString works when passwords are empty"() {
when: when:
def config = new Config() def config = new Config()
then: then:
config.toString().contains("profilingApiKey=null") config.toString().contains("apiKey=null")
config.toString().contains("profilingProxyPassword=null") config.toString().contains("profilingProxyPassword=null")
} }
def "sensitive information removed for toString/debug log"() { def "sensitive information removed for toString/debug log"() {
setup: setup:
environmentVariables.set(DD_PROFILING_API_KEY_ENV, "test-secret-api-key") environmentVariables.set(DD_API_KEY_ENV, "test-secret-api-key")
environmentVariables.set(DD_PROFILING_PROXY_PASSWORD_ENV, "test-secret-proxy-password") environmentVariables.set(DD_PROFILING_PROXY_PASSWORD_ENV, "test-secret-proxy-password")
when: when:
def config = new Config() def config = new Config()
then: then:
config.toString().contains("profilingApiKey=****") config.toString().contains("apiKey=****")
!config.toString().contains("test-secret-api-key") !config.toString().contains("test-secret-api-key")
config.toString().contains("profilingProxyPassword=****") config.toString().contains("profilingProxyPassword=****")
!config.toString().contains("test-secret-proxy-password") !config.toString().contains("test-secret-proxy-password")
config.profilingApiKey == "test-secret-api-key" config.apiKey == "test-secret-api-key"
config.profilingProxyPassword == "test-secret-proxy-password" config.profilingProxyPassword == "test-secret-proxy-password"
} }

View File

@ -0,0 +1 @@
test-api-key-very-old