Skip to content

Commit 9c88d82

Browse files
smolasezen-datadog
authored andcommitted
Add comments on missing bits for error handling
Remove unused WafHandle field Fix numLoadedRules logging Undo unnecessary changes (fixes memory leaks, race conditions) spotless Just capture ASM_DD listener in test via ConfigurationPoller stub Mock ConfigurationPoller in tests
1 parent f827d79 commit 9c88d82

File tree

4 files changed

+111
-80
lines changed

4 files changed

+111
-80
lines changed

dd-java-agent/appsec/src/main/java/com/datadog/appsec/config/AppSecConfigServiceImpl.java

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@
6060
import java.util.Map;
6161
import java.util.Set;
6262
import java.util.concurrent.ConcurrentHashMap;
63+
64+
import datadog.trace.api.telemetry.LogCollector;
6365
import okio.Okio;
6466
import org.slf4j.Logger;
6567
import org.slf4j.LoggerFactory;
@@ -97,7 +99,6 @@ public class AppSecConfigServiceImpl implements AppSecConfigService {
9799
private boolean defaultConfigActivated;
98100
private final Set<String> usedDDWafConfigKeys = new HashSet<>();
99101
private final String DEFAULT_WAF_CONFIG_RULE = "DEFAULT_WAF_CONFIG";
100-
private final AsmDDTypedListener asmDDTypedListener;
101102
private String currentRuleVersion;
102103
private List<AppSecModule> modulesToUpdateVersionIn;
103104

@@ -112,7 +113,6 @@ public AppSecConfigServiceImpl(
112113
if (tracerConfig.isAppSecWafMetrics()) {
113114
traceSegmentPostProcessors.add(statsReporter);
114115
}
115-
asmDDTypedListener = new AsmDDTypedListener();
116116
}
117117

118118
private void subscribeConfigurationPoller() {
@@ -156,7 +156,7 @@ private void subscribeConfigurationPoller() {
156156
}
157157

158158
private void subscribeRulesAndData() {
159-
this.configurationPoller.addListener(Product.ASM_DD, asmDDTypedListener);
159+
this.configurationPoller.addListener(Product.ASM_DD, new AsmDDTypedListener());
160160
this.configurationPoller.addListener(
161161
Product.ASM_DATA, new AppSecConfigConfigurationChangesTypedListener());
162162
this.configurationPoller.addListener(
@@ -233,8 +233,7 @@ public void remove(ConfigKey configKey, PollingRateHinter pollingRateHinter)
233233
}
234234
}
235235

236-
private void handleWafUpdateResultReport(
237-
String configKey, Map<String, Object> rawConfig, String... filename)
236+
private void handleWafUpdateResultReport(String configKey, Map<String, Object> rawConfig)
238237
throws AppSecModule.AppSecModuleActivationException {
239238
wafBuilder = getWafBuilder();
240239
if (modulesToUpdateVersionIn != null
@@ -244,9 +243,13 @@ private void handleWafUpdateResultReport(
244243
}
245244
try {
246245
WafDiagnostics wafDiagnostics = wafBuilder.addOrUpdateConfig(configKey, rawConfig);
247-
if (log.isInfoEnabled() && filename.length > 0) {
248-
StandardizedLogging.numLoadedRules(log, filename[0], countRules(rawConfig));
246+
if (log.isInfoEnabled()) {
247+
StandardizedLogging.numLoadedRules(log, configKey, countRules(rawConfig));
249248
}
249+
250+
// TODO: Send diagnostics via telemetry
251+
final LogCollector telemetryLogger = LogCollector.get();
252+
250253
initReporter.setReportForPublication(wafDiagnostics);
251254
if (wafDiagnostics.rulesetVersion != null
252255
&& !wafDiagnostics.rulesetVersion.isEmpty()
@@ -263,6 +266,9 @@ private void handleWafUpdateResultReport(
263266
"Invalid rule during waf config update for config key {}: {}",
264267
configKey,
265268
e.wafDiagnostics);
269+
270+
// TODO: Propagate diagostics back to remote config apply_error
271+
266272
initReporter.setReportForPublication(e.wafDiagnostics);
267273
throw new RuntimeException(e);
268274
} catch (UnclassifiedWafException e) {

dd-java-agent/appsec/src/main/java/com/datadog/appsec/ddwaf/WAFModule.java

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ public class WAFModule implements AppSecModule {
8282
private static final Map<String, ActionInfo> DEFAULT_ACTIONS;
8383

8484
private static final String EXPLOIT_DETECTED_MSG = "Exploit detected";
85-
private WafHandle wafHandle;
8685
private boolean init = true;
8786
private String rulesetVersion;
8887
private WafBuilder wafBuilder;
@@ -99,9 +98,11 @@ private ActionInfo(String type, Map<String, Object> parameters) {
9998

10099
private static class CtxAndAddresses {
101100
final Collection<Address<?>> addressesOfInterest;
101+
final WafHandle ctx;
102102

103-
private CtxAndAddresses(Collection<Address<?>> addressesOfInterest) {
103+
private CtxAndAddresses(Collection<Address<?>> addressesOfInterest, WafHandle ctx) {
104104
this.addressesOfInterest = addressesOfInterest;
105+
this.ctx = ctx;
105106
}
106107
}
107108

@@ -137,6 +138,8 @@ static void createLimitsObject() {
137138
Config.get().getAppSecWafTimeout());
138139
}
139140

141+
private final boolean wafMetricsEnabled =
142+
Config.get().isAppSecWafMetrics(); // could be static if not for tests
140143
private final AtomicReference<CtxAndAddresses> ctxAndAddresses = new AtomicReference<>();
141144
private final RateLimiter rateLimiter;
142145

@@ -197,24 +200,27 @@ private void applyConfig(AppSecModuleConfigurer.Reconfiguration reconf)
197200

198201
private void initOrUpdateWafHandle(AppSecModuleConfigurer.Reconfiguration reconf)
199202
throws AppSecModuleActivationException {
200-
WafHandle oldHandle = wafHandle;
203+
CtxAndAddresses prevContextAndAddresses = this.ctxAndAddresses.get();
204+
WafHandle newHandle;
201205
try {
202-
wafHandle = wafBuilder.buildWafHandleInstance();
203-
reconf.reloadSubscriptions();
206+
newHandle = wafBuilder.buildWafHandleInstance();
204207
} catch (AbstractWafException e) {
205-
log.info("Could not initialize waf handle, no rules were added!", e);
206208
throw new AppSecModuleActivationException(
207209
"Could not initialize waf handle, no rules were added!", e);
208-
} finally {
209-
if (oldHandle != null && oldHandle.isOnline()) {
210-
oldHandle.close();
211-
}
212210
}
213211

214-
CtxAndAddresses newContextAndAddresses = new CtxAndAddresses(getUsedAddresses(wafHandle));
215-
if (!this.ctxAndAddresses.compareAndSet(ctxAndAddresses.get(), newContextAndAddresses)) {
212+
Collection<Address<?>> addresses = getUsedAddresses(newHandle);
213+
CtxAndAddresses newContextAndAddresses = new CtxAndAddresses(addresses, newHandle);
214+
if (!this.ctxAndAddresses.compareAndSet(prevContextAndAddresses, newContextAndAddresses)) {
215+
newHandle.close();
216216
throw new AppSecModuleActivationException("Concurrent update of WAF configuration");
217217
}
218+
219+
if (prevContextAndAddresses != null) {
220+
prevContextAndAddresses.ctx.close();
221+
}
222+
223+
reconf.reloadSubscriptions();
218224
}
219225

220226
private static RateLimiter getRateLimiter(Monitoring monitoring) {
@@ -289,13 +295,19 @@ public void onDataAvailable(
289295
DataBundle newData,
290296
GatewayContext gwCtx) {
291297
Waf.ResultWithData resultWithData;
298+
CtxAndAddresses ctxAndAddr = ctxAndAddresses.get();
299+
if (ctxAndAddr == null) {
300+
log.debug("Skipped; the WAF is not configured");
301+
return;
302+
}
292303
if (reqCtx.isWafContextClosed()) {
293304
log.debug("Skipped; the WAF context is closed");
294305
if (gwCtx.isRasp) {
295306
WafMetricCollector.get().raspRuleSkipped(gwCtx.raspRuleType);
296307
}
297308
return;
298309
}
310+
299311
StandardizedLogging.executingWAF(log);
300312
long start = 0L;
301313
if (log.isDebugEnabled()) {
@@ -307,7 +319,7 @@ public void onDataAvailable(
307319
}
308320

309321
try {
310-
resultWithData = doRunWaf(reqCtx, newData, gwCtx);
322+
resultWithData = doRunWaf(reqCtx, newData, ctxAndAddr, gwCtx);
311323
} catch (TimeoutWafException tpe) {
312324
if (gwCtx.isRasp) {
313325
reqCtx.increaseRaspTimeouts();
@@ -497,8 +509,13 @@ private StackTraceEvent createExploitStackTraceEvent(String stackId) {
497509
}
498510

499511
private Waf.ResultWithData doRunWaf(
500-
AppSecRequestContext reqCtx, DataBundle newData, GatewayContext gwCtx)
512+
AppSecRequestContext reqCtx,
513+
DataBundle newData,
514+
CtxAndAddresses ctxAndAddr,
515+
GatewayContext gwCtx)
501516
throws AbstractWafException {
517+
WafContext wafContext =
518+
reqCtx.getOrCreateWafContext(ctxAndAddr.ctx, wafMetricsEnabled, gwCtx.isRasp);
502519
WafMetrics metrics;
503520
if (gwCtx.isRasp) {
504521
metrics = reqCtx.getRaspMetrics();
@@ -508,18 +525,17 @@ private Waf.ResultWithData doRunWaf(
508525
}
509526

510527
if (gwCtx.isTransient) {
511-
return runWafTransient(
512-
reqCtx.getOrCreateWafContext(wafHandle, gwCtx.isRasp), metrics, newData);
528+
return runWafTransient(wafContext, metrics, newData, ctxAndAddr);
513529
} else {
514-
return runWafContext(
515-
reqCtx.getOrCreateWafContext(wafHandle, gwCtx.isRasp), metrics, newData);
530+
return runWafContext(wafContext, metrics, newData, ctxAndAddr);
516531
}
517532
}
518533

519534
private Waf.ResultWithData runWafContext(
520-
WafContext wafContext, WafMetrics metrics, DataBundle newData) throws AbstractWafException {
535+
WafContext wafContext, WafMetrics metrics, DataBundle newData, CtxAndAddresses ctxAndAddr)
536+
throws AbstractWafException {
521537
return wafContext.run(
522-
new DataBundleMapWrapper(getUsedAddresses(wafHandle), newData), LIMITS, metrics);
538+
new DataBundleMapWrapper(ctxAndAddr.addressesOfInterest, newData), LIMITS, metrics);
523539
}
524540
}
525541

@@ -534,9 +550,10 @@ private static void incrementErrorCodeMetric(
534550
}
535551

536552
private Waf.ResultWithData runWafTransient(
537-
WafContext wafContext, WafMetrics metrics, DataBundle newData) throws AbstractWafException {
553+
WafContext wafContext, WafMetrics metrics, DataBundle newData, CtxAndAddresses ctxAndAddr)
554+
throws AbstractWafException {
538555
return wafContext.runEphemeral(
539-
new DataBundleMapWrapper(getUsedAddresses(wafHandle), newData), LIMITS, metrics);
556+
new DataBundleMapWrapper(ctxAndAddr.addressesOfInterest, newData), LIMITS, metrics);
540557
}
541558

542559
private Collection<AppSecEvent> buildEvents(Waf.ResultWithData actionWithData) {

dd-java-agent/appsec/src/main/java/com/datadog/appsec/gateway/AppSecRequestContext.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,8 +239,9 @@ public int getRaspTimeouts() {
239239
return raspTimeouts;
240240
}
241241

242-
public WafContext getOrCreateWafContext(WafHandle wafHandle, boolean isRasp) {
243-
if (Config.get().isAppSecWafMetrics()) {
242+
public WafContext getOrCreateWafContext(
243+
WafHandle wafHandle, boolean createMetrics, boolean isRasp) {
244+
if (createMetrics) {
244245
if (wafMetrics == null) {
245246
this.wafMetrics = new WafMetrics();
246247
}

0 commit comments

Comments
 (0)