Skip to content

Commit 275d80d

Browse files
authored
Upgrade libddwaf native bindings (#5792)
Implement new major version for native-appsec native module, which provides an improved management system for WAF configuration updates and diagnostic result, used in telemetry logs and RC error reporting.
1 parent c569d20 commit 275d80d

File tree

16 files changed

+770
-778
lines changed

16 files changed

+770
-778
lines changed

integration-tests/appsec/graphql.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ describe('graphql', () => {
109109
assert.property(payload[1][0].metrics, '_dd.appsec.waf.duration')
110110
assert.propertyVal(payload[1][0].meta, 'appsec.event', 'true')
111111
assert.property(payload[1][0].meta, '_dd.appsec.json')
112-
assert.propertyVal(payload[1][0].meta, '_dd.appsec.json', JSON.stringify(result))
112+
assert.deepStrictEqual(JSON.parse(payload[1][0].meta['_dd.appsec.json']), result)
113113
})
114114

115115
await axios({

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@
8686
},
8787
"dependencies": {
8888
"@datadog/libdatadog": "0.7.0",
89-
"@datadog/native-appsec": "8.5.2",
89+
"@datadog/native-appsec": "9.0.0",
9090
"@datadog/native-iast-taint-tracking": "4.0.0",
9191
"@datadog/native-metrics": "3.1.1",
9292
"@datadog/pprof": "5.9.0",

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

Lines changed: 61 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,26 @@
11
'use strict'
22

3+
const dc = require('dc-polyfill')
4+
const zlib = require('zlib')
5+
36
const Limiter = require('../rate_limiter')
47
const { storage } = require('../../../datadog-core')
58
const web = require('../plugins/util/web')
69
const { ipHeaderList } = require('../plugins/util/ip_extractor')
710
const {
811
incrementWafInitMetric,
912
incrementWafUpdatesMetric,
13+
incrementWafConfigErrorsMetric,
1014
incrementWafRequestsMetric,
1115
updateWafRequestsMetricTags,
1216
updateRaspRequestsMetricTags,
1317
updateRaspRuleSkippedMetricTags,
1418
updateRateLimitedMetric,
1519
getRequestMetrics
1620
} = require('./telemetry')
17-
const zlib = require('zlib')
1821
const { keepTrace } = require('../priority_sampler')
1922
const { ASM } = require('../standalone/product')
23+
const { DIAGNOSTIC_KEYS } = require('./waf/diagnostics')
2024

2125
const REQUEST_HEADER_TAG_PREFIX = 'http.request.headers.'
2226
const RESPONSE_HEADER_TAG_PREFIX = 'http.response.headers.'
@@ -25,6 +29,8 @@ const COLLECTED_REQUEST_BODY_MAX_STRING_LENGTH = 4096
2529
const COLLECTED_REQUEST_BODY_MAX_DEPTH = 20
2630
const COLLECTED_REQUEST_BODY_MAX_ELEMENTS_PER_NODE = 256
2731

32+
const telemetryLogCh = dc.channel('datadog:telemetry:log')
33+
2834
// default limiter, configurable with setRateLimit()
2935
let limiter = new Limiter(100)
3036

@@ -216,17 +222,64 @@ function getCollectedHeaders (req, res, shouldCollectEventHeaders, storedRespons
216222
function reportWafInit (wafVersion, rulesVersion, diagnosticsRules = {}, success = false) {
217223
if (success) {
218224
metricsQueue.set('_dd.appsec.waf.version', wafVersion)
219-
220-
metricsQueue.set('_dd.appsec.event_rules.loaded', diagnosticsRules.loaded?.length || 0)
221-
metricsQueue.set('_dd.appsec.event_rules.error_count', diagnosticsRules.failed?.length || 0)
222-
if (diagnosticsRules.failed?.length) {
223-
metricsQueue.set('_dd.appsec.event_rules.errors', JSON.stringify(diagnosticsRules.errors))
224-
}
225225
}
226226

227227
incrementWafInitMetric(wafVersion, rulesVersion, success)
228228
}
229229

230+
function logWafDiagnosticMessage (product, rcConfigId, configKey, message, level) {
231+
const tags =
232+
`log_type:rc::${product.toLowerCase()}::diagnostic,appsec_config_key:${configKey},rc_config_id:${rcConfigId}`
233+
telemetryLogCh.publish({
234+
message,
235+
level,
236+
tags
237+
})
238+
}
239+
240+
function reportWafConfigUpdate (product, rcConfigId, diagnostics, wafVersion) {
241+
if (diagnostics.error) {
242+
logWafDiagnosticMessage(product, rcConfigId, '', diagnostics.error, 'ERROR')
243+
incrementWafConfigErrorsMetric(wafVersion, diagnostics.ruleset_version)
244+
}
245+
246+
for (const configKey of DIAGNOSTIC_KEYS) {
247+
const configDiagnostics = diagnostics[configKey]
248+
if (!configDiagnostics) continue
249+
250+
if (configDiagnostics.error) {
251+
logWafDiagnosticMessage(product, rcConfigId, configKey, configDiagnostics.error, 'ERROR')
252+
incrementWafConfigErrorsMetric(wafVersion, diagnostics.ruleset_version)
253+
continue
254+
}
255+
256+
if (configDiagnostics.errors) {
257+
for (const [errorMessage, errorIds] of Object.entries(configDiagnostics.errors)) {
258+
logWafDiagnosticMessage(
259+
product,
260+
rcConfigId,
261+
configKey,
262+
`"${errorMessage}": ${JSON.stringify(errorIds)}`,
263+
'ERROR'
264+
)
265+
incrementWafConfigErrorsMetric(wafVersion, diagnostics.ruleset_version)
266+
}
267+
}
268+
269+
if (configDiagnostics.warnings) {
270+
for (const [warningMessage, warningIds] of Object.entries(configDiagnostics.warnings)) {
271+
logWafDiagnosticMessage(
272+
product,
273+
rcConfigId,
274+
configKey,
275+
`"${warningMessage}": ${JSON.stringify(warningIds)}`,
276+
'WARN'
277+
)
278+
}
279+
}
280+
}
281+
}
282+
230283
function reportMetrics (metrics, raspRule) {
231284
const store = storage('legacy').getStore()
232285
const rootSpan = store?.req && web.root(store.req)
@@ -485,6 +538,7 @@ module.exports = {
485538
filterExtendedHeaders,
486539
formatHeaderName,
487540
reportWafInit,
541+
reportWafConfigUpdate,
488542
reportMetrics,
489543
reportAttack,
490544
reportWafUpdate: incrementWafUpdatesMetric,

0 commit comments

Comments
 (0)