Skip to content

Commit 9af5347

Browse files
authored
Update metrics: appsec.waf.updates and appsec.waf.init (#8280)
1 parent 911db1b commit 9af5347

File tree

5 files changed

+114
-42
lines changed

5 files changed

+114
-42
lines changed

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

+13-6
Original file line numberDiff line numberDiff line change
@@ -245,12 +245,6 @@ private void initializeNewWafCtx(
245245
currentRulesVersion = initReport.rulesetVersion;
246246
}
247247

248-
if (prevContextAndAddresses == null) {
249-
WafMetricCollector.get().wafInit(Powerwaf.LIB_VERSION, currentRulesVersion);
250-
} else {
251-
WafMetricCollector.get().wafUpdates(currentRulesVersion);
252-
}
253-
254248
if (initReport != null) {
255249
log.info(
256250
"Created {} WAF context with rules ({} OK, {} BAD), version {}",
@@ -273,11 +267,13 @@ private void initializeNewWafCtx(
273267
}
274268
} catch (InvalidRuleSetException irse) {
275269
initReport = irse.ruleSetInfo;
270+
sendWafMetrics(prevContextAndAddresses, false);
276271
throw new AppSecModuleActivationException("Error creating WAF rules", irse);
277272
} catch (RuntimeException | AbstractPowerwafException e) {
278273
if (newPwafCtx != null) {
279274
newPwafCtx.close();
280275
}
276+
sendWafMetrics(prevContextAndAddresses, false);
281277
throw new AppSecModuleActivationException("Error creating WAF rules", e);
282278
} finally {
283279
if (initReport != null) {
@@ -287,16 +283,27 @@ private void initializeNewWafCtx(
287283

288284
if (!this.ctxAndAddresses.compareAndSet(prevContextAndAddresses, newContextAndAddresses)) {
289285
newPwafCtx.close();
286+
sendWafMetrics(prevContextAndAddresses, false);
290287
throw new AppSecModuleActivationException("Concurrent update of WAF configuration");
291288
}
292289

290+
sendWafMetrics(prevContextAndAddresses, true);
291+
293292
if (prevContextAndAddresses != null) {
294293
prevContextAndAddresses.ctx.close();
295294
}
296295

297296
reconf.reloadSubscriptions();
298297
}
299298

299+
private void sendWafMetrics(CtxAndAddresses prevContextAndAddresses, boolean success) {
300+
if (prevContextAndAddresses == null) {
301+
WafMetricCollector.get().wafInit(Powerwaf.LIB_VERSION, currentRulesVersion, success);
302+
} else {
303+
WafMetricCollector.get().wafUpdates(currentRulesVersion, success);
304+
}
305+
}
306+
300307
private Map<String, ActionInfo> calculateEffectiveActions(
301308
CtxAndAddresses prevContextAndAddresses, AppSecConfig ruleConfig) {
302309
Map<String, ActionInfo> actionInfoMap;

dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/powerwaf/PowerWAFModuleSpecification.groovy

+64-11
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,10 @@ class PowerWAFModuleSpecification extends DDSpecification {
7070
Additive pwafAdditive
7171
PowerwafMetrics metrics
7272

73+
WafMetricCollector wafMetricCollector = Mock(WafMetricCollector)
74+
7375
void setup() {
76+
WafMetricCollector.INSTANCE = wafMetricCollector
7477
AgentTracer.forceRegister(tracer)
7578
}
7679

@@ -206,6 +209,8 @@ class PowerWAFModuleSpecification extends DDSpecification {
206209
ctx.closeAdditive()
207210

208211
then:
212+
1 * wafMetricCollector.wafInit(Powerwaf.LIB_VERSION, _, true)
213+
1 * wafMetricCollector.wafUpdates(_, true)
209214
1 * reconf.reloadSubscriptions()
210215
1 * flow.setAction({ Flow.Action.RequestBlockingAction rba ->
211216
rba.statusCode == 501 &&
@@ -241,6 +246,7 @@ class PowerWAFModuleSpecification extends DDSpecification {
241246
ctx.closeAdditive()
242247

243248
then:
249+
1 * wafMetricCollector.wafInit(Powerwaf.LIB_VERSION, _, true)
244250
1 * flow.setAction({ Flow.Action.RequestBlockingAction rba ->
245251
rba.statusCode == 403 &&
246252
rba.blockingContentType == BlockingContentType.AUTO
@@ -282,6 +288,7 @@ class PowerWAFModuleSpecification extends DDSpecification {
282288
ctx.closeAdditive()
283289

284290
then:
291+
1 * wafMetricCollector.wafUpdates(_, true)
285292
1 * reconf.reloadSubscriptions()
286293
1 * flow.setAction({ Flow.Action.RequestBlockingAction rba ->
287294
rba.statusCode == 403 &&
@@ -364,6 +371,7 @@ class PowerWAFModuleSpecification extends DDSpecification {
364371
ctx.closeAdditive()
365372

366373
then:
374+
1 * wafMetricCollector.wafUpdates(_, true)
367375
1 * reconf.reloadSubscriptions()
368376
1 * flow.setAction({ Flow.Action.RequestBlockingAction rba ->
369377
rba.statusCode == 403 &&
@@ -440,7 +448,10 @@ class PowerWAFModuleSpecification extends DDSpecification {
440448
}
441449

442450
then:
451+
1 * wafMetricCollector.wafInit(Powerwaf.LIB_VERSION, _, true)
452+
1 * wafMetricCollector.wafUpdates(_, true)
443453
1 * reconf.reloadSubscriptions()
454+
0 * _
444455

445456
when:
446457
dataListener.onDataAvailable(flow, ctx, ATTACK_BUNDLE, gwCtx)
@@ -522,7 +533,10 @@ class PowerWAFModuleSpecification extends DDSpecification {
522533
}
523534

524535
then:
536+
1 * wafMetricCollector.wafInit(Powerwaf.LIB_VERSION, _, true)
537+
1 * wafMetricCollector.wafUpdates(_, true)
525538
1 * reconf.reloadSubscriptions()
539+
0 * _
526540

527541
when:
528542
dataListener.onDataAvailable(flow, ctx, ATTACK_BUNDLE, gwCtx)
@@ -597,7 +611,10 @@ class PowerWAFModuleSpecification extends DDSpecification {
597611
}
598612

599613
then:
614+
1 * wafMetricCollector.wafInit(Powerwaf.LIB_VERSION, _, true)
615+
2 * wafMetricCollector.wafUpdates(_, true)
600616
2 * reconf.reloadSubscriptions()
617+
0 * _
601618

602619
when:
603620
dataListener.onDataAvailable(flow, ctx, ATTACK_BUNDLE, gwCtx)
@@ -972,9 +989,6 @@ class PowerWAFModuleSpecification extends DDSpecification {
972989
TraceSegment segment = Mock()
973990
TraceSegmentPostProcessor pp = service.traceSegmentPostProcessors.last()
974991
975-
def mockWafMetricCollector = Mock(WafMetricCollector)
976-
WafMetricCollector.INSTANCE = mockWafMetricCollector
977-
978992
when:
979993
dataListener.onDataAvailable(flow, ctx, db, gwCtx)
980994
@@ -987,7 +1001,7 @@ class PowerWAFModuleSpecification extends DDSpecification {
9871001
pwafAdditive = it[0].openAdditive() }
9881002
1 * ctx.getWafMetrics()
9891003
1 * ctx.increaseWafTimeouts()
990-
1 * mockWafMetricCollector.get().wafRequestTimeout()
1004+
1 * wafMetricCollector.get().wafRequestTimeout()
9911005
0 * _
9921006
9931007
when:
@@ -1014,9 +1028,6 @@ class PowerWAFModuleSpecification extends DDSpecification {
10141028
TraceSegment segment = Mock()
10151029
TraceSegmentPostProcessor pp = service.traceSegmentPostProcessors.last()
10161030
1017-
def mockWafMetricCollector = Mock(WafMetricCollector)
1018-
WafMetricCollector.INSTANCE = mockWafMetricCollector
1019-
10201031
gwCtx = new GatewayContext(false, RuleType.SQL_INJECTION)
10211032
10221033
when:
@@ -1032,8 +1043,8 @@ class PowerWAFModuleSpecification extends DDSpecification {
10321043
1 * ctx.getRaspMetrics()
10331044
1 * ctx.getRaspMetricsCounter()
10341045
1 * ctx.increaseRaspTimeouts()
1035-
1 * mockWafMetricCollector.get().raspTimeout(gwCtx.raspRuleType)
1036-
1 * mockWafMetricCollector.raspRuleEval(RuleType.SQL_INJECTION)
1046+
1 * wafMetricCollector.get().raspTimeout(gwCtx.raspRuleType)
1047+
1 * wafMetricCollector.raspRuleEval(RuleType.SQL_INJECTION)
10371048
0 * _
10381049
10391050
when:
@@ -1059,6 +1070,7 @@ class PowerWAFModuleSpecification extends DDSpecification {
10591070
10601071
then:
10611072
thrown AppSecModule.AppSecModuleActivationException
1073+
0 * _
10621074
10631075
when:
10641076
cfgService.listeners['waf'].onNewSubconfig(defaultConfig['waf'], reconf)
@@ -1070,7 +1082,14 @@ class PowerWAFModuleSpecification extends DDSpecification {
10701082
1 * ctx.getOrCreateAdditive(_, true, false) >> {
10711083
pwafAdditive = it[0].openAdditive() }
10721084
1 * ctx.reportEvents(_ as Collection<AppSecEvent>)
1085+
1 * ctx.isAdditiveClosed()
1086+
1 * ctx.getWafMetrics()
1087+
1 * ctx.isThrottled(null)
1088+
1 * ctx.closeAdditive()
1089+
2 * tracer.activeSpan()
1090+
1 * wafMetricCollector.wafInit(Powerwaf.LIB_VERSION, _, true)
10731091
1 * reconf.reloadSubscriptions()
1092+
0 * _
10741093
}
10751094
10761095
void 'rule data given through configuration'() {
@@ -1102,6 +1121,7 @@ class PowerWAFModuleSpecification extends DDSpecification {
11021121
ctx.closeAdditive()
11031122
11041123
then:
1124+
1 * wafMetricCollector.wafUpdates(_, true)
11051125
1 * reconf.reloadSubscriptions()
11061126
1 * ctx.getOrCreateAdditive(_, true, false) >> { pwafAdditive = it[0].openAdditive() }
11071127
2 * tracer.activeSpan()
@@ -1159,6 +1179,7 @@ class PowerWAFModuleSpecification extends DDSpecification {
11591179
ctx.closeAdditive()
11601180
11611181
then: 'no match; rule is disabled'
1182+
1 * wafMetricCollector.wafUpdates(_, true)
11621183
1 * reconf.reloadSubscriptions()
11631184
1 * ctx.getOrCreateAdditive(_, true, false) >> {
11641185
pwafAdditive = it[0].openAdditive() }
@@ -1189,6 +1210,7 @@ class PowerWAFModuleSpecification extends DDSpecification {
11891210
1 * ctx.getWafMetrics()
11901211
1 * ctx.isAdditiveClosed() >> false
11911212
1 * ctx.closeAdditive() >> {pwafAdditive.close()}
1213+
1 * wafMetricCollector.wafUpdates(_, true)
11921214
1 * reconf.reloadSubscriptions()
11931215
_ * ctx.increaseWafTimeouts()
11941216
_ * ctx.increaseRaspTimeouts()
@@ -1206,6 +1228,7 @@ class PowerWAFModuleSpecification extends DDSpecification {
12061228
ctx.closeAdditive()
12071229
12081230
then: 'now we have match'
1231+
1 * wafMetricCollector.wafUpdates(_, true)
12091232
1 * reconf.reloadSubscriptions()
12101233
1 * ctx.getOrCreateAdditive(_, true, false) >> {
12111234
pwafAdditive = it[0].openAdditive() }
@@ -1235,6 +1258,7 @@ class PowerWAFModuleSpecification extends DDSpecification {
12351258
ctx.closeAdditive()
12361259
12371260
then: 'nothing again; we disabled the rule'
1261+
1 * wafMetricCollector.wafUpdates(_, true)
12381262
1 * reconf.reloadSubscriptions()
12391263
1 * ctx.getOrCreateAdditive(_, true, false) >> { pwafAdditive = it[0].openAdditive() }
12401264
1 * ctx.getWafMetrics()
@@ -1265,6 +1289,7 @@ class PowerWAFModuleSpecification extends DDSpecification {
12651289
ctx.closeAdditive()
12661290
12671291
then:
1292+
1 * wafMetricCollector.wafUpdates(_, true)
12681293
1 * reconf.reloadSubscriptions()
12691294
// no attack
12701295
1 * ctx.getOrCreateAdditive(_, true, false) >> { pwafAdditive = it[0].openAdditive() }
@@ -1289,6 +1314,7 @@ class PowerWAFModuleSpecification extends DDSpecification {
12891314
ctx.closeAdditive()
12901315
12911316
then:
1317+
1 * wafMetricCollector.wafUpdates(_, true)
12921318
1 * reconf.reloadSubscriptions()
12931319
// no attack
12941320
1 * ctx.getOrCreateAdditive(_, true, false) >> {
@@ -1314,6 +1340,7 @@ class PowerWAFModuleSpecification extends DDSpecification {
13141340
ctx.closeAdditive()
13151341
13161342
then:
1343+
1 * wafMetricCollector.wafUpdates(_, true)
13171344
1 * reconf.reloadSubscriptions()
13181345
// attack found
13191346
1 * ctx.getOrCreateAdditive(_, true, false) >> {
@@ -1342,6 +1369,7 @@ class PowerWAFModuleSpecification extends DDSpecification {
13421369
ctx.closeAdditive()
13431370
13441371
then:
1372+
1 * wafMetricCollector.wafUpdates(_, true)
13451373
1 * reconf.reloadSubscriptions()
13461374
// no attack
13471375
1 * ctx.getOrCreateAdditive(_, true, false) >> {
@@ -1390,7 +1418,9 @@ class PowerWAFModuleSpecification extends DDSpecification {
13901418
pwafModule.config(cfgService)
13911419
13921420
then:
1421+
1 * wafMetricCollector.wafInit(Powerwaf.LIB_VERSION, _, true)
13931422
!pwafModule.dataSubscriptions.first().subscribedAddresses.contains(doesNotExistAddress)
1423+
0 * _
13941424
}
13951425
13961426
void 'bad initial configuration is given results in no subscriptions'() {
@@ -1403,6 +1433,7 @@ class PowerWAFModuleSpecification extends DDSpecification {
14031433
then:
14041434
thrown AppSecModule.AppSecModuleActivationException
14051435
pwafModule.dataSubscriptions.empty
1436+
0 * _
14061437
}
14071438
14081439
void 'rule data not a config'() {
@@ -1414,9 +1445,8 @@ class PowerWAFModuleSpecification extends DDSpecification {
14141445
14151446
then:
14161447
thrown AppSecModule.AppSecModuleActivationException
1417-
1418-
then:
14191448
pwafModule.ctxAndAddresses.get() == null
1449+
0 * _
14201450
}
14211451
14221452
void 'bad ResultWithData - empty list'() {
@@ -1554,7 +1584,18 @@ class PowerWAFModuleSpecification extends DDSpecification {
15541584
ctx.closeAdditive()
15551585

15561586
then:
1587+
1 * ctx.isAdditiveClosed()
1588+
1 * ctx.getOrCreateAdditive(_ as PowerwafContext, true, false) >> {
1589+
pwafAdditive = it[0].openAdditive()
1590+
}
1591+
1 * ctx.getWafMetrics()
1592+
1 * ctx.isThrottled(null)
1593+
1 * ctx.reportEvents(_ as Collection<AppSecEvent>)
1594+
1 * ctx.closeAdditive()
1595+
2 * tracer.activeSpan()
1596+
1 * flow.isBlocking()
15571597
0 * flow.setAction(_)
1598+
0 * _
15581599

15591600
when:
15601601
final ipData = new AppSecData(exclusion: [
@@ -1576,11 +1617,22 @@ class PowerWAFModuleSpecification extends DDSpecification {
15761617
ctx.closeAdditive()
15771618

15781619
then:
1620+
1 * wafMetricCollector.wafUpdates(_, true)
15791621
1 * reconf.reloadSubscriptions()
15801622
1 * flow.setAction({ Flow.Action.RequestBlockingAction rba ->
15811623
rba.statusCode == 402 && rba.blockingContentType == BlockingContentType.AUTO
15821624
})
1625+
1 * flow.isBlocking()
15831626
1 * ctx.isAdditiveClosed() >> false
1627+
1 * ctx.getOrCreateAdditive(_ as PowerwafContext, true, false) >> {
1628+
pwafAdditive = it[0].openAdditive()
1629+
}
1630+
1 * ctx.getWafMetrics()
1631+
1 * ctx.isThrottled(null)
1632+
1 * ctx.reportEvents(_ as Collection<AppSecEvent>)
1633+
1 * ctx.closeAdditive()
1634+
2 * tracer.activeSpan()
1635+
0 * _
15841636
}
15851637

15861638
void 'http endpoint fingerprint support'() {
@@ -1668,6 +1720,7 @@ class PowerWAFModuleSpecification extends DDSpecification {
16681720
then:
16691721
1 * ctx.closeAdditive()
16701722
1 * ctx.isAdditiveClosed() >> true
1723+
1 * wafMetricCollector.wafInit(Powerwaf.LIB_VERSION, _, true)
16711724
0 * _
16721725
}
16731726

0 commit comments

Comments
 (0)