Skip to content

Commit a0fe0c5

Browse files
authored
Report waf init and update success and failure (#5388)
* Report waf init and update success * handle waf init failure * do not report ecent rules when success fails * remove default value of diagnosticsRules * use default args to report init
1 parent 450abff commit a0fe0c5

File tree

9 files changed

+163
-61
lines changed

9 files changed

+163
-61
lines changed

packages/dd-trace/src/appsec/reporter.js

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,16 +88,18 @@ function formatHeaderName (name) {
8888
.toLowerCase()
8989
}
9090

91-
function reportWafInit (wafVersion, rulesVersion, diagnosticsRules = {}) {
92-
metricsQueue.set('_dd.appsec.waf.version', wafVersion)
93-
94-
metricsQueue.set('_dd.appsec.event_rules.loaded', diagnosticsRules.loaded?.length || 0)
95-
metricsQueue.set('_dd.appsec.event_rules.error_count', diagnosticsRules.failed?.length || 0)
96-
if (diagnosticsRules.failed?.length) {
97-
metricsQueue.set('_dd.appsec.event_rules.errors', JSON.stringify(diagnosticsRules.errors))
91+
function reportWafInit (wafVersion, rulesVersion, diagnosticsRules = {}, success = false) {
92+
if (success) {
93+
metricsQueue.set('_dd.appsec.waf.version', wafVersion)
94+
95+
metricsQueue.set('_dd.appsec.event_rules.loaded', diagnosticsRules.loaded?.length || 0)
96+
metricsQueue.set('_dd.appsec.event_rules.error_count', diagnosticsRules.failed?.length || 0)
97+
if (diagnosticsRules.failed?.length) {
98+
metricsQueue.set('_dd.appsec.event_rules.errors', JSON.stringify(diagnosticsRules.errors))
99+
}
98100
}
99101

100-
incrementWafInitMetric(wafVersion, rulesVersion)
102+
incrementWafInitMetric(wafVersion, rulesVersion, success)
101103
}
102104

103105
function reportMetrics (metrics, raspRule) {

packages/dd-trace/src/appsec/telemetry/index.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,16 +74,16 @@ function updateWafRequestsMetricTags (metrics, req) {
7474
return trackWafMetrics(store, metrics)
7575
}
7676

77-
function incrementWafInitMetric (wafVersion, rulesVersion) {
77+
function incrementWafInitMetric (wafVersion, rulesVersion, success) {
7878
if (!enabled) return
7979

80-
incrementWafInit(wafVersion, rulesVersion)
80+
incrementWafInit(wafVersion, rulesVersion, success)
8181
}
8282

83-
function incrementWafUpdatesMetric (wafVersion, rulesVersion) {
83+
function incrementWafUpdatesMetric (wafVersion, rulesVersion, success) {
8484
if (!enabled) return
8585

86-
incrementWafUpdates(wafVersion, rulesVersion)
86+
incrementWafUpdates(wafVersion, rulesVersion, success)
8787
}
8888

8989
function incrementWafRequestsMetric (req) {

packages/dd-trace/src/appsec/telemetry/waf.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,16 +91,22 @@ function getOrCreateMetricTags (store, versionsTags) {
9191
return metricTags
9292
}
9393

94-
function incrementWafInit (wafVersion, rulesVersion) {
94+
function incrementWafInit (wafVersion, rulesVersion, success) {
9595
const versionsTags = getVersionsTags(wafVersion, rulesVersion)
96+
appsecMetrics.count('waf.init', { ...versionsTags, success }).inc()
9697

97-
appsecMetrics.count('waf.init', versionsTags).inc()
98+
if (!success) {
99+
appsecMetrics.count('waf.config_errors', versionsTags).inc()
100+
}
98101
}
99102

100-
function incrementWafUpdates (wafVersion, rulesVersion) {
103+
function incrementWafUpdates (wafVersion, rulesVersion, success) {
101104
const versionsTags = getVersionsTags(wafVersion, rulesVersion)
105+
appsecMetrics.count('waf.updates', { ...versionsTags, success }).inc()
102106

103-
appsecMetrics.count('waf.updates', versionsTags).inc()
107+
if (!success) {
108+
appsecMetrics.count('waf.config_errors', versionsTags).inc()
109+
}
104110
}
105111

106112
function incrementWafRequests (store) {

packages/dd-trace/src/appsec/waf/waf_manager.js

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,23 @@ class WAFManager {
1111
this.config = config
1212
this.wafTimeout = config.wafTimeout
1313
this.ddwaf = this._loadDDWAF(rules)
14-
this.ddwafVersion = this.ddwaf.constructor.version()
1514
this.rulesVersion = this.ddwaf.diagnostics.ruleset_version
1615

17-
Reporter.reportWafInit(this.ddwafVersion, this.rulesVersion, this.ddwaf.diagnostics.rules)
16+
Reporter.reportWafInit(this.ddwafVersion, this.rulesVersion, this.ddwaf.diagnostics.rules, true)
1817
}
1918

2019
_loadDDWAF (rules) {
2120
try {
2221
// require in `try/catch` because this can throw at require time
2322
const { DDWAF } = require('@datadog/native-appsec')
23+
this.ddwafVersion = DDWAF.version()
2424

2525
const { obfuscatorKeyRegex, obfuscatorValueRegex } = this.config
2626
return new DDWAF(rules, { obfuscatorKeyRegex, obfuscatorValueRegex })
2727
} catch (err) {
28+
this.ddwafVersion = this.ddwafVersion || 'unknown'
29+
Reporter.reportWafInit(this.ddwafVersion, 'unknown')
30+
2831
log.error('[ASM] AppSec could not load native package. In-app WAF features will not be available.')
2932

3033
throw err
@@ -49,13 +52,19 @@ class WAFManager {
4952
}
5053

5154
update (newRules) {
52-
this.ddwaf.update(newRules)
55+
try {
56+
this.ddwaf.update(newRules)
5357

54-
if (this.ddwaf.diagnostics.ruleset_version) {
55-
this.rulesVersion = this.ddwaf.diagnostics.ruleset_version
56-
}
58+
if (this.ddwaf.diagnostics.ruleset_version) {
59+
this.rulesVersion = this.ddwaf.diagnostics.ruleset_version
60+
}
5761

58-
Reporter.reportWafUpdate(this.ddwafVersion, this.rulesVersion)
62+
Reporter.reportWafUpdate(this.ddwafVersion, this.rulesVersion, true)
63+
} catch (error) {
64+
Reporter.reportWafUpdate(this.ddwafVersion, 'unknown', false)
65+
66+
throw error
67+
}
5968
}
6069

6170
destroy () {

packages/dd-trace/test/appsec/index.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,7 @@ describe('AppSec Index', function () {
646646
responseBody.publish({ req, res, body })
647647

648648
expect(apiSecuritySampler.sampleRequest).to.have.been.calledOnceWith(req, res)
649-
expect(waf.run).to.been.calledOnceWith({
649+
expect(waf.run).to.have.been.calledOnceWith({
650650
persistent: {
651651
[addresses.HTTP_INCOMING_RESPONSE_BODY]: body
652652
}

packages/dd-trace/test/appsec/reporter.spec.js

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ describe('reporter', () => {
101101
}
102102

103103
it('should add some entries to metricsQueue', () => {
104-
Reporter.reportWafInit(wafVersion, rulesVersion, diagnosticsRules)
104+
Reporter.reportWafInit(wafVersion, rulesVersion, diagnosticsRules, true)
105105

106106
expect(Reporter.metricsQueue.get('_dd.appsec.waf.version')).to.be.eq(wafVersion)
107107
expect(Reporter.metricsQueue.get('_dd.appsec.event_rules.loaded')).to.be.eq(3)
@@ -110,23 +110,32 @@ describe('reporter', () => {
110110
.to.be.eq(JSON.stringify(diagnosticsRules.errors))
111111
})
112112

113+
it('should not add entries to metricsQueue with success false', () => {
114+
Reporter.reportWafInit(wafVersion, rulesVersion, diagnosticsRules, false)
115+
116+
expect(Reporter.metricsQueue.get('_dd.appsec.waf.version')).to.be.undefined
117+
expect(Reporter.metricsQueue.get('_dd.appsec.event_rules.loaded')).to.be.undefined
118+
expect(Reporter.metricsQueue.get('_dd.appsec.event_rules.error_count')).to.be.undefined
119+
expect(Reporter.metricsQueue.get('_dd.appsec.event_rules.errors')).to.be.undefined
120+
})
121+
113122
it('should call incrementWafInitMetric', () => {
114-
Reporter.reportWafInit(wafVersion, rulesVersion, diagnosticsRules)
123+
Reporter.reportWafInit(wafVersion, rulesVersion, diagnosticsRules, true)
115124

116-
expect(telemetry.incrementWafInitMetric).to.have.been.calledOnceWithExactly(wafVersion, rulesVersion)
125+
expect(telemetry.incrementWafInitMetric).to.have.been.calledOnceWithExactly(wafVersion, rulesVersion, true)
117126
})
118127

119128
it('should not fail with undefined arguments', () => {
120129
const wafVersion = undefined
121130
const rulesVersion = undefined
122131
const diagnosticsRules = undefined
123132

124-
Reporter.reportWafInit(wafVersion, rulesVersion, diagnosticsRules)
133+
Reporter.reportWafInit(wafVersion, rulesVersion, diagnosticsRules, true)
125134

126135
expect(Reporter.metricsQueue.get('_dd.appsec.event_rules.loaded')).to.be.eq(0)
127136
expect(Reporter.metricsQueue.get('_dd.appsec.event_rules.error_count')).to.be.eq(0)
128137

129-
expect(telemetry.incrementWafInitMetric).to.have.been.calledOnceWithExactly(wafVersion, rulesVersion)
138+
expect(telemetry.incrementWafInitMetric).to.have.been.calledOnceWithExactly(wafVersion, rulesVersion, true)
130139
})
131140
})
132141

@@ -380,9 +389,9 @@ describe('reporter', () => {
380389

381390
describe('reportWafUpdate', () => {
382391
it('should call incrementWafUpdatesMetric', () => {
383-
Reporter.reportWafUpdate('0.0.1', '0.0.2')
392+
Reporter.reportWafUpdate('0.0.1', '0.0.2', true)
384393

385-
expect(telemetry.incrementWafUpdatesMetric).to.have.been.calledOnceWithExactly('0.0.1', '0.0.2')
394+
expect(telemetry.incrementWafUpdatesMetric).to.have.been.calledOnceWithExactly('0.0.1', '0.0.2', true)
386395
})
387396
})
388397

packages/dd-trace/test/appsec/telemetry/waf.spec.js

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -185,21 +185,22 @@ describe('Appsec Waf Telemetry metrics', () => {
185185

186186
describe('incWafInitMetric', () => {
187187
it('should increment waf.init metric', () => {
188-
appsecTelemetry.incrementWafInitMetric(wafVersion, rulesVersion)
188+
appsecTelemetry.incrementWafInitMetric(wafVersion, rulesVersion, true)
189189

190190
expect(count).to.have.been.calledOnceWithExactly('waf.init', {
191191
waf_version: wafVersion,
192-
event_rules_version: rulesVersion
192+
event_rules_version: rulesVersion,
193+
success: true
193194
})
194195
expect(inc).to.have.been.calledOnce
195196
})
196197

197198
it('should increment waf.init metric multiple times', () => {
198199
sinon.restore()
199200

200-
appsecTelemetry.incrementWafInitMetric(wafVersion, rulesVersion)
201-
appsecTelemetry.incrementWafInitMetric(wafVersion, rulesVersion)
202-
appsecTelemetry.incrementWafInitMetric(wafVersion, rulesVersion)
201+
appsecTelemetry.incrementWafInitMetric(wafVersion, rulesVersion, true)
202+
appsecTelemetry.incrementWafInitMetric(wafVersion, rulesVersion, true)
203+
appsecTelemetry.incrementWafInitMetric(wafVersion, rulesVersion, true)
203204

204205
const { metrics } = appsecNamespace.toJSON()
205206
expect(metrics.series.length).to.be.eq(1)
@@ -208,26 +209,45 @@ describe('Appsec Waf Telemetry metrics', () => {
208209
expect(metrics.series[0].points[0][1]).to.be.eq(3)
209210
expect(metrics.series[0].tags).to.include('waf_version:0.0.1')
210211
expect(metrics.series[0].tags).to.include('event_rules_version:0.0.2')
212+
expect(metrics.series[0].tags).to.include('success:true')
213+
})
214+
215+
it('should increment waf.init and waf.config_errors on failed init', () => {
216+
sinon.restore()
217+
218+
appsecTelemetry.incrementWafInitMetric(wafVersion, rulesVersion, false)
219+
220+
const { metrics } = appsecNamespace.toJSON()
221+
expect(metrics.series.length).to.be.eq(2)
222+
expect(metrics.series[0].metric).to.be.eq('waf.init')
223+
expect(metrics.series[0].tags).to.include('waf_version:0.0.1')
224+
expect(metrics.series[0].tags).to.include('event_rules_version:0.0.2')
225+
expect(metrics.series[0].tags).to.include('success:false')
226+
227+
expect(metrics.series[1].metric).to.be.eq('waf.config_errors')
228+
expect(metrics.series[1].tags).to.include('waf_version:0.0.1')
229+
expect(metrics.series[1].tags).to.include('event_rules_version:0.0.2')
211230
})
212231
})
213232

214233
describe('incWafUpdatesMetric', () => {
215234
it('should increment waf.updates metric', () => {
216-
appsecTelemetry.incrementWafUpdatesMetric(wafVersion, rulesVersion)
235+
appsecTelemetry.incrementWafUpdatesMetric(wafVersion, rulesVersion, true)
217236

218237
expect(count).to.have.been.calledOnceWithExactly('waf.updates', {
219238
waf_version: wafVersion,
220-
event_rules_version: rulesVersion
239+
event_rules_version: rulesVersion,
240+
success: true
221241
})
222242
expect(inc).to.have.been.calledOnce
223243
})
224244

225245
it('should increment waf.updates metric multiple times', () => {
226246
sinon.restore()
227247

228-
appsecTelemetry.incrementWafUpdatesMetric(wafVersion, rulesVersion)
229-
appsecTelemetry.incrementWafUpdatesMetric(wafVersion, rulesVersion)
230-
appsecTelemetry.incrementWafUpdatesMetric(wafVersion, rulesVersion)
248+
appsecTelemetry.incrementWafUpdatesMetric(wafVersion, rulesVersion, true)
249+
appsecTelemetry.incrementWafUpdatesMetric(wafVersion, rulesVersion, true)
250+
appsecTelemetry.incrementWafUpdatesMetric(wafVersion, rulesVersion, true)
231251

232252
const { metrics } = appsecNamespace.toJSON()
233253
expect(metrics.series.length).to.be.eq(1)
@@ -236,6 +256,24 @@ describe('Appsec Waf Telemetry metrics', () => {
236256
expect(metrics.series[0].points[0][1]).to.be.eq(3)
237257
expect(metrics.series[0].tags).to.include('waf_version:0.0.1')
238258
expect(metrics.series[0].tags).to.include('event_rules_version:0.0.2')
259+
expect(metrics.series[0].tags).to.include('success:true')
260+
})
261+
262+
it('should increment waf.updates and waf.config_errors on failed update', () => {
263+
sinon.restore()
264+
265+
appsecTelemetry.incrementWafUpdatesMetric(wafVersion, rulesVersion, false)
266+
267+
const { metrics } = appsecNamespace.toJSON()
268+
expect(metrics.series.length).to.be.eq(2)
269+
expect(metrics.series[0].metric).to.be.eq('waf.updates')
270+
expect(metrics.series[0].tags).to.include('waf_version:0.0.1')
271+
expect(metrics.series[0].tags).to.include('event_rules_version:0.0.2')
272+
expect(metrics.series[0].tags).to.include('success:false')
273+
274+
expect(metrics.series[1].metric).to.be.eq('waf.config_errors')
275+
expect(metrics.series[1].tags).to.include('waf_version:0.0.1')
276+
expect(metrics.series[1].tags).to.include('event_rules_version:0.0.2')
239277
})
240278
})
241279

@@ -333,7 +371,7 @@ describe('Appsec Waf Telemetry metrics', () => {
333371
metrics: true
334372
})
335373

336-
appsecTelemetry.incrementWafInitMetric(wafVersion, rulesVersion)
374+
appsecTelemetry.incrementWafInitMetric(wafVersion, rulesVersion, true)
337375

338376
expect(count).to.not.have.been.called
339377
expect(inc).to.not.have.been.called
@@ -345,7 +383,7 @@ describe('Appsec Waf Telemetry metrics', () => {
345383
metrics: false
346384
})
347385

348-
appsecTelemetry.incrementWafInitMetric(wafVersion, rulesVersion)
386+
appsecTelemetry.incrementWafInitMetric(wafVersion, rulesVersion, true)
349387

350388
expect(count).to.not.have.been.called
351389
expect(inc).to.not.have.been.called

0 commit comments

Comments
 (0)