Skip to content

Commit

Permalink
fixes and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
iunanua committed Feb 4, 2025
1 parent 3116b76 commit af58e8a
Show file tree
Hide file tree
Showing 16 changed files with 180 additions and 324 deletions.
3 changes: 2 additions & 1 deletion packages/dd-trace/src/appsec/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ function enable (_config) {
responseWriteHead.subscribe(onResponseWriteHead)
responseSetHeader.subscribe(onResponseSetHeader)

if (!_config.apmTracing.enabled) {
const apmTracingEnabled = _config.apmTracing?.enabled ?? true
if (!apmTracingEnabled) {
prioritySamplerConfigure.subscribe(onPrioritySamplerConfigure)
}

Expand Down
3 changes: 2 additions & 1 deletion packages/dd-trace/src/exporters/agent/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ class AgentExporter {
}))

const headers = {}
if (stats.enabled || !config.apmTracing.enabled) {
const apmTracingEnabled = config.apmTracing?.enabled ?? true
if (stats.enabled || !apmTracingEnabled) {
headers['Datadog-Client-Computed-Stats'] = 'yes'
}

Expand Down
4 changes: 2 additions & 2 deletions packages/dd-trace/src/proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const dogstatsd = require('./dogstatsd')
const NoopDogStatsDClient = require('./noop/dogstatsd')
const spanleak = require('./spanleak')
const { SSIHeuristics } = require('./profiling/ssi-heuristics')
const apmTracing = require('./standalone')
const standalone = require('./standalone')
const LLMObsSDK = require('./llmobs/sdk')

class LazyModule {
Expand Down Expand Up @@ -214,7 +214,7 @@ class Tracer extends NoopProxy {
this._modules.llmobs.enable(config)
}
if (!this._tracingInitialized) {
const prioritySampler = apmTracing.configure(config)
const prioritySampler = standalone.configure(config)
this._tracer = new DatadogTracer(config, prioritySampler)
this.dataStreamsCheckpointer = this._tracer.dataStreamsCheckpointer
this.appsec = new AppsecSdk(this._tracer, config)
Expand Down
3 changes: 2 additions & 1 deletion packages/dd-trace/src/span_stats.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ class SpanStatsProcessor {
this.bucketSizeNs = interval * 1e9
this.buckets = new TimeBuckets()
this.hostname = os.hostname()
this.enabled = enabled && apmTracing.enabled
const apmTracingEnabled = apmTracing?.enabled ?? true
this.enabled = enabled && apmTracingEnabled
this.env = env
this.tags = tags || {}
this.sequence = 0
Expand Down
30 changes: 9 additions & 21 deletions packages/dd-trace/src/standalone/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use strict'

const { channel } = require('dc-polyfill')
const PrioritySampler = require('../priority_sampler')
const TraceSourcePrioritySampler = require('./tracesource_priority_sampler')
const { USER_KEEP } = require('../../../../ext/priority')
const TraceState = require('../opentracing/propagation/tracestate')
Expand All @@ -12,30 +11,19 @@ const startCh = channel('dd-trace:span:start')
const injectCh = channel('dd-trace:span:inject')
const extractCh = channel('dd-trace:span:extract')

let enabled

function configure (config) {
const configChanged = enabled !== config.apmTracing.enabled
if (!configChanged) return

enabled = config.apmTracing.enabled
if (startCh.hasSubscribers) startCh.unsubscribe(onSpanStart)
if (injectCh.hasSubscribers) injectCh.unsubscribe(onSpanInject)
if (extractCh.hasSubscribers) extractCh.unsubscribe(onSpanExtract)

let prioritySampler
if (enabled) {
prioritySampler = new PrioritySampler(config.env, config.sampler)
const apmTracingEnabled = config.apmTracing?.enabled ?? true
if (apmTracingEnabled) return

if (startCh.hasSubscribers) startCh.unsubscribe(onSpanStart)
if (injectCh.hasSubscribers) injectCh.unsubscribe(onSpanInject)
if (extractCh.hasSubscribers) extractCh.unsubscribe(onSpanExtract)
} else {
prioritySampler = new TraceSourcePrioritySampler(config.env)

startCh.subscribe(onSpanStart)
injectCh.subscribe(onSpanInject)
extractCh.subscribe(onSpanExtract)
}
startCh.subscribe(onSpanStart)
injectCh.subscribe(onSpanInject)
extractCh.subscribe(onSpanExtract)

return prioritySampler
return new TraceSourcePrioritySampler(config.env)
}

function onSpanStart ({ span, fields }) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const { MANUAL_KEEP } = require('../../../../ext/tags')
const { USER_KEEP, AUTO_KEEP, AUTO_REJECT } = require('../../../../ext/priority')
const { SAMPLING_MECHANISM_DEFAULT } = require('../constants')
const { addTraceSourceTag, hasTraceSourcePropagationTag } = require('./tracesource')
const RateLimiter = require('../rate_limiter')

const configureCh = channel('datadog:priority-sampler:configure')

Expand All @@ -18,6 +19,7 @@ class TraceSourcePrioritySampler extends PrioritySampler {
configure (env, config) {
// rules not supported
this._env = env
this._limiter = new RateLimiter(0)

configureCh.publish({ prioritySampler: this })
}
Expand Down
67 changes: 15 additions & 52 deletions packages/dd-trace/test/appsec/iast/vulnerability-reporter.spec.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
const { addVulnerability, sendVulnerabilities, clearCache, start, stop } =
require('../../../src/appsec/iast/vulnerability-reporter')
const VulnerabilityAnalyzer = require('../../../../dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer')
const appsecStandalone = require('../../../src/appsec/standalone')
const { APPSEC_PROPAGATION_KEY, SAMPLING_MECHANISM_APPSEC } = require('../../../src/constants')
const { USER_KEEP } = require('../../../../../ext/priority')
const { ASM } = require('../../../src/standalone/product')

describe('vulnerability-reporter', () => {
let vulnerabilityAnalyzer
Expand Down Expand Up @@ -140,7 +139,7 @@ describe('vulnerability-reporter', () => {
'"stackId":1,"evidence":{"value":"sha1"},"location":{"spanId":42,"path":"filename.js","line":73}}]}'
})
expect(prioritySampler.setPriority)
.to.have.been.calledOnceWithExactly(onTheFlySpan, USER_KEEP, SAMPLING_MECHANISM_APPSEC)
.to.have.been.calledOnceWithExactly(onTheFlySpan, USER_KEEP, ASM)
expect(onTheFlySpan.finish).to.have.been.calledOnce
})

Expand Down Expand Up @@ -309,7 +308,7 @@ describe('vulnerability-reporter', () => {
'_dd.iast.json': '{"sources":[],"vulnerabilities":[{"type":"INSECURE_HASHING","hash":3254801297,' +
'"evidence":{"value":"sha1"},"location":{"spanId":888}}]}'
})
expect(prioritySampler.setPriority).to.have.been.calledOnceWithExactly(span, USER_KEEP, SAMPLING_MECHANISM_APPSEC)
expect(prioritySampler.setPriority).to.have.been.calledOnceWithExactly(span, USER_KEEP, ASM)
})

it('should send only valid vulnerabilities', () => {
Expand All @@ -322,7 +321,7 @@ describe('vulnerability-reporter', () => {
'_dd.iast.json': '{"sources":[],"vulnerabilities":[{"type":"INSECURE_HASHING","hash":3254801297,' +
'"evidence":{"value":"sha1"},"location":{"spanId":888}}]}'
})
expect(prioritySampler.setPriority).to.have.been.calledOnceWithExactly(span, USER_KEEP, SAMPLING_MECHANISM_APPSEC)
expect(prioritySampler.setPriority).to.have.been.calledOnceWithExactly(span, USER_KEEP, ASM)
})

it('should send vulnerabilities with evidence, ranges and sources', () => {
Expand Down Expand Up @@ -381,9 +380,9 @@ describe('vulnerability-reporter', () => {

expect(prioritySampler.setPriority).to.have.been.calledTwice
expect(prioritySampler.setPriority.firstCall)
.to.have.been.calledWithExactly(span, USER_KEEP, SAMPLING_MECHANISM_APPSEC)
.to.have.been.calledWithExactly(span, USER_KEEP, ASM)
expect(prioritySampler.setPriority.secondCall)
.to.have.been.calledWithExactly(span, USER_KEEP, SAMPLING_MECHANISM_APPSEC)
.to.have.been.calledWithExactly(span, USER_KEEP, ASM)
})

it('should send multiple vulnerabilities with same tainted source', () => {
Expand Down Expand Up @@ -441,9 +440,9 @@ describe('vulnerability-reporter', () => {

expect(prioritySampler.setPriority).to.have.been.calledTwice
expect(prioritySampler.setPriority.firstCall)
.to.have.been.calledWithExactly(span, USER_KEEP, SAMPLING_MECHANISM_APPSEC)
.to.have.been.calledWithExactly(span, USER_KEEP, ASM)
expect(prioritySampler.setPriority.secondCall)
.to.have.been.calledWithExactly(span, USER_KEEP, SAMPLING_MECHANISM_APPSEC)
.to.have.been.calledWithExactly(span, USER_KEEP, ASM)
})

it('should send once with multiple vulnerabilities', () => {
Expand All @@ -466,11 +465,11 @@ describe('vulnerability-reporter', () => {
})
expect(prioritySampler.setPriority).to.have.been.calledThrice
expect(prioritySampler.setPriority.firstCall)
.to.have.been.calledWithExactly(span, USER_KEEP, SAMPLING_MECHANISM_APPSEC)
.to.have.been.calledWithExactly(span, USER_KEEP, ASM)
expect(prioritySampler.setPriority.secondCall)
.to.have.been.calledWithExactly(span, USER_KEEP, SAMPLING_MECHANISM_APPSEC)
.to.have.been.calledWithExactly(span, USER_KEEP, ASM)
expect(prioritySampler.setPriority.thirdCall)
.to.have.been.calledWithExactly(span, USER_KEEP, SAMPLING_MECHANISM_APPSEC)
.to.have.been.calledWithExactly(span, USER_KEEP, ASM)
})

it('should send once vulnerability with one vulnerability', () => {
Expand All @@ -483,7 +482,7 @@ describe('vulnerability-reporter', () => {
'_dd.iast.json': '{"sources":[],"vulnerabilities":[{"type":"INSECURE_HASHING","hash":3410512691,' +
'"evidence":{"value":"sha1"},"location":{"spanId":888,"path":"filename.js","line":88}}]}'
})
expect(prioritySampler.setPriority).to.have.been.calledOnceWithExactly(span, USER_KEEP, SAMPLING_MECHANISM_APPSEC)
expect(prioritySampler.setPriority).to.have.been.calledOnceWithExactly(span, USER_KEEP, ASM)
})

it('should not send duplicated vulnerabilities', () => {
Expand All @@ -499,7 +498,7 @@ describe('vulnerability-reporter', () => {
'_dd.iast.json': '{"sources":[],"vulnerabilities":[{"type":"INSECURE_HASHING","hash":3410512691,' +
'"evidence":{"value":"sha1"},"location":{"spanId":888,"path":"filename.js","line":88}}]}'
})
expect(prioritySampler.setPriority).to.have.been.calledOnceWithExactly(span, USER_KEEP, SAMPLING_MECHANISM_APPSEC)
expect(prioritySampler.setPriority).to.have.been.calledOnceWithExactly(span, USER_KEEP, ASM)
})

it('should not deduplicate vulnerabilities if not enabled', () => {
Expand Down Expand Up @@ -532,45 +531,9 @@ describe('vulnerability-reporter', () => {
})
expect(prioritySampler.setPriority).to.have.been.calledTwice
expect(prioritySampler.setPriority.firstCall)
.to.have.been.calledWithExactly(span, USER_KEEP, SAMPLING_MECHANISM_APPSEC)
.to.have.been.calledWithExactly(span, USER_KEEP, ASM)
expect(prioritySampler.setPriority.secondCall)
.to.have.been.calledWithExactly(span, USER_KEEP, SAMPLING_MECHANISM_APPSEC)
})

it('should add _dd.p.appsec trace tag with standalone enabled', () => {
appsecStandalone.configure({ appsec: { standalone: { enabled: true } } })
const iastContext = { rootSpan: span }
addVulnerability(iastContext,
vulnerabilityAnalyzer._createVulnerability('INSECURE_HASHING', { value: 'sha1' }, 999), [])

sendVulnerabilities(iastContext.vulnerabilities, span)

expect(span.addTags).to.have.been.calledOnceWithExactly({
'_dd.iast.json': '{"sources":[],"vulnerabilities":[{"type":"INSECURE_HASHING","hash":3254801297,' +
'"evidence":{"value":"sha1"},"location":{"spanId":999}}]}'
})

expect(prioritySampler.setPriority).to.have.been.calledOnceWithExactly(span, USER_KEEP, SAMPLING_MECHANISM_APPSEC)

expect(span.context()._trace.tags).to.have.property(APPSEC_PROPAGATION_KEY)
})

it('should not add _dd.p.appsec trace tag with standalone disabled', () => {
appsecStandalone.configure({ appsec: {} })
const iastContext = { rootSpan: span }
addVulnerability(iastContext,
vulnerabilityAnalyzer._createVulnerability('INSECURE_HASHING', { value: 'sha1' }, 999), [])

sendVulnerabilities(iastContext.vulnerabilities, span)

expect(span.addTags).to.have.been.calledOnceWithExactly({
'_dd.iast.json': '{"sources":[],"vulnerabilities":[{"type":"INSECURE_HASHING","hash":3254801297,' +
'"evidence":{"value":"sha1"},"location":{"spanId":999}}]}'
})

expect(prioritySampler.setPriority).to.have.been.calledOnceWithExactly(span, USER_KEEP, SAMPLING_MECHANISM_APPSEC)

expect(span.context()._trace.tags).to.not.have.property(APPSEC_PROPAGATION_KEY)
.to.have.been.calledWithExactly(span, USER_KEEP, ASM)
})
})

Expand Down
24 changes: 8 additions & 16 deletions packages/dd-trace/test/appsec/reporter.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@
const proxyquire = require('proxyquire')
const { storage } = require('../../../datadog-core')
const zlib = require('zlib')
const { SAMPLING_MECHANISM_APPSEC } = require('../../src/constants')
const { ASM } = require('../../src/standalone/product')
const { USER_KEEP } = require('../../../../ext/priority')

describe('reporter', () => {
let Reporter
let span
let web
let telemetry
let sample
let prioritySampler

beforeEach(() => {
Expand Down Expand Up @@ -42,14 +41,9 @@ describe('reporter', () => {
getRequestMetrics: sinon.stub()
}

sample = sinon.stub()

Reporter = proxyquire('../../src/appsec/reporter', {
'../plugins/util/web': web,
'./telemetry': telemetry,
'./standalone': {
sample
}
'./telemetry': telemetry
})
})

Expand Down Expand Up @@ -238,7 +232,7 @@ describe('reporter', () => {
'_dd.origin': 'appsec',
'_dd.appsec.json': '{"triggers":[{"rule":{},"rule_matches":[{}]}]}'
})
expect(prioritySampler.setPriority).to.have.been.calledOnceWithExactly(span, USER_KEEP, SAMPLING_MECHANISM_APPSEC)
expect(prioritySampler.setPriority).to.have.been.calledOnceWithExactly(span, USER_KEEP, ASM)
})

it('should add tags to request span', () => {
Expand All @@ -252,7 +246,7 @@ describe('reporter', () => {
'_dd.appsec.json': '{"triggers":[{"rule":{},"rule_matches":[{}]}]}',
'network.client.ip': '8.8.8.8'
})
expect(prioritySampler.setPriority).to.have.been.calledOnceWithExactly(span, USER_KEEP, SAMPLING_MECHANISM_APPSEC)
expect(prioritySampler.setPriority).to.have.been.calledOnceWithExactly(span, USER_KEEP, ASM)
})

it('should not add manual.keep when rate limit is reached', (done) => {
Expand Down Expand Up @@ -293,7 +287,7 @@ describe('reporter', () => {
'_dd.appsec.json': '{"triggers":[]}',
'network.client.ip': '8.8.8.8'
})
expect(prioritySampler.setPriority).to.have.been.calledOnceWithExactly(span, USER_KEEP, SAMPLING_MECHANISM_APPSEC)
expect(prioritySampler.setPriority).to.have.been.calledOnceWithExactly(span, USER_KEEP, ASM)
})

it('should merge attacks json', () => {
Expand All @@ -309,7 +303,7 @@ describe('reporter', () => {
'_dd.appsec.json': '{"triggers":[{"rule":{},"rule_matches":[{}]},{"rule":{}},{"rule":{},"rule_matches":[{}]}]}',
'network.client.ip': '8.8.8.8'
})
expect(prioritySampler.setPriority).to.have.been.calledOnceWithExactly(span, USER_KEEP, SAMPLING_MECHANISM_APPSEC)
expect(prioritySampler.setPriority).to.have.been.calledOnceWithExactly(span, USER_KEEP, ASM)
})

it('should call standalone sample', () => {
Expand All @@ -326,9 +320,7 @@ describe('reporter', () => {
'network.client.ip': '8.8.8.8'
})

expect(prioritySampler.setPriority).to.have.been.calledOnceWithExactly(span, USER_KEEP, SAMPLING_MECHANISM_APPSEC)

expect(sample).to.have.been.calledOnceWithExactly(span)
expect(prioritySampler.setPriority).to.have.been.calledOnceWithExactly(span, USER_KEEP, ASM)
})
})

Expand Down Expand Up @@ -677,7 +669,7 @@ describe('reporter', () => {

Reporter.finishRequest(req, wafContext, {})

expect(prioritySampler.setPriority).to.have.been.calledOnceWithExactly(span, USER_KEEP, SAMPLING_MECHANISM_APPSEC)
expect(prioritySampler.setPriority).to.have.been.calledOnceWithExactly(span, USER_KEEP, ASM)
})
})
})
Loading

0 comments on commit af58e8a

Please sign in to comment.