Skip to content

Commit

Permalink
Implement Propagation
Browse files Browse the repository at this point in the history
  • Loading branch information
e-n-0 committed Jul 4, 2024
1 parent 7ce9837 commit d6a3d2f
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 18 deletions.
1 change: 1 addition & 0 deletions tracer/src/Datadog.Trace/AppSec/Security.cs
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,7 @@ internal void SetTraceSamplingPriority(Span span)
else if (_rateLimiter?.Allowed(span) ?? false)
{
span.Context.TraceContext?.SetSamplingPriority(SamplingPriorityValues.UserKeep, SamplingMechanism.Asm);
span.Context.TraceContext?.Tags.SetTag(Tags.PropagatedAppSec, "1");
}
}

Expand Down
2 changes: 2 additions & 0 deletions tracer/src/Datadog.Trace/Iast/IastModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,7 @@ private static IastModuleResponse GetScope(string evidenceValue, IntegrationId i
if (traceContext?.RootSpan is { } rootSpan)
{
rootSpan.Context.TraceContext?.SetSamplingPriority(SamplingPriorityValues.UserKeep, SamplingMechanism.Asm);
rootSpan.Context.TraceContext?.Tags.SetTag(Tags.PropagatedAppSec, "1");
}

traceContext?.IastRequestContext?.AddVulnerability(vulnerability);
Expand Down Expand Up @@ -699,6 +700,7 @@ private static IastModuleResponse AddVulnerabilityAsSingleSpan(Tracer tracer, In
scope.Span.Type = SpanTypes.IastVulnerability;
tracer.TracerManager.Telemetry.IntegrationGeneratedSpan(integrationId);
scope.Span.Context.TraceContext?.SetSamplingPriority(SamplingPriorityValues.UserKeep, SamplingMechanism.Asm);
scope.Span.Context.TraceContext?.Tags.SetTag(Tags.PropagatedAppSec, "1");
return new IastModuleResponse(scope);
}

Expand Down
18 changes: 16 additions & 2 deletions tracer/src/Datadog.Trace/Propagators/DatadogContextPropagator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ private DatadogContextPropagator()
public void Inject<TCarrier, TCarrierSetter>(SpanContext context, TCarrier carrier, TCarrierSetter carrierSetter)
where TCarrierSetter : struct, ICarrierSetter<TCarrier>
{
// Case 1 (1): If appsec standalone is enabled and appsec propagation is disabled (no ASM events) -> stop propagation
if (Tracer.Instance.Settings.AppsecStandaloneEnabledInternal && context.TraceContext.Tags.GetTag(Tags.PropagatedAppSec) != "1")
{
return;
}

TelemetryFactory.Metrics.RecordCountContextHeaderStyleInjected(MetricTags.ContextHeaderStyle.Datadog);
var invariantCulture = CultureInfo.InvariantCulture;

Expand All @@ -43,7 +49,6 @@ private DatadogContextPropagator()
}

var propagatedTagsHeader = context.PrepareTagsHeaderForPropagation();

if (!string.IsNullOrEmpty(propagatedTagsHeader))
{
carrierSetter.Set(carrier, HttpHeaderNames.PropagatedTags, propagatedTagsHeader!);
Expand All @@ -67,9 +72,18 @@ private DatadogContextPropagator()
var samplingPriority = ParseUtility.ParseInt32(carrier, carrierGetter, HttpHeaderNames.SamplingPriority);
var origin = ParseUtility.ParseString(carrier, carrierGetter, HttpHeaderNames.Origin);
var propagatedTraceTags = ParseUtility.ParseString(carrier, carrierGetter, HttpHeaderNames.PropagatedTags);

var traceTags = TagPropagation.ParseHeader(propagatedTraceTags);

// Case 1 (2):
// When in appsec standalone mode, only distributed traces with the `_dd.p.appsec` tag
// are propagated downstream, however we need 1 trace per minute sent to the backend, so
// we unset sampling priority so the rate limiter decides.
if (Tracer.Instance.Settings.AppsecStandaloneEnabledInternal)
{
// If the trace has appsec propagation tag, the default priority is user keep
samplingPriority = traceTags.GetTag(Tags.PropagatedAppSec) == "1" ? SamplingPriorityValues.UserKeep : SamplingPriorityValues.Default;
}

// reconstruct 128-bit trace id from the lower 64 bits in "x-datadog-traceid"
// and the upper 64 bits in "_dd.p.tid"
var traceId = GetFullTraceId((ulong)traceIdLower, traceTags);
Expand Down
6 changes: 6 additions & 0 deletions tracer/src/Datadog.Trace/Tags.cs
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,12 @@ public static partial class Tags
/// </summary>
internal const string AppSecWafInitRuleErrors = "_dd.appsec.event_rules.errors";

/// <summary>
/// A boolean allowing the propagation to downstream services the information that the current distributed trace
/// is containing at least one ASM security event, no matter its type (threats, business logic events, IAST, etc.).
/// </summary>
internal const string PropagatedAppSec = "_dd.p.appsec";

/// <summary>
/// Should contain the public IP of the host initiating the request.
/// </summary>
Expand Down
27 changes: 23 additions & 4 deletions tracer/src/Datadog.Trace/Tracer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -419,13 +419,32 @@ internal SpanContext CreateSpanContext(ISpanContext parent = null, string servic

if (traceContext == null)
{
// If parent is SpanContext but its TraceContext is null, then it was extracted from
// propagation headers. Create a new TraceContext (this will start a new trace) and initialize
// If parent is SpanContext but its TraceContext is null, then it was extracted from propagation headers.

var propagatedTags = parentSpanContext.PropagatedTags;
var samplingPriority = parentSpanContext.SamplingPriority;
/*if (Settings?.AppsecStandaloneEnabledInternal == true)
{
// When in appsec standalone mode, only distributed traces with the `_dd.p.appsec` tag
// are propagated downstream, however we need 1 trace per minute sent to the backend, so
// we unset sampling priority so the rate limiter decides.
if (propagatedTags?.GetTag(Tags.PropagatedAppSec) != null)
{
// If the trace has appsec propagation tag, the default priority is user keep
samplingPriority = SamplingPriorityValues.UserKeep;
}
else
{
samplingPriority = SamplingPriorityValues.Default;
}
}*/

// Create a new TraceContext (this will start a new trace) and initialize
// it with the propagated values (sampling priority, origin, tags, W3C trace state, etc).
traceContext = new TraceContext(this, parentSpanContext.PropagatedTags);
traceContext = new TraceContext(this, propagatedTags);
TelemetryFactory.Metrics.RecordCountTraceSegmentCreated(MetricTags.TraceContinuation.Continued);

var samplingPriority = parentSpanContext.SamplingPriority ?? DistributedTracer.Instance.GetSamplingPriority();
samplingPriority ??= DistributedTracer.Instance.GetSamplingPriority();
traceContext.SetSamplingPriority(samplingPriority);
traceContext.Origin = parentSpanContext.Origin;
traceContext.AdditionalW3CTraceState = parentSpanContext.AdditionalW3CTraceState;
Expand Down
12 changes: 0 additions & 12 deletions tracer/src/Datadog.Trace/TracerManagerFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -272,18 +272,6 @@ protected virtual ITraceSampler GetSampler(ImmutableTracerSettings settings)

var sampler = new TraceSampler(new TracerRateLimiter(maxTracesPerInterval: settings.MaxTracesSubmittedPerSecondInternal, intervalMilliseconds: null));

// remote sampling rules
var remoteSamplingRulesJson = settings.RemoteSamplingRules;

if (!string.IsNullOrWhiteSpace(remoteSamplingRulesJson))
{
var samplerStandalone = new TraceSampler(new TracerRateLimiter(1, 60_000));
samplerStandalone.RegisterRule(new GlobalSamplingRateRule(1.0f));
return samplerStandalone;
}

var sampler = new TraceSampler(new TracerRateLimiter(settings.MaxTracesSubmittedPerSecondInternal, null));

// sampling rules (remote value overrides local value)
var samplingRulesJson = settings.CustomSamplingRulesInternal;

Expand Down

0 comments on commit d6a3d2f

Please sign in to comment.