Skip to content
Closed
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
@@ -1,19 +1,19 @@
package datadog.trace.core.tagprocessor;

import static datadog.json.JsonPathParser.parseJsonPaths;

import datadog.json.JsonPath;
import datadog.json.JsonStreamParser;
import datadog.json.PathCursor;
import datadog.trace.api.Config;
import datadog.trace.api.ConfigDefaults;
import datadog.trace.api.TagMap;
import datadog.trace.api.telemetry.LogCollector;
import datadog.trace.bootstrap.instrumentation.api.AgentSpanLink;
import datadog.trace.core.DDSpanContext;
import datadog.trace.payloadtags.PayloadTagsData;
import datadog.trace.payloadtags.json.JsonPath;
import datadog.trace.payloadtags.json.JsonPathParser;
import datadog.trace.payloadtags.json.JsonStreamParser;
import datadog.trace.payloadtags.json.PathCursor;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand All @@ -38,7 +38,7 @@ public static PayloadTagsProcessor create(Config config) {
new RedactionRules.Builder()
.addRedactionJsonPaths(ConfigDefaults.DEFAULT_CLOUD_COMMON_PAYLOAD_TAGGING)
.addRedactionJsonPaths(ConfigDefaults.DEFAULT_CLOUD_REQUEST_PAYLOAD_TAGGING)
.addRedactionJsonPaths(config.getCloudRequestPayloadTagging())
.addParsedRedactionJsonPaths(config.getCloudRequestPayloadTagging())
.build());
}
if (config.isCloudResponsePayloadTaggingEnabled()) {
Expand All @@ -47,7 +47,7 @@ public static PayloadTagsProcessor create(Config config) {
new RedactionRules.Builder()
.addRedactionJsonPaths(ConfigDefaults.DEFAULT_CLOUD_COMMON_PAYLOAD_TAGGING)
.addRedactionJsonPaths(ConfigDefaults.DEFAULT_CLOUD_RESPONSE_PAYLOAD_TAGGING)
.addRedactionJsonPaths(config.getCloudResponsePayloadTagging())
.addParsedRedactionJsonPaths(config.getCloudResponsePayloadTagging())
.build());
}
if (redactionRulesByTagPrefix.isEmpty()) {
Expand Down Expand Up @@ -145,20 +145,9 @@ public RedactionRules.Builder addRedactionJsonPaths(List<String> jsonPaths) {
return this;
}

private static List<JsonPath> parseJsonPaths(List<String> rules) {
if (rules.isEmpty() || rules.size() == 1 && rules.get(0).equalsIgnoreCase("all")) {
return Collections.emptyList();
}
List<JsonPath> result = new ArrayList<>(rules.size());
for (String rule : rules) {
try {
JsonPath jp = JsonPathParser.parse(rule);
result.add(jp);
} catch (Exception ex) {
log.warn("Skipping failed to parse redaction rule '{}'. {}", rule, ex.getMessage());
}
}
return result;
public RedactionRules.Builder addParsedRedactionJsonPaths(List<JsonPath> jsonPaths) {
this.redactionRules.addAll(jsonPaths);
return this;
}

RedactionRules build() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package datadog.trace.core.tagprocessor
import com.squareup.moshi.JsonWriter
import datadog.trace.payloadtags.PayloadTagsData
import datadog.trace.payloadtags.PayloadTagsData.PathAndValue
import datadog.trace.payloadtags.json.PathCursor
import datadog.json.PathCursor
import datadog.trace.test.util.DDSpecification
import datadog.trace.api.Config
import okio.Buffer
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package datadog.trace.payloadtags.json

import datadog.json.JsonPath
import datadog.json.JsonPathParser
import spock.lang.Specification

class JsonPathParserSpec extends Specification {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package datadog.trace.payloadtags.json

import datadog.json.JsonPath
import datadog.json.PathCursor
import spock.lang.Specification

class JsonPathSpec extends Specification {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package datadog.trace.payloadtags.json

import datadog.json.PathCursor
import spock.lang.Specification

class PathCursorSpec extends Specification {
Expand Down
1 change: 1 addition & 0 deletions internal-api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ dependencies {
api(project(":components:yaml"))
api(project(":utils:config-utils"))
api(project(":utils:time-utils"))
api(project(":utils:json-utils"))

// has to be loaded by system classloader:
// it contains annotations that are also present in the instrumented application classes
Expand Down
45 changes: 39 additions & 6 deletions internal-api/src/main/java/datadog/trace/api/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static datadog.environment.JavaVirtualMachine.isJavaVersion;
import static datadog.environment.JavaVirtualMachine.isJavaVersionAtLeast;
import static datadog.json.JsonPathParser.parseJsonPaths;
import static datadog.trace.api.ConfigDefaults.DEFAULT_ADD_SPAN_POINTERS;
import static datadog.trace.api.ConfigDefaults.DEFAULT_AGENT_HOST;
import static datadog.trace.api.ConfigDefaults.DEFAULT_AGENT_TIMEOUT;
Expand Down Expand Up @@ -677,6 +678,7 @@
import datadog.environment.JavaVirtualMachine;
import datadog.environment.OperatingSystem;
import datadog.environment.SystemProperties;
import datadog.json.JsonPath;
import datadog.trace.api.civisibility.CiVisibilityWellKnownTags;
import datadog.trace.api.config.GeneralConfig;
import datadog.trace.api.config.OtlpConfig;
Expand Down Expand Up @@ -822,6 +824,7 @@ public static String getHostName() {
private final String agentUnixDomainSocket;
private final String agentNamedPipe;
private final int agentTimeout;

/** Should be set to {@code true} when running in agentless mode in a JVM without TLS */
private final boolean forceClearTextHttpForIntakeClient;

Expand Down Expand Up @@ -1283,8 +1286,8 @@ public static String getHostName() {
private final String agentlessLogSubmissionProduct;

private final Set<String> cloudPayloadTaggingServices;
@Nullable private final List<String> cloudRequestPayloadTagging;
@Nullable private final List<String> cloudResponsePayloadTagging;
@Nullable private final List<JsonPath> cloudRequestPayloadTagging;
@Nullable private final List<JsonPath> cloudResponsePayloadTagging;
private final int cloudPayloadTaggingMaxDepth;
private final int cloudPayloadTaggingMaxTags;

Expand Down Expand Up @@ -2861,10 +2864,40 @@ PROFILING_DATADOG_PROFILER_ENABLED, isDatadogProfilerSafeInCurrentEnvironment())
this.cloudPayloadTaggingServices =
configProvider.getSet(
TRACE_CLOUD_PAYLOAD_TAGGING_SERVICES, DEFAULT_TRACE_CLOUD_PAYLOAD_TAGGING_SERVICES);
this.cloudRequestPayloadTagging =

List<String> cloudReqPayloadTaggingConf =
configProvider.getList(TRACE_CLOUD_REQUEST_PAYLOAD_TAGGING, null);
this.cloudResponsePayloadTagging =

if (null == cloudReqPayloadTaggingConf) {
// if no configuration is provided, disable payload tagging
this.cloudRequestPayloadTagging = null;
} else if (cloudReqPayloadTaggingConf.size() == 1
&& cloudReqPayloadTaggingConf.get(0).equalsIgnoreCase("all")) {
// if "all" is specified enable all JSON paths
this.cloudRequestPayloadTagging = Collections.emptyList();
} else {
// parse and validate JSON paths. if none are valid, disable payload tagging
List<JsonPath> validRequestJsonPaths = parseJsonPaths(cloudReqPayloadTaggingConf);
this.cloudRequestPayloadTagging =
validRequestJsonPaths.isEmpty() ? null : validRequestJsonPaths;
}

List<String> cloudRespPayloadTaggingConf =
configProvider.getList(TRACE_CLOUD_RESPONSE_PAYLOAD_TAGGING, null);
if (null == cloudRespPayloadTaggingConf) {
// if no configuration is provided, disable payload tagging
this.cloudResponsePayloadTagging = null;
} else if (cloudRespPayloadTaggingConf.size() == 1
&& cloudRespPayloadTaggingConf.get(0).equalsIgnoreCase("all")) {
// if "all" is specified enable all JSON paths
this.cloudResponsePayloadTagging = Collections.emptyList();
} else {
// parse and validate JSON paths. if none are valid, disable payload tagging
List<JsonPath> validResponseJsonPaths = parseJsonPaths(cloudRespPayloadTaggingConf);
this.cloudResponsePayloadTagging =
validResponseJsonPaths.isEmpty() ? null : validResponseJsonPaths;
}

this.cloudPayloadTaggingMaxDepth =
configProvider.getInteger(TRACE_CLOUD_PAYLOAD_TAGGING_MAX_DEPTH, 10);
this.cloudPayloadTaggingMaxTags =
Expand Down Expand Up @@ -5315,7 +5348,7 @@ public boolean isCloudPayloadTaggingEnabled() {
return isCloudRequestPayloadTaggingEnabled() || isCloudResponsePayloadTaggingEnabled();
}

public List<String> getCloudRequestPayloadTagging() {
public List<JsonPath> getCloudRequestPayloadTagging() {
return cloudRequestPayloadTagging == null
? Collections.emptyList()
: cloudRequestPayloadTagging;
Expand All @@ -5325,7 +5358,7 @@ public boolean isCloudRequestPayloadTaggingEnabled() {
return cloudRequestPayloadTagging != null;
}

public List<String> getCloudResponsePayloadTagging() {
public List<JsonPath> getCloudResponsePayloadTagging() {
return cloudResponsePayloadTagging == null
? Collections.emptyList()
: cloudResponsePayloadTagging;
Expand Down
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ include(
":utils:test-utils",
":utils:time-utils",
":utils:version-utils",
"utils:json-utils",
)

// smoke tests
Expand Down
17 changes: 17 additions & 0 deletions utils/json-utils/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
plugins {
`java-library`
}

apply(from = "$rootDir/gradle/java.gradle")

dependencies {
implementation(libs.slf4j)
implementation(libs.moshi)
implementation(libs.okio)

modules {
module("com.squareup.okio:okio") {
replacedBy("com.datadoghq.okio:okio") // embed our patched fork
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package datadog.trace.payloadtags.json;
package datadog.json;

import java.util.ArrayList;
import java.util.Collection;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package datadog.trace.payloadtags.json;
package datadog.json;

import static java.lang.Character.isDigit;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class JsonPathParser {

public static final class ParseError extends Exception {
Expand All @@ -26,6 +32,24 @@ public ParseError(CharSequence path, int position, String error) {
private static final char DOUBLE_QUOTE = '"';
private static final char ESC = '\\';

private static final Logger log = LoggerFactory.getLogger(JsonPathParser.class);

public static List<JsonPath> parseJsonPaths(List<String> rules) {
if (rules.isEmpty() || rules.size() == 1 && rules.get(0).equalsIgnoreCase("all")) {
return Collections.emptyList();
}
List<JsonPath> result = new ArrayList<>(rules.size());
for (String rule : rules) {
try {
JsonPath jp = JsonPathParser.parse(rule);
result.add(jp);
} catch (Exception ex) {
log.warn("Skipping failed to parse redaction rule '{}'. {}", rule, ex.getMessage());
}
}
return result;
}

public static JsonPath parse(String path) throws ParseError {
Cursor cur = new Cursor(path);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package datadog.trace.payloadtags.json;
package datadog.json;

import com.squareup.moshi.JsonReader;
import java.io.ByteArrayInputStream;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package datadog.trace.payloadtags.json;
package datadog.json;

import java.util.Arrays;

Expand Down
Loading