Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ public static void processRequestEnd(AgentSpan span) {
return;
}

// A null trigger type means processRequestStart never ran, so the invocation was not analysed
// at all, which is not the same as an unsupported trigger.
if (!triggerType.isHttp()) {
span.setMetric(UNSUPPORTED_EVENT_TYPE_METRIC, 1);
return;
Expand Down Expand Up @@ -189,10 +191,8 @@ public static void processResponseData(AgentSpan span, Object result) {
}

RequestContext requestContext = span.getRequestContext();
if (requestContext == null || requestContext.getData(RequestContextSlot.APPSEC) == null) {
log.debug("Span has no AppSec request context, skipping response processing");
return;
}
boolean hasAppSecContext =
requestContext != null && requestContext.getData(RequestContextSlot.APPSEC) != null;

try {
byte[] bytes = ((ByteArrayOutputStream) result).toByteArray();
Expand All @@ -219,6 +219,14 @@ public static void processResponseData(AgentSpan span, Object result) {
span.setError(isError, ErrorPriorities.HTTP_SERVER_DECORATOR);
}

// http.status_code is a tracing tag and is published above whether or not AppSec ran: a
// failure inside processRequestStart must not also cost the span its status. The WAF
// callbacks below, in contrast, have nowhere to deliver without an AppSec request context.
if (!hasAppSecContext) {
log.debug("Span has no AppSec request context, skipping response WAF callbacks");
return;
}

AgentTracer.TracerAPI tracer = AgentTracer.get();
CallbackProvider cbp = tracer.getCallbackProvider(RequestContextSlot.APPSEC);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1753,13 +1753,35 @@ void processResponseDataDoesNothingForNullResult() {
}

@Test
void processResponseDataDoesNothingWhenSpanHasNoRequestContext() {
void processResponseDataPublishesStatusButNoWafEventsWhenSpanHasNoRequestContext() {
LambdaAppSecHandler.setCurrentTriggerType(LambdaTriggerType.API_GATEWAY_V1_REST);
AgentSpan span = mock(AgentSpan.class);
when(span.getRequestContext()).thenReturn(null);
ByteArrayOutputStream result = createOutputStream("{\"statusCode\": 200}");
setupMockResponseCallbacks(null, null, null, null);
LambdaAppSecHandler.processResponseData(span, result);
// no exception expected
AgentTracer.TracerAPI tracer = mock(AgentTracer.TracerAPI.class);
AgentTracer.forceRegister(tracer);

LambdaAppSecHandler.processResponseData(span, createOutputStream("{\"statusCode\": 200}"));

verify(span).setHttpStatusCode(200);
verify(tracer, never()).getCallbackProvider(RequestContextSlot.APPSEC);
}

@Test
void processResponseDataStillPublishesStatusWhenSpanHasNoAppSecContext() {
// An exception inside processRequestStart leaves an HTTP trigger type recorded but no AppSec
// context on the span. http.status_code is a tracing tag and must survive that.
LambdaAppSecHandler.setCurrentTriggerType(LambdaTriggerType.API_GATEWAY_V1_REST);
RequestContext requestContext = mock(RequestContext.class);
AgentSpan span = mock(AgentSpan.class);
when(span.getRequestContext()).thenReturn(requestContext);
AgentTracer.TracerAPI tracer = mock(AgentTracer.TracerAPI.class);
AgentTracer.forceRegister(tracer);

LambdaAppSecHandler.processResponseData(
span, createOutputStream("{\"statusCode\": 503, \"body\": \"boom\"}"));

verify(span).setHttpStatusCode(503);
verify(tracer, never()).getCallbackProvider(RequestContextSlot.APPSEC);
}

@Test
Expand Down
Loading