datadog 2.8.0 → 2.10.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 (128) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +62 -1
  3. data/ext/datadog_profiling_native_extension/clock_id.h +2 -2
  4. data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +66 -56
  5. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +1 -1
  6. data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.h +1 -1
  7. data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +16 -16
  8. data/ext/datadog_profiling_native_extension/collectors_stack.c +7 -7
  9. data/ext/datadog_profiling_native_extension/collectors_stack.h +2 -2
  10. data/ext/datadog_profiling_native_extension/collectors_thread_context.c +221 -127
  11. data/ext/datadog_profiling_native_extension/heap_recorder.c +50 -92
  12. data/ext/datadog_profiling_native_extension/heap_recorder.h +2 -2
  13. data/ext/datadog_profiling_native_extension/http_transport.c +4 -4
  14. data/ext/datadog_profiling_native_extension/private_vm_api_access.c +3 -0
  15. data/ext/datadog_profiling_native_extension/private_vm_api_access.h +3 -1
  16. data/ext/datadog_profiling_native_extension/profiling.c +10 -8
  17. data/ext/datadog_profiling_native_extension/ruby_helpers.c +8 -8
  18. data/ext/datadog_profiling_native_extension/stack_recorder.c +63 -76
  19. data/ext/datadog_profiling_native_extension/stack_recorder.h +2 -2
  20. data/ext/datadog_profiling_native_extension/time_helpers.h +1 -1
  21. data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.c +47 -0
  22. data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.h +31 -0
  23. data/ext/libdatadog_api/crashtracker.c +3 -0
  24. data/lib/datadog/appsec/actions_handler.rb +27 -0
  25. data/lib/datadog/appsec/assets/waf_rules/recommended.json +355 -157
  26. data/lib/datadog/appsec/assets/waf_rules/strict.json +62 -32
  27. data/lib/datadog/appsec/component.rb +14 -8
  28. data/lib/datadog/appsec/configuration/settings.rb +9 -0
  29. data/lib/datadog/appsec/context.rb +74 -0
  30. data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +12 -8
  31. data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +6 -6
  32. data/lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb +4 -4
  33. data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +1 -7
  34. data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +20 -30
  35. data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +6 -6
  36. data/lib/datadog/appsec/contrib/rack/gateway/response.rb +3 -3
  37. data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +67 -96
  38. data/lib/datadog/appsec/contrib/rack/reactive/request.rb +11 -11
  39. data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +6 -6
  40. data/lib/datadog/appsec/contrib/rack/reactive/response.rb +7 -7
  41. data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +10 -11
  42. data/lib/datadog/appsec/contrib/rack/request_middleware.rb +43 -60
  43. data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +23 -33
  44. data/lib/datadog/appsec/contrib/rails/patcher.rb +4 -14
  45. data/lib/datadog/appsec/contrib/rails/reactive/action.rb +7 -7
  46. data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +45 -65
  47. data/lib/datadog/appsec/contrib/sinatra/patcher.rb +5 -28
  48. data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +6 -6
  49. data/lib/datadog/appsec/event.rb +6 -6
  50. data/lib/datadog/appsec/ext.rb +8 -1
  51. data/lib/datadog/appsec/metrics/collector.rb +38 -0
  52. data/lib/datadog/appsec/metrics/exporter.rb +35 -0
  53. data/lib/datadog/appsec/metrics/telemetry.rb +23 -0
  54. data/lib/datadog/appsec/metrics.rb +13 -0
  55. data/lib/datadog/appsec/monitor/gateway/watcher.rb +23 -32
  56. data/lib/datadog/appsec/monitor/reactive/set_user.rb +6 -6
  57. data/lib/datadog/appsec/processor/rule_loader.rb +0 -3
  58. data/lib/datadog/appsec/processor.rb +4 -3
  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 +17 -8
  64. data/lib/datadog/auto_instrument.rb +3 -0
  65. data/lib/datadog/core/configuration/agent_settings_resolver.rb +39 -11
  66. data/lib/datadog/core/configuration/components.rb +4 -2
  67. data/lib/datadog/core/configuration.rb +1 -1
  68. data/lib/datadog/{tracing → core}/contrib/rails/utils.rb +1 -3
  69. data/lib/datadog/core/crashtracking/component.rb +1 -3
  70. data/lib/datadog/core/telemetry/event.rb +87 -3
  71. data/lib/datadog/core/telemetry/logging.rb +2 -2
  72. data/lib/datadog/core/telemetry/metric.rb +22 -0
  73. data/lib/datadog/core/telemetry/worker.rb +33 -0
  74. data/lib/datadog/di/base.rb +115 -0
  75. data/lib/datadog/di/code_tracker.rb +7 -4
  76. data/lib/datadog/di/component.rb +19 -11
  77. data/lib/datadog/di/configuration/settings.rb +11 -1
  78. data/lib/datadog/di/contrib/railtie.rb +15 -0
  79. data/lib/datadog/di/contrib.rb +26 -0
  80. data/lib/datadog/di/error.rb +5 -0
  81. data/lib/datadog/di/instrumenter.rb +39 -18
  82. data/lib/datadog/di/{init.rb → preload.rb} +2 -4
  83. data/lib/datadog/di/probe_manager.rb +4 -4
  84. data/lib/datadog/di/probe_notification_builder.rb +22 -2
  85. data/lib/datadog/di/probe_notifier_worker.rb +5 -6
  86. data/lib/datadog/di/redactor.rb +0 -1
  87. data/lib/datadog/di/remote.rb +30 -9
  88. data/lib/datadog/di/transport.rb +2 -4
  89. data/lib/datadog/di.rb +5 -108
  90. data/lib/datadog/kit/appsec/events.rb +3 -3
  91. data/lib/datadog/kit/identity.rb +4 -4
  92. data/lib/datadog/profiling/component.rb +55 -53
  93. data/lib/datadog/profiling/http_transport.rb +1 -26
  94. data/lib/datadog/tracing/contrib/action_cable/integration.rb +5 -2
  95. data/lib/datadog/tracing/contrib/action_mailer/integration.rb +6 -2
  96. data/lib/datadog/tracing/contrib/action_pack/integration.rb +5 -2
  97. data/lib/datadog/tracing/contrib/action_view/integration.rb +5 -2
  98. data/lib/datadog/tracing/contrib/active_job/integration.rb +5 -2
  99. data/lib/datadog/tracing/contrib/active_record/integration.rb +6 -2
  100. data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +3 -1
  101. data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +3 -1
  102. data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +10 -0
  103. data/lib/datadog/tracing/contrib/active_support/integration.rb +5 -2
  104. data/lib/datadog/tracing/contrib/auto_instrument.rb +2 -2
  105. data/lib/datadog/tracing/contrib/aws/integration.rb +3 -0
  106. data/lib/datadog/tracing/contrib/concurrent_ruby/integration.rb +3 -0
  107. data/lib/datadog/tracing/contrib/extensions.rb +15 -3
  108. data/lib/datadog/tracing/contrib/http/integration.rb +3 -0
  109. data/lib/datadog/tracing/contrib/httprb/integration.rb +3 -0
  110. data/lib/datadog/tracing/contrib/kafka/integration.rb +3 -0
  111. data/lib/datadog/tracing/contrib/mongodb/integration.rb +3 -0
  112. data/lib/datadog/tracing/contrib/opensearch/integration.rb +3 -0
  113. data/lib/datadog/tracing/contrib/presto/integration.rb +3 -0
  114. data/lib/datadog/tracing/contrib/rack/integration.rb +2 -2
  115. data/lib/datadog/tracing/contrib/rails/framework.rb +2 -2
  116. data/lib/datadog/tracing/contrib/rails/patcher.rb +1 -1
  117. data/lib/datadog/tracing/contrib/rest_client/integration.rb +3 -0
  118. data/lib/datadog/tracing/span.rb +12 -4
  119. data/lib/datadog/tracing/span_event.rb +123 -3
  120. data/lib/datadog/tracing/span_operation.rb +6 -0
  121. data/lib/datadog/tracing/transport/serializable_trace.rb +24 -6
  122. data/lib/datadog/version.rb +1 -1
  123. metadata +40 -17
  124. data/lib/datadog/appsec/contrib/sinatra/ext.rb +0 -14
  125. data/lib/datadog/appsec/processor/context.rb +0 -107
  126. data/lib/datadog/appsec/reactive/operation.rb +0 -68
  127. data/lib/datadog/appsec/scope.rb +0 -58
  128. data/lib/datadog/core/crashtracking/agent_base_url.rb +0 -21
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": "2.2",
3
3
  "metadata": {
4
- "rules_version": "1.13.1"
4
+ "rules_version": "1.13.3"
5
5
  },
6
6
  "rules": [
7
7
  {
@@ -10,7 +10,8 @@
10
10
  "tags": {
11
11
  "type": "security_scanner",
12
12
  "crs_id": "913100",
13
- "category": "attack_attempt"
13
+ "category": "attack_attempt",
14
+ "module": "waf"
14
15
  },
15
16
  "conditions": [
16
17
  {
@@ -84,7 +85,8 @@
84
85
  "tags": {
85
86
  "type": "http_protocol_violation",
86
87
  "crs_id": "921120",
87
- "category": "attack_attempt"
88
+ "category": "attack_attempt",
89
+ "module": "waf"
88
90
  },
89
91
  "conditions": [
90
92
  {
@@ -127,7 +129,8 @@
127
129
  "crs_id": "921140",
128
130
  "category": "attack_attempt",
129
131
  "capec": "1000/210/272/220/273",
130
- "cwe": "113"
132
+ "cwe": "113",
133
+ "module": "waf"
131
134
  },
132
135
  "conditions": [
133
136
  {
@@ -154,7 +157,8 @@
154
157
  "tags": {
155
158
  "type": "command_injection",
156
159
  "crs_id": "932100",
157
- "category": "attack_attempt"
160
+ "category": "attack_attempt",
161
+ "module": "waf"
158
162
  },
159
163
  "conditions": [
160
164
  {
@@ -193,7 +197,8 @@
193
197
  "tags": {
194
198
  "type": "command_injection",
195
199
  "crs_id": "932115",
196
- "category": "attack_attempt"
200
+ "category": "attack_attempt",
201
+ "module": "waf"
197
202
  },
198
203
  "conditions": [
199
204
  {
@@ -690,7 +695,8 @@
690
695
  "tags": {
691
696
  "type": "command_injection",
692
697
  "crs_id": "932130",
693
- "category": "attack_attempt"
698
+ "category": "attack_attempt",
699
+ "module": "waf"
694
700
  },
695
701
  "conditions": [
696
702
  {
@@ -729,7 +735,8 @@
729
735
  "tags": {
730
736
  "type": "command_injection",
731
737
  "crs_id": "932150",
732
- "category": "attack_attempt"
738
+ "category": "attack_attempt",
739
+ "module": "waf"
733
740
  },
734
741
  "conditions": [
735
742
  {
@@ -768,7 +775,8 @@
768
775
  "tags": {
769
776
  "type": "php_code_injection",
770
777
  "crs_id": "933110",
771
- "category": "attack_attempt"
778
+ "category": "attack_attempt",
779
+ "module": "waf"
772
780
  },
773
781
  "conditions": [
774
782
  {
@@ -818,7 +826,8 @@
818
826
  "tags": {
819
827
  "type": "php_code_injection",
820
828
  "crs_id": "933180",
821
- "category": "attack_attempt"
829
+ "category": "attack_attempt",
830
+ "module": "waf"
822
831
  },
823
832
  "conditions": [
824
833
  {
@@ -857,7 +866,8 @@
857
866
  "tags": {
858
867
  "type": "php_code_injection",
859
868
  "crs_id": "933210",
860
- "category": "attack_attempt"
869
+ "category": "attack_attempt",
870
+ "module": "waf"
861
871
  },
862
872
  "conditions": [
863
873
  {
@@ -897,7 +907,8 @@
897
907
  "type": "xss",
898
908
  "crs_id": "941100",
899
909
  "category": "attack_attempt",
900
- "cwe": "79"
910
+ "cwe": "79",
911
+ "module": "waf"
901
912
  },
902
913
  "conditions": [
903
914
  {
@@ -948,7 +959,8 @@
948
959
  "tags": {
949
960
  "type": "xss",
950
961
  "crs_id": "941130",
951
- "category": "attack_attempt"
962
+ "category": "attack_attempt",
963
+ "module": "waf"
952
964
  },
953
965
  "conditions": [
954
966
  {
@@ -994,7 +1006,8 @@
994
1006
  "tags": {
995
1007
  "type": "xss",
996
1008
  "crs_id": "941150",
997
- "category": "attack_attempt"
1009
+ "category": "attack_attempt",
1010
+ "module": "waf"
998
1011
  },
999
1012
  "conditions": [
1000
1013
  {
@@ -1041,7 +1054,8 @@
1041
1054
  "tags": {
1042
1055
  "type": "xss",
1043
1056
  "crs_id": "941160",
1044
- "category": "attack_attempt"
1057
+ "category": "attack_attempt",
1058
+ "module": "waf"
1045
1059
  },
1046
1060
  "conditions": [
1047
1061
  {
@@ -1093,7 +1107,8 @@
1093
1107
  "tags": {
1094
1108
  "type": "xss",
1095
1109
  "crs_id": "941190",
1096
- "category": "attack_attempt"
1110
+ "category": "attack_attempt",
1111
+ "module": "waf"
1097
1112
  },
1098
1113
  "conditions": [
1099
1114
  {
@@ -1134,7 +1149,8 @@
1134
1149
  "tags": {
1135
1150
  "type": "xss",
1136
1151
  "crs_id": "941250",
1137
- "category": "attack_attempt"
1152
+ "category": "attack_attempt",
1153
+ "module": "waf"
1138
1154
  },
1139
1155
  "conditions": [
1140
1156
  {
@@ -1175,7 +1191,8 @@
1175
1191
  "tags": {
1176
1192
  "type": "xss",
1177
1193
  "crs_id": "941260",
1178
- "category": "attack_attempt"
1194
+ "category": "attack_attempt",
1195
+ "module": "waf"
1179
1196
  },
1180
1197
  "conditions": [
1181
1198
  {
@@ -1216,7 +1233,8 @@
1216
1233
  "tags": {
1217
1234
  "type": "xss",
1218
1235
  "crs_id": "941370",
1219
- "category": "attack_attempt"
1236
+ "category": "attack_attempt",
1237
+ "module": "waf"
1220
1238
  },
1221
1239
  "conditions": [
1222
1240
  {
@@ -1255,7 +1273,8 @@
1255
1273
  "tags": {
1256
1274
  "type": "js_code_injection",
1257
1275
  "crs_id": "941380",
1258
- "category": "attack_attempt"
1276
+ "category": "attack_attempt",
1277
+ "module": "waf"
1259
1278
  },
1260
1279
  "conditions": [
1261
1280
  {
@@ -1294,7 +1313,8 @@
1294
1313
  "tags": {
1295
1314
  "type": "sql_injection",
1296
1315
  "crs_id": "942151",
1297
- "category": "attack_attempt"
1316
+ "category": "attack_attempt",
1317
+ "module": "waf"
1298
1318
  },
1299
1319
  "conditions": [
1300
1320
  {
@@ -1333,7 +1353,8 @@
1333
1353
  "tags": {
1334
1354
  "type": "sql_injection",
1335
1355
  "crs_id": "942170",
1336
- "category": "attack_attempt"
1356
+ "category": "attack_attempt",
1357
+ "module": "waf"
1337
1358
  },
1338
1359
  "conditions": [
1339
1360
  {
@@ -1372,7 +1393,8 @@
1372
1393
  "type": "sql_injection",
1373
1394
  "crs_id": "942190",
1374
1395
  "category": "attack_attempt",
1375
- "cwe": "89"
1396
+ "cwe": "89",
1397
+ "module": "waf"
1376
1398
  },
1377
1399
  "conditions": [
1378
1400
  {
@@ -1413,7 +1435,8 @@
1413
1435
  "tags": {
1414
1436
  "type": "sql_injection",
1415
1437
  "crs_id": "942230",
1416
- "category": "attack_attempt"
1438
+ "category": "attack_attempt",
1439
+ "module": "waf"
1417
1440
  },
1418
1441
  "conditions": [
1419
1442
  {
@@ -1452,7 +1475,8 @@
1452
1475
  "tags": {
1453
1476
  "type": "sql_injection",
1454
1477
  "crs_id": "942320",
1455
- "category": "attack_attempt"
1478
+ "category": "attack_attempt",
1479
+ "module": "waf"
1456
1480
  },
1457
1481
  "conditions": [
1458
1482
  {
@@ -1490,7 +1514,8 @@
1490
1514
  "tags": {
1491
1515
  "type": "sql_injection",
1492
1516
  "crs_id": "942350",
1493
- "category": "attack_attempt"
1517
+ "category": "attack_attempt",
1518
+ "module": "waf"
1494
1519
  },
1495
1520
  "conditions": [
1496
1521
  {
@@ -1528,7 +1553,8 @@
1528
1553
  "tags": {
1529
1554
  "type": "java_code_injection",
1530
1555
  "crs_id": "944240",
1531
- "category": "attack_attempt"
1556
+ "category": "attack_attempt",
1557
+ "module": "waf"
1532
1558
  },
1533
1559
  "conditions": [
1534
1560
  {
@@ -1573,7 +1599,8 @@
1573
1599
  "type": "lfi",
1574
1600
  "category": "attack_attempt",
1575
1601
  "cwe": "22",
1576
- "capec": "1000/255/153/126"
1602
+ "capec": "1000/255/153/126",
1603
+ "module": "waf"
1577
1604
  },
1578
1605
  "conditions": [
1579
1606
  {
@@ -1612,7 +1639,8 @@
1612
1639
  "type": "lfi",
1613
1640
  "category": "attack_attempt",
1614
1641
  "cwe": "22",
1615
- "capec": "1000/255/153/126"
1642
+ "capec": "1000/255/153/126",
1643
+ "module": "waf"
1616
1644
  },
1617
1645
  "conditions": [
1618
1646
  {
@@ -1653,7 +1681,8 @@
1653
1681
  "tags": {
1654
1682
  "type": "nosql_injection",
1655
1683
  "category": "attack_attempt",
1656
- "cwe": "943"
1684
+ "cwe": "943",
1685
+ "module": "waf"
1657
1686
  },
1658
1687
  "conditions": [
1659
1688
  {
@@ -1689,7 +1718,8 @@
1689
1718
  "name": "Node.js: Prototype pollution",
1690
1719
  "tags": {
1691
1720
  "type": "js_code_injection",
1692
- "category": "attack_attempt"
1721
+ "category": "attack_attempt",
1722
+ "module": "waf"
1693
1723
  },
1694
1724
  "conditions": [
1695
1725
  {
@@ -3060,4 +3090,4 @@
3060
3090
  }
3061
3091
  }
3062
3092
  ]
3063
- }
3093
+ }
@@ -3,6 +3,7 @@
3
3
  require_relative 'processor'
4
4
  require_relative 'processor/rule_merger'
5
5
  require_relative 'processor/rule_loader'
6
+ require_relative 'actions_handler'
6
7
 
7
8
  module Datadog
8
9
  module AppSec
@@ -23,7 +24,7 @@ module Datadog
23
24
  devise_integration = Datadog::AppSec::Contrib::Devise::Integration.new
24
25
  settings.appsec.instrument(:devise) unless devise_integration.patcher.patched?
25
26
 
26
- new(processor: processor)
27
+ new(processor, telemetry)
27
28
  end
28
29
 
29
30
  private
@@ -72,21 +73,26 @@ module Datadog
72
73
  end
73
74
  end
74
75
 
75
- attr_reader :processor
76
+ attr_reader :processor, :telemetry
76
77
 
77
- def initialize(processor:)
78
+ def initialize(processor, telemetry)
78
79
  @processor = processor
80
+ @telemetry = telemetry
81
+
79
82
  @mutex = Mutex.new
80
83
  end
81
84
 
82
85
  def reconfigure(ruleset:, telemetry:)
83
86
  @mutex.synchronize do
84
- new = Processor.new(ruleset: ruleset, telemetry: telemetry)
87
+ new_processor = Processor.new(ruleset: ruleset, telemetry: telemetry)
88
+
89
+ if new_processor && new_processor.ready?
90
+ old_processor = @processor
91
+
92
+ @telemetry = telemetry
93
+ @processor = new_processor
85
94
 
86
- if new && new.ready?
87
- old = @processor
88
- @processor = new
89
- old.finalize if old
95
+ old_processor.finalize if old_processor
90
96
  end
91
97
  end
92
98
  end
@@ -49,6 +49,15 @@ module Datadog
49
49
  end
50
50
  end
51
51
 
52
+ # RASP or Runtime Application Self-Protection
53
+ # is a collection of techniques and heuristics aimed at detecting malicious inputs and preventing
54
+ # any potential side-effects on the application resulting from the use of said malicious inputs.
55
+ option :rasp_enabled do |o|
56
+ o.type :bool, nilable: true
57
+ o.env 'DD_APPSEC_RASP_ENABLED'
58
+ o.default true
59
+ end
60
+
52
61
  option :ruleset do |o|
53
62
  o.env 'DD_APPSEC_RULES'
54
63
  o.default :recommended
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'metrics'
4
+
5
+ module Datadog
6
+ module AppSec
7
+ # This class accumulates the context over the request life-cycle and exposes
8
+ # interface sufficient for instrumentation to perform threat detection.
9
+ class Context
10
+ ActiveContextError = Class.new(StandardError)
11
+
12
+ attr_reader :trace, :span, :events
13
+
14
+ class << self
15
+ def activate(context)
16
+ raise ArgumentError, 'not a Datadog::AppSec::Context' unless context.instance_of?(Context)
17
+ raise ActiveContextError, 'another context is active, nested contexts are not supported' if active
18
+
19
+ Thread.current[Ext::ACTIVE_CONTEXT_KEY] = context
20
+ end
21
+
22
+ def deactivate
23
+ active&.finalize
24
+ ensure
25
+ Thread.current[Ext::ACTIVE_CONTEXT_KEY] = nil
26
+ end
27
+
28
+ def active
29
+ Thread.current[Ext::ACTIVE_CONTEXT_KEY]
30
+ end
31
+ end
32
+
33
+ def initialize(trace, span, security_engine)
34
+ @trace = trace
35
+ @span = span
36
+ @events = []
37
+ @security_engine = security_engine
38
+ @waf_runner = security_engine.new_runner
39
+ @metrics = Metrics::Collector.new
40
+ end
41
+
42
+ def run_waf(persistent_data, ephemeral_data, timeout = WAF::LibDDWAF::DDWAF_RUN_TIMEOUT)
43
+ result = @waf_runner.run(persistent_data, ephemeral_data, timeout)
44
+
45
+ @metrics.record_waf(result)
46
+ result
47
+ end
48
+
49
+ def run_rasp(type, persistent_data, ephemeral_data, timeout = WAF::LibDDWAF::DDWAF_RUN_TIMEOUT)
50
+ result = @waf_runner.run(persistent_data, ephemeral_data, timeout)
51
+
52
+ Metrics::Telemetry.report_rasp(type, result)
53
+ @metrics.record_rasp(result)
54
+
55
+ result
56
+ end
57
+
58
+ def extract_schema
59
+ @waf_runner.run({ 'waf.context.processor' => { 'extract-schema' => true } }, {})
60
+ end
61
+
62
+ def export_metrics
63
+ return if @span.nil?
64
+
65
+ Metrics::Exporter.export_waf_metrics(@metrics.waf, @span)
66
+ Metrics::Exporter.export_rasp_metrics(@metrics.rasp, @span)
67
+ end
68
+
69
+ def finalize
70
+ @waf_runner.finalize
71
+ end
72
+ end
73
+ end
74
+ end
@@ -9,8 +9,10 @@ module Datadog
9
9
  module_function
10
10
 
11
11
  def detect_sql_injection(sql, adapter_name)
12
- scope = AppSec.active_scope
13
- return unless scope
12
+ return unless AppSec.rasp_enabled?
13
+
14
+ context = AppSec.active_context
15
+ return unless context
14
16
 
15
17
  # libddwaf expects db system to be lowercase,
16
18
  # in case of sqlite adapter, libddwaf expects 'sqlite' as db system
@@ -23,19 +25,21 @@ module Datadog
23
25
  }
24
26
 
25
27
  waf_timeout = Datadog.configuration.appsec.waf_timeout
26
- result = scope.processor_context.run({}, ephemeral_data, waf_timeout)
28
+ result = context.run_rasp(Ext::RASP_SQLI, {}, ephemeral_data, waf_timeout)
27
29
 
28
- if result.status == :match
29
- Datadog::AppSec::Event.tag_and_keep!(scope, result)
30
+ if result.match?
31
+ Datadog::AppSec::Event.tag_and_keep!(context, result)
30
32
 
31
33
  event = {
32
34
  waf_result: result,
33
- trace: scope.trace,
34
- span: scope.service_entry_span,
35
+ trace: context.trace,
36
+ span: context.span,
35
37
  sql: sql,
36
38
  actions: result.actions
37
39
  }
38
- scope.processor_context.events << event
40
+ context.events << event
41
+
42
+ ActionsHandler.handle(result.actions)
39
43
  end
40
44
  end
41
45
 
@@ -23,9 +23,9 @@ module Datadog
23
23
 
24
24
  automated_track_user_events_mode = track_user_events_configuration.mode
25
25
 
26
- appsec_scope = Datadog::AppSec.active_scope
26
+ appsec_context = Datadog::AppSec.active_context
27
27
 
28
- return result unless appsec_scope
28
+ return result unless appsec_context
29
29
 
30
30
  devise_resource = resource ? Resource.new(resource) : nil
31
31
 
@@ -39,8 +39,8 @@ module Datadog
39
39
  end
40
40
 
41
41
  Tracking.track_login_success(
42
- appsec_scope.trace,
43
- appsec_scope.service_entry_span,
42
+ appsec_context.trace,
43
+ appsec_context.span,
44
44
  user_id: event_information.user_id,
45
45
  **event_information.to_h
46
46
  )
@@ -59,8 +59,8 @@ module Datadog
59
59
  end
60
60
 
61
61
  Tracking.track_login_failure(
62
- appsec_scope.trace,
63
- appsec_scope.service_entry_span,
62
+ appsec_context.trace,
63
+ appsec_context.span,
64
64
  user_id: event_information.user_id,
65
65
  user_exists: user_exists,
66
66
  **event_information.to_h
@@ -20,8 +20,8 @@ module Datadog
20
20
 
21
21
  automated_track_user_events_mode = track_user_events_configuration.mode
22
22
 
23
- appsec_scope = Datadog::AppSec.active_scope
24
- return super unless appsec_scope
23
+ appsec_context = Datadog::AppSec.active_context
24
+ return super unless appsec_context
25
25
 
26
26
  super do |resource|
27
27
  if resource.persisted?
@@ -36,8 +36,8 @@ module Datadog
36
36
  end
37
37
 
38
38
  Tracking.track_signup(
39
- appsec_scope.trace,
40
- appsec_scope.service_entry_span,
39
+ appsec_context.trace,
40
+ appsec_context.span,
41
41
  user_id: event_information.user_id,
42
42
  **event_information.to_h
43
43
  )
@@ -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,8 @@
2
2
 
3
3
  require 'json'
4
4
  require_relative '../../../instrumentation/gateway'
5
+ require_relative '../../../reactive/engine'
5
6
  require_relative '../reactive/multiplex'
6
- require_relative '../../../reactive/operation'
7
7
 
8
8
  module Datadog
9
9
  module AppSec
@@ -22,40 +22,30 @@ module Datadog
22
22
  # This time we don't throw but use next
23
23
  def watch_multiplex(gateway = Instrumentation.gateway)
24
24
  gateway.watch('graphql.multiplex', :appsec) do |stack, gateway_multiplex|
25
- block = false
26
25
  event = nil
27
-
28
- scope = AppSec::Scope.active_scope
29
-
30
- if scope
31
- AppSec::Reactive::Operation.new('graphql.multiplex') do |op|
32
- GraphQL::Reactive::Multiplex.subscribe(op, scope.processor_context) do |result|
33
- event = {
34
- waf_result: result,
35
- trace: scope.trace,
36
- span: scope.service_entry_span,
37
- multiplex: gateway_multiplex,
38
- actions: result.actions
39
- }
40
-
41
- Datadog::AppSec::Event.tag_and_keep!(scope, result)
42
- scope.processor_context.events << event
43
- end
44
-
45
- block = GraphQL::Reactive::Multiplex.publish(op, gateway_multiplex)
26
+ context = AppSec::Context.active
27
+ engine = AppSec::Reactive::Engine.new
28
+
29
+ if context
30
+ GraphQL::Reactive::Multiplex.subscribe(engine, context) do |result|
31
+ event = {
32
+ waf_result: result,
33
+ trace: context.trace,
34
+ span: context.span,
35
+ multiplex: gateway_multiplex,
36
+ actions: result.actions
37
+ }
38
+
39
+ Datadog::AppSec::Event.tag_and_keep!(context, result)
40
+ context.events << event
41
+
42
+ Datadog::AppSec::ActionsHandler.handle(result.actions)
46
43
  end
47
- end
48
-
49
- next [nil, [[:block, event]]] if block
50
-
51
- ret, res = stack.call(gateway_multiplex.arguments)
52
44
 
53
- if event
54
- res ||= []
55
- res << [:monitor, event]
45
+ GraphQL::Reactive::Multiplex.publish(engine, gateway_multiplex)
56
46
  end
57
47
 
58
- [ret, res]
48
+ stack.call(gateway_multiplex.arguments)
59
49
  end
60
50
  end
61
51
  end
@@ -12,16 +12,16 @@ module Datadog
12
12
  ].freeze
13
13
  private_constant :ADDRESSES
14
14
 
15
- def self.publish(op, gateway_multiplex)
15
+ def self.publish(engine, gateway_multiplex)
16
16
  catch(:block) do
17
- op.publish('graphql.server.all_resolvers', gateway_multiplex.arguments)
17
+ engine.publish('graphql.server.all_resolvers', gateway_multiplex.arguments)
18
18
 
19
19
  nil
20
20
  end
21
21
  end
22
22
 
23
- def self.subscribe(op, waf_context)
24
- op.subscribe(*ADDRESSES) do |*values|
23
+ def self.subscribe(engine, context)
24
+ engine.subscribe(*ADDRESSES) do |*values|
25
25
  Datadog.logger.debug { "reacted to #{ADDRESSES.inspect}: #{values.inspect}" }
26
26
  arguments = values[0]
27
27
 
@@ -30,9 +30,9 @@ module Datadog
30
30
  }
31
31
 
32
32
  waf_timeout = Datadog.configuration.appsec.waf_timeout
33
- result = waf_context.run(persistent_data, {}, waf_timeout)
33
+ result = context.run_waf(persistent_data, {}, waf_timeout)
34
34
 
35
- next if result.status != :match
35
+ next unless result.match?
36
36
 
37
37
  yield result
38
38
  throw(:block, true) unless result.actions.empty?
@@ -9,14 +9,14 @@ module Datadog
9
9
  module Gateway
10
10
  # Gateway Response argument.
11
11
  class Response < Instrumentation::Gateway::Argument
12
- attr_reader :body, :status, :headers, :scope
12
+ attr_reader :body, :status, :headers, :context
13
13
 
14
- def initialize(body, status, headers, scope:)
14
+ def initialize(body, status, headers, context:)
15
15
  super()
16
16
  @body = body
17
17
  @status = status
18
18
  @headers = headers.each_with_object({}) { |(k, v), h| h[k.downcase] = v }
19
- @scope = scope
19
+ @context = context
20
20
  end
21
21
 
22
22
  def response