UNPKG

dd-trace

Version:

Datadog APM tracing client for JavaScript

106 lines (94 loc) 3.92 kB
const vulnerabilityReporter = require('./vulnerability-reporter') const { enableAllAnalyzers, disableAllAnalyzers } = require('./analyzers') const web = require('../../plugins/util/web') const { storage } = require('../../../../datadog-core') const overheadController = require('./overhead-controller') const dc = require('dc-polyfill') const iastContextFunctions = require('./iast-context') const { enableTaintTracking, disableTaintTracking, createTransaction, removeTransaction, taintTrackingPlugin } = require('./taint-tracking') const { IAST_ENABLED_TAG_KEY } = require('./tags') const iastTelemetry = require('./telemetry') const { enable: enableFsPlugin, disable: disableFsPlugin, IAST_MODULE } = require('../rasp/fs-plugin') const securityControls = require('./security-controls') // TODO Change to `apm:http:server:request:[start|close]` when the subscription // order of the callbacks can be enforce const requestStart = dc.channel('dd-trace:incomingHttpRequestStart') const requestClose = dc.channel('dd-trace:incomingHttpRequestEnd') const iastResponseEnd = dc.channel('datadog:iast:response-end') let isEnabled = false function enable (config, _tracer) { if (isEnabled) return iastTelemetry.configure(config, config.iast?.telemetryVerbosity) enableFsPlugin(IAST_MODULE) enableAllAnalyzers(config) enableTaintTracking(config.iast, iastTelemetry.verbosity) requestStart.subscribe(onIncomingHttpRequestStart) requestClose.subscribe(onIncomingHttpRequestEnd) overheadController.configure(config.iast) overheadController.startGlobalContext() securityControls.configure(config.iast) vulnerabilityReporter.start(config, _tracer) isEnabled = true } function disable () { if (!isEnabled) return isEnabled = false iastTelemetry.stop() disableFsPlugin(IAST_MODULE) disableAllAnalyzers() disableTaintTracking() overheadController.finishGlobalContext() if (requestStart.hasSubscribers) requestStart.unsubscribe(onIncomingHttpRequestStart) if (requestClose.hasSubscribers) requestClose.unsubscribe(onIncomingHttpRequestEnd) vulnerabilityReporter.stop() } function onIncomingHttpRequestStart (data) { if (data?.req) { const store = storage('legacy').getStore() if (store) { const topContext = web.getContext(data.req) if (topContext) { const rootSpan = topContext.span const isRequestAcquired = overheadController.acquireRequest(rootSpan) if (isRequestAcquired) { const iastContext = iastContextFunctions.saveIastContext(store, topContext, { rootSpan, req: data.req }) createTransaction(rootSpan.context().toSpanId(), iastContext) overheadController.initializeRequestContext(iastContext) iastTelemetry.onRequestStart(iastContext) taintTrackingPlugin.taintRequest(data.req, iastContext) } if (rootSpan.addTags) { rootSpan.addTags({ [IAST_ENABLED_TAG_KEY]: isRequestAcquired ? 1 : 0 }) } } } } } function onIncomingHttpRequestEnd (data) { if (data?.req) { const store = storage('legacy').getStore() const topContext = web.getContext(data.req) const iastContext = iastContextFunctions.getIastContext(store, topContext) if (iastContext?.rootSpan) { iastResponseEnd.publish(data) const vulnerabilities = iastContext.vulnerabilities const rootSpan = iastContext.rootSpan vulnerabilityReporter.sendVulnerabilities(vulnerabilities, rootSpan) removeTransaction(iastContext) iastTelemetry.onRequestEnd(iastContext, iastContext.rootSpan) } // TODO web.getContext(data.req) is required when the request is aborted if (iastContextFunctions.cleanIastContext(store, topContext, iastContext)) { overheadController.releaseRequest() } } } module.exports = { enable, disable, onIncomingHttpRequestEnd, onIncomingHttpRequestStart }