5
5
import static datadog .remoteconfig .Capabilities .CAPABILITY_ASM_AUTO_USER_INSTRUM_MODE ;
6
6
import static datadog .remoteconfig .Capabilities .CAPABILITY_ASM_CUSTOM_BLOCKING_RESPONSE ;
7
7
import static datadog .remoteconfig .Capabilities .CAPABILITY_ASM_CUSTOM_RULES ;
8
+ import static datadog .remoteconfig .Capabilities .CAPABILITY_ASM_DD_MULTICONFIG ;
8
9
import static datadog .remoteconfig .Capabilities .CAPABILITY_ASM_DD_RULES ;
9
10
import static datadog .remoteconfig .Capabilities .CAPABILITY_ASM_EXCLUSIONS ;
10
11
import static datadog .remoteconfig .Capabilities .CAPABILITY_ASM_EXCLUSION_DATA ;
18
19
import static datadog .remoteconfig .Capabilities .CAPABILITY_ASM_RASP_SSRF ;
19
20
import static datadog .remoteconfig .Capabilities .CAPABILITY_ASM_REQUEST_BLOCKING ;
20
21
import static datadog .remoteconfig .Capabilities .CAPABILITY_ASM_SESSION_FINGERPRINT ;
22
+ import static datadog .remoteconfig .Capabilities .CAPABILITY_ASM_TRACE_TAGGING_RULES ;
21
23
import static datadog .remoteconfig .Capabilities .CAPABILITY_ASM_TRUSTED_IPS ;
22
24
import static datadog .remoteconfig .Capabilities .CAPABILITY_ASM_USER_BLOCKING ;
23
25
import static datadog .remoteconfig .Capabilities .CAPABILITY_ENDPOINT_FINGERPRINT ;
37
39
import com .datadog .ddwaf .exception .InvalidRuleSetException ;
38
40
import com .datadog .ddwaf .exception .UnclassifiedWafException ;
39
41
import com .squareup .moshi .JsonAdapter ;
40
- import com .squareup .moshi .Moshi ;
41
- import com .squareup .moshi .Types ;
42
+ import com .squareup .moshi .JsonReader ;
43
+ import com .squareup .moshi .JsonWriter ;
42
44
import datadog .remoteconfig .ConfigurationEndListener ;
43
45
import datadog .remoteconfig .ConfigurationPoller ;
44
46
import datadog .remoteconfig .PollingRateHinter ;
60
62
import java .util .ArrayList ;
61
63
import java .util .Collections ;
62
64
import java .util .HashMap ;
65
+ import java .util .LinkedHashMap ;
63
66
import java .util .List ;
64
67
import java .util .Map ;
65
68
import java .util .Set ;
@@ -92,10 +95,7 @@ public class AppSecConfigServiceImpl implements AppSecConfigService {
92
95
new WAFInitializationResultReporter ();
93
96
private final WAFStatsReporter statsReporter = new WAFStatsReporter ();
94
97
95
- private static final JsonAdapter <Map <String , Object >> ADAPTER =
96
- new Moshi .Builder ()
97
- .build ()
98
- .adapter (Types .newParameterizedType (Map .class , String .class , Object .class ));
98
+ private static final JsonAdapter <Object > ADAPTER = new SafeMapAdapter ();
99
99
100
100
private boolean hasUserWafConfig ;
101
101
private boolean defaultConfigActivated ;
@@ -104,7 +104,7 @@ public class AppSecConfigServiceImpl implements AppSecConfigService {
104
104
Collections .newSetFromMap (new ConcurrentHashMap <>());
105
105
private final Set <String > ignoredConfigKeys =
106
106
Collections .newSetFromMap (new ConcurrentHashMap <>());
107
- private final String DEFAULT_WAF_CONFIG_RULE = "DEFAULT_WAF_CONFIG " ;
107
+ private final String DEFAULT_WAF_CONFIG_RULE = "ASM_DD/default " ;
108
108
private String currentRuleVersion ;
109
109
private List <AppSecModule > modulesToUpdateVersionIn ;
110
110
@@ -137,6 +137,7 @@ private void subscribeConfigurationPoller() {
137
137
private long getRulesAndDataCapabilities () {
138
138
long capabilities =
139
139
CAPABILITY_ASM_DD_RULES
140
+ | CAPABILITY_ASM_DD_MULTICONFIG
140
141
| CAPABILITY_ASM_IP_BLOCKING
141
142
| CAPABILITY_ASM_EXCLUSIONS
142
143
| CAPABILITY_ASM_EXCLUSION_DATA
@@ -148,7 +149,8 @@ private long getRulesAndDataCapabilities() {
148
149
| CAPABILITY_ENDPOINT_FINGERPRINT
149
150
| CAPABILITY_ASM_SESSION_FINGERPRINT
150
151
| CAPABILITY_ASM_NETWORK_FINGERPRINT
151
- | CAPABILITY_ASM_HEADER_FINGERPRINT ;
152
+ | CAPABILITY_ASM_HEADER_FINGERPRINT
153
+ | CAPABILITY_ASM_TRACE_TAGGING_RULES ;
152
154
if (tracerConfig .isAppSecRaspEnabled ()) {
153
155
capabilities |= CAPABILITY_ASM_RASP_SQLI ;
154
156
capabilities |= CAPABILITY_ASM_RASP_SSRF ;
@@ -210,7 +212,8 @@ public void accept(ConfigKey configKey, byte[] content, PollingRateHinter pollin
210
212
}
211
213
final String key = configKey .toString ();
212
214
Map <String , Object > contentMap =
213
- ADAPTER .fromJson (Okio .buffer (Okio .source (new ByteArrayInputStream (content ))));
215
+ (Map <String , Object >)
216
+ ADAPTER .fromJson (Okio .buffer (Okio .source (new ByteArrayInputStream (content ))));
214
217
if (contentMap == null || contentMap .isEmpty ()) {
215
218
ignoredConfigKeys .add (key );
216
219
} else {
@@ -255,7 +258,7 @@ private class AppSecConfigChangesDDListener extends AppSecConfigChangesListener
255
258
@ Override
256
259
protected void beforeApply (final String key , final Map <String , Object > config ) {
257
260
if (defaultConfigActivated ) { // if we get any config, remove the default one
258
- log .debug ("Removing default config" );
261
+ log .debug ("Removing default config ASM_DD/default " );
259
262
try {
260
263
wafBuilder .removeConfig (DEFAULT_WAF_CONFIG_RULE );
261
264
} catch (UnclassifiedWafException e ) {
@@ -466,7 +469,8 @@ private static Map<String, Object> loadDefaultWafConfig() throws IOException {
466
469
throw new IOException ("Resource " + DEFAULT_CONFIG_LOCATION + " not found" );
467
470
}
468
471
469
- Map <String , Object > ret = ADAPTER .fromJson (Okio .buffer (Okio .source (is )));
472
+ Map <String , Object > ret =
473
+ (Map <String , Object >) ADAPTER .fromJson (Okio .buffer (Okio .source (is )));
470
474
471
475
StandardizedLogging ._initialConfigSourceAndLibddwafVersion (log , "<bundled config>" );
472
476
if (log .isInfoEnabled ()) {
@@ -483,7 +487,8 @@ private static Map<String, Object> loadUserWafConfig(Config tracerConfig) throws
483
487
return null ;
484
488
}
485
489
try (InputStream is = new FileInputStream (filename )) {
486
- Map <String , Object > ret = ADAPTER .fromJson (Okio .buffer (Okio .source (is )));
490
+ Map <String , Object > ret =
491
+ (Map <String , Object >) ADAPTER .fromJson (Okio .buffer (Okio .source (is )));
487
492
488
493
StandardizedLogging ._initialConfigSourceAndLibddwafVersion (log , filename );
489
494
if (log .isInfoEnabled ()) {
@@ -512,6 +517,7 @@ public void close() {
512
517
this .configurationPoller .removeCapabilities (
513
518
CAPABILITY_ASM_ACTIVATION
514
519
| CAPABILITY_ASM_DD_RULES
520
+ | CAPABILITY_ASM_DD_MULTICONFIG
515
521
| CAPABILITY_ASM_IP_BLOCKING
516
522
| CAPABILITY_ASM_EXCLUSIONS
517
523
| CAPABILITY_ASM_EXCLUSION_DATA
@@ -529,7 +535,8 @@ public void close() {
529
535
| CAPABILITY_ENDPOINT_FINGERPRINT
530
536
| CAPABILITY_ASM_SESSION_FINGERPRINT
531
537
| CAPABILITY_ASM_NETWORK_FINGERPRINT
532
- | CAPABILITY_ASM_HEADER_FINGERPRINT );
538
+ | CAPABILITY_ASM_HEADER_FINGERPRINT
539
+ | CAPABILITY_ASM_TRACE_TAGGING_RULES );
533
540
this .configurationPoller .removeListeners (Product .ASM_DD );
534
541
this .configurationPoller .removeListeners (Product .ASM_DATA );
535
542
this .configurationPoller .removeListeners (Product .ASM );
@@ -601,4 +608,59 @@ private static WafConfig createWafConfig(Config config) {
601
608
}
602
609
return wafConfig ;
603
610
}
611
+
612
+ private static class SafeMapAdapter extends JsonAdapter <Object > {
613
+ @ Override
614
+ public Object fromJson (JsonReader reader ) throws IOException {
615
+ switch (reader .peek ()) {
616
+ case BEGIN_OBJECT :
617
+ Map <String , Object > map = new LinkedHashMap <>();
618
+ reader .beginObject ();
619
+ while (reader .hasNext ()) {
620
+ map .put (reader .nextName (), fromJson (reader ));
621
+ }
622
+ reader .endObject ();
623
+ return map ;
624
+
625
+ case BEGIN_ARRAY :
626
+ List <Object > list = new ArrayList <>();
627
+ reader .beginArray ();
628
+ while (reader .hasNext ()) {
629
+ list .add (fromJson (reader ));
630
+ }
631
+ reader .endArray ();
632
+ return list ;
633
+
634
+ case STRING :
635
+ return reader .nextString ();
636
+ case NUMBER :
637
+ String numberStr = reader .nextString ();
638
+ try {
639
+ if (numberStr .contains ("." )) {
640
+ return Double .parseDouble (numberStr );
641
+ } else {
642
+ return Long .parseLong (numberStr );
643
+ }
644
+ } catch (NumberFormatException e ) {
645
+ // Fallback to string if parsing fails
646
+ return numberStr ;
647
+ }
648
+
649
+ case BOOLEAN :
650
+ return reader .nextBoolean ();
651
+
652
+ case NULL :
653
+ reader .nextNull ();
654
+ return null ;
655
+
656
+ default :
657
+ throw new IllegalStateException ("Unexpected token: " + reader .peek ());
658
+ }
659
+ }
660
+
661
+ @ Override
662
+ public void toJson (JsonWriter writer , Object value ) throws IOException {
663
+ throw new UnsupportedOperationException ("Serialization not supported" );
664
+ }
665
+ }
604
666
}
0 commit comments