Skip to content

Commit

Permalink
Merge pull request #4281 from DataDog/appsec-use-throw-for-rack-blocking
Browse files Browse the repository at this point in the history
Switch AppSec rack blocking to throw
  • Loading branch information
y9v authored Jan 14, 2025
2 parents 6dc5d1a + 629e7b5 commit 5235204
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 40 deletions.
6 changes: 3 additions & 3 deletions lib/datadog/appsec/contrib/rack/gateway/watcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def watch_request(gateway = Instrumentation.gateway)
end

block = Rack::Reactive::Request.publish(engine, gateway_request)
next [nil, [[:block, event]]] if block
throw(Datadog::AppSec::Ext::INTERRUPT, event[:actions]) if block

stack.call(gateway_request.request)
end
Expand Down Expand Up @@ -79,7 +79,7 @@ def watch_response(gateway = Instrumentation.gateway)
end

block = Rack::Reactive::Response.publish(engine, gateway_response)
next [nil, [[:block, event]]] if block
throw(Datadog::AppSec::Ext::INTERRUPT, event[:actions]) if block

stack.call(gateway_response.response)
end
Expand Down Expand Up @@ -110,7 +110,7 @@ def watch_request_body(gateway = Instrumentation.gateway)
end

block = Rack::Reactive::RequestBody.publish(engine, gateway_request)
next [nil, [[:block, event]]] if block
throw(Datadog::AppSec::Ext::INTERRUPT, event[:actions]) if block

stack.call(gateway_request.request)
end
Expand Down
19 changes: 9 additions & 10 deletions lib/datadog/appsec/contrib/rack/request_body_middleware.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,18 @@ def call(env)

# TODO: handle exceptions, except for @app.call

request_return, request_response = Instrumentation.gateway.push(
'rack.request.body',
Gateway::Request.new(env)
) do
@app.call(env)
end
http_response = nil
block_actions = catch(::Datadog::AppSec::Ext::INTERRUPT) do
http_response, = Instrumentation.gateway.push('rack.request.body', Gateway::Request.new(env)) do
@app.call(env)
end

if request_response
blocked_event = request_response.find { |action, _event| action == :block }
request_return = AppSec::Response.negotiate(env, blocked_event.last[:actions]).to_rack if blocked_event
nil
end

request_return
return AppSec::Response.negotiate(env, block_actions).to_rack if block_actions

http_response
end
end
end
Expand Down
43 changes: 17 additions & 26 deletions lib/datadog/appsec/contrib/rack/request_middleware.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def initialize(app, opt = {})
@rack_headers = {}
end

# rubocop:disable Metrics/AbcSize,Metrics/PerceivedComplexity,Metrics/CyclomaticComplexity,Metrics/MethodLength
# rubocop:disable Metrics/AbcSize,Metrics/MethodLength
def call(env)
return @app.call(env) unless Datadog::AppSec.enabled?

Expand Down Expand Up @@ -69,34 +69,30 @@ def call(env)

return @app.call(env) unless ready

gateway_request = Gateway::Request.new(env)

add_appsec_tags(processor, ctx)
add_request_tags(ctx, env)

request_return, request_response = catch(::Datadog::AppSec::Ext::INTERRUPT) do
Instrumentation.gateway.push('rack.request', gateway_request) do
http_response = nil
gateway_request = Gateway::Request.new(env)
gateway_response = nil

block_actions = catch(::Datadog::AppSec::Ext::INTERRUPT) do
http_response, = Instrumentation.gateway.push('rack.request', gateway_request) do
@app.call(env)
end
end

if request_response
blocked_event = request_response.find { |action, _options| action == :block }
request_return = AppSec::Response.negotiate(env, blocked_event.last[:actions]).to_rack if blocked_event
end
gateway_response = Gateway::Response.new(
http_response[2], http_response[0], http_response[1], context: ctx
)

gateway_response = Gateway::Response.new(
request_return[2],
request_return[0],
request_return[1],
context: ctx,
)
Instrumentation.gateway.push('rack.response', gateway_response)

_response_return, response_response = Instrumentation.gateway.push('rack.response', gateway_response)
nil
end

result = ctx.waf_runner.extract_schema
http_response = AppSec::Response.negotiate(env, block_actions).to_rack if block_actions

if result
if (result = ctx.waf_runner.extract_schema)
ctx.waf_runner.events << {
trace: ctx.trace,
span: ctx.span,
Expand All @@ -111,19 +107,14 @@ def call(env)

AppSec::Event.record(ctx.span, *ctx.waf_runner.events)

if response_response
blocked_event = response_response.find { |action, _options| action == :block }
request_return = AppSec::Response.negotiate(env, blocked_event.last[:actions]).to_rack if blocked_event
end

request_return
http_response
ensure
if ctx
add_waf_runtime_tags(ctx)
Datadog::AppSec::Context.deactivate
end
end
# rubocop:enable Metrics/AbcSize,Metrics/PerceivedComplexity,Metrics/CyclomaticComplexity,Metrics/MethodLength
# rubocop:enable Metrics/AbcSize,Metrics/MethodLength

private

Expand Down
2 changes: 1 addition & 1 deletion lib/datadog/appsec/monitor/gateway/watcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def watch_user_id(gateway = Instrumentation.gateway)
end

block = Monitor::Reactive::SetUser.publish(engine, user)
throw(Datadog::AppSec::Ext::INTERRUPT, [nil, [[:block, event]]]) if block
throw(Datadog::AppSec::Ext::INTERRUPT, event[:actions]) if block

stack.call(user)
end
Expand Down

0 comments on commit 5235204

Please sign in to comment.