Allow setting trusted certs for OTLP Trace exporter (#2429)
This commit is contained in:
parent
015708b7a7
commit
045dd0c1a3
|
|
@ -1,4 +1,5 @@
|
|||
import nebula.plugin.release.git.opinion.Strategies
|
||||
import ru.vyarus.gradle.plugin.animalsniffer.AnimalSniffer
|
||||
|
||||
plugins {
|
||||
id "com.diffplug.spotless"
|
||||
|
|
@ -377,8 +378,10 @@ subprojects {
|
|||
}
|
||||
|
||||
plugins.withId("ru.vyarus.animalsniffer") {
|
||||
animalsnifferTest {
|
||||
enabled = false
|
||||
tasks.withType(AnimalSniffer) {
|
||||
if (name.startsWith('animalsnifferTest')) {
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
// If JMH enabled ignore animalsniffer.
|
||||
plugins.withId("me.champeau.gradle.jmh") {
|
||||
|
|
|
|||
|
|
@ -3,15 +3,25 @@ plugins {
|
|||
id "maven-publish"
|
||||
|
||||
id "me.champeau.gradle.jmh"
|
||||
id "org.unbroken-dome.test-sets"
|
||||
id "ru.vyarus.animalsniffer"
|
||||
}
|
||||
|
||||
description = 'OpenTelemetry Protocol Trace Exporter'
|
||||
ext.moduleName = "io.opentelemetry.exporter.otlp.trace"
|
||||
|
||||
testSets {
|
||||
testGrpcNetty
|
||||
testGrpcNettyShaded
|
||||
testGrpcOkhttp
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api project(':sdk:trace')
|
||||
|
||||
compileOnly "io.grpc:grpc-netty"
|
||||
compileOnly "io.grpc:grpc-netty-shaded"
|
||||
|
||||
implementation project(':sdk-extensions:otproto'),
|
||||
libraries.grpc_api,
|
||||
libraries.grpc_protobuf,
|
||||
|
|
@ -19,11 +29,25 @@ dependencies {
|
|||
libraries.protobuf
|
||||
|
||||
testImplementation project(':sdk:testing'),
|
||||
'com.linecorp.armeria:armeria-grpc',
|
||||
'com.linecorp.armeria:armeria-junit5',
|
||||
"io.grpc:grpc-testing:${grpcVersion}"
|
||||
|
||||
testRuntime "io.grpc:grpc-netty-shaded:${grpcVersion}"
|
||||
testGrpcNettyImplementation 'com.linecorp.armeria:armeria-grpc',
|
||||
'com.linecorp.armeria:armeria-junit5'
|
||||
|
||||
testGrpcNettyShadedImplementation 'com.linecorp.armeria:armeria-grpc',
|
||||
'com.linecorp.armeria:armeria-junit5'
|
||||
|
||||
testGrpcOkhttpImplementation 'com.linecorp.armeria:armeria-grpc',
|
||||
'com.linecorp.armeria:armeria-junit5'
|
||||
|
||||
testGrpcNettyRuntimeOnly "io.grpc:grpc-netty:${grpcVersion}",
|
||||
libraries.slf4jsimple
|
||||
|
||||
testGrpcNettyShadedRuntimeOnly "io.grpc:grpc-netty-shaded:${grpcVersion}",
|
||||
libraries.slf4jsimple
|
||||
|
||||
testGrpcOkhttpRuntimeOnly "io.grpc:grpc-okhttp:${grpcVersion}",
|
||||
libraries.slf4jsimple
|
||||
|
||||
jmh project(':sdk:testing')
|
||||
|
||||
|
|
|
|||
|
|
@ -11,12 +11,16 @@ import com.google.common.base.Splitter;
|
|||
import io.grpc.ManagedChannel;
|
||||
import io.grpc.ManagedChannelBuilder;
|
||||
import io.grpc.Metadata;
|
||||
import io.grpc.netty.GrpcSslContexts;
|
||||
import io.grpc.netty.NettyChannelBuilder;
|
||||
import io.grpc.stub.MetadataUtils;
|
||||
import io.opentelemetry.sdk.common.export.ConfigBuilder;
|
||||
import io.opentelemetry.sdk.extension.otproto.CommonProperties;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.net.ssl.SSLException;
|
||||
|
||||
/** Builder utility for this exporter. */
|
||||
public final class OtlpGrpcSpanExporterBuilder extends ConfigBuilder<OtlpGrpcSpanExporterBuilder> {
|
||||
|
|
@ -31,6 +35,7 @@ public final class OtlpGrpcSpanExporterBuilder extends ConfigBuilder<OtlpGrpcSpa
|
|||
private String endpoint = OtlpGrpcSpanExporter.DEFAULT_ENDPOINT;
|
||||
private boolean useTls = false;
|
||||
@Nullable private Metadata metadata;
|
||||
@Nullable private byte[] trustedCertificatesPem;
|
||||
|
||||
/**
|
||||
* Sets the managed chanel to use when communicating with the backend. Takes precedence over
|
||||
|
|
@ -78,6 +83,16 @@ public final class OtlpGrpcSpanExporterBuilder extends ConfigBuilder<OtlpGrpcSpa
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the certificate chain to use for verifying servers when TLS is enabled. The {@code byte[]}
|
||||
* should contain an X.509 certificate collection in PEM format. If not set, TLS connections will
|
||||
* use the system default trusted certificates.
|
||||
*/
|
||||
public OtlpGrpcSpanExporterBuilder setTrustedCertificates(byte[] trustedCertificatesPem) {
|
||||
this.trustedCertificatesPem = trustedCertificatesPem;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add header to request. Optional. Applicable only if {@link
|
||||
* OtlpGrpcSpanExporterBuilder#endpoint} is set to build channel.
|
||||
|
|
@ -114,6 +129,51 @@ public final class OtlpGrpcSpanExporterBuilder extends ConfigBuilder<OtlpGrpcSpa
|
|||
managedChannelBuilder.intercept(MetadataUtils.newAttachHeadersInterceptor(metadata));
|
||||
}
|
||||
|
||||
if (trustedCertificatesPem != null) {
|
||||
// gRPC does not abstract TLS configuration so we need to check the implementation and act
|
||||
// accordingly.
|
||||
if (managedChannelBuilder
|
||||
.getClass()
|
||||
.getName()
|
||||
.equals("io.grpc.netty.NettyChannelBuilder")) {
|
||||
NettyChannelBuilder nettyBuilder = (NettyChannelBuilder) managedChannelBuilder;
|
||||
try {
|
||||
nettyBuilder.sslContext(
|
||||
GrpcSslContexts.forClient()
|
||||
.trustManager(new ByteArrayInputStream(trustedCertificatesPem))
|
||||
.build());
|
||||
} catch (IllegalArgumentException | SSLException e) {
|
||||
throw new IllegalStateException(
|
||||
"Could not set trusted certificates for gRPC TLS connection, are they valid "
|
||||
+ "X.509 in PEM format?",
|
||||
e);
|
||||
}
|
||||
} else if (managedChannelBuilder
|
||||
.getClass()
|
||||
.getName()
|
||||
.equals("io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder")) {
|
||||
io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder nettyBuilder =
|
||||
(io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder) managedChannelBuilder;
|
||||
try {
|
||||
nettyBuilder.sslContext(
|
||||
io.grpc.netty.shaded.io.grpc.netty.GrpcSslContexts.forClient()
|
||||
.trustManager(new ByteArrayInputStream(trustedCertificatesPem))
|
||||
.build());
|
||||
} catch (IllegalArgumentException | SSLException e) {
|
||||
throw new IllegalStateException(
|
||||
"Could not set trusted certificates for gRPC TLS connection, are they valid "
|
||||
+ "X.509 in PEM format?",
|
||||
e);
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException(
|
||||
"TLS cerificate configuration only supported with Netty. "
|
||||
+ "If you need to configure a certificate, switch to grpc-netty or "
|
||||
+ "grpc-netty-shaded.");
|
||||
}
|
||||
// TODO(anuraaga): Support okhttp.
|
||||
}
|
||||
|
||||
channel = managedChannelBuilder.build();
|
||||
}
|
||||
return new OtlpGrpcSpanExporter(channel, deadlineMs);
|
||||
|
|
|
|||
|
|
@ -5,17 +5,10 @@
|
|||
|
||||
package io.opentelemetry.exporter.otlp.trace;
|
||||
|
||||
import static com.google.common.base.Charsets.US_ASCII;
|
||||
import static io.grpc.Metadata.ASCII_STRING_MARSHALLER;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.awaitility.Awaitility.await;
|
||||
|
||||
import com.google.common.io.Closer;
|
||||
import com.linecorp.armeria.common.RequestHeaders;
|
||||
import com.linecorp.armeria.server.ServerBuilder;
|
||||
import com.linecorp.armeria.server.ServiceRequestContext;
|
||||
import com.linecorp.armeria.server.grpc.GrpcService;
|
||||
import com.linecorp.armeria.testing.junit5.server.ServerExtension;
|
||||
import io.grpc.ManagedChannel;
|
||||
import io.grpc.Server;
|
||||
import io.grpc.Status;
|
||||
|
|
@ -24,8 +17,6 @@ import io.grpc.inprocess.InProcessChannelBuilder;
|
|||
import io.grpc.inprocess.InProcessServerBuilder;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
import io.opentelemetry.api.trace.Span.Kind;
|
||||
import io.opentelemetry.api.trace.SpanId;
|
||||
import io.opentelemetry.api.trace.TraceId;
|
||||
import io.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest;
|
||||
import io.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse;
|
||||
import io.opentelemetry.proto.collector.trace.v1.TraceServiceGrpc;
|
||||
|
|
@ -36,50 +27,15 @@ import io.opentelemetry.sdk.testing.trace.TestSpanData;
|
|||
import io.opentelemetry.sdk.trace.data.SpanData;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
class OtlpGrpcSpanExporterTest {
|
||||
|
||||
@RegisterExtension
|
||||
public static ServerExtension server =
|
||||
new ServerExtension() {
|
||||
@Override
|
||||
protected void configure(ServerBuilder sb) throws Exception {
|
||||
sb.service(
|
||||
GrpcService.builder()
|
||||
.addService(
|
||||
new TraceServiceGrpc.TraceServiceImplBase() {
|
||||
@Override
|
||||
public void export(
|
||||
ExportTraceServiceRequest request,
|
||||
StreamObserver<ExportTraceServiceResponse> responseObserver) {
|
||||
RequestHeaders headers =
|
||||
ServiceRequestContext.current().request().headers();
|
||||
if (headers.get("key").equals("value")
|
||||
&& headers.get("key2").equals("value2=")
|
||||
&& headers.get("key3").equals("val=ue3")
|
||||
&& headers.get("key4").equals("value4")
|
||||
&& !headers.contains("key5")) {
|
||||
responseObserver.onNext(
|
||||
ExportTraceServiceResponse.getDefaultInstance());
|
||||
responseObserver.onCompleted();
|
||||
} else {
|
||||
responseObserver.onError(new AssertionError("Invalid metadata"));
|
||||
}
|
||||
}
|
||||
})
|
||||
.build());
|
||||
}
|
||||
};
|
||||
|
||||
private static final String TRACE_ID = "00000000000000000000000000abc123";
|
||||
private static final String SPAN_ID = "0000000000def456";
|
||||
|
||||
|
|
@ -90,53 +46,6 @@ class OtlpGrpcSpanExporterTest {
|
|||
|
||||
private final Closer closer = Closer.create();
|
||||
|
||||
@Test
|
||||
void configTest() {
|
||||
Properties options = new Properties();
|
||||
String endpoint = "localhost:" + server.httpPort();
|
||||
options.put("otel.exporter.otlp.span.timeout", "5124");
|
||||
options.put("otel.exporter.otlp.span.endpoint", endpoint);
|
||||
options.put("otel.exporter.otlp.span.insecure", "true");
|
||||
options.put(
|
||||
"otel.exporter.otlp.span.headers",
|
||||
"key=value,key2=value2=,key3=val=ue3, key4 = value4 ,key5= ");
|
||||
OtlpGrpcSpanExporterBuilder builder = OtlpGrpcSpanExporter.builder().readProperties(options);
|
||||
assertThat(builder)
|
||||
.extracting("metadata")
|
||||
.extracting("namesAndValues")
|
||||
.isEqualTo(
|
||||
new Object[] {
|
||||
"key".getBytes(US_ASCII),
|
||||
ASCII_STRING_MARSHALLER.toAsciiString("value").getBytes(US_ASCII),
|
||||
"key2".getBytes(US_ASCII),
|
||||
ASCII_STRING_MARSHALLER.toAsciiString("value2=").getBytes(US_ASCII),
|
||||
"key3".getBytes(US_ASCII),
|
||||
ASCII_STRING_MARSHALLER.toAsciiString("val=ue3").getBytes(US_ASCII),
|
||||
"key4".getBytes(US_ASCII),
|
||||
ASCII_STRING_MARSHALLER.toAsciiString("value4").getBytes(US_ASCII)
|
||||
});
|
||||
OtlpGrpcSpanExporter exporter = builder.build();
|
||||
|
||||
assertThat(exporter.getDeadlineMs()).isEqualTo(5124);
|
||||
assertThat(
|
||||
exporter
|
||||
.export(
|
||||
Arrays.asList(
|
||||
TestSpanData.builder()
|
||||
.setTraceId(TraceId.getInvalid())
|
||||
.setSpanId(SpanId.getInvalid())
|
||||
.setName("name")
|
||||
.setKind(Kind.CLIENT)
|
||||
.setStartEpochNanos(1)
|
||||
.setEndEpochNanos(2)
|
||||
.setStatus(SpanData.Status.ok())
|
||||
.setHasEnded(true)
|
||||
.build()))
|
||||
.join(10, TimeUnit.SECONDS)
|
||||
.isSuccess())
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void setup() throws IOException {
|
||||
Server server =
|
||||
|
|
|
|||
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.exporter.otlp.trace;
|
||||
|
||||
import static com.google.common.base.Charsets.US_ASCII;
|
||||
import static io.grpc.Metadata.ASCII_STRING_MARSHALLER;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.linecorp.armeria.common.RequestHeaders;
|
||||
import com.linecorp.armeria.server.ServerBuilder;
|
||||
import com.linecorp.armeria.server.ServiceRequestContext;
|
||||
import com.linecorp.armeria.server.grpc.GrpcService;
|
||||
import com.linecorp.armeria.testing.junit5.server.ServerExtension;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
import io.opentelemetry.api.trace.Span;
|
||||
import io.opentelemetry.api.trace.SpanId;
|
||||
import io.opentelemetry.api.trace.TraceId;
|
||||
import io.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest;
|
||||
import io.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse;
|
||||
import io.opentelemetry.proto.collector.trace.v1.TraceServiceGrpc;
|
||||
import io.opentelemetry.sdk.testing.trace.TestSpanData;
|
||||
import io.opentelemetry.sdk.trace.data.SpanData;
|
||||
import java.util.Arrays;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
class OtlpGrpcSpanExporterTest {
|
||||
|
||||
@RegisterExtension
|
||||
public static ServerExtension server =
|
||||
new ServerExtension() {
|
||||
@Override
|
||||
protected void configure(ServerBuilder sb) throws Exception {
|
||||
sb.service(
|
||||
GrpcService.builder()
|
||||
.addService(
|
||||
new TraceServiceGrpc.TraceServiceImplBase() {
|
||||
@Override
|
||||
public void export(
|
||||
ExportTraceServiceRequest request,
|
||||
StreamObserver<ExportTraceServiceResponse> responseObserver) {
|
||||
RequestHeaders headers =
|
||||
ServiceRequestContext.current().request().headers();
|
||||
if (headers.get("key").equals("value")
|
||||
&& headers.get("key2").equals("value2=")
|
||||
&& headers.get("key3").equals("val=ue3")
|
||||
&& headers.get("key4").equals("value4")
|
||||
&& !headers.contains("key5")) {
|
||||
responseObserver.onNext(
|
||||
ExportTraceServiceResponse.getDefaultInstance());
|
||||
responseObserver.onCompleted();
|
||||
} else {
|
||||
responseObserver.onError(new AssertionError("Invalid metadata"));
|
||||
}
|
||||
}
|
||||
})
|
||||
.build());
|
||||
}
|
||||
};
|
||||
|
||||
@Test
|
||||
void configTest() {
|
||||
Properties options = new Properties();
|
||||
String endpoint = "localhost:" + server.httpPort();
|
||||
options.put("otel.exporter.otlp.span.timeout", "5124");
|
||||
options.put("otel.exporter.otlp.span.endpoint", endpoint);
|
||||
options.put("otel.exporter.otlp.span.insecure", "true");
|
||||
options.put(
|
||||
"otel.exporter.otlp.span.headers",
|
||||
"key=value,key2=value2=,key3=val=ue3, key4 = value4 ,key5= ");
|
||||
OtlpGrpcSpanExporterBuilder builder = OtlpGrpcSpanExporter.builder().readProperties(options);
|
||||
assertThat(builder)
|
||||
.extracting("metadata")
|
||||
.extracting("namesAndValues")
|
||||
.isEqualTo(
|
||||
new Object[] {
|
||||
"key".getBytes(US_ASCII),
|
||||
ASCII_STRING_MARSHALLER.toAsciiString("value").getBytes(US_ASCII),
|
||||
"key2".getBytes(US_ASCII),
|
||||
ASCII_STRING_MARSHALLER.toAsciiString("value2=").getBytes(US_ASCII),
|
||||
"key3".getBytes(US_ASCII),
|
||||
ASCII_STRING_MARSHALLER.toAsciiString("val=ue3").getBytes(US_ASCII),
|
||||
"key4".getBytes(US_ASCII),
|
||||
ASCII_STRING_MARSHALLER.toAsciiString("value4").getBytes(US_ASCII)
|
||||
});
|
||||
OtlpGrpcSpanExporter exporter = builder.build();
|
||||
|
||||
assertThat(exporter.getDeadlineMs()).isEqualTo(5124);
|
||||
assertThat(
|
||||
exporter
|
||||
.export(
|
||||
Arrays.asList(
|
||||
TestSpanData.builder()
|
||||
.setTraceId(TraceId.getInvalid())
|
||||
.setSpanId(SpanId.getInvalid())
|
||||
.setName("name")
|
||||
.setKind(Span.Kind.CLIENT)
|
||||
.setStartEpochNanos(1)
|
||||
.setEndEpochNanos(2)
|
||||
.setStatus(SpanData.Status.ok())
|
||||
.setHasEnded(true)
|
||||
.build()))
|
||||
.join(10, TimeUnit.SECONDS)
|
||||
.isSuccess())
|
||||
.isTrue();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.exporter.otlp.trace;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
import com.linecorp.armeria.server.ServerBuilder;
|
||||
import com.linecorp.armeria.server.grpc.GrpcService;
|
||||
import com.linecorp.armeria.testing.junit5.server.SelfSignedCertificateExtension;
|
||||
import com.linecorp.armeria.testing.junit5.server.ServerExtension;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
import io.opentelemetry.api.trace.Span;
|
||||
import io.opentelemetry.api.trace.SpanId;
|
||||
import io.opentelemetry.api.trace.TraceId;
|
||||
import io.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest;
|
||||
import io.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse;
|
||||
import io.opentelemetry.proto.collector.trace.v1.TraceServiceGrpc;
|
||||
import io.opentelemetry.sdk.testing.trace.TestSpanData;
|
||||
import io.opentelemetry.sdk.trace.data.SpanData;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
class TlsExportTest {
|
||||
|
||||
@RegisterExtension
|
||||
@Order(1)
|
||||
public static SelfSignedCertificateExtension certificate = new SelfSignedCertificateExtension();
|
||||
|
||||
@RegisterExtension
|
||||
@Order(2)
|
||||
public static ServerExtension server =
|
||||
new ServerExtension() {
|
||||
@Override
|
||||
protected void configure(ServerBuilder sb) {
|
||||
sb.service(
|
||||
GrpcService.builder()
|
||||
.addService(
|
||||
new TraceServiceGrpc.TraceServiceImplBase() {
|
||||
@Override
|
||||
public void export(
|
||||
ExportTraceServiceRequest request,
|
||||
StreamObserver<ExportTraceServiceResponse> responseObserver) {
|
||||
responseObserver.onNext(ExportTraceServiceResponse.getDefaultInstance());
|
||||
responseObserver.onCompleted();
|
||||
}
|
||||
})
|
||||
.build());
|
||||
sb.tls(certificate.certificateFile(), certificate.privateKeyFile());
|
||||
}
|
||||
};
|
||||
|
||||
@Test
|
||||
void testTlsExport() throws Exception {
|
||||
OtlpGrpcSpanExporter exporter =
|
||||
OtlpGrpcSpanExporter.builder()
|
||||
.setEndpoint("localhost:" + server.httpsPort())
|
||||
.setUseTls(true)
|
||||
.setTrustedCertificates(Files.readAllBytes(certificate.certificateFile().toPath()))
|
||||
.build();
|
||||
assertThat(
|
||||
exporter
|
||||
.export(
|
||||
Arrays.asList(
|
||||
TestSpanData.builder()
|
||||
.setTraceId(TraceId.getInvalid())
|
||||
.setSpanId(SpanId.getInvalid())
|
||||
.setName("name")
|
||||
.setKind(Span.Kind.CLIENT)
|
||||
.setStartEpochNanos(1)
|
||||
.setEndEpochNanos(2)
|
||||
.setStatus(SpanData.Status.ok())
|
||||
.setHasEnded(true)
|
||||
.build()))
|
||||
.join(10, TimeUnit.SECONDS)
|
||||
.isSuccess())
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTlsExport_untrusted() throws Exception {
|
||||
OtlpGrpcSpanExporter exporter =
|
||||
OtlpGrpcSpanExporter.builder()
|
||||
.setEndpoint("localhost:" + server.httpsPort())
|
||||
.setUseTls(true)
|
||||
.build();
|
||||
assertThat(
|
||||
exporter
|
||||
.export(
|
||||
Arrays.asList(
|
||||
TestSpanData.builder()
|
||||
.setTraceId(TraceId.getInvalid())
|
||||
.setSpanId(SpanId.getInvalid())
|
||||
.setName("name")
|
||||
.setKind(Span.Kind.CLIENT)
|
||||
.setStartEpochNanos(1)
|
||||
.setEndEpochNanos(2)
|
||||
.setStatus(SpanData.Status.ok())
|
||||
.setHasEnded(true)
|
||||
.build()))
|
||||
.join(10, TimeUnit.SECONDS)
|
||||
.isSuccess())
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void tlsBadCert() {
|
||||
assertThatThrownBy(
|
||||
() ->
|
||||
OtlpGrpcSpanExporter.builder()
|
||||
.setTrustedCertificates("foobar".getBytes(StandardCharsets.UTF_8))
|
||||
.build())
|
||||
.isInstanceOf(IllegalStateException.class)
|
||||
.hasMessageContaining("Could not set trusted certificates");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.exporter.otlp.trace;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
import com.linecorp.armeria.server.ServerBuilder;
|
||||
import com.linecorp.armeria.server.grpc.GrpcService;
|
||||
import com.linecorp.armeria.testing.junit5.server.SelfSignedCertificateExtension;
|
||||
import com.linecorp.armeria.testing.junit5.server.ServerExtension;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
import io.opentelemetry.api.trace.Span;
|
||||
import io.opentelemetry.api.trace.SpanId;
|
||||
import io.opentelemetry.api.trace.TraceId;
|
||||
import io.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest;
|
||||
import io.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse;
|
||||
import io.opentelemetry.proto.collector.trace.v1.TraceServiceGrpc;
|
||||
import io.opentelemetry.sdk.testing.trace.TestSpanData;
|
||||
import io.opentelemetry.sdk.trace.data.SpanData;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
class TlsExportTest {
|
||||
|
||||
@RegisterExtension
|
||||
@Order(1)
|
||||
public static SelfSignedCertificateExtension certificate = new SelfSignedCertificateExtension();
|
||||
|
||||
@RegisterExtension
|
||||
@Order(2)
|
||||
public static ServerExtension server =
|
||||
new ServerExtension() {
|
||||
@Override
|
||||
protected void configure(ServerBuilder sb) {
|
||||
sb.service(
|
||||
GrpcService.builder()
|
||||
.addService(
|
||||
new TraceServiceGrpc.TraceServiceImplBase() {
|
||||
@Override
|
||||
public void export(
|
||||
ExportTraceServiceRequest request,
|
||||
StreamObserver<ExportTraceServiceResponse> responseObserver) {
|
||||
responseObserver.onNext(ExportTraceServiceResponse.getDefaultInstance());
|
||||
responseObserver.onCompleted();
|
||||
}
|
||||
})
|
||||
.build());
|
||||
sb.tls(certificate.certificateFile(), certificate.privateKeyFile());
|
||||
}
|
||||
};
|
||||
|
||||
@Test
|
||||
void testTlsExport() throws Exception {
|
||||
OtlpGrpcSpanExporter exporter =
|
||||
OtlpGrpcSpanExporter.builder()
|
||||
.setEndpoint("localhost:" + server.httpsPort())
|
||||
.setUseTls(true)
|
||||
.setTrustedCertificates(Files.readAllBytes(certificate.certificateFile().toPath()))
|
||||
.build();
|
||||
assertThat(
|
||||
exporter
|
||||
.export(
|
||||
Arrays.asList(
|
||||
TestSpanData.builder()
|
||||
.setTraceId(TraceId.getInvalid())
|
||||
.setSpanId(SpanId.getInvalid())
|
||||
.setName("name")
|
||||
.setKind(Span.Kind.CLIENT)
|
||||
.setStartEpochNanos(1)
|
||||
.setEndEpochNanos(2)
|
||||
.setStatus(SpanData.Status.ok())
|
||||
.setHasEnded(true)
|
||||
.build()))
|
||||
.join(10, TimeUnit.SECONDS)
|
||||
.isSuccess())
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTlsExport_untrusted() throws Exception {
|
||||
OtlpGrpcSpanExporter exporter =
|
||||
OtlpGrpcSpanExporter.builder()
|
||||
.setEndpoint("localhost:" + server.httpsPort())
|
||||
.setUseTls(true)
|
||||
.build();
|
||||
assertThat(
|
||||
exporter
|
||||
.export(
|
||||
Arrays.asList(
|
||||
TestSpanData.builder()
|
||||
.setTraceId(TraceId.getInvalid())
|
||||
.setSpanId(SpanId.getInvalid())
|
||||
.setName("name")
|
||||
.setKind(Span.Kind.CLIENT)
|
||||
.setStartEpochNanos(1)
|
||||
.setEndEpochNanos(2)
|
||||
.setStatus(SpanData.Status.ok())
|
||||
.setHasEnded(true)
|
||||
.build()))
|
||||
.join(10, TimeUnit.SECONDS)
|
||||
.isSuccess())
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void tlsBadCert() {
|
||||
assertThatThrownBy(
|
||||
() ->
|
||||
OtlpGrpcSpanExporter.builder()
|
||||
.setTrustedCertificates("foobar".getBytes(StandardCharsets.UTF_8))
|
||||
.build())
|
||||
.isInstanceOf(IllegalStateException.class)
|
||||
.hasMessageContaining("Could not set trusted certificates");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.exporter.otlp.trace;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
import com.linecorp.armeria.server.ServerBuilder;
|
||||
import com.linecorp.armeria.server.grpc.GrpcService;
|
||||
import com.linecorp.armeria.testing.junit5.server.SelfSignedCertificateExtension;
|
||||
import com.linecorp.armeria.testing.junit5.server.ServerExtension;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
import io.opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest;
|
||||
import io.opentelemetry.proto.collector.trace.v1.ExportTraceServiceResponse;
|
||||
import io.opentelemetry.proto.collector.trace.v1.TraceServiceGrpc;
|
||||
import java.nio.file.Files;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
class TlsExportTest {
|
||||
|
||||
@RegisterExtension
|
||||
@Order(1)
|
||||
public static SelfSignedCertificateExtension certificate = new SelfSignedCertificateExtension();
|
||||
|
||||
@RegisterExtension
|
||||
@Order(2)
|
||||
public static ServerExtension server =
|
||||
new ServerExtension() {
|
||||
@Override
|
||||
protected void configure(ServerBuilder sb) {
|
||||
sb.service(
|
||||
GrpcService.builder()
|
||||
.addService(
|
||||
new TraceServiceGrpc.TraceServiceImplBase() {
|
||||
@Override
|
||||
public void export(
|
||||
ExportTraceServiceRequest request,
|
||||
StreamObserver<ExportTraceServiceResponse> responseObserver) {
|
||||
responseObserver.onNext(ExportTraceServiceResponse.getDefaultInstance());
|
||||
responseObserver.onCompleted();
|
||||
}
|
||||
})
|
||||
.build());
|
||||
sb.tls(certificate.certificateFile(), certificate.privateKeyFile());
|
||||
}
|
||||
};
|
||||
|
||||
@Test
|
||||
void testTlsExport() {
|
||||
// Currently not supported.
|
||||
assertThatThrownBy(
|
||||
() ->
|
||||
OtlpGrpcSpanExporter.builder()
|
||||
.setTrustedCertificates(
|
||||
Files.readAllBytes(certificate.certificateFile().toPath()))
|
||||
.build())
|
||||
.isInstanceOf(IllegalStateException.class)
|
||||
.hasMessageContaining("TLS cerificate configuration only supported with Netty.");
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue