datadog 2.9.0 → 2.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +72 -1
  3. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +2 -2
  4. data/ext/datadog_profiling_native_extension/collectors_stack.c +3 -3
  5. data/ext/datadog_profiling_native_extension/collectors_stack.h +2 -2
  6. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +46 -6
  7. data/ext/datadog_profiling_native_extension/extconf.rb +4 -0
  8. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.c +2 -0
  9. data/ext/datadog_profiling_native_extension/gvl_profiling_helper.h +0 -8
  10. data/ext/datadog_profiling_native_extension/heap_recorder.c +51 -93
  11. data/ext/datadog_profiling_native_extension/heap_recorder.h +1 -1
  12. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +56 -0
  13. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +7 -0
  14. data/ext/datadog_profiling_native_extension/profiling.c +7 -0
  15. data/ext/datadog_profiling_native_extension/stack_recorder.c +9 -22
  16. data/ext/datadog_profiling_native_extension/stack_recorder.h +1 -1
  17. data/ext/libdatadog_api/crashtracker.c +4 -4
  18. data/ext/libdatadog_extconf_helpers.rb +1 -1
  19. data/lib/datadog/appsec/actions_handler.rb +27 -0
  20. data/lib/datadog/appsec/component.rb +14 -8
  21. data/lib/datadog/appsec/configuration/settings.rb +73 -11
  22. data/lib/datadog/appsec/context.rb +28 -8
  23. data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +6 -2
  24. data/lib/datadog/appsec/contrib/active_record/patcher.rb +0 -3
  25. data/lib/datadog/appsec/contrib/devise/configuration.rb +76 -0
  26. data/lib/datadog/appsec/contrib/devise/event.rb +4 -7
  27. data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +16 -21
  28. data/lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb +8 -15
  29. data/lib/datadog/appsec/contrib/devise/patcher/rememberable_patch.rb +1 -1
  30. data/lib/datadog/appsec/contrib/devise/patcher.rb +0 -3
  31. data/lib/datadog/appsec/contrib/devise/tracking.rb +1 -1
  32. data/lib/datadog/appsec/contrib/excon/integration.rb +41 -0
  33. data/lib/datadog/appsec/contrib/excon/patcher.rb +28 -0
  34. data/lib/datadog/appsec/contrib/excon/ssrf_detection_middleware.rb +43 -0
  35. data/lib/datadog/appsec/contrib/faraday/connection_patch.rb +22 -0
  36. data/lib/datadog/appsec/contrib/faraday/integration.rb +42 -0
  37. data/lib/datadog/appsec/contrib/faraday/patcher.rb +53 -0
  38. data/lib/datadog/appsec/contrib/faraday/rack_builder_patch.rb +22 -0
  39. data/lib/datadog/appsec/contrib/faraday/ssrf_detection_middleware.rb +42 -0
  40. data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +1 -7
  41. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +11 -14
  42. data/lib/datadog/appsec/contrib/graphql/patcher.rb +0 -3
  43. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +65 -70
  44. data/lib/datadog/appsec/contrib/rack/patcher.rb +0 -3
  45. data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +3 -3
  46. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +11 -22
  47. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +20 -24
  48. data/lib/datadog/appsec/contrib/rails/patcher.rb +3 -16
  49. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +38 -47
  50. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +3 -29
  51. data/lib/datadog/appsec/ext.rb +6 -1
  52. data/lib/datadog/appsec/metrics/collector.rb +38 -0
  53. data/lib/datadog/appsec/metrics/exporter.rb +35 -0
  54. data/lib/datadog/appsec/metrics/telemetry.rb +23 -0
  55. data/lib/datadog/appsec/metrics.rb +13 -0
  56. data/lib/datadog/appsec/monitor/gateway/watcher.rb +19 -24
  57. data/lib/datadog/appsec/processor.rb +4 -3
  58. data/lib/datadog/appsec/remote.rb +4 -0
  59. data/lib/datadog/appsec/response.rb +18 -80
  60. data/lib/datadog/appsec/security_engine/result.rb +67 -0
  61. data/lib/datadog/appsec/security_engine/runner.rb +88 -0
  62. data/lib/datadog/appsec/security_engine.rb +9 -0
  63. data/lib/datadog/appsec.rb +16 -5
  64. data/lib/datadog/core/configuration/components.rb +7 -1
  65. data/lib/datadog/core/configuration/ext.rb +1 -1
  66. data/lib/datadog/core/configuration/option_definition.rb +2 -0
  67. data/lib/datadog/core/configuration/settings.rb +22 -6
  68. data/lib/datadog/core/encoding.rb +16 -0
  69. data/lib/datadog/core/environment/agent_info.rb +77 -0
  70. data/lib/datadog/core/remote/transport/http/api.rb +13 -18
  71. data/lib/datadog/core/remote/transport/http/config.rb +0 -18
  72. data/lib/datadog/core/remote/transport/http/negotiation.rb +1 -18
  73. data/lib/datadog/core/remote/transport/http.rb +7 -12
  74. data/lib/datadog/core/remote/transport/negotiation.rb +13 -1
  75. data/lib/datadog/core/telemetry/event.rb +5 -0
  76. data/lib/datadog/core/transport/http/adapters/unix_socket.rb +1 -1
  77. data/lib/datadog/{tracing → core}/transport/http/api/instance.rb +1 -1
  78. data/lib/datadog/{tracing → core}/transport/http/api/spec.rb +1 -1
  79. data/lib/datadog/{tracing → core}/transport/http/builder.rb +37 -17
  80. data/lib/datadog/core/transport/response.rb +4 -0
  81. data/lib/datadog/di/code_tracker.rb +15 -8
  82. data/lib/datadog/di/component.rb +3 -0
  83. data/lib/datadog/di/configuration/settings.rb +14 -0
  84. data/lib/datadog/di/contrib.rb +2 -0
  85. data/lib/datadog/di/logger.rb +30 -0
  86. data/lib/datadog/di/probe.rb +3 -6
  87. data/lib/datadog/di/probe_manager.rb +5 -2
  88. data/lib/datadog/di/probe_notification_builder.rb +6 -0
  89. data/lib/datadog/di/probe_notifier_worker.rb +15 -4
  90. data/lib/datadog/di/redactor.rb +0 -1
  91. data/lib/datadog/di/remote.rb +29 -8
  92. data/lib/datadog/di/utils.rb +91 -0
  93. data/lib/datadog/di.rb +3 -0
  94. data/lib/datadog/profiling/component.rb +2 -8
  95. data/lib/datadog/profiling/load_native_extension.rb +1 -33
  96. data/lib/datadog/tracing/configuration/ext.rb +1 -0
  97. data/lib/datadog/tracing/contrib/aws/integration.rb +1 -1
  98. data/lib/datadog/tracing/contrib/extensions.rb +29 -3
  99. data/lib/datadog/tracing/contrib/graphql/configuration/error_extension_env_parser.rb +21 -0
  100. data/lib/datadog/tracing/contrib/graphql/configuration/settings.rb +11 -0
  101. data/lib/datadog/tracing/contrib/graphql/ext.rb +5 -0
  102. data/lib/datadog/tracing/contrib/graphql/unified_trace.rb +102 -11
  103. data/lib/datadog/tracing/contrib/http/integration.rb +3 -0
  104. data/lib/datadog/tracing/contrib/rack/header_collection.rb +11 -1
  105. data/lib/datadog/tracing/contrib/rack/middlewares.rb +1 -1
  106. data/lib/datadog/tracing/contrib/span_attribute_schema.rb +6 -1
  107. data/lib/datadog/tracing/transport/http/api.rb +11 -2
  108. data/lib/datadog/tracing/transport/http/traces.rb +0 -3
  109. data/lib/datadog/tracing/transport/http.rb +12 -7
  110. data/lib/datadog/tracing/transport/serializable_trace.rb +8 -4
  111. data/lib/datadog/tracing/transport/traces.rb +25 -8
  112. data/lib/datadog/version.rb +1 -1
  113. metadata +51 -42
  114. data/ext/datadog_profiling_loader/datadog_profiling_loader.c +0 -142
  115. data/ext/datadog_profiling_loader/extconf.rb +0 -60
  116. data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +0 -46
  117. data/lib/datadog/appsec/contrib/patcher.rb +0 -12
  118. data/lib/datadog/appsec/contrib/rack/reactive/request.rb +0 -69
  119. data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +0 -47
  120. data/lib/datadog/appsec/contrib/rack/reactive/response.rb +0 -53
  121. data/lib/datadog/appsec/contrib/rails/reactive/action.rb +0 -53
  122. data/lib/datadog/appsec/contrib/sinatra/ext.rb +0 -14
  123. data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +0 -48
  124. data/lib/datadog/appsec/monitor/reactive/set_user.rb +0 -45
  125. data/lib/datadog/appsec/processor/context.rb +0 -107
  126. data/lib/datadog/appsec/reactive/address_hash.rb +0 -22
  127. data/lib/datadog/appsec/reactive/engine.rb +0 -47
  128. data/lib/datadog/appsec/reactive/subscriber.rb +0 -19
  129. data/lib/datadog/core/remote/transport/http/api/instance.rb +0 -39
  130. data/lib/datadog/core/remote/transport/http/api/spec.rb +0 -21
  131. data/lib/datadog/core/remote/transport/http/builder.rb +0 -219
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative '../configuration'
3
4
  require_relative '../tracking'
4
5
  require_relative '../resource'
5
6
  require_relative '../event'
@@ -14,33 +15,27 @@ module Datadog
14
15
  # rubocop:disable Metrics/MethodLength
15
16
  def validate(resource, &block)
16
17
  result = super
17
- return result unless AppSec.enabled?
18
- return result if @_datadog_skip_track_login_event
19
-
20
- track_user_events_configuration = Datadog.configuration.appsec.track_user_events
21
-
22
- return result unless track_user_events_configuration.enabled
23
-
24
- automated_track_user_events_mode = track_user_events_configuration.mode
25
18
 
26
- appsec_context = Datadog::AppSec.active_context
27
-
28
- return result unless appsec_context
19
+ return result unless AppSec.enabled?
20
+ return result if @_datadog_appsec_skip_track_login_event
21
+ return result unless Configuration.auto_user_instrumentation_enabled?
22
+ return result unless AppSec.active_context
29
23
 
30
24
  devise_resource = resource ? Resource.new(resource) : nil
31
-
32
- event_information = Event.new(devise_resource, automated_track_user_events_mode)
25
+ event_information = Event.new(devise_resource, Configuration.auto_user_instrumentation_mode)
33
26
 
34
27
  if result
35
28
  if event_information.user_id
36
- Datadog.logger.debug { 'User Login Event success' }
29
+ Datadog.logger.debug { 'AppSec: User successful login event' }
37
30
  else
38
- Datadog.logger.debug { 'User Login Event success, but can\'t extract user ID. Tracking empty event' }
31
+ Datadog.logger.debug do
32
+ "AppSec: User successful login event, but can't extract user ID. Tracking empty event"
33
+ end
39
34
  end
40
35
 
41
36
  Tracking.track_login_success(
42
- appsec_context.trace,
43
- appsec_context.span,
37
+ AppSec.active_context.trace,
38
+ AppSec.active_context.span,
44
39
  user_id: event_information.user_id,
45
40
  **event_information.to_h
46
41
  )
@@ -52,15 +47,15 @@ module Datadog
52
47
 
53
48
  if resource
54
49
  user_exists = true
55
- Datadog.logger.debug { 'User Login Event failure users exists' }
50
+ Datadog.logger.debug { 'AppSec: User failed login event, but user exists' }
56
51
  else
57
52
  user_exists = false
58
- Datadog.logger.debug { 'User Login Event failure user do not exists' }
53
+ Datadog.logger.debug { 'AppSec: User failed login event and user does not exist' }
59
54
  end
60
55
 
61
56
  Tracking.track_login_failure(
62
- appsec_context.trace,
63
- appsec_context.span,
57
+ AppSec.active_context.trace,
58
+ AppSec.active_context.span,
64
59
  user_id: event_information.user_id,
65
60
  user_exists: user_exists,
66
61
  **event_information.to_h
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative '../configuration'
3
4
  require_relative '../tracking'
4
5
  require_relative '../resource'
5
6
  require_relative '../event'
@@ -13,31 +14,23 @@ module Datadog
13
14
  module RegistrationControllerPatch
14
15
  def create
15
16
  return super unless AppSec.enabled?
16
-
17
- track_user_events_configuration = Datadog.configuration.appsec.track_user_events
18
-
19
- return super unless track_user_events_configuration.enabled
20
-
21
- automated_track_user_events_mode = track_user_events_configuration.mode
22
-
23
- appsec_context = Datadog::AppSec.active_context
24
- return super unless appsec_context
17
+ return super unless Configuration.auto_user_instrumentation_enabled?
18
+ return super unless AppSec.active_context
25
19
 
26
20
  super do |resource|
27
21
  if resource.persisted?
28
22
  devise_resource = Resource.new(resource)
29
-
30
- event_information = Event.new(devise_resource, automated_track_user_events_mode)
23
+ event_information = Event.new(devise_resource, Configuration.auto_user_instrumentation_mode)
31
24
 
32
25
  if event_information.user_id
33
- Datadog.logger.debug { 'User Signup Event' }
26
+ Datadog.logger.debug { 'AppSec: User signup event' }
34
27
  else
35
- Datadog.logger.warn { 'User Signup Event, but can\'t extract user ID. Tracking empty event' }
28
+ Datadog.logger.warn { "AppSec: User signup event, but can't extract user ID. Tracking empty event" }
36
29
  end
37
30
 
38
31
  Tracking.track_signup(
39
- appsec_context.trace,
40
- appsec_context.span,
32
+ AppSec.active_context.trace,
33
+ AppSec.active_context.span,
41
34
  user_id: event_information.user_id,
42
35
  **event_information.to_h
43
36
  )
@@ -9,7 +9,7 @@ module Datadog
9
9
  # Rememberable strategy as Login Success events.
10
10
  module RememberablePatch
11
11
  def validate(*args)
12
- @_datadog_skip_track_login_event = true
12
+ @_datadog_appsec_skip_track_login_event = true
13
13
 
14
14
  super
15
15
  end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../patcher'
4
3
  require_relative 'patcher/authenticatable_patch'
5
4
  require_relative 'patcher/rememberable_patch'
6
5
  require_relative 'patcher/registration_controller_patch'
@@ -11,8 +10,6 @@ module Datadog
11
10
  module Devise
12
11
  # Patcher for AppSec on Devise
13
12
  module Patcher
14
- include Datadog::AppSec::Contrib::Patcher
15
-
16
13
  module_function
17
14
 
18
15
  def patched?
@@ -40,7 +40,7 @@ module Datadog
40
40
  return if trace.nil? || span.nil?
41
41
 
42
42
  span.set_tag("appsec.events.#{event}.track", 'true')
43
- span.set_tag("_dd.appsec.events.#{event}.auto.mode", Datadog.configuration.appsec.track_user_events.mode)
43
+ span.set_tag("_dd.appsec.events.#{event}.auto.mode", Configuration.track_user_events_mode)
44
44
 
45
45
  others.each do |k, v|
46
46
  raise ArgumentError, 'key cannot be :track' if k.to_sym == :track
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../integration'
4
+ require_relative 'patcher'
5
+
6
+ module Datadog
7
+ module AppSec
8
+ module Contrib
9
+ module Excon
10
+ # This class provides helper methods that are used when patching Excon
11
+ class Integration
12
+ include Datadog::AppSec::Contrib::Integration
13
+
14
+ MINIMUM_VERSION = Gem::Version.new('0.50.0')
15
+
16
+ register_as :excon
17
+
18
+ def self.version
19
+ Gem.loaded_specs['excon'] && Gem.loaded_specs['excon'].version
20
+ end
21
+
22
+ def self.loaded?
23
+ !defined?(::Excon).nil?
24
+ end
25
+
26
+ def self.compatible?
27
+ super && version >= MINIMUM_VERSION
28
+ end
29
+
30
+ def self.auto_instrument?
31
+ false
32
+ end
33
+
34
+ def patcher
35
+ Patcher
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module AppSec
5
+ module Contrib
6
+ module Excon
7
+ # AppSec patcher module for Excon
8
+ module Patcher
9
+ module_function
10
+
11
+ def patched?
12
+ Patcher.instance_variable_get(:@patched)
13
+ end
14
+
15
+ def target_version
16
+ Integration.version
17
+ end
18
+
19
+ def patch
20
+ require_relative 'ssrf_detection_middleware'
21
+
22
+ ::Excon.defaults[:middlewares].insert(0, SSRFDetectionMiddleware)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,43 @@
1
+ # rubocop:disable Naming/FileName
2
+ # frozen_string_literal: true
3
+
4
+ require 'excon'
5
+
6
+ module Datadog
7
+ module AppSec
8
+ module Contrib
9
+ module Excon
10
+ # AppSec Middleware for Excon
11
+ class SSRFDetectionMiddleware < ::Excon::Middleware::Base
12
+ def request_call(data)
13
+ return super unless AppSec.rasp_enabled? && AppSec.active_context
14
+
15
+ context = AppSec.active_context
16
+
17
+ request_url = URI.join("#{data[:scheme]}://#{data[:host]}", data[:path]).to_s
18
+ ephemeral_data = { 'server.io.net.url' => request_url }
19
+
20
+ result = context.run_rasp(Ext::RASP_SSRF, {}, ephemeral_data, Datadog.configuration.appsec.waf_timeout)
21
+
22
+ if result.match?
23
+ Datadog::AppSec::Event.tag_and_keep!(context, result)
24
+
25
+ context.events << {
26
+ waf_result: result,
27
+ trace: context.trace,
28
+ span: context.span,
29
+ request_url: request_url,
30
+ actions: result.actions
31
+ }
32
+
33
+ ActionsHandler.handle(result.actions)
34
+ end
35
+
36
+ super
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ # rubocop:enable Naming/FileName
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module AppSec
5
+ module Contrib
6
+ module Faraday
7
+ # Handles installation of our middleware if the user has *not*
8
+ # already explicitly configured our middleware for this correction.
9
+ #
10
+ # Wraps Faraday::Connection#initialize:
11
+ # https://github.com/lostisland/faraday/blob/ff9dc1d1219a1bbdba95a9a4cf5d135b97247ee2/lib/faraday/connection.rb#L62-L92
12
+ module ConnectionPatch
13
+ def initialize(*args, &block)
14
+ super.tap do
15
+ use(:datadog_appsec) unless builder.handlers.any? { |h| h.klass == SSRFDetectionMiddleware }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../integration'
4
+
5
+ require_relative 'patcher'
6
+
7
+ module Datadog
8
+ module AppSec
9
+ module Contrib
10
+ module Faraday
11
+ # This class provides helper methods that are used when patching Faraday
12
+ class Integration
13
+ include Datadog::AppSec::Contrib::Integration
14
+
15
+ MINIMUM_VERSION = Gem::Version.new('0.14.0')
16
+
17
+ register_as :faraday, auto_patch: true
18
+
19
+ def self.version
20
+ Gem.loaded_specs['faraday'] && Gem.loaded_specs['faraday'].version
21
+ end
22
+
23
+ def self.loaded?
24
+ !defined?(::Faraday).nil?
25
+ end
26
+
27
+ def self.compatible?
28
+ super && version >= MINIMUM_VERSION
29
+ end
30
+
31
+ def self.auto_instrument?
32
+ true
33
+ end
34
+
35
+ def patcher
36
+ Patcher
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module AppSec
5
+ module Contrib
6
+ module Faraday
7
+ # Patcher for Faraday
8
+ module Patcher
9
+ module_function
10
+
11
+ def patched?
12
+ Patcher.instance_variable_get(:@patched)
13
+ end
14
+
15
+ def target_version
16
+ Integration.version
17
+ end
18
+
19
+ def patch
20
+ require_relative 'ssrf_detection_middleware'
21
+ require_relative 'connection_patch'
22
+ require_relative 'rack_builder_patch'
23
+
24
+ ::Faraday::Middleware.register_middleware(datadog_appsec: SSRFDetectionMiddleware)
25
+ configure_default_faraday_connection
26
+
27
+ Patcher.instance_variable_set(:@patched, true)
28
+ end
29
+
30
+ def configure_default_faraday_connection
31
+ if target_version >= Gem::Version.new('1.0.0')
32
+ # Patch the default connection (e.g. +Faraday.get+)
33
+ ::Faraday.default_connection.use(:datadog_appsec)
34
+
35
+ # Patch new connection instances (e.g. +Faraday.new+)
36
+ ::Faraday::Connection.prepend(ConnectionPatch)
37
+ else
38
+ # Patch the default connection (e.g. +Faraday.get+)
39
+ #
40
+ # We insert our middleware before the 'adapter', which is
41
+ # always the last handler.
42
+ idx = ::Faraday.default_connection.builder.handlers.size - 1
43
+ ::Faraday.default_connection.builder.insert(idx, SSRFDetectionMiddleware)
44
+
45
+ # Patch new connection instances (e.g. +Faraday.new+)
46
+ ::Faraday::RackBuilder.prepend(RackBuilderPatch)
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Datadog
4
+ module AppSec
5
+ module Contrib
6
+ module Faraday
7
+ # Handles installation of our middleware if the user has *not*
8
+ # already explicitly configured it for this correction.
9
+ #
10
+ # RackBuilder class was introduced in faraday 0.9.0:
11
+ # https://github.com/lostisland/faraday/commit/77d7546d6d626b91086f427c56bc2cdd951353b3
12
+ module RackBuilderPatch
13
+ def adapter(*args)
14
+ use(:datadog_appsec) unless @handlers.any? { |h| h.klass == SSRFDetectionMiddleware }
15
+
16
+ super
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,42 @@
1
+ # rubocop:disable Naming/FileName
2
+ # frozen_string_literal: true
3
+
4
+ module Datadog
5
+ module AppSec
6
+ module Contrib
7
+ module Faraday
8
+ # AppSec SSRF detection Middleware for Faraday
9
+ class SSRFDetectionMiddleware < ::Faraday::Middleware
10
+ def call(request_env)
11
+ context = AppSec.active_context
12
+
13
+ return @app.call(request_env) unless context && AppSec.rasp_enabled?
14
+
15
+ ephemeral_data = {
16
+ 'server.io.net.url' => request_env.url.to_s
17
+ }
18
+
19
+ result = context.run_rasp(Ext::RASP_SSRF, {}, ephemeral_data, Datadog.configuration.appsec.waf_timeout)
20
+
21
+ if result.match?
22
+ Datadog::AppSec::Event.tag_and_keep!(context, result)
23
+
24
+ context.events << {
25
+ waf_result: result,
26
+ trace: context.trace,
27
+ span: context.span,
28
+ request_url: request_env.url,
29
+ actions: result.actions
30
+ }
31
+
32
+ ActionsHandler.handle(result.actions)
33
+ end
34
+
35
+ @app.call(request_env)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ # rubocop:enable Naming/FileName
@@ -16,16 +16,10 @@ module Datadog
16
16
 
17
17
  gateway_multiplex = Gateway::Multiplex.new(multiplex)
18
18
 
19
- multiplex_return, multiplex_response = Instrumentation.gateway.push('graphql.multiplex', gateway_multiplex) do
19
+ multiplex_return, _gateway_multiplex = Instrumentation.gateway.push('graphql.multiplex', gateway_multiplex) do
20
20
  super
21
21
  end
22
22
 
23
- # Returns an error * the number of queries so that the entire multiplex is blocked
24
- if multiplex_response
25
- blocked_event = multiplex_response.find { |action, _options| action == :block }
26
- multiplex_return = AppSec::Response.graphql_response(gateway_multiplex) if blocked_event
27
- end
28
-
29
23
  multiplex_return
30
24
  end
31
25
  end
@@ -2,8 +2,6 @@
2
2
 
3
3
  require 'json'
4
4
  require_relative '../../../instrumentation/gateway'
5
- require_relative '../../../reactive/engine'
6
- require_relative '../reactive/multiplex'
7
5
 
8
6
  module Datadog
9
7
  module AppSec
@@ -19,17 +17,21 @@ module Datadog
19
17
  watch_multiplex(gateway)
20
18
  end
21
19
 
22
- # This time we don't throw but use next
23
20
  def watch_multiplex(gateway = Instrumentation.gateway)
24
21
  gateway.watch('graphql.multiplex', :appsec) do |stack, gateway_multiplex|
25
- block = false
26
- event = nil
27
22
  context = AppSec::Context.active
28
- engine = AppSec::Reactive::Engine.new
29
23
 
30
24
  if context
31
- GraphQL::Reactive::Multiplex.subscribe(engine, context) do |result|
32
- event = {
25
+ persistent_data = {
26
+ 'graphql.server.all_resolvers' => gateway_multiplex.arguments
27
+ }
28
+
29
+ result = context.run_waf(persistent_data, {}, Datadog.configuration.appsec.waf_timeout)
30
+
31
+ if result.match?
32
+ Datadog::AppSec::Event.tag_and_keep!(context, result)
33
+
34
+ context.events << {
33
35
  waf_result: result,
34
36
  trace: context.trace,
35
37
  span: context.span,
@@ -37,15 +39,10 @@ module Datadog
37
39
  actions: result.actions
38
40
  }
39
41
 
40
- Datadog::AppSec::Event.tag_and_keep!(context, result)
41
- context.waf_runner.events << event
42
+ Datadog::AppSec::ActionsHandler.handle(result.actions)
42
43
  end
43
-
44
- block = GraphQL::Reactive::Multiplex.publish(engine, gateway_multiplex)
45
44
  end
46
45
 
47
- next [nil, [[:block, event]]] if block
48
-
49
46
  stack.call(gateway_multiplex.arguments)
50
47
  end
51
48
  end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../patcher'
4
3
  require_relative 'gateway/watcher'
5
4
 
6
5
  if Gem.loaded_specs['graphql'] && Gem.loaded_specs['graphql'].version >= Gem::Version.new('2.0.19')
@@ -13,8 +12,6 @@ module Datadog
13
12
  module GraphQL
14
13
  # Patcher for AppSec on GraphQL
15
14
  module Patcher
16
- include Datadog::AppSec::Contrib::Patcher
17
-
18
15
  module_function
19
16
 
20
17
  def patched?