Skip to content

Commit 3e089a7

Browse files
committed
Create metric: appsec.rasp.error
1 parent ec92bff commit 3e089a7

File tree

3 files changed

+89
-1
lines changed

3 files changed

+89
-1
lines changed

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ public class AppSecRequestContext implements DataBundle, Closeable {
124124
private volatile boolean blocked;
125125
private volatile int wafTimeouts;
126126
private volatile int raspTimeouts;
127+
private volatile int raspInternalErrors;
128+
private volatile int raspInvalidObjectErrors;
129+
private volatile int raspInvalidArgumentErrors;
127130

128131
// keep a reference to the last published usr.id
129132
private volatile String userId;
@@ -139,6 +142,18 @@ public class AppSecRequestContext implements DataBundle, Closeable {
139142
private static final AtomicIntegerFieldUpdater<AppSecRequestContext> RASP_TIMEOUTS_UPDATER =
140143
AtomicIntegerFieldUpdater.newUpdater(AppSecRequestContext.class, "raspTimeouts");
141144

145+
private static final AtomicIntegerFieldUpdater<AppSecRequestContext>
146+
RASP_INTERNAL_ERRORS_UPDATER =
147+
AtomicIntegerFieldUpdater.newUpdater(AppSecRequestContext.class, "raspInternalErrors");
148+
private static final AtomicIntegerFieldUpdater<AppSecRequestContext>
149+
RASP_INVALID_OBJECT_ERRORS_UPDATER =
150+
AtomicIntegerFieldUpdater.newUpdater(
151+
AppSecRequestContext.class, "raspInvalidObjectErrors");
152+
private static final AtomicIntegerFieldUpdater<AppSecRequestContext>
153+
RASP_INVALID_ARGUMENT_ERRORS_UPDATER =
154+
AtomicIntegerFieldUpdater.newUpdater(
155+
AppSecRequestContext.class, "raspInvalidArgumentErrors");
156+
142157
// to be called by the Event Dispatcher
143158
public void addAll(DataBundle newData) {
144159
for (Map.Entry<Address<?>, Object> entry : newData) {
@@ -188,6 +203,22 @@ public void increaseRaspTimeouts() {
188203
RASP_TIMEOUTS_UPDATER.incrementAndGet(this);
189204
}
190205

206+
public void increaseRaspErrorCode(int code) {
207+
switch (code) {
208+
case -3:
209+
RASP_INTERNAL_ERRORS_UPDATER.incrementAndGet(this);
210+
break;
211+
case -2:
212+
RASP_INVALID_OBJECT_ERRORS_UPDATER.incrementAndGet(this);
213+
break;
214+
case -1:
215+
RASP_INVALID_ARGUMENT_ERRORS_UPDATER.incrementAndGet(this);
216+
break;
217+
default:
218+
break;
219+
}
220+
}
221+
191222
public int getWafTimeouts() {
192223
return wafTimeouts;
193224
}

dd-java-agent/appsec/src/main/java/com/datadog/appsec/powerwaf/PowerWAFModule.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import io.sqreen.powerwaf.exception.AbstractPowerwafException;
4747
import io.sqreen.powerwaf.exception.InvalidRuleSetException;
4848
import io.sqreen.powerwaf.exception.TimeoutPowerwafException;
49+
import io.sqreen.powerwaf.exception.UnclassifiedPowerwafException;
4950
import java.io.IOException;
5051
import java.lang.reflect.Constructor;
5152
import java.lang.reflect.InvocationHandler;
@@ -439,11 +440,21 @@ public void onDataAvailable(
439440
log.debug(LogCollector.EXCLUDE_TELEMETRY, "Timeout calling the WAF", tpe);
440441
}
441442
return;
442-
} catch (AbstractPowerwafException e) {
443+
} catch (UnclassifiedPowerwafException e) {
443444
if (!reqCtx.isAdditiveClosed()) {
444445
log.error("Error calling WAF", e);
445446
}
446447
return;
448+
} catch (AbstractPowerwafException e) {
449+
if (gwCtx.isRasp) {
450+
reqCtx.increaseRaspErrorCode(e.code);
451+
WafMetricCollector.get().raspErrorCode(gwCtx.raspRuleType, e.code);
452+
} else {
453+
// TODO APPSEC-56703
454+
// reqCtx.increaseWafErrorCode(e.code);
455+
// WafMetricCollector.get().wafErrorCode(e.code);
456+
}
457+
return;
447458
} finally {
448459
if (log.isDebugEnabled()) {
449460
long elapsed = System.currentTimeMillis() - start;

internal-api/src/main/java/datadog/trace/api/telemetry/WafMetricCollector.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,17 @@
66
import java.util.List;
77
import java.util.concurrent.ArrayBlockingQueue;
88
import java.util.concurrent.BlockingQueue;
9+
import java.util.concurrent.ConcurrentMap;
10+
import java.util.concurrent.ConcurrentSkipListMap;
911
import java.util.concurrent.atomic.AtomicInteger;
1012
import java.util.concurrent.atomic.AtomicLong;
1113
import java.util.concurrent.atomic.AtomicLongArray;
1214

1315
public class WafMetricCollector implements MetricCollector<WafMetricCollector.WafMetric> {
1416

1517
public static WafMetricCollector INSTANCE = new WafMetricCollector();
18+
private static final int ABSTRACT_POWERWAF_EXCEPTION_NUMBER =
19+
3; // only 3 error codes are possible for now in AbstractPowerwafException
1620

1721
public static WafMetricCollector get() {
1822
return WafMetricCollector.INSTANCE;
@@ -40,6 +44,8 @@ private WafMetricCollector() {
4044
new AtomicLongArray(RuleType.getNumValues());
4145
private static final AtomicLongArray raspTimeoutCounter =
4246
new AtomicLongArray(RuleType.getNumValues());
47+
private static final ConcurrentMap<Integer, AtomicLongArray> raspErrorCodeCounter =
48+
new ConcurrentSkipListMap<>();
4349
private static final AtomicLongArray missingUserLoginQueue =
4450
new AtomicLongArray(LoginFramework.getNumValues() * LoginEvent.getNumValues());
4551
private static final AtomicLongArray missingUserIdQueue =
@@ -104,6 +110,10 @@ public void raspTimeout(final RuleType ruleType) {
104110
raspTimeoutCounter.incrementAndGet(ruleType.ordinal());
105111
}
106112

113+
public void raspErrorCode(final RuleType ruleType, final int ddwafRunErrorCode) {
114+
raspErrorCodeCounter.get(ddwafRunErrorCode).incrementAndGet(ruleType.ordinal());
115+
}
116+
107117
public void missingUserLogin(final LoginFramework framework, final LoginEvent eventType) {
108118
missingUserLoginQueue.incrementAndGet(
109119
framework.ordinal() * LoginEvent.getNumValues() + eventType.ordinal());
@@ -216,6 +226,21 @@ public void prepareMetrics() {
216226
}
217227
}
218228

229+
// RASP rule type for each possible error code
230+
for (int i = -1 * ABSTRACT_POWERWAF_EXCEPTION_NUMBER; i < 0; i++) {
231+
raspErrorCodeCounter.put(i, new AtomicLongArray(RuleType.getNumValues()));
232+
233+
for (RuleType ruleType : RuleType.values()) {
234+
long counter = raspErrorCodeCounter.get(i).getAndSet(ruleType.ordinal(), 0);
235+
if (counter > 0) {
236+
if (!rawMetricsQueue.offer(
237+
new RaspError(counter, ruleType, WafMetricCollector.wafVersion, i))) {
238+
return;
239+
}
240+
}
241+
}
242+
}
243+
219244
// Missing user login
220245
for (LoginFramework framework : LoginFramework.values()) {
221246
for (LoginEvent event : LoginEvent.values()) {
@@ -367,6 +392,27 @@ public RaspTimeout(final long counter, final RuleType ruleType, final String waf
367392
}
368393
}
369394

395+
public static class RaspError extends WafMetric {
396+
public RaspError(
397+
final long counter,
398+
final RuleType ruleType,
399+
final String wafVersion,
400+
final Integer ddwafRunError) {
401+
super(
402+
"rasp.error",
403+
counter,
404+
ruleType.variant != null
405+
? new String[] {
406+
"rule_type:" + ruleType.type,
407+
"rule_variant:" + ruleType.variant,
408+
"waf_version:" + wafVersion,
409+
"event_rules_version:" + rulesVersion,
410+
"waf_error:" + ddwafRunError
411+
}
412+
: new String[] {"rule_type:" + ruleType.type, "waf_version:" + wafVersion});
413+
}
414+
}
415+
370416
public static class AtomicRequestCounter {
371417

372418
private final AtomicLong atomicLong = new AtomicLong();

0 commit comments

Comments
 (0)