Skip to content

Commit 4570eef

Browse files
authored
Custom block code and msg (#398)
* TODOs * add FilterResult and custom status code and msg for blocking * add response msg and tests * fix tests * revert grpc changes
1 parent 2a24d17 commit 4570eef

File tree

21 files changed

+179
-80
lines changed

21 files changed

+179
-80
lines changed

filter-api/src/main/java/org/hypertrace/agent/filter/MultiFilter.java

+11-10
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import io.opentelemetry.api.trace.Span;
2020
import java.util.List;
2121
import java.util.Map;
22+
import org.hypertrace.agent.core.filter.FilterResult;
2223
import org.hypertrace.agent.filter.api.Filter;
2324
import org.slf4j.Logger;
2425
import org.slf4j.LoggerFactory;
@@ -34,12 +35,12 @@ public MultiFilter(List<Filter> filters) {
3435
}
3536

3637
@Override
37-
public boolean evaluateRequestHeaders(Span span, Map<String, String> headers) {
38-
boolean shouldBlock = false;
38+
public FilterResult evaluateRequestHeaders(Span span, Map<String, String> headers) {
3939
for (Filter filter : filters) {
4040
try {
41-
if (filter.evaluateRequestHeaders(span, headers)) {
42-
shouldBlock = true;
41+
FilterResult filterResult = filter.evaluateRequestHeaders(span, headers);
42+
if (filterResult.shouldBlock()) {
43+
return filterResult;
4344
}
4445
} catch (Throwable t) {
4546
logger.warn(
@@ -48,16 +49,16 @@ public boolean evaluateRequestHeaders(Span span, Map<String, String> headers) {
4849
t);
4950
}
5051
}
51-
return shouldBlock;
52+
return new FilterResult(false, 0, "");
5253
}
5354

5455
@Override
55-
public boolean evaluateRequestBody(Span span, String body, Map<String, String> headers) {
56-
boolean shouldBlock = false;
56+
public FilterResult evaluateRequestBody(Span span, String body, Map<String, String> headers) {
5757
for (Filter filter : filters) {
5858
try {
59-
if (filter.evaluateRequestBody(span, body, headers)) {
60-
shouldBlock = true;
59+
FilterResult filterResult = filter.evaluateRequestBody(span, body, headers);
60+
if (filterResult.shouldBlock()) {
61+
return filterResult;
6162
}
6263
} catch (Throwable t) {
6364
logger.warn(
@@ -66,6 +67,6 @@ public boolean evaluateRequestBody(Span span, String body, Map<String, String> h
6667
t);
6768
}
6869
}
69-
return shouldBlock;
70+
return new FilterResult(false, 0, "");
7071
}
7172
}

filter-api/src/main/java/org/hypertrace/agent/filter/api/Filter.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import io.opentelemetry.api.trace.Span;
2020
import java.util.Map;
21+
import org.hypertrace.agent.core.filter.FilterResult;
2122
import org.hypertrace.agent.filter.FilterRegistry;
2223

2324
/**
@@ -32,7 +33,7 @@ public interface Filter {
3233
* @param headers are used for blocking evaluation.
3334
* @return filter result
3435
*/
35-
boolean evaluateRequestHeaders(Span span, Map<String, String> headers);
36+
FilterResult evaluateRequestHeaders(Span span, Map<String, String> headers);
3637

3738
/**
3839
* Evaluate the execution.
@@ -42,5 +43,5 @@ public interface Filter {
4243
* @param headers of the request associated with this body
4344
* @return filter result
4445
*/
45-
boolean evaluateRequestBody(Span span, String body, Map<String, String> headers);
46+
FilterResult evaluateRequestBody(Span span, String body, Map<String, String> headers);
4647
}

instrumentation/grpc-1.6/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/grpc/v1_6/server/GrpcServerInterceptor.java

+6-2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import io.opentelemetry.javaagent.instrumentation.hypertrace.grpc.v1_6.GrpcSpanDecorator;
3030
import java.util.Map;
3131
import org.hypertrace.agent.core.config.InstrumentationConfig;
32+
import org.hypertrace.agent.core.filter.FilterResult;
3233
import org.hypertrace.agent.core.instrumentation.HypertraceSemanticAttributes;
3334
import org.hypertrace.agent.filter.FilterRegistry;
3435
import org.slf4j.Logger;
@@ -57,8 +58,11 @@ public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
5758
GrpcSpanDecorator.addMetadataAttributes(mapHeaders, currentSpan);
5859
}
5960

60-
boolean block = FilterRegistry.getFilter().evaluateRequestHeaders(currentSpan, mapHeaders);
61-
if (block) {
61+
FilterResult filterResult =
62+
FilterRegistry.getFilter().evaluateRequestHeaders(currentSpan, mapHeaders);
63+
if (filterResult.shouldBlock()) {
64+
// We cannot send custom message in grpc calls
65+
// TODO: map http codes with grpc codes. filterResult.getBlockingStatusCode()
6266
call.close(Status.PERMISSION_DENIED, new Metadata());
6367
@SuppressWarnings("unchecked")
6468
ServerCall.Listener<ReqT> noop = NoopServerCallListener.INSTANCE;

instrumentation/grpc-1.6/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/grpc/v1_6/GrpcInstrumentationTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ public void serverRequestBlocking() throws TimeoutException, InterruptedExceptio
159159
try {
160160
Response response = blockingStub.sayHello(REQUEST);
161161
} catch (StatusRuntimeException ex) {
162-
Assertions.assertEquals(Status.PERMISSION_DENIED, ex.getStatus());
162+
Assertions.assertEquals(Status.PERMISSION_DENIED.getCode(), ex.getStatus().getCode());
163163
}
164164

165165
TEST_WRITER.waitForSpans(2);

instrumentation/micronaut-1.0/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/micronaut/MicronautInstrumentationTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ public void blocking() throws IOException, TimeoutException, InterruptedExceptio
175175

176176
try (Response response = httpClient.newCall(request).execute()) {
177177
Assertions.assertEquals(403, response.code());
178-
Assertions.assertTrue(response.body().string().isEmpty());
178+
Assertions.assertEquals("Hypertrace Blocked Request", response.body().string());
179179
}
180180

181181
List<List<SpanData>> traces = TEST_WRITER.getTraces();

instrumentation/micronaut-3.0/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/micronaut/v3/MicronautInstrumentationTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ public void blocking() throws IOException, TimeoutException, InterruptedExceptio
175175

176176
try (Response response = httpClient.newCall(request).execute()) {
177177
Assertions.assertEquals(403, response.code());
178-
Assertions.assertTrue(response.body().string().isEmpty());
178+
Assertions.assertEquals("Hypertrace Blocked Request", response.body().string());
179179
}
180180

181181
List<List<SpanData>> traces = TEST_WRITER.getTraces();

instrumentation/netty/netty-4.0/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_0/server/HttpServerBlockingRequestHandler.java

+22-8
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package io.opentelemetry.javaagent.instrumentation.hypertrace.netty.v4_0.server;
1818

19+
import io.netty.buffer.Unpooled;
1920
import io.netty.channel.Channel;
2021
import io.netty.channel.ChannelFutureListener;
2122
import io.netty.channel.ChannelHandlerContext;
@@ -30,7 +31,9 @@
3031
import io.opentelemetry.context.Context;
3132
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
3233
import io.opentelemetry.javaagent.instrumentation.hypertrace.netty.v4_0.AttributeKeys;
34+
import java.nio.charset.StandardCharsets;
3335
import java.util.Map;
36+
import org.hypertrace.agent.core.filter.FilterResult;
3437
import org.hypertrace.agent.filter.FilterRegistry;
3538

3639
public class HttpServerBlockingRequestHandler extends ChannelInboundHandlerAdapter {
@@ -52,26 +55,37 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) {
5255
if (msg instanceof HttpRequest) {
5356
Attribute<Map<String, String>> headersAttr = channel.attr(AttributeKeys.REQUEST_HEADERS);
5457
Map<String, String> headers = headersAttr.getAndRemove();
55-
if (headers != null && FilterRegistry.getFilter().evaluateRequestHeaders(span, headers)) {
56-
forbidden(ctx, (HttpRequest) msg);
57-
return;
58+
if (headers != null) {
59+
FilterResult filterResult =
60+
FilterRegistry.getFilter().evaluateRequestHeaders(span, headers);
61+
if (filterResult.shouldBlock()) {
62+
forbidden(ctx, (HttpRequest) msg, filterResult);
63+
return;
64+
}
5865
}
5966
}
6067
if (msg instanceof HttpContent) {
61-
if (FilterRegistry.getFilter().evaluateRequestBody(span, null, null)) {
68+
FilterResult filterResult = FilterRegistry.getFilter().evaluateRequestBody(span, null, null);
69+
if (filterResult.shouldBlock()) {
6270
Attribute<?> requestAttr = channel.attr(AttributeKeys.REQUEST);
6371
HttpRequest req = ((HttpRequestAndChannel) (requestAttr.get())).request();
64-
forbidden(ctx, req);
72+
forbidden(ctx, req, filterResult);
6573
return;
6674
}
6775
}
6876
ctx.fireChannelRead(msg);
6977
}
7078

71-
static void forbidden(ChannelHandlerContext ctx, HttpRequest request) {
79+
static void forbidden(ChannelHandlerContext ctx, HttpRequest request, FilterResult filterResult) {
7280
DefaultFullHttpResponse blockResponse =
73-
new DefaultFullHttpResponse(request.getProtocolVersion(), HttpResponseStatus.FORBIDDEN);
74-
blockResponse.headers().add("Content-Length", "0");
81+
new DefaultFullHttpResponse(
82+
request.getProtocolVersion(),
83+
new HttpResponseStatus(
84+
filterResult.getBlockingStatusCode(), HttpResponseStatus.FORBIDDEN.reasonPhrase()),
85+
Unpooled.copiedBuffer(filterResult.getBlockingMsg().getBytes(StandardCharsets.UTF_8)));
86+
blockResponse
87+
.headers()
88+
.add("Content-Length", String.valueOf(filterResult.getBlockingMsg().length()));
7589
ReferenceCountUtil.release(request);
7690
ctx.writeAndFlush(blockResponse).addListener(ChannelFutureListener.CLOSE);
7791
}

instrumentation/netty/netty-4.0/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_0/server/AbstractNetty40ServerInstrumentationTest.java

+5-9
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ public void blocking() throws IOException, TimeoutException, InterruptedExceptio
148148

149149
try (Response response = httpClient.newCall(request).execute()) {
150150
Assertions.assertEquals(403, response.code());
151-
Assertions.assertTrue(response.body().string().isEmpty());
151+
Assertions.assertEquals("Hypertrace Blocked Request", response.body().string());
152152
}
153153

154154
List<List<SpanData>> traces = TEST_WRITER.getTraces();
@@ -168,9 +168,7 @@ public void blocking() throws IOException, TimeoutException, InterruptedExceptio
168168
.getAttributes()
169169
.get(HypertraceSemanticAttributes.httpResponseHeader(RESPONSE_HEADER_NAME)));
170170
Assertions.assertNull(
171-
spanData
172-
.getAttributes()
173-
.get(HypertraceSemanticAttributes.httpResponseHeader(RESPONSE_BODY)));
171+
spanData.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY));
174172

175173
RequestBody requestBody = blockedRequestBody(true, 3000, 75);
176174
Request request2 =
@@ -182,7 +180,7 @@ public void blocking() throws IOException, TimeoutException, InterruptedExceptio
182180

183181
try (Response response = httpClient.newCall(request2).execute()) {
184182
Assertions.assertEquals(403, response.code());
185-
Assertions.assertTrue(response.body().string().isEmpty());
183+
Assertions.assertEquals("Hypertrace Blocked Request", response.body().string());
186184
}
187185

188186
List<List<SpanData>> traces2 = TEST_WRITER.getTraces();
@@ -202,9 +200,7 @@ public void blocking() throws IOException, TimeoutException, InterruptedExceptio
202200
.getAttributes()
203201
.get(HypertraceSemanticAttributes.httpResponseHeader(RESPONSE_HEADER_NAME)));
204202
Assertions.assertNull(
205-
spanData2
206-
.getAttributes()
207-
.get(HypertraceSemanticAttributes.httpResponseHeader(RESPONSE_BODY)));
203+
spanData2.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY));
208204
}
209205

210206
@Test
@@ -264,7 +260,7 @@ public void connectionKeepAlive() throws IOException, TimeoutException, Interrup
264260

265261
try (Response response = httpClient.newCall(request2).execute()) {
266262
Assertions.assertEquals(403, response.code());
267-
Assertions.assertTrue(response.body().string().isEmpty());
263+
Assertions.assertEquals("Hypertrace Blocked Request", response.body().string());
268264
}
269265

270266
List<List<SpanData>> traces2 = TEST_WRITER.getTraces();

instrumentation/netty/netty-4.1/src/main/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_1/server/HttpServerBlockingRequestHandler.java

+22-8
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package io.opentelemetry.javaagent.instrumentation.hypertrace.netty.v4_1.server;
1818

19+
import io.netty.buffer.Unpooled;
1920
import io.netty.channel.Channel;
2021
import io.netty.channel.ChannelFutureListener;
2122
import io.netty.channel.ChannelHandlerContext;
@@ -30,7 +31,9 @@
3031
import io.opentelemetry.context.Context;
3132
import io.opentelemetry.instrumentation.netty.v4.common.HttpRequestAndChannel;
3233
import io.opentelemetry.javaagent.instrumentation.hypertrace.netty.v4_1.AttributeKeys;
34+
import java.nio.charset.StandardCharsets;
3335
import java.util.Map;
36+
import org.hypertrace.agent.core.filter.FilterResult;
3437
import org.hypertrace.agent.filter.FilterRegistry;
3538

3639
public class HttpServerBlockingRequestHandler extends ChannelInboundHandlerAdapter {
@@ -51,26 +54,37 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) {
5154
if (msg instanceof HttpRequest) {
5255
Attribute<Map<String, String>> headersAttr = channel.attr(AttributeKeys.REQUEST_HEADERS);
5356
Map<String, String> headers = headersAttr.getAndRemove();
54-
if (headers != null && FilterRegistry.getFilter().evaluateRequestHeaders(span, headers)) {
55-
forbidden(ctx, (HttpRequest) msg);
56-
return;
57+
if (headers != null) {
58+
FilterResult filterResult =
59+
FilterRegistry.getFilter().evaluateRequestHeaders(span, headers);
60+
if (filterResult.shouldBlock()) {
61+
forbidden(ctx, (HttpRequest) msg, filterResult);
62+
return;
63+
}
5764
}
5865
}
5966
if (msg instanceof HttpContent) {
60-
if (FilterRegistry.getFilter().evaluateRequestBody(span, null, null)) {
67+
FilterResult filterResult = FilterRegistry.getFilter().evaluateRequestBody(span, null, null);
68+
if (filterResult.shouldBlock()) {
6169
Attribute<?> requestAttr = channel.attr(AttributeKeys.REQUEST);
6270
HttpRequest req = ((HttpRequestAndChannel) (requestAttr.get())).request();
63-
forbidden(ctx, req);
71+
forbidden(ctx, req, filterResult);
6472
return;
6573
}
6674
}
6775
ctx.fireChannelRead(msg);
6876
}
6977

70-
static void forbidden(ChannelHandlerContext ctx, HttpRequest request) {
78+
static void forbidden(ChannelHandlerContext ctx, HttpRequest request, FilterResult filterResult) {
7179
DefaultFullHttpResponse blockResponse =
72-
new DefaultFullHttpResponse(request.protocolVersion(), HttpResponseStatus.FORBIDDEN);
73-
blockResponse.headers().add("Content-Length", "0");
80+
new DefaultFullHttpResponse(
81+
request.protocolVersion(),
82+
new HttpResponseStatus(
83+
filterResult.getBlockingStatusCode(), HttpResponseStatus.FORBIDDEN.reasonPhrase()),
84+
Unpooled.copiedBuffer(filterResult.getBlockingMsg().getBytes(StandardCharsets.UTF_8)));
85+
blockResponse
86+
.headers()
87+
.add("Content-Length", String.valueOf(filterResult.getBlockingMsg().length()));
7488
ReferenceCountUtil.release(request);
7589
ctx.writeAndFlush(blockResponse).addListener(ChannelFutureListener.CLOSE);
7690
}

instrumentation/netty/netty-4.1/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_1/server/AbstractNetty41ServerInstrumentationTest.java

+5-9
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ public void blocking() throws IOException, TimeoutException, InterruptedExceptio
148148

149149
try (Response response = httpClient.newCall(request).execute()) {
150150
Assertions.assertEquals(403, response.code());
151-
Assertions.assertTrue(response.body().string().isEmpty());
151+
Assertions.assertEquals("Hypertrace Blocked Request", response.body().string());
152152
}
153153

154154
List<List<SpanData>> traces = TEST_WRITER.getTraces();
@@ -168,9 +168,7 @@ public void blocking() throws IOException, TimeoutException, InterruptedExceptio
168168
.getAttributes()
169169
.get(HypertraceSemanticAttributes.httpResponseHeader(RESPONSE_HEADER_NAME)));
170170
Assertions.assertNull(
171-
spanData
172-
.getAttributes()
173-
.get(HypertraceSemanticAttributes.httpResponseHeader(RESPONSE_BODY)));
171+
spanData.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY));
174172

175173
RequestBody requestBody = blockedRequestBody(true, 3000, 75);
176174
Request request2 =
@@ -182,7 +180,7 @@ public void blocking() throws IOException, TimeoutException, InterruptedExceptio
182180

183181
try (Response response = httpClient.newCall(request2).execute()) {
184182
Assertions.assertEquals(403, response.code());
185-
Assertions.assertTrue(response.body().string().isEmpty());
183+
Assertions.assertEquals("Hypertrace Blocked Request", response.body().string());
186184
}
187185

188186
List<List<SpanData>> traces2 = TEST_WRITER.getTraces();
@@ -202,9 +200,7 @@ public void blocking() throws IOException, TimeoutException, InterruptedExceptio
202200
.getAttributes()
203201
.get(HypertraceSemanticAttributes.httpResponseHeader(RESPONSE_HEADER_NAME)));
204202
Assertions.assertNull(
205-
spanData2
206-
.getAttributes()
207-
.get(HypertraceSemanticAttributes.httpResponseHeader(RESPONSE_BODY)));
203+
spanData2.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY));
208204
}
209205

210206
@Test
@@ -264,7 +260,7 @@ public void connectionKeepAlive() throws IOException, TimeoutException, Interrup
264260

265261
try (Response response = httpClient.newCall(request2).execute()) {
266262
Assertions.assertEquals(403, response.code());
267-
Assertions.assertTrue(response.body().string().isEmpty());
263+
Assertions.assertEquals("Hypertrace Blocked Request", response.body().string());
268264
}
269265

270266
List<List<SpanData>> traces2 = TEST_WRITER.getTraces();

0 commit comments

Comments
 (0)