Skip to content

Commit 934fc35

Browse files
committed
Refactor http libraries contribs to look the same
1 parent 3be3958 commit 934fc35

File tree

6 files changed

+60
-37
lines changed

6 files changed

+60
-37
lines changed

lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ module Contrib
1414
module Excon
1515
# AppSec Middleware for Excon
1616
class SSRFDetectionMiddleware < ::Excon::Middleware::Base
17-
ANALYZE_BODY_KEY = :__datadog_appsec_analyze_body
17+
SAMPLE_BODY_KEY = :__datadog_appsec_sample_downstream_body
1818

1919
def request_call(data)
2020
context = AppSec.active_context
2121
return super unless context && AppSec.rasp_enabled?
2222

23-
data[ANALYZE_BODY_KEY] = analyze_body?(context)
23+
mark_body_sampling!(data, context: context)
2424

2525
headers = normalize_headers(data[:headers])
2626
ephemeral_data = {
@@ -29,9 +29,8 @@ def request_call(data)
2929
'server.io.net.request.headers' => headers
3030
}
3131

32-
if data[ANALYZE_BODY_KEY] && (media_type = Utils::HTTP::MediaType.parse(headers['content-type']))
33-
body = Utils::HTTP::Body.parse(data[:body], media_type: media_type)
34-
ephemeral_data['server.io.net.request.body'] = body if body
32+
if data[SAMPLE_BODY_KEY] && (body = parse_body(data[:body], content_type: headers['content-type']))
33+
ephemeral_data['server.io.net.request.body'] = body
3534
end
3635

3736
timeout = Datadog.configuration.appsec.waf_timeout
@@ -51,9 +50,8 @@ def response_call(data)
5150
'server.io.net.response.headers' => headers
5251
}
5352

54-
if data[ANALYZE_BODY_KEY] && (media_type = Utils::HTTP::MediaType.parse(headers['content-type']))
55-
body = Utils::HTTP::Body.parse(data.dig(:response, :body), media_type: media_type)
56-
ephemeral_data['server.io.net.response.body'] = body if body
53+
if data[SAMPLE_BODY_KEY] && (body = parse_body(data.dig(:response, :body), content_type: headers['content-type']))
54+
ephemeral_data['server.io.net.response.body'] = body
5755
end
5856

5957
timeout = Datadog.configuration.appsec.waf_timeout
@@ -65,13 +63,20 @@ def response_call(data)
6563

6664
private
6765

68-
def analyze_body?(context)
66+
def mark_body_sampling!(data, context:)
6967
max = Datadog.configuration.appsec.api_security.downstream_body_analysis.max_requests
70-
return false if context.state[:downstream_body_analyzed_count] >= max
71-
return false unless context.downstream_body_sampler.sample?
68+
return if context.state[:downstream_body_analyzed_count] >= max
69+
return unless context.downstream_body_sampler.sample?
7270

7371
context.state[:downstream_body_analyzed_count] += 1
74-
true
72+
data[SAMPLE_BODY_KEY] = true
73+
end
74+
75+
def parse_body(body, content_type:)
76+
media_type = Utils::HTTP::MediaType.parse(content_type)
77+
return unless media_type
78+
79+
Utils::HTTP::Body.parse(body, media_type: media_type)
7580
end
7681

7782
def request_url(data)

lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ module Contrib
1212
module Faraday
1313
# AppSec SSRF detection Middleware for Faraday
1414
class SSRFDetectionMiddleware < ::Faraday::Middleware
15-
ANALYZE_BODY_KEY = :__datadog_appsec_analyze_body
15+
SAMPLE_BODY_KEY = :__datadog_appsec_sample_downstream_body
1616

1717
def call(env)
1818
context = AppSec.active_context
1919
return @app.call(env) unless context && AppSec.rasp_enabled?
2020

21-
env[ANALYZE_BODY_KEY] = analyze_body?(context)
21+
mark_body_sampling!(env, context: context)
2222

2323
headers = normalize_headers(env.request_headers)
2424
ephemeral_data = {
@@ -27,9 +27,8 @@ def call(env)
2727
'server.io.net.request.headers' => headers
2828
}
2929

30-
if env[ANALYZE_BODY_KEY] && (media_type = Utils::HTTP::MediaType.parse(headers['content-type']))
31-
body = Utils::HTTP::Body.parse(env.body, media_type: media_type)
32-
ephemeral_data['server.io.net.request.body'] = body if body
30+
if env[SAMPLE_BODY_KEY] && (body = parse_body(env.body, content_type: headers['content-type']))
31+
ephemeral_data['server.io.net.request.body'] = body
3332
end
3433

3534
timeout = Datadog.configuration.appsec.waf_timeout
@@ -48,23 +47,29 @@ def on_complete(env, context:)
4847
'server.io.net.response.headers' => headers
4948
}
5049

51-
if env[ANALYZE_BODY_KEY] && (media_type = Utils::HTTP::MediaType.parse(headers['content-type']))
52-
body = Utils::HTTP::Body.parse(env.body, media_type: media_type)
53-
ephemeral_data['server.io.net.response.body'] = body if body
50+
if env[SAMPLE_BODY_KEY] && (body = parse_body(env.body, content_type: headers['content-type']))
51+
ephemeral_data['server.io.net.response.body'] = body
5452
end
5553

5654
timeout = Datadog.configuration.appsec.waf_timeout
5755
result = context.run_rasp(Ext::RASP_SSRF, {}, ephemeral_data, timeout, phase: Ext::RASP_RESPONSE_PHASE)
5856
handle(result, context: context) if result.match?
5957
end
6058

61-
def analyze_body?(context)
59+
def mark_body_sampling!(env, context:)
6260
max = Datadog.configuration.appsec.api_security.downstream_body_analysis.max_requests
63-
return false if context.state[:downstream_body_analyzed_count] >= max
64-
return false unless context.downstream_body_sampler.sample?
61+
return if context.state[:downstream_body_analyzed_count] >= max
62+
return unless context.downstream_body_sampler.sample?
6563

6664
context.state[:downstream_body_analyzed_count] += 1
67-
true
65+
env[SAMPLE_BODY_KEY] = true
66+
end
67+
68+
def parse_body(body, content_type:)
69+
media_type = Utils::HTTP::MediaType.parse(content_type)
70+
return unless media_type
71+
72+
Utils::HTTP::Body.parse(body, media_type: media_type)
6873
end
6974

7075
def normalize_headers(headers)

lib/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rb

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,9 @@ def execute(&block)
2323
'server.io.net.request.headers' => headers
2424
}
2525

26-
analyze_body = analyze_body?(context)
27-
if analyze_body && payload && (media_type = Utils::HTTP::MediaType.parse(headers['content-type']))
28-
body = Utils::HTTP::Body.parse(payload.to_s, media_type: media_type)
29-
ephemeral_data['server.io.net.request.body'] = body if body
26+
sample_body = mark_body_sampling!(context)
27+
if sample_body && (body = parse_body(payload.to_s, content_type: headers['content-type']))
28+
ephemeral_data['server.io.net.request.body'] = body
3029
end
3130

3231
timeout = Datadog.configuration.appsec.waf_timeout
@@ -41,9 +40,8 @@ def execute(&block)
4140
'server.io.net.response.headers' => headers
4241
}
4342

44-
if analyze_body && (media_type = Utils::HTTP::MediaType.parse(headers['content-type']))
45-
body = Utils::HTTP::Body.parse(response.body, media_type: media_type)
46-
ephemeral_data['server.io.net.response.body'] = body if body
43+
if sample_body && (body = parse_body(response.body, content_type: headers['content-type']))
44+
ephemeral_data['server.io.net.response.body'] = body
4745
end
4846

4947
result = context.run_rasp(Ext::RASP_SSRF, {}, ephemeral_data, timeout, phase: Ext::RASP_RESPONSE_PHASE)
@@ -54,7 +52,7 @@ def execute(&block)
5452

5553
private
5654

57-
def analyze_body?(context)
55+
def mark_body_sampling!(context)
5856
max = Datadog.configuration.appsec.api_security.downstream_body_analysis.max_requests
5957
return false if context.state[:downstream_body_analyzed_count] >= max
6058
return false unless context.downstream_body_sampler.sample?
@@ -63,6 +61,15 @@ def analyze_body?(context)
6361
true
6462
end
6563

64+
def parse_body(body, content_type:)
65+
return if body.empty?
66+
67+
media_type = Utils::HTTP::MediaType.parse(content_type)
68+
return unless media_type
69+
70+
Utils::HTTP::Body.parse(body, media_type: media_type)
71+
end
72+
6673
# NOTE: Starting version 2.1.0 headers are already normalized via internal
6774
# variable `@processed_headers_lowercase`. In case it's available,
6875
# we use it to avoid unnecessary transformation.

sig/datadog/appsec/contrib/excon/ssrf_detection_middleware.rbs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,17 @@ module Datadog
33
module Contrib
44
module Excon
55
class SSRFDetectionMiddleware
6-
ANALYZE_BODY_KEY: ::Symbol
6+
SAMPLE_BODY_KEY: ::Symbol
77

88
def request_call: (::Excon::Middleware::Base::datum data) -> Excon::Middleware::Base::datum
99

1010
def response_call: (::Excon::Middleware::Base::datum data) -> ::Excon::Middleware::Base::datum
1111

1212
private
1313

14-
def analyze_body?: (Context context) -> bool
14+
def mark_body_sampling!: (::Excon::Middleware::Base::datum data, context: Context) -> void
15+
16+
def parse_body: (Utils::HTTP::Body::body body, content_type: ::String?) -> untyped
1517

1618
def request_url: (::Excon::Middleware::Base::datum data) -> ::String
1719

sig/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rbs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,17 @@ module Datadog
33
module Contrib
44
module Faraday
55
class SSRFDetectionMiddleware < ::Faraday::Middleware
6-
ANALYZE_BODY_KEY: ::Symbol
6+
SAMPLE_BODY_KEY: ::Symbol
77

88
def call: (::Faraday::Env env) -> untyped
99

1010
private
1111

1212
def on_complete: (::Faraday::Env env, context: Context) -> void
1313

14-
def analyze_body?: (Context context) -> bool
14+
def mark_body_sampling!: (::Faraday::Env env, context: Context) -> void
15+
16+
def parse_body: (Utils::HTTP::Body::body body, content_type: ::String?) -> untyped
1517

1618
def normalize_headers: (::Faraday::Utils::Headers? headers) -> ::Hash[::String, ::String]
1719

sig/datadog/appsec/contrib/rest_client/request_ssrf_detection_patch.rbs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ module Datadog
99

1010
private
1111

12-
def analyze_body?: (Context context) -> bool
12+
def mark_body_sampling!: (Context context) -> bool
13+
14+
def parse_body: (::String body, content_type: ::String?) -> untyped
1315

1416
def normalize_request_headers: () -> headers
1517

0 commit comments

Comments
 (0)