Skip to content

Commit ce506c9

Browse files
committed
wip
1 parent 826630f commit ce506c9

4 files changed

Lines changed: 31 additions & 150 deletions

File tree

dd-java-agent/appsec/src/main/java/com/datadog/appsec/gateway/GatewayBridge.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -686,12 +686,14 @@ private NoopFlow onRequestEnded(RequestContext ctx_, IGSpanInfo spanInfo) {
686686

687687
Collection<AppSecEvent> collectedEvents = ctx.transferCollectedEvents();
688688

689-
final Object route = tags.get(Tags.HTTP_ROUTE);
690-
if (route != null) {
691-
ctx.setRoute(route.toString());
689+
if (apiSecurityPostProcessor != null) {
690+
final Object route = tags.get(Tags.HTTP_ROUTE);
691+
if (route != null) {
692+
ctx.setRoute(route.toString());
693+
}
694+
// TODO: Move this to traceSegmentPostProcessors
695+
apiSecurityPostProcessor.processTraceSegment(traceSeg, ctx, null);
692696
}
693-
// TODO: Move this to traceSegmentPostProcessors
694-
apiSecurityPostProcessor.processTraceSegment(traceSeg, ctx, null);
695697

696698
for (TraceSegmentPostProcessor pp : this.traceSegmentPostProcessors) {
697699
pp.processTraceSegment(traceSeg, ctx, collectedEvents);

dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/api/security/ApiSecurityProcessorTest.groovy

Lines changed: 24 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ import com.datadog.appsec.event.EventProducerService
44
import com.datadog.appsec.event.ExpiredSubscriberInfoException
55
import com.datadog.appsec.event.data.KnownAddresses
66
import com.datadog.appsec.gateway.AppSecRequestContext
7-
import datadog.trace.api.gateway.RequestContext
7+
import datadog.trace.api.ProductTraceSource
8+
import datadog.trace.api.config.AppSecConfig
9+
import datadog.trace.api.config.GeneralConfig
810
import datadog.trace.api.internal.TraceSegment
9-
import datadog.trace.bootstrap.instrumentation.api.AgentSpan
11+
import datadog.trace.bootstrap.instrumentation.api.Tags
1012
import datadog.trace.test.util.DDSpecification
1113

1214
class ApiSecurityProcessorTest extends DDSpecification {
@@ -29,18 +31,14 @@ class ApiSecurityProcessorTest extends DDSpecification {
2931
1 * producer.getDataSubscribers(KnownAddresses.WAF_CONTEXT_PROCESSOR) >> subInfo
3032
1 * subInfo.isEmpty() >> false
3133
1 * producer.publishDataEvent(_, ctx, _, _)
32-
1 * ctx.commitDerivatives(traceSegment)
33-
1 * ctx.closeWafContext()
34-
1 * ctx.close()
34+
1 * traceSegment.setTagTop('asm.keep', true)
3535
0 * _
3636
}
3737

3838
void 'no schema extracted if sampling is false'() {
3939
given:
4040
def sampler = Mock(ApiSecuritySampler)
4141
def producer = Mock(EventProducerService)
42-
def span = Mock(AgentSpan)
43-
def reqCtx = Mock(RequestContext)
4442
def ctx = Mock(AppSecRequestContext)
4543
def traceSegment = Mock(TraceSegment)
4644
def processor = new ApiSecurityProcessor(sampler, producer)
@@ -50,45 +48,30 @@ class ApiSecurityProcessorTest extends DDSpecification {
5048

5149
then:
5250
noExceptionThrown()
53-
1 * span.getRequestContext() >> reqCtx
54-
1 * reqCtx.getData(_) >> ctx
5551
1 * sampler.sample(ctx) >> false
56-
1 * ctx.closeWafContext()
57-
1 * ctx.close()
5852
0 * _
5953
}
6054

61-
void 'permit is released even if request context close throws'() {
55+
void 'process null appsec request context does nothing'() {
6256
given:
6357
def sampler = Mock(ApiSecuritySampler)
6458
def producer = Mock(EventProducerService)
65-
def span = Mock(AgentSpan)
66-
def reqCtx = Mock(RequestContext)
6759
def traceSegment = Mock(TraceSegment)
68-
def ctx = Mock(AppSecRequestContext)
6960
def processor = new ApiSecurityProcessor(sampler, producer)
7061

7162
when:
72-
processor.processTraceSegment(traceSegment, ctx, null)
63+
processor.processTraceSegment(traceSegment, null, null)
7364

7465
then:
7566
noExceptionThrown()
76-
1 * span.getRequestContext() >> reqCtx
77-
1 * reqCtx.getData(_) >> ctx
78-
1 * sampler.sample(ctx) >> true
79-
1 * reqCtx.getTraceSegment() >> traceSegment
80-
1 * producer.getDataSubscribers(_) >> null
81-
1 * ctx.closeWafContext()
82-
1 * ctx.close() >> { throw new RuntimeException() }
8367
0 * _
8468
}
8569

86-
void 'context is cleaned up on timeout'() {
70+
void 'empty event subscription does not break the process'() {
8771
given:
8872
def sampler = Mock(ApiSecuritySampler)
8973
def producer = Mock(EventProducerService)
90-
def span = Mock(AgentSpan)
91-
def reqCtx = Mock(RequestContext)
74+
def subInfo = Mock(EventProducerService.DataSubscriberInfo)
9275
def traceSegment = Mock(TraceSegment)
9376
def ctx = Mock(AppSecRequestContext)
9477
def processor = new ApiSecurityProcessor(sampler, producer)
@@ -98,39 +81,17 @@ class ApiSecurityProcessorTest extends DDSpecification {
9881

9982
then:
10083
noExceptionThrown()
101-
1 * span.getRequestContext() >> reqCtx
102-
1 * reqCtx.getData(_) >> ctx
103-
1 * ctx.closeWafContext()
104-
1 * ctx.close()
105-
0 * _
106-
}
107-
108-
void 'process null appsec request context does nothing'() {
109-
given:
110-
def sampler = Mock(ApiSecuritySampler)
111-
def producer = Mock(EventProducerService)
112-
def span = Mock(AgentSpan)
113-
def traceSegment = Mock(TraceSegment)
114-
def reqCtx = Mock(RequestContext)
115-
def processor = new ApiSecurityProcessor(sampler, producer)
116-
117-
when:
118-
processor.processTraceSegment(traceSegment, null, null)
119-
120-
then:
121-
noExceptionThrown()
122-
1 * span.getRequestContext() >> reqCtx
123-
1 * reqCtx.getData(_) >> null
84+
1 * sampler.sample(ctx) >> true
85+
1 * producer.getDataSubscribers(_) >> subInfo
86+
1 * subInfo.isEmpty() >> true
12487
0 * _
12588
}
12689

127-
void 'empty event subscription does not break the process'() {
90+
void 'expired event subscription does not break the process'() {
12891
given:
12992
def sampler = Mock(ApiSecuritySampler)
13093
def producer = Mock(EventProducerService)
13194
def subInfo = Mock(EventProducerService.DataSubscriberInfo)
132-
def span = Mock(AgentSpan)
133-
def reqCtx = Mock(RequestContext)
13495
def traceSegment = Mock(TraceSegment)
13596
def ctx = Mock(AppSecRequestContext)
13697
def processor = new ApiSecurityProcessor(sampler, producer)
@@ -140,42 +101,34 @@ class ApiSecurityProcessorTest extends DDSpecification {
140101

141102
then:
142103
noExceptionThrown()
143-
1 * span.getRequestContext() >> reqCtx
144-
1 * reqCtx.getData(_) >> ctx
145104
1 * sampler.sample(ctx) >> true
146-
1 * reqCtx.getTraceSegment() >> traceSegment
147105
1 * producer.getDataSubscribers(_) >> subInfo
148-
1 * subInfo.isEmpty() >> true
149-
1 * ctx.closeWafContext()
150-
1 * ctx.close()
106+
1 * subInfo.isEmpty() >> false
107+
1 * producer.publishDataEvent(_, ctx, _, _) >> { throw new ExpiredSubscriberInfoException() }
151108
0 * _
152109
}
153110

154-
void 'expired event subscription does not break the process'() {
111+
void 'test api security sampling with tracing disabled'() {
155112
given:
113+
injectSysConfig(GeneralConfig.APM_TRACING_ENABLED, "false")
114+
injectSysConfig(AppSecConfig.API_SECURITY_ENABLED, "true")
156115
def sampler = Mock(ApiSecuritySampler)
157-
def producer = Mock(EventProducerService)
158116
def subInfo = Mock(EventProducerService.DataSubscriberInfo)
159-
def span = Mock(AgentSpan)
160-
def reqCtx = Mock(RequestContext)
117+
def producer = Mock(EventProducerService)
161118
def traceSegment = Mock(TraceSegment)
162-
def ctx = Mock(AppSecRequestContext)
163119
def processor = new ApiSecurityProcessor(sampler, producer)
120+
def ctx = Mock(AppSecRequestContext)
164121

165122
when:
166123
processor.processTraceSegment(traceSegment, ctx, null)
167124

168125
then:
169-
noExceptionThrown()
170-
1 * span.getRequestContext() >> reqCtx
171-
1 * reqCtx.getData(_) >> ctx
172126
1 * sampler.sample(ctx) >> true
173-
1 * reqCtx.getTraceSegment() >> traceSegment
174-
1 * producer.getDataSubscribers(_) >> subInfo
127+
1 * producer.getDataSubscribers(KnownAddresses.WAF_CONTEXT_PROCESSOR) >> subInfo
175128
1 * subInfo.isEmpty() >> false
176-
1 * producer.publishDataEvent(_, ctx, _, _) >> { throw new ExpiredSubscriberInfoException() }
177-
1 * ctx.closeWafContext()
178-
1 * ctx.close()
129+
1 * producer.publishDataEvent(_, ctx, _, _)
130+
1 * traceSegment.setTagTop('asm.keep', true)
131+
1 * traceSegment.setTagTop(Tags.PROPAGATED_TRACE_SOURCE, ProductTraceSource.ASM)
179132
0 * _
180133
}
181134
}

dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/gateway/GatewayBridgeSpecification.groovy

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import com.datadog.appsec.event.data.KnownAddresses
1010
import com.datadog.appsec.report.AppSecEvent
1111
import com.datadog.appsec.report.AppSecEventWrapper
1212
import datadog.trace.api.ProductTraceSource
13-
import datadog.trace.api.config.GeneralConfig
1413
import datadog.trace.api.function.TriConsumer
1514
import datadog.trace.api.function.TriFunction
1615
import datadog.trace.api.gateway.BlockResponseFunction
@@ -1202,26 +1201,6 @@ class GatewayBridgeSpecification extends DDSpecification {
12021201
0 * traceSegment.setTagTop(Tags.PROPAGATED_TRACE_SOURCE, ProductTraceSource.ASM)
12031202
}
12041203
1205-
void 'test api security sampling with tracing disabled'() {
1206-
given:
1207-
injectSysConfig(GeneralConfig.APM_TRACING_ENABLED, "false")
1208-
AppSecRequestContext mockAppSecCtx = Mock(AppSecRequestContext)
1209-
RequestContext mockCtx = Stub(RequestContext) {
1210-
getData(RequestContextSlot.APPSEC) >> mockAppSecCtx
1211-
getTraceSegment() >> traceSegment
1212-
}
1213-
IGSpanInfo spanInfo = Mock(AgentSpan)
1214-
when:
1215-
def flow = requestEndedCB.apply(mockCtx, spanInfo)
1216-
then:
1217-
1 * mockAppSecCtx.transferCollectedEvents() >> []
1218-
1 * spanInfo.getTags() >> ['http.route': 'route']
1219-
1 * apiSecurityProcessor.processTraceSegment(_, _, _ )
1220-
1 * traceSegment.setTagTop(Tags.ASM_KEEP, true)
1221-
1 * traceSegment.setTagTop(Tags.PROPAGATED_TRACE_SOURCE, ProductTraceSource.ASM)
1222-
}
1223-
1224-
12251204
void 'test default writeRequestHeaders'(){
12261205
given:
12271206
def allowedHeaders = ['x-allowed-header', 'x-multiple-allowed-header', 'x-always-included'] as Set

dd-trace-core/src/test/groovy/datadog/trace/common/writer/TraceProcessingWorkerTest.groovy

Lines changed: 0 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@ import datadog.trace.common.sampling.SingleSpanSampler
44
import datadog.trace.common.writer.ddagent.PrioritizationStrategy.PublishResult
55
import datadog.trace.core.CoreSpan
66
import datadog.trace.core.DDSpan
7-
import datadog.trace.core.DDSpanContext
8-
import datadog.trace.core.PendingTrace
97
import datadog.trace.core.monitor.HealthMetrics
10-
import datadog.trace.bootstrap.instrumentation.api.SpanPostProcessor
118
import datadog.trace.test.util.DDSpecification
129
import spock.util.concurrent.PollingConditions
1310

@@ -152,56 +149,6 @@ class TraceProcessingWorkerTest extends DDSpecification {
152149
priority << [SAMPLER_DROP, USER_DROP, SAMPLER_KEEP, USER_KEEP, UNSET]
153150
}
154151

155-
def "trace should be post-processed"() {
156-
setup:
157-
AtomicInteger acceptedCount = new AtomicInteger()
158-
PayloadDispatcherImpl countingDispatcher = Mock(PayloadDispatcherImpl)
159-
countingDispatcher.addTrace(_) >> {
160-
acceptedCount.getAndIncrement()
161-
}
162-
HealthMetrics healthMetrics = Mock(HealthMetrics)
163-
164-
def span1 = DDSpan.create("test", 0, Mock(DDSpanContext) {
165-
getTraceCollector() >> Mock(PendingTrace) {
166-
getCurrentTimeNano() >> 0
167-
}
168-
}, [])
169-
def processedSpan1 = false
170-
171-
// Span 2 - should NOT be post-processed
172-
def span2 = DDSpan.create("test", 0, Mock(DDSpanContext) {
173-
getTraceCollector() >> Mock(PendingTrace) {
174-
getCurrentTimeNano() >> 0
175-
}
176-
}, [])
177-
def processedSpan2 = false
178-
179-
SpanPostProcessor.Holder.INSTANCE = Mock(SpanPostProcessor) {
180-
process(span1, _) >> { processedSpan1 = true }
181-
process(span2, _) >> { processedSpan2 = true }
182-
}
183-
184-
TraceProcessingWorker worker = new TraceProcessingWorker(10, healthMetrics,
185-
countingDispatcher, {
186-
false
187-
}, FAST_LANE, 100, TimeUnit.SECONDS, null)
188-
worker.start()
189-
190-
when: "traces are submitted"
191-
worker.publish(span1, SAMPLER_KEEP, [span1, span2])
192-
worker.publish(span2, SAMPLER_KEEP, [span1, span2])
193-
194-
then: "traces are passed through unless rejected on submission"
195-
conditions.eventually {
196-
assert processedSpan1
197-
assert processedSpan2
198-
}
199-
200-
cleanup:
201-
SpanPostProcessor.Holder.INSTANCE = SpanPostProcessor.Holder.NOOP
202-
worker.close()
203-
}
204-
205152
def "traces should be processed"() {
206153
setup:
207154
AtomicInteger acceptedCount = new AtomicInteger()

0 commit comments

Comments
 (0)