From db8ade397f5e4ba3fccfaa4cb1488db0a59648f4 Mon Sep 17 00:00:00 2001 From: Francisco Bento Date: Fri, 5 May 2023 15:35:48 -0300 Subject: [PATCH] Add new TLS related APIs on Jaeger buiders. (#5422) --- .../opentelemetry-exporter-jaeger.txt | 4 ++- ...ry-sdk-extension-jaeger-remote-sampler.txt | 4 ++- .../jaeger/JaegerGrpcSpanExporterBuilder.java | 12 +++++++ .../jaeger/JaegerGrpcSpanExporterTest.java | 21 ++++++++++++ .../sampler/JaegerRemoteSamplerBuilder.java | 10 ++++++ .../sampler/JaegerRemoteSamplerTest.java | 34 +++++++++++++++++++ 6 files changed, 83 insertions(+), 2 deletions(-) diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-jaeger.txt b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-jaeger.txt index df26146497b..48d81fc8131 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-exporter-jaeger.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-exporter-jaeger.txt @@ -1,2 +1,4 @@ Comparing source compatibility of against -No changes. \ No newline at end of file +*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.exporter.jaeger.JaegerGrpcSpanExporterBuilder (not serializable) + === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 + +++ NEW METHOD: PUBLIC(+) io.opentelemetry.exporter.jaeger.JaegerGrpcSpanExporterBuilder setSslContext(javax.net.ssl.SSLContext, javax.net.ssl.X509TrustManager) diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-jaeger-remote-sampler.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-jaeger-remote-sampler.txt index df26146497b..5d00da675b8 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-jaeger-remote-sampler.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-jaeger-remote-sampler.txt @@ -1,2 +1,4 @@ Comparing source compatibility of against -No changes. \ No newline at end of file +*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.sdk.extension.trace.jaeger.sampler.JaegerRemoteSamplerBuilder (not serializable) + === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 + +++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.extension.trace.jaeger.sampler.JaegerRemoteSamplerBuilder setSslContext(javax.net.ssl.SSLContext, javax.net.ssl.X509TrustManager) diff --git a/exporters/jaeger/src/main/java/io/opentelemetry/exporter/jaeger/JaegerGrpcSpanExporterBuilder.java b/exporters/jaeger/src/main/java/io/opentelemetry/exporter/jaeger/JaegerGrpcSpanExporterBuilder.java index e70f9061a7c..0fb7c566173 100644 --- a/exporters/jaeger/src/main/java/io/opentelemetry/exporter/jaeger/JaegerGrpcSpanExporterBuilder.java +++ b/exporters/jaeger/src/main/java/io/opentelemetry/exporter/jaeger/JaegerGrpcSpanExporterBuilder.java @@ -16,6 +16,8 @@ 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 JaegerGrpcSpanExporterBuilder { @@ -119,6 +121,16 @@ public JaegerGrpcSpanExporterBuilder setClientTls(byte[] privateKeyPem, byte[] c 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 JaegerGrpcSpanExporterBuilder 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()}. diff --git a/exporters/jaeger/src/test/java/io/opentelemetry/exporter/jaeger/JaegerGrpcSpanExporterTest.java b/exporters/jaeger/src/test/java/io/opentelemetry/exporter/jaeger/JaegerGrpcSpanExporterTest.java index d9b0e66f1db..88cbd138e37 100644 --- a/exporters/jaeger/src/test/java/io/opentelemetry/exporter/jaeger/JaegerGrpcSpanExporterTest.java +++ b/exporters/jaeger/src/test/java/io/opentelemetry/exporter/jaeger/JaegerGrpcSpanExporterTest.java @@ -26,6 +26,7 @@ import io.opentelemetry.api.trace.TraceFlags; import io.opentelemetry.api.trace.TraceId; import io.opentelemetry.api.trace.TraceState; +import io.opentelemetry.exporter.internal.TlsUtil; import io.opentelemetry.exporter.internal.grpc.OkHttpGrpcExporter; import io.opentelemetry.exporter.jaeger.proto.api_v2.Collector; import io.opentelemetry.exporter.jaeger.proto.api_v2.Model; @@ -50,6 +51,11 @@ import java.util.concurrent.CompletionStage; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.TimeUnit; +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.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; @@ -309,6 +315,21 @@ void validClientKeyConfig() throws Exception { .doesNotThrowAnyException(); } + @Test + void validSslContextConfig() throws Exception { + X509TrustManager trustManager = TlsUtil.trustManager(serverTls.certificate().getEncoded()); + + X509KeyManager keyManager = + TlsUtil.keyManager( + clientTls.privateKey().getEncoded(), clientTls.certificate().getEncoded()); + + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(new KeyManager[] {keyManager}, new TrustManager[] {trustManager}, null); + + assertThatCode(() -> JaegerGrpcSpanExporter.builder().setSslContext(sslContext, trustManager)) + .doesNotThrowAnyException(); + } + @Test @SuppressWarnings("PreferJavaTimeOverload") void invalidConfig() { diff --git a/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSamplerBuilder.java b/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSamplerBuilder.java index e41c94a2a85..c2327b6067e 100644 --- a/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSamplerBuilder.java +++ b/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSamplerBuilder.java @@ -92,6 +92,16 @@ public JaegerRemoteSamplerBuilder setClientTls(byte[] privateKeyPem, byte[] cert 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 JaegerRemoteSamplerBuilder setSslContext( + SSLContext sslContext, X509TrustManager trustManager) { + tlsConfigHelper.setSslContext(sslContext, trustManager); + return this; + } + /** * Sets the polling interval for configuration updates. If unset, defaults to {@value * DEFAULT_POLLING_INTERVAL_MILLIS}ms. Must be positive. diff --git a/sdk-extensions/jaeger-remote-sampler/src/test/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSamplerTest.java b/sdk-extensions/jaeger-remote-sampler/src/test/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSamplerTest.java index ce0a9a6d523..d1b16920e2e 100644 --- a/sdk-extensions/jaeger-remote-sampler/src/test/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSamplerTest.java +++ b/sdk-extensions/jaeger-remote-sampler/src/test/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSamplerTest.java @@ -20,6 +20,7 @@ import com.linecorp.armeria.testing.junit5.server.ServerExtension; import io.github.netmikey.logunit.api.LogCapturer; import io.netty.handler.ssl.ClientAuth; +import io.opentelemetry.exporter.internal.TlsUtil; import io.opentelemetry.internal.testing.slf4j.SuppressLogger; import io.opentelemetry.sdk.extension.trace.jaeger.proto.api_v2.Sampling; import io.opentelemetry.sdk.extension.trace.jaeger.proto.api_v2.Sampling.RateLimitingSamplingStrategy; @@ -34,6 +35,11 @@ import java.util.concurrent.TimeUnit; 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.awaitility.core.ThrowingRunnable; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Order; @@ -192,6 +198,34 @@ public Stream provideArguments(ExtensionContext context) th } } + @Test + void tlsViaSslContext() throws Exception { + X509TrustManager trustManager = TlsUtil.trustManager(certificate.certificate().getEncoded()); + + X509KeyManager keyManager = + TlsUtil.keyManager( + clientCertificate.privateKey().getEncoded(), + clientCertificate.certificate().getEncoded()); + + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(new KeyManager[] {keyManager}, new TrustManager[] {trustManager}, null); + + try (JaegerRemoteSampler sampler = + JaegerRemoteSampler.builder() + .setEndpoint(server.httpsUri().toString()) + .setPollingInterval(1, TimeUnit.SECONDS) + .setSslContext(sslContext, trustManager) + .setServiceName(SERVICE_NAME) + .build()) { + assertThat(sampler).extracting("delegate").isInstanceOf(OkHttpGrpcService.class); + + await().untilAsserted(samplerIsType(sampler, RateLimitingSampler.class)); + + // verify + assertThat(sampler.getDescription()).contains("RateLimitingSampler{999.00}"); + } + } + @Test void description() { try (JaegerRemoteSampler sampler =