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 ;
3638import com .datadog .ddwaf .exception .InvalidRuleSetException ;
3739import com .datadog .ddwaf .exception .UnclassifiedWafException ;
3840import com .squareup .moshi .JsonAdapter ;
39- import com .squareup .moshi .Moshi ;
40- import com .squareup .moshi .Types ;
41+ import com .squareup .moshi .JsonReader ;
42+ import com .squareup .moshi .JsonWriter ;
4143import datadog .remoteconfig .ConfigurationEndListener ;
4244import datadog .remoteconfig .ConfigurationPoller ;
4345import datadog .remoteconfig .PollingRateHinter ;
5860import java .util .Collections ;
5961import java .util .HashMap ;
6062import java .util .HashSet ;
63+ import java .util .LinkedHashMap ;
6164import java .util .List ;
6265import java .util .Map ;
6366import java .util .Set ;
@@ -90,15 +93,12 @@ public class AppSecConfigServiceImpl implements AppSecConfigService {
9093 new WAFInitializationResultReporter ();
9194 private final WAFStatsReporter statsReporter = new WAFStatsReporter ();
9295
93- private static final JsonAdapter <Map <String , Object >> ADAPTER =
94- new Moshi .Builder ()
95- .build ()
96- .adapter (Types .newParameterizedType (Map .class , String .class , Object .class ));
96+ private static final JsonAdapter <Object > ADAPTER = new SafeMapAdapter ();
9797
9898 private boolean hasUserWafConfig ;
9999 private boolean defaultConfigActivated ;
100100 private final Set <String > usedDDWafConfigKeys = new HashSet <>();
101- private final String DEFAULT_WAF_CONFIG_RULE = "DEFAULT_WAF_CONFIG " ;
101+ private final String DEFAULT_WAF_CONFIG_RULE = "ASM_DD/default " ;
102102 private String currentRuleVersion ;
103103 private List <AppSecModule > modulesToUpdateVersionIn ;
104104
@@ -129,6 +129,7 @@ private void subscribeConfigurationPoller() {
129129
130130 long capabilities =
131131 CAPABILITY_ASM_DD_RULES
132+ | CAPABILITY_ASM_DD_MULTICONFIG
132133 | CAPABILITY_ASM_IP_BLOCKING
133134 | CAPABILITY_ASM_EXCLUSIONS
134135 | CAPABILITY_ASM_EXCLUSION_DATA
@@ -140,7 +141,8 @@ private void subscribeConfigurationPoller() {
140141 | CAPABILITY_ENDPOINT_FINGERPRINT
141142 | CAPABILITY_ASM_SESSION_FINGERPRINT
142143 | CAPABILITY_ASM_NETWORK_FINGERPRINT
143- | CAPABILITY_ASM_HEADER_FINGERPRINT ;
144+ | CAPABILITY_ASM_HEADER_FINGERPRINT
145+ | CAPABILITY_ASM_TRACE_TAGGING_RULES ;
144146 if (tracerConfig .isAppSecRaspEnabled ()) {
145147 capabilities |= CAPABILITY_ASM_RASP_SQLI ;
146148 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 ) {
@@ -306,7 +309,10 @@ private void subscribeAsmFeatures() {
306309 private void distributeSubConfigurations (
307310 String key , AppSecModuleConfigurer .Reconfiguration reconfiguration ) {
308311 if (usedDDWafConfigKeys .isEmpty () && !defaultConfigActivated && !hasUserWafConfig ) {
309- // no config left in the WAF builder, add the default config
312+ // ASM_DD Failure Fallback: If none of the configurations obtained through ASM_DD were loaded
313+ // successfully,
314+ // libraries must revert back to the default configuration
315+ log .debug ("No ASM_DD configurations loaded, falling back to default configuration" );
310316 init ();
311317 }
312318 for (Map .Entry <String , SubconfigListener > entry : subconfigListeners .entrySet ()) {
@@ -427,7 +433,8 @@ private static Map<String, Object> loadDefaultWafConfig() throws IOException {
427433 throw new IOException ("Resource " + DEFAULT_CONFIG_LOCATION + " not found" );
428434 }
429435
430- Map <String , Object > ret = ADAPTER .fromJson (Okio .buffer (Okio .source (is )));
436+ Map <String , Object > ret =
437+ (Map <String , Object >) ADAPTER .fromJson (Okio .buffer (Okio .source (is )));
431438
432439 StandardizedLogging ._initialConfigSourceAndLibddwafVersion (log , "<bundled config>" );
433440 if (log .isInfoEnabled ()) {
@@ -444,7 +451,8 @@ private static Map<String, Object> loadUserWafConfig(Config tracerConfig) throws
444451 return null ;
445452 }
446453 try (InputStream is = new FileInputStream (filename )) {
447- Map <String , Object > ret = ADAPTER .fromJson (Okio .buffer (Okio .source (is )));
454+ Map <String , Object > ret =
455+ (Map <String , Object >) ADAPTER .fromJson (Okio .buffer (Okio .source (is )));
448456
449457 StandardizedLogging ._initialConfigSourceAndLibddwafVersion (log , filename );
450458 if (log .isInfoEnabled ()) {
@@ -473,6 +481,7 @@ public void close() {
473481 this .configurationPoller .removeCapabilities (
474482 CAPABILITY_ASM_ACTIVATION
475483 | CAPABILITY_ASM_DD_RULES
484+ | CAPABILITY_ASM_DD_MULTICONFIG
476485 | CAPABILITY_ASM_IP_BLOCKING
477486 | CAPABILITY_ASM_EXCLUSIONS
478487 | CAPABILITY_ASM_EXCLUSION_DATA
@@ -490,7 +499,8 @@ public void close() {
490499 | CAPABILITY_ENDPOINT_FINGERPRINT
491500 | CAPABILITY_ASM_SESSION_FINGERPRINT
492501 | CAPABILITY_ASM_NETWORK_FINGERPRINT
493- | CAPABILITY_ASM_HEADER_FINGERPRINT );
502+ | CAPABILITY_ASM_HEADER_FINGERPRINT
503+ | CAPABILITY_ASM_TRACE_TAGGING_RULES );
494504 this .configurationPoller .removeListeners (Product .ASM_DD );
495505 this .configurationPoller .removeListeners (Product .ASM_DATA );
496506 this .configurationPoller .removeListeners (Product .ASM );
@@ -558,4 +568,48 @@ private static WafConfig createWafConfig(Config config) {
558568 }
559569 return wafConfig ;
560570 }
571+
572+ private static class SafeMapAdapter extends JsonAdapter <Object > {
573+ @ Override
574+ public Object fromJson (JsonReader reader ) throws IOException {
575+ switch (reader .peek ()) {
576+ case BEGIN_OBJECT :
577+ Map <String , Object > map = new LinkedHashMap <>();
578+ reader .beginObject ();
579+ while (reader .hasNext ()) {
580+ map .put (reader .nextName (), fromJson (reader ));
581+ }
582+ reader .endObject ();
583+ return map ;
584+
585+ case BEGIN_ARRAY :
586+ List <Object > list = new ArrayList <>();
587+ reader .beginArray ();
588+ while (reader .hasNext ()) {
589+ list .add (fromJson (reader ));
590+ }
591+ reader .endArray ();
592+ return list ;
593+
594+ case STRING :
595+ case NUMBER :
596+ return reader .nextString ();
597+
598+ case BOOLEAN :
599+ return reader .nextBoolean ();
600+
601+ case NULL :
602+ reader .nextNull ();
603+ return null ;
604+
605+ default :
606+ throw new IllegalStateException ("Unexpected token: " + reader .peek ());
607+ }
608+ }
609+
610+ @ Override
611+ public void toJson (JsonWriter writer , Object value ) throws IOException {
612+ throw new UnsupportedOperationException ("Serialization not supported" );
613+ }
614+ }
561615}
0 commit comments