Add new TLS related APIs on OTLP exporter builders. (#5280)

This commit is contained in:
jason plumb 2023-05-03 18:29:30 -07:00 committed by GitHub
parent f4184dfde8
commit 5f9dc3f669
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 220 additions and 2 deletions

View File

@ -1,2 +1,13 @@
Comparing source compatibility of against
No changes.
*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporterBuilder (not serializable)
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporterBuilder setSslContext(javax.net.ssl.SSLContext, javax.net.ssl.X509TrustManager)
*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporterBuilder (not serializable)
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporterBuilder setSslContext(javax.net.ssl.SSLContext, javax.net.ssl.X509TrustManager)
*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporterBuilder (not serializable)
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporterBuilder setSslContext(javax.net.ssl.SSLContext, javax.net.ssl.X509TrustManager)
*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder (not serializable)
=== CLASS FILE FORMAT VERSION: 52.0 <- 52.0
+++ NEW METHOD: PUBLIC(+) io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder setSslContext(javax.net.ssl.SSLContext, javax.net.ssl.X509TrustManager)

View File

@ -111,6 +111,12 @@ public class GrpcExporterBuilder<T extends Marshaler> {
return this;
}
public GrpcExporterBuilder<T> setSslContext(
SSLContext sslContext, X509TrustManager trustManager) {
tlsConfigHelper.setSslContext(sslContext, trustManager);
return this;
}
public GrpcExporterBuilder<T> addHeader(String key, String value) {
headers.put(key, value);
return this;

View File

@ -18,6 +18,8 @@ import io.opentelemetry.sdk.metrics.export.DefaultAggregationSelector;
import io.opentelemetry.sdk.metrics.export.MetricExporter;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;
/**
* Builder utility for {@link OtlpHttpMetricExporter}.
@ -112,6 +114,16 @@ public final class OtlpHttpMetricExporterBuilder {
return this;
}
/**
* Sets the "bring-your-own" SSLContext for use with TLS. Users should call this _or_ set raw
* certificate bytes, but not both.
*/
public OtlpHttpMetricExporterBuilder setSslContext(
SSLContext sslContext, X509TrustManager trustManager) {
delegate.setSslContext(sslContext, trustManager);
return this;
}
/**
* Set the {@link AggregationTemporalitySelector} used for {@link
* MetricExporter#getAggregationTemporality(InstrumentType)}.

View File

@ -15,6 +15,8 @@ import io.opentelemetry.exporter.internal.otlp.OtlpUserAgent;
import io.opentelemetry.exporter.internal.otlp.traces.TraceRequestMarshaler;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;
/**
* Builder utility for {@link OtlpHttpSpanExporter}.
@ -100,6 +102,16 @@ public final class OtlpHttpSpanExporterBuilder {
return this;
}
/**
* Sets the "bring-your-own" SSLContext for use with TLS. Users should call this _or_ set raw
* certificate bytes, but not both.
*/
public OtlpHttpSpanExporterBuilder setSslContext(
SSLContext sslContext, X509TrustManager trustManager) {
delegate.setSslContext(sslContext, trustManager);
return this;
}
/**
* Sets the {@link MeterProvider} to use to collect metrics related to export. If not set, uses
* {@link GlobalOpenTelemetry#getMeterProvider()}.

View File

@ -21,6 +21,8 @@ import io.opentelemetry.sdk.metrics.export.MetricExporter;
import java.net.URI;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;
/**
* Builder utility for this exporter.
@ -144,6 +146,16 @@ public final class OtlpGrpcMetricExporterBuilder {
return this;
}
/**
* Sets the "bring-your-own" SSLContext for use with TLS. Users should call this _or_ set raw
* certificate bytes, but not both.
*/
public OtlpGrpcMetricExporterBuilder setSslContext(
SSLContext sslContext, X509TrustManager trustManager) {
delegate.setSslContext(sslContext, trustManager);
return this;
}
/**
* Add header to request. Optional. Applicable only if {@link
* OtlpGrpcMetricExporterBuilder#setChannel(ManagedChannel)} is not used to set channel.

View File

@ -18,6 +18,8 @@ import io.opentelemetry.exporter.internal.otlp.traces.TraceRequestMarshaler;
import java.net.URI;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;
/** Builder utility for this exporter. */
public final class OtlpGrpcSpanExporterBuilder {
@ -128,6 +130,16 @@ public final class OtlpGrpcSpanExporterBuilder {
return this;
}
/**
* Sets the "bring-your-own" SSLContext for use with TLS. Users should call this _or_ set raw
* certificate bytes, but not both.
*/
public OtlpGrpcSpanExporterBuilder setSslContext(
SSLContext sslContext, X509TrustManager trustManager) {
delegate.setSslContext(sslContext, trustManager);
return this;
}
/**
* Add header to request. Optional. Applicable only if {@link
* OtlpGrpcSpanExporterBuilder#setChannel(ManagedChannel)} is not called.

View File

@ -28,6 +28,8 @@ import io.opentelemetry.sdk.metrics.export.DefaultAggregationSelector;
import java.time.Duration;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;
import org.junit.jupiter.api.Test;
class OtlpHttpMetricExporterTest
@ -127,6 +129,13 @@ class OtlpHttpMetricExporterTest
return this;
}
@Override
public TelemetryExporterBuilder<MetricData> setSslContext(
SSLContext sslContext, X509TrustManager trustManager) {
builder.setSslContext(sslContext, trustManager);
return this;
}
@Override
public TelemetryExporterBuilder<MetricData> setClientTls(
byte[] privateKeyPem, byte[] certificatePem) {

View File

@ -19,6 +19,8 @@ import io.opentelemetry.sdk.trace.data.SpanData;
import java.time.Duration;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;
class OtlpHttpSpanExporterTest extends AbstractHttpTelemetryExporterTest<SpanData, ResourceSpans> {
@ -72,6 +74,13 @@ class OtlpHttpSpanExporterTest extends AbstractHttpTelemetryExporterTest<SpanDat
return this;
}
@Override
public TelemetryExporterBuilder<SpanData> setSslContext(
SSLContext sslContext, X509TrustManager trustManager) {
builder.setSslContext(sslContext, trustManager);
return this;
}
@Override
public TelemetryExporterBuilder<SpanData> setClientTls(
byte[] privateKeyPem, byte[] certificatePem) {

View File

@ -15,6 +15,8 @@ import io.opentelemetry.exporter.internal.otlp.OtlpUserAgent;
import io.opentelemetry.exporter.internal.otlp.logs.LogsRequestMarshaler;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;
/** Builder utility for {@link OtlpHttpLogRecordExporter}. */
public final class OtlpHttpLogRecordExporterBuilder {
@ -97,6 +99,16 @@ public final class OtlpHttpLogRecordExporterBuilder {
return this;
}
/**
* Sets the "bring-your-own" SSLContext. Users should call this _or_ set raw certificate bytes,
* but not both.
*/
public OtlpHttpLogRecordExporterBuilder setSslSocketFactory(
SSLContext sslContext, X509TrustManager trustManager) {
delegate.setSslContext(sslContext, trustManager);
return this;
}
/**
* Sets the {@link MeterProvider} to use to collect metrics related to export. If not set, uses
* {@link GlobalOpenTelemetry#getMeterProvider()}.

View File

@ -18,6 +18,8 @@ import io.opentelemetry.exporter.internal.otlp.logs.LogsRequestMarshaler;
import java.net.URI;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;
/** Builder for {@link OtlpGrpcLogRecordExporter}. */
public final class OtlpGrpcLogRecordExporterBuilder {
@ -129,6 +131,16 @@ public final class OtlpGrpcLogRecordExporterBuilder {
return this;
}
/**
* Sets the "bring-your-own" SSLContext for use with TLS. Users should call this _or_ set raw
* certificate bytes, but not both.
*/
public OtlpGrpcLogRecordExporterBuilder setSslContext(
SSLContext sslContext, X509TrustManager trustManager) {
delegate.setSslContext(sslContext, trustManager);
return this;
}
/**
* Add header to request. Optional. Applicable only if {@link
* OtlpGrpcLogRecordExporterBuilder#setChannel(ManagedChannel)} is not used to set channel.

View File

@ -19,6 +19,8 @@ import io.opentelemetry.sdk.logs.data.LogRecordData;
import java.time.Duration;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;
class OtlpHttpLogRecordExporterTest
extends AbstractHttpTelemetryExporterTest<LogRecordData, ResourceLogs> {
@ -73,6 +75,13 @@ class OtlpHttpLogRecordExporterTest
return this;
}
@Override
public TelemetryExporterBuilder<LogRecordData> setSslContext(
SSLContext ssLContext, X509TrustManager trustManager) {
builder.setSslSocketFactory(ssLContext, trustManager);
return this;
}
@Override
public TelemetryExporterBuilder<LogRecordData> setClientTls(
byte[] privateKeyPem, byte[] certificatePem) {

View File

@ -23,6 +23,7 @@ import com.linecorp.armeria.server.logging.LoggingService;
import com.linecorp.armeria.testing.junit5.server.SelfSignedCertificateExtension;
import com.linecorp.armeria.testing.junit5.server.ServerExtension;
import io.github.netmikey.logunit.api.LogCapturer;
import io.opentelemetry.exporter.internal.TlsUtil;
import io.opentelemetry.exporter.internal.grpc.OkHttpGrpcExporter;
import io.opentelemetry.exporter.internal.grpc.UpstreamGrpcExporter;
import io.opentelemetry.exporter.internal.marshal.Marshaler;
@ -54,6 +55,11 @@ import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509KeyManager;
import javax.net.ssl.X509TrustManager;
import org.assertj.core.api.iterable.ThrowingExtractor;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
@ -318,6 +324,31 @@ public abstract class AbstractGrpcTelemetryExporterTest<T, U extends Message> {
}
}
@Test
void tlsViaSslContext() throws Exception {
X509TrustManager trustManager = TlsUtil.trustManager(certificate.certificate().getEncoded());
X509KeyManager keyManager =
TlsUtil.keyManager(
certificate.privateKey().getEncoded(), certificate.certificate().getEncoded());
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(new KeyManager[] {keyManager}, new TrustManager[] {trustManager}, null);
TelemetryExporter<T> exporter =
exporterBuilder()
.setSslContext(sslContext, trustManager)
.setEndpoint(server.httpsUri().toString())
.build();
try {
CompletableResultCode result =
exporter.export(Collections.singletonList(generateFakeTelemetry()));
assertThat(result.join(10, TimeUnit.SECONDS).isSuccess()).isTrue();
} finally {
exporter.shutdown();
}
}
@Test
@SuppressLogger(OkHttpGrpcExporter.class)
@SuppressLogger(UpstreamGrpcExporter.class)

View File

@ -26,6 +26,7 @@ import com.linecorp.armeria.server.logging.LoggingService;
import com.linecorp.armeria.testing.junit5.server.SelfSignedCertificateExtension;
import com.linecorp.armeria.testing.junit5.server.ServerExtension;
import io.github.netmikey.logunit.api.LogCapturer;
import io.opentelemetry.exporter.internal.TlsUtil;
import io.opentelemetry.exporter.internal.grpc.UpstreamGrpcExporter;
import io.opentelemetry.exporter.internal.marshal.Marshaler;
import io.opentelemetry.exporter.internal.okhttp.OkHttpExporter;
@ -56,6 +57,11 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509KeyManager;
import javax.net.ssl.X509TrustManager;
import okio.Buffer;
import okio.GzipSource;
import okio.Okio;
@ -377,6 +383,31 @@ public abstract class AbstractHttpTelemetryExporterTest<T, U extends Message> {
}
}
@Test
void tlsViaSslContext() throws Exception {
X509TrustManager trustManager = TlsUtil.trustManager(certificate.certificate().getEncoded());
X509KeyManager keyManager =
TlsUtil.keyManager(
certificate.privateKey().getEncoded(), certificate.certificate().getEncoded());
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(new KeyManager[] {keyManager}, new TrustManager[] {trustManager}, null);
TelemetryExporter<T> exporter =
exporterBuilder()
.setEndpoint(server.httpsUri() + path)
.setSslContext(sslContext, trustManager)
.build();
try {
CompletableResultCode result =
exporter.export(Collections.singletonList(generateFakeTelemetry()));
assertThat(result.join(10, TimeUnit.SECONDS).isSuccess()).isTrue();
} finally {
exporter.shutdown();
}
}
@Test
@SuppressLogger(OkHttpExporter.class)
void tls_untrusted() {
@ -464,9 +495,11 @@ public abstract class AbstractHttpTelemetryExporterTest<T, U extends Message> {
@Test
@SuppressLogger(OkHttpExporter.class)
void doubleShutdown() {
int logsSizeBefore = logs.getEvents().size();
TelemetryExporter<T> exporter = exporterBuilder().setEndpoint(server.httpUri() + path).build();
assertThat(exporter.shutdown().join(10, TimeUnit.SECONDS).isSuccess()).isTrue();
assertThat(logs.getEvents()).isEmpty();
assertThat(logs.getEvents()).hasSize(logsSizeBefore);
logs.assertDoesNotContain("Calling shutdown() multiple times.");
assertThat(exporter.shutdown().join(10, TimeUnit.SECONDS).isSuccess()).isTrue();
logs.assertContains("Calling shutdown() multiple times.");
}

View File

@ -13,6 +13,8 @@ import io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporterBuilder;
import io.opentelemetry.sdk.logs.data.LogRecordData;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;
final class GrpcLogRecordExporterBuilderWrapper implements TelemetryExporterBuilder<LogRecordData> {
private final OtlpGrpcLogRecordExporterBuilder builder;
@ -69,6 +71,13 @@ final class GrpcLogRecordExporterBuilderWrapper implements TelemetryExporterBuil
return this;
}
@Override
public TelemetryExporterBuilder<LogRecordData> setSslContext(
SSLContext sslContext, X509TrustManager trustManager) {
builder.setSslContext(sslContext, trustManager);
return this;
}
@Override
public TelemetryExporterBuilder<LogRecordData> setRetryPolicy(RetryPolicy retryPolicy) {
RetryUtil.setRetryPolicyOnDelegate(builder, retryPolicy);

View File

@ -13,6 +13,8 @@ import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporterBuilder;
import io.opentelemetry.sdk.metrics.data.MetricData;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;
final class GrpcMetricExporterBuilderWrapper implements TelemetryExporterBuilder<MetricData> {
private final OtlpGrpcMetricExporterBuilder builder;
@ -69,6 +71,13 @@ final class GrpcMetricExporterBuilderWrapper implements TelemetryExporterBuilder
return this;
}
@Override
public TelemetryExporterBuilder<MetricData> setSslContext(
SSLContext sslContext, X509TrustManager trustManager) {
builder.setSslContext(sslContext, trustManager);
return this;
}
@Override
public TelemetryExporterBuilder<MetricData> setRetryPolicy(RetryPolicy retryPolicy) {
RetryUtil.setRetryPolicyOnDelegate(builder, retryPolicy);

View File

@ -13,6 +13,8 @@ import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder;
import io.opentelemetry.sdk.trace.data.SpanData;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;
/** Wrapper of {@link OtlpGrpcSpanExporterBuilder} for use in integration tests. */
final class GrpcSpanExporterBuilderWrapper implements TelemetryExporterBuilder<SpanData> {
@ -70,6 +72,13 @@ final class GrpcSpanExporterBuilderWrapper implements TelemetryExporterBuilder<S
return this;
}
@Override
public TelemetryExporterBuilder<SpanData> setSslContext(
SSLContext sslContext, X509TrustManager trustManager) {
builder.setSslContext(sslContext, trustManager);
return this;
}
@Override
public TelemetryExporterBuilder<SpanData> setRetryPolicy(RetryPolicy retryPolicy) {
RetryUtil.setRetryPolicyOnDelegate(builder, retryPolicy);

View File

@ -164,6 +164,13 @@ public final class ManagedChannelTelemetryExporterBuilder<T>
};
}
@Override
public TelemetryExporterBuilder<T> setSslContext(
SSLContext sslContext, X509TrustManager trustManager) {
tlsConfigHelper.setSslContext(sslContext, trustManager);
return this;
}
/**
* Configure the channel builder to trust the certificates. The {@code byte[]} should contain an
* X.509 certificate collection in PEM format.

View File

@ -16,6 +16,8 @@ import io.opentelemetry.sdk.metrics.data.MetricData;
import io.opentelemetry.sdk.trace.data.SpanData;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;
public interface TelemetryExporterBuilder<T> {
@ -47,6 +49,8 @@ public interface TelemetryExporterBuilder<T> {
TelemetryExporterBuilder<T> setClientTls(byte[] privateKeyPem, byte[] certificatePem);
TelemetryExporterBuilder<T> setSslContext(SSLContext sslContext, X509TrustManager trustManager);
TelemetryExporterBuilder<T> setRetryPolicy(RetryPolicy retryPolicy);
TelemetryExporterBuilder<T> setChannel(ManagedChannel channel);