diff --git a/dd-java-agent/appsec/src/jmh/java/datadog/appsec/benchmark/EventDispatcherBenchmark.java b/dd-java-agent/appsec/src/jmh/java/datadog/appsec/benchmark/EventDispatcherBenchmark.java index fa31d8e6149..5bbc4f9ef27 100644 --- a/dd-java-agent/appsec/src/jmh/java/datadog/appsec/benchmark/EventDispatcherBenchmark.java +++ b/dd-java-agent/appsec/src/jmh/java/datadog/appsec/benchmark/EventDispatcherBenchmark.java @@ -87,7 +87,8 @@ public void onDataAvailable( ChangeableFlow flow, AppSecRequestContext context, DataBundle dataBundle, - boolean isTransient) {} + boolean isTransient, + boolean isRasp) {} @Override public Priority getPriority() { diff --git a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/blocking/BlockingServiceImpl.java b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/blocking/BlockingServiceImpl.java index 0a36358271f..e87f2c9470a 100644 --- a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/blocking/BlockingServiceImpl.java +++ b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/blocking/BlockingServiceImpl.java @@ -45,7 +45,7 @@ public BlockingDetails shouldBlockUser(@Nonnull String userId) { } SingletonDataBundle db = new SingletonDataBundle<>(KnownAddresses.USER_ID, userId); try { - flow = eventProducer.publishDataEvent(subInfo, reqCtx, db, true); + flow = eventProducer.publishDataEvent(subInfo, reqCtx, db, true, false); break; } catch (ExpiredSubscriberInfoException e) { subInfo = null; diff --git a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/event/DataListener.java b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/event/DataListener.java index a6c5f045c48..570989a4d6a 100644 --- a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/event/DataListener.java +++ b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/event/DataListener.java @@ -8,5 +8,6 @@ void onDataAvailable( ChangeableFlow flow, AppSecRequestContext context, DataBundle dataBundle, - boolean isTransient); + boolean isTransient, + boolean isRasp); } diff --git a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/event/EventDispatcher.java b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/event/EventDispatcher.java index 6db67b01f43..88636fce86c 100644 --- a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/event/EventDispatcher.java +++ b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/event/EventDispatcher.java @@ -132,7 +132,8 @@ public Flow publishDataEvent( DataSubscriberInfo subscribers, AppSecRequestContext ctx, DataBundle newData, - boolean isTransient) + boolean isTransient, + boolean isRasp) throws ExpiredSubscriberInfoException { if (!((DataSubscriberInfoImpl) subscribers).isEventDispatcher(this)) { throw new ExpiredSubscriberInfoException(); @@ -144,7 +145,7 @@ public Flow publishDataEvent( ChangeableFlow flow = new ChangeableFlow(); for (int idx : ((DataSubscriberInfoImpl) subscribers).listenerIndices) { try { - dataListenersIdx.get(idx).onDataAvailable(flow, ctx, newData, isTransient); + dataListenersIdx.get(idx).onDataAvailable(flow, ctx, newData, isTransient, isRasp); } catch (RuntimeException rte) { log.warn("AppSec callback exception", rte); } diff --git a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/event/EventProducerService.java b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/event/EventProducerService.java index 202c422ccee..d8d07ccebab 100644 --- a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/event/EventProducerService.java +++ b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/event/EventProducerService.java @@ -14,7 +14,7 @@ public interface EventProducerService { * set of addresses is identical. * *

The return value is to be passed to {@link #publishDataEvent(DataSubscriberInfo, - * AppSecRequestContext, DataBundle, boolean)}. + * AppSecRequestContext, DataBundle, boolean, boolean)}. * * @param newAddresses the addresses contained in the {@link DataBundle} that is to be passed to * publishDataEvent(). @@ -35,7 +35,8 @@ Flow publishDataEvent( DataSubscriberInfo subscribers, AppSecRequestContext ctx, DataBundle newData, - boolean isTransient) + boolean isTransient, + boolean isRasp) throws ExpiredSubscriberInfoException; interface DataSubscriberInfo { diff --git a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/event/ReplaceableEventProducerService.java b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/event/ReplaceableEventProducerService.java index 1139dd52ad9..0b38d1889b0 100644 --- a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/event/ReplaceableEventProducerService.java +++ b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/event/ReplaceableEventProducerService.java @@ -23,9 +23,10 @@ public Flow publishDataEvent( DataSubscriberInfo subscribers, AppSecRequestContext ctx, DataBundle newData, - boolean isTransient) + boolean isTransient, + boolean isRasp) throws ExpiredSubscriberInfoException { - return cur.publishDataEvent(subscribers, ctx, newData, isTransient); + return cur.publishDataEvent(subscribers, ctx, newData, isTransient, isRasp); } @Override diff --git a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/gateway/AppSecRequestContext.java b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/gateway/AppSecRequestContext.java index 7a82a1eb8d2..1d4fda19444 100644 --- a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/gateway/AppSecRequestContext.java +++ b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/gateway/AppSecRequestContext.java @@ -17,6 +17,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -112,6 +113,8 @@ public class AppSecRequestContext implements DataBundle, Closeable { private Additive additive; // set after additive is set private volatile PowerwafMetrics wafMetrics; + private volatile PowerwafMetrics raspMetrics; + private AtomicInteger raspMetricsCounter; private volatile boolean blocked; private volatile int timeouts; @@ -143,6 +146,14 @@ public PowerwafMetrics getWafMetrics() { return wafMetrics; } + public PowerwafMetrics getRaspMetrics() { + return raspMetrics; + } + + public AtomicInteger getRaspMetricsCounter() { + return raspMetricsCounter; + } + public void setBlocked() { this.blocked = true; } @@ -159,7 +170,18 @@ public int getTimeouts() { return timeouts; } - public Additive getOrCreateAdditive(PowerwafContext ctx, boolean createMetrics) { + public Additive getOrCreateAdditive(PowerwafContext ctx, boolean createMetrics, boolean isRasp) { + + if (createMetrics) { + if (wafMetrics == null) { + this.wafMetrics = ctx.createMetrics(); + } + if (isRasp && raspMetrics == null) { + this.raspMetrics = ctx.createMetrics(); + this.raspMetricsCounter = new AtomicInteger(0); + } + } + Additive curAdditive; synchronized (this) { curAdditive = this.additive; @@ -169,11 +191,6 @@ public Additive getOrCreateAdditive(PowerwafContext ctx, boolean createMetrics) curAdditive = ctx.openAdditive(); this.additive = curAdditive; } - - // new additive was created - if (createMetrics) { - this.wafMetrics = ctx.createMetrics(); - } return curAdditive; } diff --git a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/gateway/GatewayBridge.java b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/gateway/GatewayBridge.java index 67c545d7d5f..8b9046bff49 100644 --- a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/gateway/GatewayBridge.java +++ b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/gateway/GatewayBridge.java @@ -235,7 +235,7 @@ public void init() { DataBundle bundle = new SingletonDataBundle<>(KnownAddresses.REQUEST_PATH_PARAMS, data); try { - return producerService.publishDataEvent(subInfo, ctx, bundle, false); + return producerService.publishDataEvent(subInfo, ctx, bundle, false, false); } catch (ExpiredSubscriberInfoException e) { pathParamsSubInfo = null; } @@ -269,7 +269,7 @@ public void init() { DataBundle bundle = new SingletonDataBundle<>(KnownAddresses.REQUEST_BODY_RAW, bodyContent); try { - return producerService.publishDataEvent(subInfo, ctx, bundle, false); + return producerService.publishDataEvent(subInfo, ctx, bundle, false, false); } catch (ExpiredSubscriberInfoException e) { rawRequestBodySubInfo = null; } @@ -306,7 +306,7 @@ public void init() { new SingletonDataBundle<>( KnownAddresses.REQUEST_BODY_OBJECT, ObjectIntrospection.convert(obj)); try { - return producerService.publishDataEvent(subInfo, ctx, bundle, false); + return producerService.publishDataEvent(subInfo, ctx, bundle, false, false); } catch (ExpiredSubscriberInfoException e) { requestBodySubInfo = null; } @@ -385,7 +385,7 @@ public void init() { DataBundle bundle = new SingletonDataBundle<>(KnownAddresses.GRPC_SERVER_METHOD, method); try { - return producerService.publishDataEvent(subInfo, ctx, bundle, true); + return producerService.publishDataEvent(subInfo, ctx, bundle, true, false); } catch (ExpiredSubscriberInfoException e) { grpcServerMethodSubInfo = null; } @@ -413,7 +413,7 @@ public void init() { DataBundle bundle = new SingletonDataBundle<>(KnownAddresses.GRPC_SERVER_REQUEST_MESSAGE, convObj); try { - return producerService.publishDataEvent(subInfo, ctx, bundle, true); + return producerService.publishDataEvent(subInfo, ctx, bundle, true, false); } catch (ExpiredSubscriberInfoException e) { grpcServerRequestMsgSubInfo = null; } @@ -440,7 +440,7 @@ public void init() { DataBundle bundle = new SingletonDataBundle<>(KnownAddresses.GRAPHQL_SERVER_ALL_RESOLVERS, data); try { - return producerService.publishDataEvent(subInfo, ctx, bundle, true); + return producerService.publishDataEvent(subInfo, ctx, bundle, true, false); } catch (ExpiredSubscriberInfoException e) { graphqlServerRequestMsgSubInfo = null; } @@ -481,7 +481,7 @@ public void init() { .add(KnownAddresses.DB_SQL_QUERY, sql) .build(); try { - return producerService.publishDataEvent(subInfo, ctx, bundle, false); + return producerService.publishDataEvent(subInfo, ctx, bundle, false, true); } catch (ExpiredSubscriberInfoException e) { dbSqlQuerySubInfo = null; } @@ -678,7 +678,7 @@ private Flow maybePublishRequestData(AppSecRequestContext ctx) { } try { - return producerService.publishDataEvent(subInfo, ctx, bundle, false); + return producerService.publishDataEvent(subInfo, ctx, bundle, false, false); } catch (ExpiredSubscriberInfoException e) { this.initialReqDataSubInfo = null; } @@ -710,7 +710,7 @@ private Flow maybePublishResponseData(AppSecRequestContext ctx) { } try { - return producerService.publishDataEvent(subInfo, ctx, bundle, false); + return producerService.publishDataEvent(subInfo, ctx, bundle, false, false); } catch (ExpiredSubscriberInfoException e) { respDataSubInfo = null; } @@ -742,7 +742,7 @@ private void maybeExtractSchemas(AppSecRequestContext ctx) { KnownAddresses.WAF_CONTEXT_PROCESSOR, Collections.singletonMap("extract-schema", true)); try { - producerService.publishDataEvent(subInfo, ctx, bundle, false); + producerService.publishDataEvent(subInfo, ctx, bundle, false, false); return; } catch (ExpiredSubscriberInfoException e) { requestEndSubInfo = null; diff --git a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/powerwaf/PowerWAFModule.java b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/powerwaf/PowerWAFModule.java index 10c08e900c8..c38ef40ff36 100644 --- a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/powerwaf/PowerWAFModule.java +++ b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/powerwaf/PowerWAFModule.java @@ -414,7 +414,11 @@ public PowerWAFDataCallback() { @Override public void onDataAvailable( - ChangeableFlow flow, AppSecRequestContext reqCtx, DataBundle newData, boolean isTransient) { + ChangeableFlow flow, + AppSecRequestContext reqCtx, + DataBundle newData, + boolean isTransient, + boolean isRasp) { Powerwaf.ResultWithData resultWithData; CtxAndAddresses ctxAndAddr = ctxAndAddresses.get(); if (ctxAndAddr == null) { @@ -429,7 +433,7 @@ public void onDataAvailable( } try { - resultWithData = doRunPowerwaf(reqCtx, newData, ctxAndAddr, isTransient); + resultWithData = doRunPowerwaf(reqCtx, newData, ctxAndAddr, isTransient, isRasp); } catch (TimeoutPowerwafException tpe) { reqCtx.increaseTimeouts(); log.debug(LogCollector.EXCLUDE_TELEMETRY, "Timeout calling the WAF", tpe); @@ -583,11 +587,18 @@ private Powerwaf.ResultWithData doRunPowerwaf( AppSecRequestContext reqCtx, DataBundle newData, CtxAndAddresses ctxAndAddr, - boolean isTransient) + boolean isTransient, + boolean isRasp) throws AbstractPowerwafException { - Additive additive = reqCtx.getOrCreateAdditive(ctxAndAddr.ctx, wafMetricsEnabled); - PowerwafMetrics metrics = reqCtx.getWafMetrics(); + Additive additive = reqCtx.getOrCreateAdditive(ctxAndAddr.ctx, wafMetricsEnabled, isRasp); + PowerwafMetrics metrics; + if (isRasp) { + metrics = reqCtx.getRaspMetrics(); + reqCtx.getRaspMetricsCounter().incrementAndGet(); + } else { + metrics = reqCtx.getWafMetrics(); + } if (isTransient) { return runPowerwafTransient(additive, metrics, newData, ctxAndAddr); diff --git a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/powerwaf/PowerWAFStatsReporter.java b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/powerwaf/PowerWAFStatsReporter.java index f730608e88a..073aea73d03 100644 --- a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/powerwaf/PowerWAFStatsReporter.java +++ b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/powerwaf/PowerWAFStatsReporter.java @@ -8,8 +8,11 @@ import java.util.Collection; public class PowerWAFStatsReporter implements TraceSegmentPostProcessor { - private static final String TOTAL_DURATION_US_TAG = "_dd.appsec.waf.duration_ext"; - private static final String TOTAL_DDWAF_RUN_DURATION_US_TAG = "_dd.appsec.waf.duration"; + private static final String WAF_TOTAL_DURATION_US_TAG = "_dd.appsec.waf.duration_ext"; + private static final String WAF_TOTAL_DDWAF_RUN_DURATION_US_TAG = "_dd.appsec.waf.duration"; + private static final String RASP_TOTAL_DURATION_US_TAG = "_dd.appsec.rasp.duration_ext"; + private static final String RASP_TOTAL_DDWAF_RUN_DURATION_US_TAG = "_dd.appsec.rasp.duration"; + private static final String RASP_RULE_EVAL = "_dd.appsec.rasp.rule.eval"; private static final String RULE_FILE_VERSION = "_dd.appsec.event_rules.version"; public static final String TIMEOUTS_TAG = "_dd.appsec.waf.timeouts"; @@ -20,16 +23,26 @@ public class PowerWAFStatsReporter implements TraceSegmentPostProcessor { @Override public void processTraceSegment( TraceSegment segment, AppSecRequestContext ctx, Collection collectedEvents) { - PowerwafMetrics metrics = ctx.getWafMetrics(); - if (metrics != null) { - segment.setTagTop(TOTAL_DURATION_US_TAG, metrics.getTotalRunTimeNs() / 1000L); - segment.setTagTop(TOTAL_DDWAF_RUN_DURATION_US_TAG, metrics.getTotalDdwafRunTimeNs() / 1000L); + PowerwafMetrics wafMetrics = ctx.getWafMetrics(); + if (wafMetrics != null) { + segment.setTagTop(WAF_TOTAL_DURATION_US_TAG, wafMetrics.getTotalRunTimeNs() / 1000L); + segment.setTagTop( + WAF_TOTAL_DDWAF_RUN_DURATION_US_TAG, wafMetrics.getTotalDdwafRunTimeNs() / 1000L); + } + + PowerwafMetrics raspMetrics = ctx.getRaspMetrics(); + if (raspMetrics != null) { + segment.setTagTop(RASP_TOTAL_DURATION_US_TAG, raspMetrics.getTotalRunTimeNs() / 1000L); + segment.setTagTop( + RASP_TOTAL_DDWAF_RUN_DURATION_US_TAG, raspMetrics.getTotalDdwafRunTimeNs() / 1000L); + segment.setTagTop(RASP_RULE_EVAL, ctx.getRaspMetricsCounter().get()); + } - String rulesVersion = this.rulesVersion; - if (rulesVersion != null) { - segment.setTagTop(RULE_FILE_VERSION, rulesVersion); - } + String rulesVersion = this.rulesVersion; + if (rulesVersion != null) { + segment.setTagTop(RULE_FILE_VERSION, rulesVersion); } + if (ctx.getTimeouts() > 0) { segment.setTagTop(TIMEOUTS_TAG, ctx.getTimeouts()); } diff --git a/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/AppSecModuleSpecification.groovy b/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/AppSecModuleSpecification.groovy index 02fdd645276..1f81fcf0f7a 100644 --- a/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/AppSecModuleSpecification.groovy +++ b/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/AppSecModuleSpecification.groovy @@ -33,7 +33,7 @@ class AppSecModuleSpecification extends DDSpecification { } @Override - void onDataAvailable(ChangeableFlow flow, AppSecRequestContext context, DataBundle dataBundle, boolean isTransient) { + void onDataAvailable(ChangeableFlow flow, AppSecRequestContext context, DataBundle dataBundle, boolean isTransient, boolean isRasp) { } @Override diff --git a/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/blocking/BlockingServiceImplSpecification.groovy b/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/blocking/BlockingServiceImplSpecification.groovy index 9cead2a6c5f..0438f1c9040 100644 --- a/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/blocking/BlockingServiceImplSpecification.groovy +++ b/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/blocking/BlockingServiceImplSpecification.groovy @@ -41,7 +41,7 @@ class BlockingServiceImplSpecification extends DDSpecification { final OrderedCallback.Priority priority = OrderedCallback.Priority.DEFAULT @Override - void onDataAvailable(ChangeableFlow flow, AppSecRequestContext context, DataBundle dataBundle, boolean isTransient) { + void onDataAvailable(ChangeableFlow flow, AppSecRequestContext context, DataBundle dataBundle, boolean isTransient, boolean isRasp) { if (dataBundle.get(KnownAddresses.USER_ID) == 'blocked.user') { flow.action = new Flow.Action.RequestBlockingAction(405, BlockingContentType.HTML) } diff --git a/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/event/EventDispatcherSpecification.groovy b/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/event/EventDispatcherSpecification.groovy index b974581eab8..184ac56ff00 100644 --- a/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/event/EventDispatcherSpecification.groovy +++ b/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/event/EventDispatcherSpecification.groovy @@ -35,24 +35,24 @@ class EventDispatcherSpecification extends DDSpecification { DataBundle db = MapDataBundle.of( KnownAddresses.REQUEST_CLIENT_IP, '::1', KnownAddresses.REQUEST_METHOD, 'GET') - dispatcher.publishDataEvent(subscribers, ctx, db, true) + dispatcher.publishDataEvent(subscribers, ctx, db, true, false) then: 1 * dataListener3.onDataAvailable( _ as Flow, ctx, { it.hasAddress(KnownAddresses.REQUEST_CLIENT_IP) }, - true) >> { savedFlow3 = it[0] } + true, false) >> { savedFlow3 = it[0] } then: 1 * dataListener2.onDataAvailable( _ as Flow, ctx, { it.hasAddress(KnownAddresses.REQUEST_CLIENT_IP) }, - true) >> { savedFlow2 = it[0] } + true, false) >> { savedFlow2 = it[0] } savedFlow2.is(savedFlow3) then: 1 * dataListener1.onDataAvailable(_ as Flow, ctx, - _ as DataBundle, true) >> { savedFlow1 = it[0] } + _ as DataBundle, true, false) >> { savedFlow1 = it[0] } savedFlow1.is(savedFlow2) } @@ -73,11 +73,11 @@ class EventDispatcherSpecification extends DDSpecification { when: def subscribers = dispatcher.getDataSubscribers(KnownAddresses.REQUEST_CLIENT_IP, KnownAddresses.HEADERS_NO_COOKIES) - dispatcher.publishDataEvent(subscribers, ctx, db, true) + dispatcher.publishDataEvent(subscribers, ctx, db, true, false) then: assert !subscribers.empty - 1 * listener.onDataAvailable(_ as Flow, ctx, db, true) + 1 * listener.onDataAvailable(_ as Flow, ctx, db, true, false) } void 'blocking interrupts data listener calls'() { @@ -96,14 +96,14 @@ class EventDispatcherSpecification extends DDSpecification { when: def subscribers = dispatcher.getDataSubscribers(KnownAddresses.REQUEST_CLIENT_IP) DataBundle db = MapDataBundle.of(KnownAddresses.REQUEST_CLIENT_IP, '::1') - ChangeableFlow resultFlow = dispatcher.publishDataEvent(subscribers, ctx, db, true) + ChangeableFlow resultFlow = dispatcher.publishDataEvent(subscribers, ctx, db, true, false) then: - 1 * dataListener1.onDataAvailable(_ as Flow, ctx, _ as DataBundle, true) >> { + 1 * dataListener1.onDataAvailable(_ as Flow, ctx, _ as DataBundle, true, false) >> { ChangeableFlow flow = it.first() flow.action = new Flow.Action.RequestBlockingAction(404, BlockingContentType.AUTO) } - 0 * dataListener2.onDataAvailable(_ as Flow, ctx, _ as DataBundle, _ as boolean) + 0 * dataListener2.onDataAvailable(_ as Flow, ctx, _ as DataBundle, _ as boolean, _ as boolean) assert resultFlow.blocking assert resultFlow.action.statusCode == 404 assert resultFlow.action.blockingContentType == BlockingContentType.AUTO @@ -122,10 +122,10 @@ class EventDispatcherSpecification extends DDSpecification { when: def subscribers = dispatcher.getDataSubscribers(KnownAddresses.REQUEST_CLIENT_IP) - dispatcher.publishDataEvent(subscribers, ctx, db, false) + dispatcher.publishDataEvent(subscribers, ctx, db, false, false) then: - 1 * listener.onDataAvailable(_ as Flow, ctx, db, false) + 1 * listener.onDataAvailable(_ as Flow, ctx, db, false, false) 1 * ctx.addAll(db) } @@ -155,7 +155,7 @@ class EventDispatcherSpecification extends DDSpecification { EventDispatcher anotherDispatcher = new EventDispatcher() EventProducerService.DataSubscriberInfo subInfo = anotherDispatcher.getDataSubscribers(KnownAddresses.REQUEST_CLIENT_IP) - dispatcher.publishDataEvent(subInfo, Stub(AppSecRequestContext), Stub(DataBundle), false) + dispatcher.publishDataEvent(subInfo, Stub(AppSecRequestContext), Stub(DataBundle), false, false) then: thrown ExpiredSubscriberInfoException diff --git a/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/gateway/GatewayBridgeSpecification.groovy b/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/gateway/GatewayBridgeSpecification.groovy index 2a046cdfada..c72956ae1b1 100644 --- a/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/gateway/GatewayBridgeSpecification.groovy +++ b/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/gateway/GatewayBridgeSpecification.groovy @@ -214,7 +214,7 @@ class GatewayBridgeSpecification extends DDSpecification { ctx.data.rawURI = '/' ctx.data.peerAddress = '0.0.0.0' eventDispatcher.getDataSubscribers(_) >> nonEmptyDsInfo - eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, false) >> + eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, false, false) >> { bundle = it[2]; NoopFlow.INSTANCE } and: @@ -232,7 +232,7 @@ class GatewayBridgeSpecification extends DDSpecification { when: eventDispatcher.getDataSubscribers(_) >> nonEmptyDsInfo - eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, false) >> + eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, false, false) >> { bundle = it[2]; NoopFlow.INSTANCE } and: @@ -250,7 +250,7 @@ class GatewayBridgeSpecification extends DDSpecification { when: eventDispatcher.getDataSubscribers(_) >> nonEmptyDsInfo - eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, false) >> + eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, false, false) >> { bundle = it[2]; NoopFlow.INSTANCE } and: @@ -268,7 +268,7 @@ class GatewayBridgeSpecification extends DDSpecification { when: eventDispatcher.getDataSubscribers(_) >> nonEmptyDsInfo - eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, false) >> + eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, false, false) >> { bundle = it[2]; NoopFlow.INSTANCE } and: @@ -286,7 +286,7 @@ class GatewayBridgeSpecification extends DDSpecification { when: eventDispatcher.getDataSubscribers({ KnownAddresses.REQUEST_URI_RAW in it }) >> nonEmptyDsInfo - eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, false) >> + eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, false, false) >> { bundle = it[2]; NoopFlow.INSTANCE } and: @@ -317,7 +317,7 @@ class GatewayBridgeSpecification extends DDSpecification { when: eventDispatcher.getDataSubscribers({ KnownAddresses.REQUEST_URI_RAW in it }) >> nonEmptyDsInfo - eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, false) >> + eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, false, false) >> { bundle = it[2]; NoopFlow.INSTANCE } and: @@ -347,7 +347,7 @@ class GatewayBridgeSpecification extends DDSpecification { when: eventDispatcher.getDataSubscribers({ KnownAddresses.REQUEST_PATH_PARAMS in it }) >> nonEmptyDsInfo - eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, false) >> + eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, false, false) >> { bundle = it[2]; NoopFlow.INSTANCE } and: @@ -525,7 +525,7 @@ class GatewayBridgeSpecification extends DDSpecification { setup: supplier.get() >> 'foobar' eventDispatcher.getDataSubscribers({ KnownAddresses.REQUEST_BODY_RAW in it }) >> nonEmptyDsInfo - eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, false) >> + eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, false, false) >> { bundle = it[2]; NoopFlow.INSTANCE } when: @@ -557,7 +557,7 @@ class GatewayBridgeSpecification extends DDSpecification { setup: eventDispatcher.getDataSubscribers({KnownAddresses.REQUEST_BODY_OBJECT in it}) >> nonEmptyDsInfo - eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, false) >> { bundle = it[2]; NoopFlow.INSTANCE } + eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, false, false) >> { bundle = it[2]; NoopFlow.INSTANCE } when: requestBodyProcessedCB.apply(ctx, obj) @@ -591,8 +591,8 @@ class GatewayBridgeSpecification extends DDSpecification { }) then: - 1 * eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, false) >> - { a, b, db, c -> bundle = db; NoopFlow.INSTANCE } + 1 * eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, false, false) >> + { a, b, db, c, e -> bundle = db; NoopFlow.INSTANCE } bundle.get(KnownAddresses.REQUEST_BODY_OBJECT) == [foo: 'bar'] flow.result == null flow.action == Flow.Action.Noop.INSTANCE @@ -604,7 +604,7 @@ class GatewayBridgeSpecification extends DDSpecification { setup: eventDispatcher.getDataSubscribers({ KnownAddresses.REQUEST_METHOD in it }) >> nonEmptyDsInfo - eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, false) >> + eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, false, false) >> { bundle = it[2]; NoopFlow.INSTANCE } when: @@ -622,7 +622,7 @@ class GatewayBridgeSpecification extends DDSpecification { when: eventDispatcher.getDataSubscribers({ KnownAddresses.REQUEST_SCHEME in it }) >> nonEmptyDsInfo - eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, false) >> + eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, false, false) >> { bundle = it[2]; NoopFlow.INSTANCE } and: @@ -661,7 +661,7 @@ class GatewayBridgeSpecification extends DDSpecification { Flow flow2 = respHeadersDoneCB.apply(ctx) then: - 1 * eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, false) >> + 1 * eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, false, false) >> { NoopFlow.INSTANCE } flow1.result == null flow1.action == Flow.Action.Noop.INSTANCE @@ -681,8 +681,8 @@ class GatewayBridgeSpecification extends DDSpecification { }) then: - 1 * eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, true) >> - { a, b, db, c -> bundle = db; NoopFlow.INSTANCE } + 1 * eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, true, false) >> + { a, b, db, c, e -> bundle = db; NoopFlow.INSTANCE } bundle.get(KnownAddresses.GRPC_SERVER_REQUEST_MESSAGE) == [foo: 'bar'] flow.result == null flow.action == Flow.Action.Noop.INSTANCE @@ -697,7 +697,7 @@ class GatewayBridgeSpecification extends DDSpecification { Flow flow = grpcServerMethodCB.apply(ctx, '/my.package.Greeter/SayHello') then: - 1 * eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, true) >> + 1 * eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, true, false) >> { args -> bundle = args[2]; NoopFlow.INSTANCE } bundle.get(KnownAddresses.GRPC_SERVER_METHOD) == '/my.package.Greeter/SayHello' flow.result == null diff --git a/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/powerwaf/PowerWAFModuleSpecification.groovy b/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/powerwaf/PowerWAFModuleSpecification.groovy index 60ac5e3544f..58faa857c9f 100644 --- a/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/powerwaf/PowerWAFModuleSpecification.groovy +++ b/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/powerwaf/PowerWAFModuleSpecification.groovy @@ -193,7 +193,7 @@ class PowerWAFModuleSpecification extends DDSpecification { KnownAddresses.REQUEST_INFERRED_CLIENT_IP, '1.2.3.4' ) - dataListener.onDataAvailable(flow, ctx, newBundle, false) + dataListener.onDataAvailable(flow, ctx, newBundle, false, false) ctx.closeAdditive() then: @@ -202,7 +202,7 @@ class PowerWAFModuleSpecification extends DDSpecification { rba.statusCode == 501 && rba.blockingContentType == BlockingContentType.JSON }) - 1 * ctx.getOrCreateAdditive(_ as PowerwafContext, true) >> { + 1 * ctx.getOrCreateAdditive(_ as PowerwafContext, true, false) >> { pwafAdditive = it[0].openAdditive() } 2 * tracer.activeSpan() @@ -227,7 +227,7 @@ class PowerWAFModuleSpecification extends DDSpecification { KnownAddresses.USER_ID, 'user-to-block-1' ) - dataListener.onDataAvailable(flow, ctx, bundle, false) + dataListener.onDataAvailable(flow, ctx, bundle, false, false) ctx.closeAdditive() then: @@ -235,7 +235,7 @@ class PowerWAFModuleSpecification extends DDSpecification { rba.statusCode == 403 && rba.blockingContentType == BlockingContentType.AUTO }) - 1 * ctx.getOrCreateAdditive(_ as PowerwafContext, true) >> { + 1 * ctx.getOrCreateAdditive(_ as PowerwafContext, true, false) >> { pwafAdditive = it[0].openAdditive() } 2 * tracer.activeSpan() @@ -267,7 +267,7 @@ class PowerWAFModuleSpecification extends DDSpecification { it.dirtyStatus.clearDirty() } - dataListener.onDataAvailable(flow, ctx, bundle, false) + dataListener.onDataAvailable(flow, ctx, bundle, false, false) ctx.closeAdditive() then: @@ -276,7 +276,7 @@ class PowerWAFModuleSpecification extends DDSpecification { rba.statusCode == 403 && rba.blockingContentType == BlockingContentType.AUTO }) - 1 * ctx.getOrCreateAdditive(_ as PowerwafContext, true) >> { + 1 * ctx.getOrCreateAdditive(_ as PowerwafContext, true, false) >> { pwafAdditive = it[0].openAdditive() } 2 * tracer.activeSpan() @@ -292,7 +292,7 @@ class PowerWAFModuleSpecification extends DDSpecification { KnownAddresses.USER_ID, 'user-to-block-2' ) - dataListener.onDataAvailable(flow, ctx, bundle, false) + dataListener.onDataAvailable(flow, ctx, bundle, false, false) ctx.closeAdditive() then: @@ -300,7 +300,7 @@ class PowerWAFModuleSpecification extends DDSpecification { rba.statusCode == 403 && rba.blockingContentType == BlockingContentType.AUTO }) - 1 * ctx.getOrCreateAdditive(_ as PowerwafContext, true) >> { + 1 * ctx.getOrCreateAdditive(_ as PowerwafContext, true, false) >> { pwafAdditive = it[0].openAdditive() } 2 * tracer.activeSpan() @@ -347,7 +347,7 @@ class PowerWAFModuleSpecification extends DDSpecification { KnownAddresses.USER_ID, 'user-to-block-2' ) - dataListener.onDataAvailable(flow, ctx, bundle, false) + dataListener.onDataAvailable(flow, ctx, bundle, false, false) ctx.closeAdditive() then: @@ -356,7 +356,7 @@ class PowerWAFModuleSpecification extends DDSpecification { rba.statusCode == 403 && rba.blockingContentType == BlockingContentType.AUTO }) - 1 * ctx.getOrCreateAdditive(_ as PowerwafContext, true) >> { + 1 * ctx.getOrCreateAdditive(_ as PowerwafContext, true, false) >> { pwafAdditive = it[0].openAdditive() } 2 * tracer.activeSpan() @@ -372,11 +372,11 @@ class PowerWAFModuleSpecification extends DDSpecification { KnownAddresses.USER_ID, 'user-to-block-1' ) - dataListener.onDataAvailable(flow, ctx, bundle, false) + dataListener.onDataAvailable(flow, ctx, bundle, false, false) ctx.closeAdditive() then: - 1 * ctx.getOrCreateAdditive(_ as PowerwafContext, true) >> { + 1 * ctx.getOrCreateAdditive(_ as PowerwafContext, true, false) >> { pwafAdditive = it[0].openAdditive() } 1 * ctx.getWafMetrics() @@ -428,11 +428,11 @@ class PowerWAFModuleSpecification extends DDSpecification { 1 * reconf.reloadSubscriptions() when: - dataListener.onDataAvailable(flow, ctx, ATTACK_BUNDLE, false) + dataListener.onDataAvailable(flow, ctx, ATTACK_BUNDLE, false, false) ctx.closeAdditive() then: - 1 * ctx.getOrCreateAdditive(_, true) >> { + 1 * ctx.getOrCreateAdditive(_, true, false) >> { pwafAdditive = it[0].openAdditive() } 2 * tracer.activeSpan() @@ -450,11 +450,11 @@ class PowerWAFModuleSpecification extends DDSpecification { KnownAddresses.REQUEST_INFERRED_CLIENT_IP, '192.168.0.1' ) - dataListener.onDataAvailable(flow, ctx, newBundle, false) + dataListener.onDataAvailable(flow, ctx, newBundle, false, false) ctx.closeAdditive() then: - 1 * ctx.getOrCreateAdditive(_, true) >> { + 1 * ctx.getOrCreateAdditive(_, true, false) >> { pwafAdditive = it[0].openAdditive() } 1 * ctx.getWafMetrics() @@ -508,11 +508,11 @@ class PowerWAFModuleSpecification extends DDSpecification { 1 * reconf.reloadSubscriptions() when: - dataListener.onDataAvailable(flow, ctx, ATTACK_BUNDLE, false) + dataListener.onDataAvailable(flow, ctx, ATTACK_BUNDLE, false, false) ctx.closeAdditive() then: - 1 * ctx.getOrCreateAdditive(_, true) >> { + 1 * ctx.getOrCreateAdditive(_, true, false) >> { pwafAdditive = it[0].openAdditive() } 3 * tracer.activeSpan() @@ -582,7 +582,7 @@ class PowerWAFModuleSpecification extends DDSpecification { 2 * reconf.reloadSubscriptions() when: - dataListener.onDataAvailable(flow, ctx, ATTACK_BUNDLE, false) + dataListener.onDataAvailable(flow, ctx, ATTACK_BUNDLE, false, false) ctx.closeAdditive() then: @@ -591,7 +591,7 @@ class PowerWAFModuleSpecification extends DDSpecification { rba.statusCode == 401 && rba.blockingContentType == BlockingContentType.AUTO }) - 1 * ctx.getOrCreateAdditive(_, true) >> { it[0].openAdditive() } + 1 * ctx.getOrCreateAdditive(_, true, false) >> { it[0].openAdditive() } 2 * tracer.activeSpan() 1 * ctx.reportEvents(_ as Collection) 1 * ctx.getWafMetrics() @@ -607,11 +607,11 @@ class PowerWAFModuleSpecification extends DDSpecification { DataBundle bundle = MapDataBundle.of(KnownAddresses.HEADERS_NO_COOKIES, new CaseInsensitiveMap>(['user-agent': 'redirect' + variant])) def flow = new ChangeableFlow() - dataListener.onDataAvailable(flow, ctx, bundle, false) + dataListener.onDataAvailable(flow, ctx, bundle, false, false) ctx.closeAdditive() then: - 1 * ctx.getOrCreateAdditive(_, true) >> { + 1 * ctx.getOrCreateAdditive(_, true, false) >> { PowerwafContext pwCtx = it[0] as PowerwafContext pwafAdditive = pwCtx.openAdditive() metrics = pwCtx.createMetrics() @@ -672,11 +672,11 @@ class PowerWAFModuleSpecification extends DDSpecification { ChangeableFlow flow = new ChangeableFlow() when: - dataListener.onDataAvailable(flow, ctx, ATTACK_BUNDLE, false) + dataListener.onDataAvailable(flow, ctx, ATTACK_BUNDLE, false, false) ctx.closeAdditive() then: - 1 * ctx.getOrCreateAdditive(_, true) >> { + 1 * ctx.getOrCreateAdditive(_, true, false) >> { PowerwafContext pwCtx = it[0] as PowerwafContext pwafAdditive = pwCtx.openAdditive() metrics = pwCtx.createMetrics() @@ -701,11 +701,11 @@ class PowerWAFModuleSpecification extends DDSpecification { ChangeableFlow flow = new ChangeableFlow() when: - dataListener.onDataAvailable(flow, ctx, ATTACK_BUNDLE, false) + dataListener.onDataAvailable(flow, ctx, ATTACK_BUNDLE, false, false) ctx.closeAdditive() then: - 1 * ctx.getOrCreateAdditive(_, false) >> { + 1 * ctx.getOrCreateAdditive(_, false, false) >> { pwafAdditive = it[0].openAdditive() } 1 * ctx.getWafMetrics() >> null @@ -726,12 +726,12 @@ class PowerWAFModuleSpecification extends DDSpecification { when: setupWithStubConfigService() pp = service.traceSegmentPostProcessors[1] - dataListener.onDataAvailable(flow, ctx, ATTACK_BUNDLE, false) + dataListener.onDataAvailable(flow, ctx, ATTACK_BUNDLE, false, false) ctx.closeAdditive() pp.processTraceSegment(segment, ctx, []) then: - 1 * ctx.getOrCreateAdditive(_, true) >> { + 1 * ctx.getOrCreateAdditive(_, true, false) >> { PowerwafContext pwCtx = it[0] as PowerwafContext pwafAdditive = pwCtx.openAdditive() metrics = pwCtx.createMetrics() @@ -752,10 +752,10 @@ class PowerWAFModuleSpecification extends DDSpecification { ChangeableFlow flow = new ChangeableFlow() when: - dataListener.onDataAvailable(flow, ctx, ATTACK_BUNDLE, false) + dataListener.onDataAvailable(flow, ctx, ATTACK_BUNDLE, false, false) then: - 1 * ctx.getOrCreateAdditive(_, true) >> { + 1 * ctx.getOrCreateAdditive(_, true, false) >> { PowerwafContext pwCtx = it[0] as PowerwafContext pwafAdditive = pwCtx.openAdditive() metrics = pwCtx.createMetrics() @@ -778,7 +778,7 @@ class PowerWAFModuleSpecification extends DDSpecification { pwafModule = new PowerWAFModule() // replace the one created too soon when: - dataListener.onDataAvailable(Stub(ChangeableFlow), ctx, ATTACK_BUNDLE, false) + dataListener.onDataAvailable(Stub(ChangeableFlow), ctx, ATTACK_BUNDLE, false, false) ctx.closeAdditive() then: @@ -816,7 +816,7 @@ class PowerWAFModuleSpecification extends DDSpecification { when: def bundle = MapDataBundle.of(KnownAddresses.HEADERS_NO_COOKIES, new CaseInsensitiveMap>(['user-agent': [password: 'Arachni/v0']])) - dataListener.onDataAvailable(Stub(ChangeableFlow), ctx, bundle, false) + dataListener.onDataAvailable(Stub(ChangeableFlow), ctx, bundle, false, false) ctx.closeAdditive() then: @@ -839,7 +839,7 @@ class PowerWAFModuleSpecification extends DDSpecification { when: def bundle = MapDataBundle.of(KnownAddresses.HEADERS_NO_COOKIES, new CaseInsensitiveMap>(['user-agent': [password: 'Arachni/v0']])) - dataListener.onDataAvailable(Stub(ChangeableFlow), ctx, bundle, false) + dataListener.onDataAvailable(Stub(ChangeableFlow), ctx, bundle, false, false) ctx.closeAdditive() then: @@ -861,7 +861,7 @@ class PowerWAFModuleSpecification extends DDSpecification { AppSecEvent event when: - dataListener.onDataAvailable(Stub(ChangeableFlow), ctx, ATTACK_BUNDLE, false) + dataListener.onDataAvailable(Stub(ChangeableFlow), ctx, ATTACK_BUNDLE, false, false) ctx.closeAdditive() then: @@ -883,7 +883,7 @@ class PowerWAFModuleSpecification extends DDSpecification { new CaseInsensitiveMap>(['user-agent': 'Harmless'])) when: - dataListener.onDataAvailable(flow, ctx, db, false) + dataListener.onDataAvailable(flow, ctx, db, false, false) then: ctx.getOrCreateAdditive(_, true) >> { @@ -912,7 +912,7 @@ class PowerWAFModuleSpecification extends DDSpecification { ]) when: - dataListener.onDataAvailable(flow, ctx, db, false) + dataListener.onDataAvailable(flow, ctx, db, false, false) then: ctx.getOrCreateAdditive(_, true) >> { @@ -927,7 +927,7 @@ class PowerWAFModuleSpecification extends DDSpecification { DataBundle db = MapDataBundle.of(KnownAddresses.HEADERS_NO_COOKIES, [get: { null }] as List) when: - dataListener.onDataAvailable(flow, ctx, db, false) + dataListener.onDataAvailable(flow, ctx, db, false, false) then: ctx.getOrCreateAdditive(_, true) >> { @@ -949,7 +949,7 @@ class PowerWAFModuleSpecification extends DDSpecification { TraceSegmentPostProcessor pp = service.traceSegmentPostProcessors.last() when: - dataListener.onDataAvailable(flow, ctx, db, false) + dataListener.onDataAvailable(flow, ctx, db, false, false) then: ctx.getOrCreateAdditive(_, true) >> { @@ -983,11 +983,11 @@ class PowerWAFModuleSpecification extends DDSpecification { when: cfgService.listeners['waf'].onNewSubconfig(defaultConfig['waf'], reconf) dataListener = pwafModule.dataSubscriptions.first() - dataListener.onDataAvailable(Stub(ChangeableFlow), ctx, ATTACK_BUNDLE, false) + dataListener.onDataAvailable(Stub(ChangeableFlow), ctx, ATTACK_BUNDLE, false, false) ctx.closeAdditive() then: - 1 * ctx.getOrCreateAdditive(_, true) >> { + 1 * ctx.getOrCreateAdditive(_, true, false) >> { pwafAdditive = it[0].openAdditive() } 1 * ctx.reportEvents(_ as Collection) 1 * reconf.reloadSubscriptions() @@ -1018,12 +1018,12 @@ class PowerWAFModuleSpecification extends DDSpecification { dataListener = pwafModule.dataSubscriptions.first() def bundle = MapDataBundle.of(KnownAddresses.REQUEST_INFERRED_CLIENT_IP, '1.2.3.4') - dataListener.onDataAvailable(flow, ctx, bundle, false) + dataListener.onDataAvailable(flow, ctx, bundle, false, false) ctx.closeAdditive() then: 1 * reconf.reloadSubscriptions() - 1 * ctx.getOrCreateAdditive(_, true) >> { pwafAdditive = it[0].openAdditive() } + 1 * ctx.getOrCreateAdditive(_, true, false) >> { pwafAdditive = it[0].openAdditive() } 2 * tracer.activeSpan() 1 * ctx.reportEvents(_ as Collection) 1 * ctx.getWafMetrics() @@ -1074,12 +1074,12 @@ class PowerWAFModuleSpecification extends DDSpecification { dataListener = pwafModule.dataSubscriptions.first() def bundle = MapDataBundle.of(KnownAddresses.REQUEST_INFERRED_CLIENT_IP, '1.2.3.4') - dataListener.onDataAvailable(flow, ctx, bundle, false) + dataListener.onDataAvailable(flow, ctx, bundle, false, false) ctx.closeAdditive() then: 'no match; rule is disabled' 1 * reconf.reloadSubscriptions() - 1 * ctx.getOrCreateAdditive(_, true) >> { + 1 * ctx.getOrCreateAdditive(_, true, false) >> { pwafAdditive = it[0].openAdditive() } 1 * ctx.getWafMetrics() 1 * ctx.closeAdditive() >> { pwafAdditive.close() } @@ -1097,11 +1097,11 @@ class PowerWAFModuleSpecification extends DDSpecification { it.dirtyStatus.clearDirty() } - dataListener.onDataAvailable(flow, ctx, bundle, false) + dataListener.onDataAvailable(flow, ctx, bundle, false, false) ctx.closeAdditive() then: 'no match; data was cleared (though rule is no longer disabled)' - 1 * ctx.getOrCreateAdditive(_, true) >> { + 1 * ctx.getOrCreateAdditive(_, true, false) >> { pwafAdditive = it[0].openAdditive() } 1 * ctx.getWafMetrics() 1 * ctx.closeAdditive() >> {pwafAdditive.close()} @@ -1117,12 +1117,12 @@ class PowerWAFModuleSpecification extends DDSpecification { it.dirtyStatus.clearDirty() } - dataListener.onDataAvailable(flow, ctx, bundle, false) + dataListener.onDataAvailable(flow, ctx, bundle, false, false) ctx.closeAdditive() then: 'now we have match' 1 * reconf.reloadSubscriptions() - 1 * ctx.getOrCreateAdditive(_, true) >> { + 1 * ctx.getOrCreateAdditive(_, true, false) >> { pwafAdditive = it[0].openAdditive() } 2 * tracer.activeSpan() 1 * ctx.reportEvents(_ as Collection) @@ -1144,12 +1144,12 @@ class PowerWAFModuleSpecification extends DDSpecification { it.dirtyStatus.clearDirty() } - dataListener.onDataAvailable(flow, ctx, bundle, false) + dataListener.onDataAvailable(flow, ctx, bundle, false, false) ctx.closeAdditive() then: 'nothing again; we disabled the rule' 1 * reconf.reloadSubscriptions() - 1 * ctx.getOrCreateAdditive(_, true) >> { pwafAdditive = it[0].openAdditive() } + 1 * ctx.getOrCreateAdditive(_, true, false) >> { pwafAdditive = it[0].openAdditive() } 1 * ctx.getWafMetrics() 1 * ctx.closeAdditive() _ * ctx.increaseTimeouts() @@ -1172,13 +1172,13 @@ class PowerWAFModuleSpecification extends DDSpecification { it.dirtyStatus.clearDirty() } dataListener = pwafModule.dataSubscriptions.first() - dataListener.onDataAvailable(flow, ctx, ATTACK_BUNDLE, false) + dataListener.onDataAvailable(flow, ctx, ATTACK_BUNDLE, false, false) ctx.closeAdditive() then: 1 * reconf.reloadSubscriptions() // no attack - 1 * ctx.getOrCreateAdditive(_, true) >> { pwafAdditive = it[0].openAdditive() } + 1 * ctx.getOrCreateAdditive(_, true, false) >> { pwafAdditive = it[0].openAdditive() } 1 * ctx.getWafMetrics() 1 * ctx.closeAdditive() >> {pwafAdditive.close()} _ * ctx.increaseTimeouts() @@ -1194,13 +1194,13 @@ class PowerWAFModuleSpecification extends DDSpecification { service.listeners['waf'].onNewSubconfig(it, reconf) it.dirtyStatus.clearDirty() } - dataListener.onDataAvailable(flow, ctx, ATTACK_BUNDLE, false) + dataListener.onDataAvailable(flow, ctx, ATTACK_BUNDLE, false, false) ctx.closeAdditive() then: 1 * reconf.reloadSubscriptions() // no attack - 1 * ctx.getOrCreateAdditive(_, true) >> { + 1 * ctx.getOrCreateAdditive(_, true, false) >> { pwafAdditive = it[0].openAdditive() } 1 * ctx.getWafMetrics() 1 * ctx.closeAdditive() >> {pwafAdditive.close()} @@ -1217,13 +1217,13 @@ class PowerWAFModuleSpecification extends DDSpecification { service.listeners['waf'].onNewSubconfig(it, reconf) it.dirtyStatus.clearDirty() } - dataListener.onDataAvailable(flow, ctx, ATTACK_BUNDLE, false) + dataListener.onDataAvailable(flow, ctx, ATTACK_BUNDLE, false, false) ctx.closeAdditive() then: 1 * reconf.reloadSubscriptions() // attack found - 1 * ctx.getOrCreateAdditive(_, true) >> { + 1 * ctx.getOrCreateAdditive(_, true, false) >> { pwafAdditive = it[0].openAdditive() } 1 * ctx.getWafMetrics() 1 * flow.isBlocking() @@ -1243,13 +1243,13 @@ class PowerWAFModuleSpecification extends DDSpecification { service.listeners['waf'].onNewSubconfig(it, reconf) it.dirtyStatus.clearDirty() } - dataListener.onDataAvailable(flow, ctx, ATTACK_BUNDLE, false) + dataListener.onDataAvailable(flow, ctx, ATTACK_BUNDLE, false, false) ctx.closeAdditive() then: 1 * reconf.reloadSubscriptions() // no attack - 1 * ctx.getOrCreateAdditive(_, true) >> { + 1 * ctx.getOrCreateAdditive(_, true, false) >> { pwafAdditive = it[0].openAdditive() } 1 * ctx.getWafMetrics() 1 * ctx.closeAdditive() @@ -1355,10 +1355,10 @@ class PowerWAFModuleSpecification extends DDSpecification { KnownAddresses.REQUEST_BODY_OBJECT, '/cybercop' ) - dataListener.onDataAvailable(flow, ctx, transientBundle, false) + dataListener.onDataAvailable(flow, ctx, transientBundle, false, false) then: - 1 * ctx.getOrCreateAdditive(_, true) >> { + 1 * ctx.getOrCreateAdditive(_, true, false) >> { pwafAdditive = it[0].openAdditive() } 2 * tracer.activeSpan() 1 * ctx.reportEvents(_ as Collection) >> { @@ -1370,11 +1370,11 @@ class PowerWAFModuleSpecification extends DDSpecification { 0 * _ when: - dataListener.onDataAvailable(flow, ctx, ATTACK_BUNDLE, false) + dataListener.onDataAvailable(flow, ctx, ATTACK_BUNDLE, false, false) ctx.closeAdditive() then: - 1 * ctx.getOrCreateAdditive(_, true) >> { + 1 * ctx.getOrCreateAdditive(_, true, false) >> { pwafAdditive } 1 * flow.setAction({ it.blocking }) 2 * tracer.activeSpan() @@ -1401,7 +1401,7 @@ class PowerWAFModuleSpecification extends DDSpecification { when: for (int t = 0; t < 20; t++) { CountDownLatch latch = new CountDownLatch(1) - dataListener.onDataAvailable(flow, ctx, ATTACK_BUNDLE, false) + dataListener.onDataAvailable(flow, ctx, ATTACK_BUNDLE, false, false) Thread thread = new Thread({ p -> latch.countDown() ctx.closeAdditive() diff --git a/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/powerwaf/PowerWAFStatsReporterSpecification.groovy b/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/powerwaf/PowerWAFStatsReporterSpecification.groovy index 4d3d4c1eba6..4a96ec9c6d0 100644 --- a/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/powerwaf/PowerWAFStatsReporterSpecification.groovy +++ b/dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/powerwaf/PowerWAFStatsReporterSpecification.groovy @@ -5,11 +5,13 @@ import datadog.trace.api.internal.TraceSegment import datadog.trace.test.util.DDSpecification import io.sqreen.powerwaf.PowerwafMetrics +import java.util.concurrent.atomic.AtomicInteger + class PowerWAFStatsReporterSpecification extends DDSpecification { PowerWAFStatsReporter reporter = new PowerWAFStatsReporter() AppSecRequestContext ctx = Mock() - void 'reporter reports timings and version'() { + void 'reporter reports waf timings and version'() { setup: PowerwafMetrics metrics = new PowerwafMetrics() metrics.totalRunTimeNs = 2_000 @@ -27,6 +29,31 @@ class PowerWAFStatsReporterSpecification extends DDSpecification { 1 * segment.setTagTop('_dd.appsec.event_rules.version', '1.2.3') } + void 'reporter reports rasp timings and version'() { + setup: + PowerwafMetrics metrics = new PowerwafMetrics() + metrics.totalRunTimeNs = 2_000 + metrics.totalDdwafRunTimeNs = 1_000 + + PowerwafMetrics raspMetrics = new PowerwafMetrics() + raspMetrics.totalRunTimeNs = 4_000 + raspMetrics.totalDdwafRunTimeNs = 3_000 + TraceSegment segment = Mock() + reporter.rulesVersion = '1.2.3' + + when: + reporter.processTraceSegment(segment, ctx, []) + + then: + 1 * ctx.getWafMetrics() >> null + 1 * ctx.getRaspMetrics() >> raspMetrics + 1 * ctx.getRaspMetricsCounter() >> new AtomicInteger(5) + 1 * segment.setTagTop('_dd.appsec.rasp.duration', 3) + 1 * segment.setTagTop('_dd.appsec.rasp.duration_ext', 4) + 1 * segment.setTagTop('_dd.appsec.rasp.rule.eval', 5) + 1 * segment.setTagTop('_dd.appsec.event_rules.version', '1.2.3') + } + void 'reports nothing if metrics are null'() { setup: TraceSegment segment = Mock()