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
Expand Up @@ -5,6 +5,7 @@
import static datadog.remoteconfig.Capabilities.CAPABILITY_ASM_AUTO_USER_INSTRUM_MODE;
import static datadog.remoteconfig.Capabilities.CAPABILITY_ASM_CUSTOM_BLOCKING_RESPONSE;
import static datadog.remoteconfig.Capabilities.CAPABILITY_ASM_CUSTOM_RULES;
import static datadog.remoteconfig.Capabilities.CAPABILITY_ASM_DD_MULTICONFIG;
import static datadog.remoteconfig.Capabilities.CAPABILITY_ASM_DD_RULES;
import static datadog.remoteconfig.Capabilities.CAPABILITY_ASM_EXCLUSIONS;
import static datadog.remoteconfig.Capabilities.CAPABILITY_ASM_EXCLUSION_DATA;
Expand All @@ -18,6 +19,7 @@
import static datadog.remoteconfig.Capabilities.CAPABILITY_ASM_RASP_SSRF;
import static datadog.remoteconfig.Capabilities.CAPABILITY_ASM_REQUEST_BLOCKING;
import static datadog.remoteconfig.Capabilities.CAPABILITY_ASM_SESSION_FINGERPRINT;
import static datadog.remoteconfig.Capabilities.CAPABILITY_ASM_TRACE_TAGGING_RULES;
import static datadog.remoteconfig.Capabilities.CAPABILITY_ASM_TRUSTED_IPS;
import static datadog.remoteconfig.Capabilities.CAPABILITY_ASM_USER_BLOCKING;
import static datadog.remoteconfig.Capabilities.CAPABILITY_ENDPOINT_FINGERPRINT;
Expand Down Expand Up @@ -113,6 +115,8 @@ public AppSecConfigServiceImpl(
if (tracerConfig.isAppSecWafMetrics()) {
traceSegmentPostProcessors.add(statsReporter);
}
// Add trace tagging post processor for handling trace attributes
traceSegmentPostProcessors.add(new com.datadog.appsec.ddwaf.TraceTaggingPostProcessor());
}

private void subscribeConfigurationPoller() {
Expand Down Expand Up @@ -140,7 +144,9 @@ private void subscribeConfigurationPoller() {
| CAPABILITY_ENDPOINT_FINGERPRINT
| CAPABILITY_ASM_SESSION_FINGERPRINT
| CAPABILITY_ASM_NETWORK_FINGERPRINT
| CAPABILITY_ASM_HEADER_FINGERPRINT;
| CAPABILITY_ASM_HEADER_FINGERPRINT
| CAPABILITY_ASM_DD_MULTICONFIG
| CAPABILITY_ASM_TRACE_TAGGING_RULES;
if (tracerConfig.isAppSecRaspEnabled()) {
capabilities |= CAPABILITY_ASM_RASP_SQLI;
capabilities |= CAPABILITY_ASM_RASP_SSRF;
Expand Down Expand Up @@ -490,7 +496,9 @@ public void close() {
| CAPABILITY_ENDPOINT_FINGERPRINT
| CAPABILITY_ASM_SESSION_FINGERPRINT
| CAPABILITY_ASM_NETWORK_FINGERPRINT
| CAPABILITY_ASM_HEADER_FINGERPRINT);
| CAPABILITY_ASM_HEADER_FINGERPRINT
| CAPABILITY_ASM_DD_MULTICONFIG
| CAPABILITY_ASM_TRACE_TAGGING_RULES);
this.configurationPoller.removeListeners(Product.ASM_DD);
this.configurationPoller.removeListeners(Product.ASM_DATA);
this.configurationPoller.removeListeners(Product.ASM);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.datadog.appsec.ddwaf;

import com.datadog.appsec.config.TraceSegmentPostProcessor;
import com.datadog.appsec.gateway.AppSecRequestContext;
import com.datadog.appsec.report.AppSecEvent;
import datadog.trace.api.internal.TraceSegment;
import java.util.Collection;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Post processor that serializes trace attributes from the AppSec request context to the trace
* segment during trace post-processing.
*
* <p>This processor handles the new trace tagging feature where WAF rules can specify attributes to
* be added to the trace segment.
*/
public class TraceTaggingPostProcessor implements TraceSegmentPostProcessor {
private static final Logger log = LoggerFactory.getLogger(TraceTaggingPostProcessor.class);

@Override
public void processTraceSegment(
TraceSegment segment, AppSecRequestContext ctx, Collection<AppSecEvent> collectedEvents) {

Map<String, Object> traceAttributes = ctx.getTraceAttributes();
if (traceAttributes == null || traceAttributes.isEmpty()) {
return;
}

log.debug("Serializing {} trace attributes to trace segment", traceAttributes.size());

// Serialize each attribute to the trace segment
for (Map.Entry<String, Object> entry : traceAttributes.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();

if (key != null && !key.isEmpty() && value != null) {
try {
// Use setTagTop to add the attribute to the trace segment
segment.setTagTop(key, value);
log.debug("Added trace attribute: {} = {}", key, value);
} catch (Exception e) {
log.warn("Failed to serialize trace attribute {} = {}", key, value, e);
}
} else {
log.debug("Skipping invalid trace attribute: key='{}', value='{}'", key, value);
}
}
}
}
Loading