-
Notifications
You must be signed in to change notification settings - Fork 375
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tag AppSec on Rack top-level span #2858
Conversation
2c7d1e1
to
fcc90d2
Compare
277d339
to
9b73c08
Compare
lib/datadog/kit/appsec/events.rb
Outdated
if (appsec_scope = Datadog::AppSec.active_scope) | ||
trace = appsec_scope.trace | ||
span = appsec_scope.span | ||
end | ||
|
||
trace ||= Datadog::Tracing.active_trace | ||
span ||= trace.active_span || Datadog::Tracing.active_span | ||
|
||
if trace.trace_id != span.trace_id | ||
raise ArgumentError, "span #{span.span_id} does not belong to trace #{trace.trace_id}" | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably extract this to a separate helper method within appsec 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I went for the quick fix route here, as I find it awkward currently to hide that code behind the wrong abstraction.
Let's address this later and get the release done.
def active_scope(env) | ||
env['datadog.appsec.scope'] | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find this one line methods no very useful, since it requires the reader to check what the method is actually doing. In this case checking the env['datadog.appsec.scope']
is more readable in line 39 in my opinion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. Let's address this later and get the release done.
AppSec discovers service name based on top-level span. Tagging at trace level results in tags on the trace root span, which is usually Rack's top-level span. When request queuing is enabeld, though, a synthetic span is added in front, representing a service outside the application. This tag then gets mistakenly tagged with AppSec information, resulting in much confusion. The situation gets even trickier with partial flushing, as partially flushed spans may receive a trace tag. Ensuring we tag the proper span should solve both issues.
- Create a AppSec::Scope concept to capture toplevel references - Extract context management out of Processor to the more general Scope class - Propagate Scope instead of Context through Rack - Refactor Processor::Context users to find context through Scope instead
07898dc
to
3a16237
Compare
3a16237
to
114b7a0
Compare
trace ||= Datadog::Tracing.active_trace | ||
span ||= trace.active_span || Datadog::Tracing.active_span | ||
|
||
raise ArgumentError, "span #{span.span_id} does not belong to trace #{trace.id}" if trace.id != span.trace_id |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we raise or log an message letting the user that they have done something odd?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As with the active scope (prev. active context) sanity checks, this should not happen, ever. If we swallow it we'll never be aware.
Practically since we now use the AppSec scope as an override, it can only happen if a user forcefully passes both trace
and span
args outside an AppSec scope. In that case they made a mistake and will want to be aware immediately.
41edde7
to
3080fb7
Compare
…hanged to datadog.appsec.scope
d5a3357
to
3bdd5c6
Compare
Codecov Report
@@ Coverage Diff @@
## master #2858 +/- ##
==========================================
+ Coverage 98.09% 98.10% +0.01%
==========================================
Files 1269 1266 -3
Lines 69969 69990 +21
Branches 3161 3172 +11
==========================================
+ Hits 68633 68662 +29
+ Misses 1336 1328 -8 see 42 files with indirect coverage changes 📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
@@ -17,7 +17,7 @@ def initialize(app, opt = {}) | |||
end | |||
|
|||
def call(env) | |||
context = env['datadog.waf.context'] | |||
context = env['datadog.appsec.scope'] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @GustavoCaso !
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
What does this PR do?
Tag AppSec on Rack top-level span
Motivation
AppSec discovers service name based on top-level span. Tagging at trace level results in tags on the trace root span, which is usually Rack's top-level span.
When request queuing is enabeld, though, a synthetic span is added in front, representing a service outside the application. This tag then gets mistakenly tagged with AppSec information, resulting in much confusion.
The situation gets even trickier with partial flushing, as partially flushed spans may receive a trace tag.
Ensuring we tag the proper span should solve both issues.
Additional Notes
Starting this PR as draft since I am still figuring out how to handle
Datadog::Kit
tagging in a backward compatible manner.How to test the change?
Add
request_queuing: true
to Rack or Rails tracing integration, then: