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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +62 -1
- data/ext/datadog_profiling_native_extension/clock_id.h +2 -2
- data/ext/datadog_profiling_native_extension/collectors_cpu_and_wall_time_worker.c +66 -56
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.c +1 -1
- data/ext/datadog_profiling_native_extension/collectors_discrete_dynamic_sampler.h +1 -1
- data/ext/datadog_profiling_native_extension/collectors_idle_sampling_helper.c +16 -16
- data/ext/datadog_profiling_native_extension/collectors_stack.c +7 -7
- data/ext/datadog_profiling_native_extension/collectors_stack.h +2 -2
- data/ext/datadog_profiling_native_extension/collectors_thread_context.c +221 -127
- data/ext/datadog_profiling_native_extension/heap_recorder.c +50 -92
- data/ext/datadog_profiling_native_extension/heap_recorder.h +2 -2
- data/ext/datadog_profiling_native_extension/http_transport.c +4 -4
- data/ext/datadog_profiling_native_extension/private_vm_api_access.c +3 -0
- data/ext/datadog_profiling_native_extension/private_vm_api_access.h +3 -1
- data/ext/datadog_profiling_native_extension/profiling.c +10 -8
- data/ext/datadog_profiling_native_extension/ruby_helpers.c +8 -8
- data/ext/datadog_profiling_native_extension/stack_recorder.c +63 -76
- data/ext/datadog_profiling_native_extension/stack_recorder.h +2 -2
- data/ext/datadog_profiling_native_extension/time_helpers.h +1 -1
- data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.c +47 -0
- data/ext/datadog_profiling_native_extension/unsafe_api_calls_check.h +31 -0
- data/ext/libdatadog_api/crashtracker.c +3 -0
- data/lib/datadog/appsec/actions_handler.rb +27 -0
- data/lib/datadog/appsec/assets/waf_rules/recommended.json +355 -157
- data/lib/datadog/appsec/assets/waf_rules/strict.json +62 -32
- data/lib/datadog/appsec/component.rb +14 -8
- data/lib/datadog/appsec/configuration/settings.rb +9 -0
- data/lib/datadog/appsec/context.rb +74 -0
- data/lib/datadog/appsec/contrib/active_record/instrumentation.rb +12 -8
- data/lib/datadog/appsec/contrib/devise/patcher/authenticatable_patch.rb +6 -6
- data/lib/datadog/appsec/contrib/devise/patcher/registration_controller_patch.rb +4 -4
- data/lib/datadog/appsec/contrib/graphql/appsec_trace.rb +1 -7
- data/lib/datadog/appsec/contrib/graphql/gateway/watcher.rb +20 -30
- data/lib/datadog/appsec/contrib/graphql/reactive/multiplex.rb +6 -6
- data/lib/datadog/appsec/contrib/rack/gateway/response.rb +3 -3
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +67 -96
- data/lib/datadog/appsec/contrib/rack/reactive/request.rb +11 -11
- data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +6 -6
- data/lib/datadog/appsec/contrib/rack/reactive/response.rb +7 -7
- data/lib/datadog/appsec/contrib/rack/request_body_middleware.rb +10 -11
- data/lib/datadog/appsec/contrib/rack/request_middleware.rb +43 -60
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +23 -33
- data/lib/datadog/appsec/contrib/rails/patcher.rb +4 -14
- data/lib/datadog/appsec/contrib/rails/reactive/action.rb +7 -7
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +45 -65
- data/lib/datadog/appsec/contrib/sinatra/patcher.rb +5 -28
- data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +6 -6
- data/lib/datadog/appsec/event.rb +6 -6
- data/lib/datadog/appsec/ext.rb +8 -1
- data/lib/datadog/appsec/metrics/collector.rb +38 -0
- data/lib/datadog/appsec/metrics/exporter.rb +35 -0
- data/lib/datadog/appsec/metrics/telemetry.rb +23 -0
- data/lib/datadog/appsec/metrics.rb +13 -0
- data/lib/datadog/appsec/monitor/gateway/watcher.rb +23 -32
- data/lib/datadog/appsec/monitor/reactive/set_user.rb +6 -6
- data/lib/datadog/appsec/processor/rule_loader.rb +0 -3
- data/lib/datadog/appsec/processor.rb +4 -3
- data/lib/datadog/appsec/response.rb +18 -80
- data/lib/datadog/appsec/security_engine/result.rb +67 -0
- data/lib/datadog/appsec/security_engine/runner.rb +88 -0
- data/lib/datadog/appsec/security_engine.rb +9 -0
- data/lib/datadog/appsec.rb +17 -8
- data/lib/datadog/auto_instrument.rb +3 -0
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +39 -11
- data/lib/datadog/core/configuration/components.rb +4 -2
- data/lib/datadog/core/configuration.rb +1 -1
- data/lib/datadog/{tracing → core}/contrib/rails/utils.rb +1 -3
- data/lib/datadog/core/crashtracking/component.rb +1 -3
- data/lib/datadog/core/telemetry/event.rb +87 -3
- data/lib/datadog/core/telemetry/logging.rb +2 -2
- data/lib/datadog/core/telemetry/metric.rb +22 -0
- data/lib/datadog/core/telemetry/worker.rb +33 -0
- data/lib/datadog/di/base.rb +115 -0
- data/lib/datadog/di/code_tracker.rb +7 -4
- data/lib/datadog/di/component.rb +19 -11
- data/lib/datadog/di/configuration/settings.rb +11 -1
- data/lib/datadog/di/contrib/railtie.rb +15 -0
- data/lib/datadog/di/contrib.rb +26 -0
- data/lib/datadog/di/error.rb +5 -0
- data/lib/datadog/di/instrumenter.rb +39 -18
- data/lib/datadog/di/{init.rb → preload.rb} +2 -4
- data/lib/datadog/di/probe_manager.rb +4 -4
- data/lib/datadog/di/probe_notification_builder.rb +22 -2
- data/lib/datadog/di/probe_notifier_worker.rb +5 -6
- data/lib/datadog/di/redactor.rb +0 -1
- data/lib/datadog/di/remote.rb +30 -9
- data/lib/datadog/di/transport.rb +2 -4
- data/lib/datadog/di.rb +5 -108
- data/lib/datadog/kit/appsec/events.rb +3 -3
- data/lib/datadog/kit/identity.rb +4 -4
- data/lib/datadog/profiling/component.rb +55 -53
- data/lib/datadog/profiling/http_transport.rb +1 -26
- data/lib/datadog/tracing/contrib/action_cable/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/action_mailer/integration.rb +6 -2
- data/lib/datadog/tracing/contrib/action_pack/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/action_view/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/active_job/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/active_record/integration.rb +6 -2
- data/lib/datadog/tracing/contrib/active_support/cache/events/cache.rb +3 -1
- data/lib/datadog/tracing/contrib/active_support/cache/instrumentation.rb +3 -1
- data/lib/datadog/tracing/contrib/active_support/configuration/settings.rb +10 -0
- data/lib/datadog/tracing/contrib/active_support/integration.rb +5 -2
- data/lib/datadog/tracing/contrib/auto_instrument.rb +2 -2
- data/lib/datadog/tracing/contrib/aws/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/concurrent_ruby/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/extensions.rb +15 -3
- data/lib/datadog/tracing/contrib/http/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/httprb/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/kafka/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/mongodb/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/opensearch/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/presto/integration.rb +3 -0
- data/lib/datadog/tracing/contrib/rack/integration.rb +2 -2
- data/lib/datadog/tracing/contrib/rails/framework.rb +2 -2
- data/lib/datadog/tracing/contrib/rails/patcher.rb +1 -1
- data/lib/datadog/tracing/contrib/rest_client/integration.rb +3 -0
- data/lib/datadog/tracing/span.rb +12 -4
- data/lib/datadog/tracing/span_event.rb +123 -3
- data/lib/datadog/tracing/span_operation.rb +6 -0
- data/lib/datadog/tracing/transport/serializable_trace.rb +24 -6
- data/lib/datadog/version.rb +1 -1
- metadata +40 -17
- data/lib/datadog/appsec/contrib/sinatra/ext.rb +0 -14
- data/lib/datadog/appsec/processor/context.rb +0 -107
- data/lib/datadog/appsec/reactive/operation.rb +0 -68
- data/lib/datadog/appsec/scope.rb +0 -58
- 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.
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
13
|
-
|
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 =
|
28
|
+
result = context.run_rasp(Ext::RASP_SQLI, {}, ephemeral_data, waf_timeout)
|
27
29
|
|
28
|
-
if result.
|
29
|
-
Datadog::AppSec::Event.tag_and_keep!(
|
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:
|
34
|
-
span:
|
35
|
+
trace: context.trace,
|
36
|
+
span: context.span,
|
35
37
|
sql: sql,
|
36
38
|
actions: result.actions
|
37
39
|
}
|
38
|
-
|
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
|
-
|
26
|
+
appsec_context = Datadog::AppSec.active_context
|
27
27
|
|
28
|
-
return result unless
|
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
|
-
|
43
|
-
|
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
|
-
|
63
|
-
|
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
|
-
|
24
|
-
return super unless
|
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
|
-
|
40
|
-
|
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,
|
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
|
-
|
29
|
-
|
30
|
-
if
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
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
|
-
|
54
|
-
res ||= []
|
55
|
-
res << [:monitor, event]
|
45
|
+
GraphQL::Reactive::Multiplex.publish(engine, gateway_multiplex)
|
56
46
|
end
|
57
47
|
|
58
|
-
|
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(
|
15
|
+
def self.publish(engine, gateway_multiplex)
|
16
16
|
catch(:block) do
|
17
|
-
|
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(
|
24
|
-
|
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 =
|
33
|
+
result = context.run_waf(persistent_data, {}, waf_timeout)
|
34
34
|
|
35
|
-
next
|
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, :
|
12
|
+
attr_reader :body, :status, :headers, :context
|
13
13
|
|
14
|
-
def initialize(body, status, headers,
|
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
|
-
@
|
19
|
+
@context = context
|
20
20
|
end
|
21
21
|
|
22
22
|
def response
|