Skip to content

Commit c5076ec

Browse files
authored
Merge pull request DataDog#2344 from DataDog/tyler/netty-client-https-testing
Add self signed ssl to test server and test netty client
2 parents 340dae7 + 0743bdc commit c5076ec

17 files changed

Lines changed: 308 additions & 48 deletions

File tree

dd-java-agent/instrumentation/dropwizard/dropwizard.gradle

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ dependencies {
1212
testCompile project(':dd-java-agent:instrumentation:jax-rs-annotations-2')
1313
testCompile project(':dd-java-agent:instrumentation:servlet:request-3')
1414

15+
// Don't want to conflict with jetty from the test server.
16+
testCompile(project(':dd-java-agent:testing')) {
17+
exclude group: 'org.eclipse.jetty', module: 'jetty-server'
18+
}
19+
1520
// First version with DropwizardTestSupport:
1621
testCompile group: 'io.dropwizard', name: 'dropwizard-testing', version: '0.8.0'
1722
testCompile group: 'javax.xml.bind', name: 'jaxb-api', version: '2.2.3'

dd-java-agent/instrumentation/netty-3.8/src/latestDepTest/groovy/Netty38ClientTest.groovy

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ import datadog.trace.instrumentation.netty38.client.NettyHttpClientDecorator
88
import spock.lang.AutoCleanup
99
import spock.lang.Shared
1010

11+
import javax.net.ssl.SSLContext
12+
import javax.net.ssl.TrustManager
13+
import javax.net.ssl.X509TrustManager
14+
import java.security.cert.X509Certificate
1115
import java.util.concurrent.ExecutionException
1216
import java.util.concurrent.TimeUnit
1317

@@ -20,6 +24,21 @@ class Netty38ClientTest extends HttpClientTest {
2024
@Shared
2125
def clientConfig = new AsyncHttpClientConfig.Builder()
2226
.setRequestTimeout(TimeUnit.SECONDS.toMillis(10).toInteger())
27+
.setSSLContext({
28+
SSLContext context = SSLContext.getInstance("TLSv1.2")
29+
TrustManager[] trustManager = new TrustManager[1]
30+
trustManager[0] = new X509TrustManager() {
31+
X509Certificate[] getAcceptedIssuers() {
32+
return new X509Certificate[0]
33+
}
34+
35+
void checkClientTrusted(X509Certificate[] certificate, String str) {}
36+
37+
void checkServerTrusted(X509Certificate[] certificate, String str) {}
38+
}
39+
context.init(null, trustManager, null)
40+
return context
41+
}())
2342
.build()
2443

2544
@Shared
@@ -43,7 +62,7 @@ class Netty38ClientTest extends HttpClientTest {
4362
}
4463

4564
@Override
46-
String component() {
65+
CharSequence component() {
4766
return NettyHttpClientDecorator.DECORATE.component()
4867
}
4968

@@ -62,6 +81,11 @@ class Netty38ClientTest extends HttpClientTest {
6281
false
6382
}
6483

84+
@Override
85+
boolean testSecure() {
86+
true
87+
}
88+
6589
@Override
6690
boolean testRemoteConnection() {
6791
return false

dd-java-agent/instrumentation/netty-3.8/src/main/java/datadog/trace/instrumentation/netty38/client/HttpClientRequestTracingHandler.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.propagate;
66
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.startSpan;
77
import static datadog.trace.instrumentation.netty38.client.NettyHttpClientDecorator.DECORATE;
8+
import static datadog.trace.instrumentation.netty38.client.NettyHttpClientDecorator.DECORATE_SECURE;
89
import static datadog.trace.instrumentation.netty38.client.NettyHttpClientDecorator.NETTY_CLIENT_REQUEST;
910
import static datadog.trace.instrumentation.netty38.client.NettyResponseInjectAdapter.SETTER;
1011

@@ -52,13 +53,15 @@ public void writeRequested(final ChannelHandlerContext ctx, final MessageEvent m
5253
final HttpRequest request = (HttpRequest) msg.getMessage();
5354

5455
channelTraceContext.setClientParentSpan(activeSpan());
56+
boolean isSecure = ctx.getPipeline().get("sslHandler") != null;
57+
NettyHttpClientDecorator decorate = isSecure ? DECORATE_SECURE : DECORATE;
5558

5659
final AgentSpan span = startSpan(NETTY_CLIENT_REQUEST);
5760
span.setMeasured(true);
5861
try (final AgentScope scope = activateSpan(span)) {
59-
DECORATE.afterStart(span);
60-
DECORATE.onRequest(span, request);
61-
DECORATE.onPeerConnection(span, (InetSocketAddress) ctx.getChannel().getRemoteAddress());
62+
decorate.afterStart(span);
63+
decorate.onRequest(span, request);
64+
decorate.onPeerConnection(span, (InetSocketAddress) ctx.getChannel().getRemoteAddress());
6265

6366
propagate().inject(span, request.headers(), SETTER);
6467

dd-java-agent/instrumentation/netty-3.8/src/main/java/datadog/trace/instrumentation/netty38/client/NettyHttpClientDecorator.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,15 @@ public class NettyHttpClientDecorator extends HttpClientDecorator<HttpRequest, H
1616
public static final CharSequence NETTY_CLIENT_REQUEST =
1717
UTF8BytesString.createConstant("netty.client.request");
1818

19-
public static final NettyHttpClientDecorator DECORATE = new NettyHttpClientDecorator();
19+
public static final NettyHttpClientDecorator DECORATE = new NettyHttpClientDecorator("http://");
20+
public static final NettyHttpClientDecorator DECORATE_SECURE =
21+
new NettyHttpClientDecorator("https://");
22+
23+
private final String uriPrefix;
24+
25+
public NettyHttpClientDecorator(String uriPrefix) {
26+
this.uriPrefix = uriPrefix;
27+
}
2028

2129
@Override
2230
protected String[] instrumentationNames() {
@@ -37,7 +45,7 @@ protected String method(final HttpRequest httpRequest) {
3745
protected URI url(final HttpRequest request) throws URISyntaxException {
3846
final URI uri = new URI(request.getUri());
3947
if ((uri.getHost() == null || uri.getHost().equals("")) && request.headers().contains(HOST)) {
40-
return new URI("http://" + request.headers().get(HOST) + request.getUri());
48+
return new URI(uriPrefix + request.headers().get(HOST) + request.getUri());
4149
} else {
4250
return uri;
4351
}

dd-java-agent/instrumentation/netty-3.8/src/test/groovy/Netty38ClientTest.groovy

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ import datadog.trace.instrumentation.netty38.client.NettyHttpClientDecorator
88
import spock.lang.AutoCleanup
99
import spock.lang.Shared
1010

11+
import javax.net.ssl.SSLContext
12+
import javax.net.ssl.TrustManager
13+
import javax.net.ssl.X509TrustManager
14+
import java.security.cert.X509Certificate
1115
import java.util.concurrent.ExecutionException
1216
import java.util.concurrent.TimeUnit
1317

@@ -20,6 +24,21 @@ class Netty38ClientTest extends HttpClientTest {
2024
@Shared
2125
def clientConfig = new AsyncHttpClientConfig.Builder()
2226
.setRequestTimeoutInMs(TimeUnit.SECONDS.toMillis(10).toInteger())
27+
.setSSLContext({
28+
SSLContext context = SSLContext.getInstance("TLSv1.2")
29+
TrustManager[] trustManager = new TrustManager[1]
30+
trustManager[0] = new X509TrustManager() {
31+
X509Certificate[] getAcceptedIssuers() {
32+
return new X509Certificate[0]
33+
}
34+
35+
void checkClientTrusted(X509Certificate[] certificate, String str) {}
36+
37+
void checkServerTrusted(X509Certificate[] certificate, String str) {}
38+
}
39+
context.init(null, trustManager, null)
40+
return context
41+
}())
2342
.build()
2443

2544
@Shared
@@ -62,6 +81,11 @@ class Netty38ClientTest extends HttpClientTest {
6281
false
6382
}
6483

84+
@Override
85+
boolean testSecure() {
86+
true
87+
}
88+
6589
@Override
6690
boolean testRemoteConnection() {
6791
return false

dd-java-agent/instrumentation/netty-4.0/src/main/java/datadog/trace/instrumentation/netty40/client/HttpClientRequestTracingHandler.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.propagate;
66
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.startSpan;
77
import static datadog.trace.instrumentation.netty40.client.NettyHttpClientDecorator.DECORATE;
8+
import static datadog.trace.instrumentation.netty40.client.NettyHttpClientDecorator.DECORATE_SECURE;
89
import static datadog.trace.instrumentation.netty40.client.NettyHttpClientDecorator.NETTY_CLIENT_REQUEST;
910
import static datadog.trace.instrumentation.netty40.client.NettyResponseInjectAdapter.SETTER;
1011

@@ -39,13 +40,15 @@ public void write(final ChannelHandlerContext ctx, final Object msg, final Chann
3940
final HttpRequest request = (HttpRequest) msg;
4041

4142
ctx.channel().attr(AttributeKeys.CLIENT_PARENT_ATTRIBUTE_KEY).set(activeSpan());
43+
boolean isSecure = ctx.pipeline().get("ssl") != null;
44+
NettyHttpClientDecorator decorate = isSecure ? DECORATE_SECURE : DECORATE;
4245

4346
final AgentSpan span = startSpan(NETTY_CLIENT_REQUEST);
4447
span.setMeasured(true);
4548
try (final AgentScope scope = activateSpan(span)) {
46-
DECORATE.afterStart(span);
47-
DECORATE.onRequest(span, request);
48-
DECORATE.onPeerConnection(span, (InetSocketAddress) ctx.channel().remoteAddress());
49+
decorate.afterStart(span);
50+
decorate.onRequest(span, request);
51+
decorate.onPeerConnection(span, (InetSocketAddress) ctx.channel().remoteAddress());
4952

5053
// AWS calls are often signed, so we can't add headers without breaking the signature.
5154
if (!request.headers().contains("amz-sdk-invocation-id")) {

dd-java-agent/instrumentation/netty-4.0/src/main/java/datadog/trace/instrumentation/netty40/client/NettyHttpClientDecorator.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,20 @@
1212

1313
@Slf4j
1414
public class NettyHttpClientDecorator extends HttpClientDecorator<HttpRequest, HttpResponse> {
15+
1516
public static final CharSequence NETTY_CLIENT = UTF8BytesString.createConstant("netty-client");
1617
public static final CharSequence NETTY_CLIENT_REQUEST =
1718
UTF8BytesString.createConstant("netty.client.request");
1819

19-
public static final NettyHttpClientDecorator DECORATE = new NettyHttpClientDecorator();
20+
public static final NettyHttpClientDecorator DECORATE = new NettyHttpClientDecorator("http://");
21+
public static final NettyHttpClientDecorator DECORATE_SECURE =
22+
new NettyHttpClientDecorator("https://");
23+
24+
private final String uriPrefix;
25+
26+
public NettyHttpClientDecorator(String uriPrefix) {
27+
this.uriPrefix = uriPrefix;
28+
}
2029

2130
@Override
2231
protected String[] instrumentationNames() {
@@ -37,7 +46,7 @@ protected String method(final HttpRequest httpRequest) {
3746
protected URI url(final HttpRequest request) throws URISyntaxException {
3847
final URI uri = new URI(request.getUri());
3948
if ((uri.getHost() == null || uri.getHost().equals("")) && request.headers().contains(HOST)) {
40-
return new URI("http://" + request.headers().get(HOST) + request.getUri());
49+
return new URI(uriPrefix + request.headers().get(HOST) + request.getUri());
4150
} else {
4251
return uri;
4352
}

dd-java-agent/instrumentation/netty-4.0/src/test/groovy/Netty40ClientTest.groovy

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import datadog.trace.agent.test.base.HttpClientTest
22
import datadog.trace.bootstrap.instrumentation.api.Tags
33
import datadog.trace.instrumentation.netty40.client.NettyHttpClientDecorator
4+
import io.netty.handler.ssl.SslContextBuilder
5+
import io.netty.handler.ssl.util.InsecureTrustManagerFactory
46
import org.asynchttpclient.AsyncCompletionHandler
57
import org.asynchttpclient.AsyncHttpClient
68
import org.asynchttpclient.DefaultAsyncHttpClientConfig
@@ -25,8 +27,10 @@ class Netty40ClientTest extends HttpClientTest {
2527
@Shared
2628
def clientConfig = DefaultAsyncHttpClientConfig.Builder.newInstance()
2729
.setRequestTimeout(TimeUnit.SECONDS.toMillis(10).toInteger())
30+
.setSslContext(SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build())
2831
.setMaxRequestRetry(0)
29-
@Shared
32+
33+
// Can't be @Shared otherwise field-injected classes get loaded too early.
3034
@AutoCleanup
3135
AsyncHttpClient asyncHttpClient = asyncHttpClient(clientConfig)
3236

@@ -67,6 +71,11 @@ class Netty40ClientTest extends HttpClientTest {
6771
false
6872
}
6973

74+
@Override
75+
boolean testSecure() {
76+
true
77+
}
78+
7079
@Override
7180
boolean testRemoteConnection() {
7281
return false

dd-java-agent/instrumentation/netty-4.1/src/main/java/datadog/trace/instrumentation/netty41/client/HttpClientRequestTracingHandler.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.propagate;
66
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.startSpan;
77
import static datadog.trace.instrumentation.netty41.client.NettyHttpClientDecorator.DECORATE;
8+
import static datadog.trace.instrumentation.netty41.client.NettyHttpClientDecorator.DECORATE_SECURE;
89
import static datadog.trace.instrumentation.netty41.client.NettyHttpClientDecorator.NETTY_CLIENT_REQUEST;
910
import static datadog.trace.instrumentation.netty41.client.NettyResponseInjectAdapter.SETTER;
1011

@@ -39,13 +40,15 @@ public void write(final ChannelHandlerContext ctx, final Object msg, final Chann
3940
final HttpRequest request = (HttpRequest) msg;
4041

4142
ctx.channel().attr(AttributeKeys.CLIENT_PARENT_ATTRIBUTE_KEY).set(activeSpan());
43+
boolean isSecure = ctx.pipeline().get("ssl") != null;
44+
NettyHttpClientDecorator decorate = isSecure ? DECORATE_SECURE : DECORATE;
4245

4346
final AgentSpan span = startSpan(NETTY_CLIENT_REQUEST);
4447
span.setMeasured(true);
4548
try (final AgentScope scope = activateSpan(span)) {
46-
DECORATE.afterStart(span);
47-
DECORATE.onRequest(span, request);
48-
DECORATE.onPeerConnection(span, (InetSocketAddress) ctx.channel().remoteAddress());
49+
decorate.afterStart(span);
50+
decorate.onRequest(span, request);
51+
decorate.onPeerConnection(span, (InetSocketAddress) ctx.channel().remoteAddress());
4952

5053
// AWS calls are often signed, so we can't add headers without breaking the signature.
5154
if (!request.headers().contains("amz-sdk-invocation-id")) {
@@ -57,8 +60,8 @@ public void write(final ChannelHandlerContext ctx, final Object msg, final Chann
5760
try {
5861
ctx.write(msg, prm);
5962
} catch (final Throwable throwable) {
60-
DECORATE.onError(span, throwable);
61-
DECORATE.beforeFinish(span);
63+
decorate.onError(span, throwable);
64+
decorate.beforeFinish(span);
6265
span.finish();
6366
throw throwable;
6467
}

dd-java-agent/instrumentation/netty-4.1/src/main/java/datadog/trace/instrumentation/netty41/client/NettyHttpClientDecorator.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,15 @@ public class NettyHttpClientDecorator extends HttpClientDecorator<HttpRequest, H
1717
public static final CharSequence NETTY_CLIENT_REQUEST =
1818
UTF8BytesString.createConstant("netty.client.request");
1919

20-
public static final NettyHttpClientDecorator DECORATE = new NettyHttpClientDecorator();
20+
public static final NettyHttpClientDecorator DECORATE = new NettyHttpClientDecorator("http://");
21+
public static final NettyHttpClientDecorator DECORATE_SECURE =
22+
new NettyHttpClientDecorator("https://");
23+
24+
private final String uriPrefix;
25+
26+
public NettyHttpClientDecorator(String uriPrefix) {
27+
this.uriPrefix = uriPrefix;
28+
}
2129

2230
@Override
2331
protected String[] instrumentationNames() {
@@ -38,7 +46,7 @@ protected String method(final HttpRequest httpRequest) {
3846
protected URI url(final HttpRequest request) throws URISyntaxException {
3947
final URI uri = new URI(request.uri());
4048
if ((uri.getHost() == null || uri.getHost().equals("")) && request.headers().contains(HOST)) {
41-
return new URI("http://" + request.headers().get(HOST) + request.uri());
49+
return new URI(uriPrefix + request.headers().get(HOST) + request.uri());
4250
} else {
4351
return uri;
4452
}

0 commit comments

Comments
 (0)