55import static datadog .remoteconfig .Capabilities .CAPABILITY_ASM_AUTO_USER_INSTRUM_MODE ;
66import static datadog .remoteconfig .Capabilities .CAPABILITY_ASM_CUSTOM_BLOCKING_RESPONSE ;
77import static datadog .remoteconfig .Capabilities .CAPABILITY_ASM_CUSTOM_RULES ;
8+ import static datadog .remoteconfig .Capabilities .CAPABILITY_ASM_DD_MULTICONFIG ;
89import static datadog .remoteconfig .Capabilities .CAPABILITY_ASM_DD_RULES ;
910import static datadog .remoteconfig .Capabilities .CAPABILITY_ASM_EXCLUSIONS ;
1011import static datadog .remoteconfig .Capabilities .CAPABILITY_ASM_EXCLUSION_DATA ;
1819import static datadog .remoteconfig .Capabilities .CAPABILITY_ASM_RASP_SSRF ;
1920import static datadog .remoteconfig .Capabilities .CAPABILITY_ASM_REQUEST_BLOCKING ;
2021import static datadog .remoteconfig .Capabilities .CAPABILITY_ASM_SESSION_FINGERPRINT ;
22+ import static datadog .remoteconfig .Capabilities .CAPABILITY_ASM_TRACE_TAGGING_RULES ;
2123import static datadog .remoteconfig .Capabilities .CAPABILITY_ASM_TRUSTED_IPS ;
2224import static datadog .remoteconfig .Capabilities .CAPABILITY_ASM_USER_BLOCKING ;
2325import static datadog .remoteconfig .Capabilities .CAPABILITY_ENDPOINT_FINGERPRINT ;
3739import com .datadog .ddwaf .exception .InvalidRuleSetException ;
3840import com .datadog .ddwaf .exception .UnclassifiedWafException ;
3941import 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 ;
4244import datadog .remoteconfig .ConfigurationEndListener ;
4345import datadog .remoteconfig .ConfigurationPoller ;
4446import datadog .remoteconfig .PollingRateHinter ;
6163import java .util .Collections ;
6264import java .util .HashMap ;
6365import java .util .HashSet ;
66+ import java .util .LinkedHashMap ;
6467import java .util .List ;
6568import java .util .Map ;
6669import java .util .Set ;
@@ -92,15 +95,12 @@ public class AppSecConfigServiceImpl implements AppSecConfigService {
9295 new WAFInitializationResultReporter ();
9396 private final WAFStatsReporter statsReporter = new WAFStatsReporter ();
9497
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 ();
9999
100100 private boolean hasUserWafConfig ;
101101 private boolean defaultConfigActivated ;
102102 private final Set <String > usedDDWafConfigKeys = new HashSet <>();
103- private final String DEFAULT_WAF_CONFIG_RULE = "DEFAULT_WAF_CONFIG " ;
103+ private final String DEFAULT_WAF_CONFIG_RULE = "ASM_DD/default " ;
104104 private String currentRuleVersion ;
105105 private List <AppSecModule > modulesToUpdateVersionIn ;
106106
@@ -131,6 +131,7 @@ private void subscribeConfigurationPoller() {
131131
132132 long capabilities =
133133 CAPABILITY_ASM_DD_RULES
134+ | CAPABILITY_ASM_DD_MULTICONFIG
134135 | CAPABILITY_ASM_IP_BLOCKING
135136 | CAPABILITY_ASM_EXCLUSIONS
136137 | CAPABILITY_ASM_EXCLUSION_DATA
@@ -142,7 +143,8 @@ private void subscribeConfigurationPoller() {
142143 | CAPABILITY_ENDPOINT_FINGERPRINT
143144 | CAPABILITY_ASM_SESSION_FINGERPRINT
144145 | CAPABILITY_ASM_NETWORK_FINGERPRINT
145- | CAPABILITY_ASM_HEADER_FINGERPRINT ;
146+ | CAPABILITY_ASM_HEADER_FINGERPRINT
147+ | CAPABILITY_ASM_TRACE_TAGGING_RULES ;
146148 if (tracerConfig .isAppSecRaspEnabled ()) {
147149 capabilities |= CAPABILITY_ASM_RASP_SQLI ;
148150 capabilities |= CAPABILITY_ASM_RASP_SSRF ;
@@ -185,7 +187,8 @@ public void accept(ConfigKey configKey, byte[] content, PollingRateHinter pollin
185187 }
186188 } else {
187189 Map <String , Object > contentMap =
188- ADAPTER .fromJson (Okio .buffer (Okio .source (new ByteArrayInputStream (content ))));
190+ (Map <String , Object >)
191+ ADAPTER .fromJson (Okio .buffer (Okio .source (new ByteArrayInputStream (content ))));
189192 try {
190193 handleWafUpdateResultReport (configKey .toString (), contentMap );
191194 } catch (AppSecModule .AppSecModuleActivationException e ) {
@@ -211,7 +214,7 @@ private class AppSecConfigChangesDDListener extends AppSecConfigChangesListener
211214 public void accept (ConfigKey configKey , byte [] content , PollingRateHinter pollingRateHinter )
212215 throws IOException {
213216 if (defaultConfigActivated ) { // if we get any config, remove the default one
214- log .debug ("Removing default config" );
217+ log .debug ("Removing default config ASM_DD/default " );
215218 try {
216219 wafBuilder .removeConfig (DEFAULT_WAF_CONFIG_RULE );
217220 } catch (UnclassifiedWafException e ) {
@@ -425,7 +428,8 @@ private static Map<String, Object> loadDefaultWafConfig() throws IOException {
425428 throw new IOException ("Resource " + DEFAULT_CONFIG_LOCATION + " not found" );
426429 }
427430
428- Map <String , Object > ret = ADAPTER .fromJson (Okio .buffer (Okio .source (is )));
431+ Map <String , Object > ret =
432+ (Map <String , Object >) ADAPTER .fromJson (Okio .buffer (Okio .source (is )));
429433
430434 StandardizedLogging ._initialConfigSourceAndLibddwafVersion (log , "<bundled config>" );
431435 if (log .isInfoEnabled ()) {
@@ -442,7 +446,8 @@ private static Map<String, Object> loadUserWafConfig(Config tracerConfig) throws
442446 return null ;
443447 }
444448 try (InputStream is = new FileInputStream (filename )) {
445- Map <String , Object > ret = ADAPTER .fromJson (Okio .buffer (Okio .source (is )));
449+ Map <String , Object > ret =
450+ (Map <String , Object >) ADAPTER .fromJson (Okio .buffer (Okio .source (is )));
446451
447452 StandardizedLogging ._initialConfigSourceAndLibddwafVersion (log , filename );
448453 if (log .isInfoEnabled ()) {
@@ -471,6 +476,7 @@ public void close() {
471476 this .configurationPoller .removeCapabilities (
472477 CAPABILITY_ASM_ACTIVATION
473478 | CAPABILITY_ASM_DD_RULES
479+ | CAPABILITY_ASM_DD_MULTICONFIG
474480 | CAPABILITY_ASM_IP_BLOCKING
475481 | CAPABILITY_ASM_EXCLUSIONS
476482 | CAPABILITY_ASM_EXCLUSION_DATA
@@ -488,7 +494,8 @@ public void close() {
488494 | CAPABILITY_ENDPOINT_FINGERPRINT
489495 | CAPABILITY_ASM_SESSION_FINGERPRINT
490496 | CAPABILITY_ASM_NETWORK_FINGERPRINT
491- | CAPABILITY_ASM_HEADER_FINGERPRINT );
497+ | CAPABILITY_ASM_HEADER_FINGERPRINT
498+ | CAPABILITY_ASM_TRACE_TAGGING_RULES );
492499 this .configurationPoller .removeListeners (Product .ASM_DD );
493500 this .configurationPoller .removeListeners (Product .ASM_DATA );
494501 this .configurationPoller .removeListeners (Product .ASM );
@@ -558,4 +565,59 @@ private static WafConfig createWafConfig(Config config) {
558565 }
559566 return wafConfig ;
560567 }
568+
569+ private static class SafeMapAdapter extends JsonAdapter <Object > {
570+ @ Override
571+ public Object fromJson (JsonReader reader ) throws IOException {
572+ switch (reader .peek ()) {
573+ case BEGIN_OBJECT :
574+ Map <String , Object > map = new LinkedHashMap <>();
575+ reader .beginObject ();
576+ while (reader .hasNext ()) {
577+ map .put (reader .nextName (), fromJson (reader ));
578+ }
579+ reader .endObject ();
580+ return map ;
581+
582+ case BEGIN_ARRAY :
583+ List <Object > list = new ArrayList <>();
584+ reader .beginArray ();
585+ while (reader .hasNext ()) {
586+ list .add (fromJson (reader ));
587+ }
588+ reader .endArray ();
589+ return list ;
590+
591+ case STRING :
592+ return reader .nextString ();
593+ case NUMBER :
594+ String numberStr = reader .nextString ();
595+ try {
596+ if (numberStr .contains ("." )) {
597+ return Double .parseDouble (numberStr );
598+ } else {
599+ return Long .parseLong (numberStr );
600+ }
601+ } catch (NumberFormatException e ) {
602+ // Fallback to string if parsing fails
603+ return numberStr ;
604+ }
605+
606+ case BOOLEAN :
607+ return reader .nextBoolean ();
608+
609+ case NULL :
610+ reader .nextNull ();
611+ return null ;
612+
613+ default :
614+ throw new IllegalStateException ("Unexpected token: " + reader .peek ());
615+ }
616+ }
617+
618+ @ Override
619+ public void toJson (JsonWriter writer , Object value ) throws IOException {
620+ throw new UnsupportedOperationException ("Serialization not supported" );
621+ }
622+ }
561623}
0 commit comments