Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import io.opentelemetry.sdk.common.export.RetryPolicy;
import io.opentelemetry.sdk.common.internal.StandardComponentId;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
Expand Down Expand Up @@ -274,6 +275,22 @@ public OtlpHttpLogRecordExporterBuilder setExecutorService(ExecutorService execu
return this;
}

/**
* Sets the TLS protocol versions enabled for HTTPS connections. If unset, sender defaults are
* used.
*
* <p>Protocol names use the JSSE convention, for example {@code TLSv1.2} and {@code TLSv1.3}. The
* JVM security policy may prevent use of configured protocols.
*
* @param enabledProtocols the non-empty list of TLS protocol versions to enable
* @return this builder
*/
public OtlpHttpLogRecordExporterBuilder setEnabledProtocols(List<String> enabledProtocols) {
requireNonNull(enabledProtocols, "enabledProtocols");
delegate.setEnabledProtocols(enabledProtocols);
return this;
}

/**
* Constructs a new instance of the exporter based on the builder's values.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import io.opentelemetry.sdk.metrics.export.MetricExporter;
import java.time.Duration;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
Expand Down Expand Up @@ -333,6 +334,22 @@ public OtlpHttpMetricExporterBuilder setExecutorService(ExecutorService executor
return this;
}

/**
* Sets the TLS protocol versions enabled for HTTPS connections. If unset, sender defaults are
* used.
*
* <p>Protocol names use the JSSE convention, for example {@code TLSv1.2} and {@code TLSv1.3}. The
* JVM security policy may prevent use of configured protocols.
*
* @param enabledProtocols the non-empty list of TLS protocol versions to enable
* @return this builder
*/
public OtlpHttpMetricExporterBuilder setEnabledProtocols(List<String> enabledProtocols) {
requireNonNull(enabledProtocols, "enabledProtocols");
delegate.setEnabledProtocols(enabledProtocols);
return this;
}

OtlpHttpMetricExporterBuilder exportAsJson() {
delegate.exportAsJson();
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import io.opentelemetry.sdk.common.export.RetryPolicy;
import io.opentelemetry.sdk.common.internal.StandardComponentId;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
Expand Down Expand Up @@ -275,6 +276,22 @@ public OtlpHttpSpanExporterBuilder setExecutorService(ExecutorService executorSe
return this;
}

/**
* Sets the TLS protocol versions enabled for HTTPS connections. If unset, sender defaults are
* used.
*
* <p>Protocol names use the JSSE convention, for example {@code TLSv1.2} and {@code TLSv1.3}. The
* JVM security policy may prevent use of configured protocols.
*
* @param enabledProtocols the non-empty list of TLS protocol versions to enable
* @return this builder
*/
public OtlpHttpSpanExporterBuilder setEnabledProtocols(List<String> enabledProtocols) {
requireNonNull(enabledProtocols, "enabledProtocols");
delegate.setEnabledProtocols(enabledProtocols);
return this;
}

/**
* Constructs a new instance of the exporter based on the builder's values.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ public final class HttpExporterBuilder {
private ComponentLoader componentLoader =
ComponentLoader.forClassLoader(HttpExporterBuilder.class.getClassLoader());
@Nullable private ExecutorService executorService;
@Nullable private List<String> enabledProtocols;

public HttpExporterBuilder(
StandardComponentId.ExporterType exporterType, String defaultEndpoint) {
Expand Down Expand Up @@ -167,6 +168,14 @@ public HttpExporterBuilder setExecutorService(ExecutorService executorService) {
return this;
}

public HttpExporterBuilder setEnabledProtocols(List<String> enabledProtocols) {
if (enabledProtocols.isEmpty()) {
throw new IllegalArgumentException("enabledProtocols must not be empty");
}
this.enabledProtocols = Collections.unmodifiableList(new ArrayList<>(enabledProtocols));
return this;
}

public HttpExporterBuilder exportAsJson() {
this.exportAsJson = true;
exporterType = mapToJsonTypeIfPossible(exporterType);
Expand Down Expand Up @@ -204,6 +213,7 @@ public HttpExporterBuilder copy() {
copy.internalTelemetryVersion = internalTelemetryVersion;
copy.proxyOptions = proxyOptions;
copy.componentLoader = componentLoader;
copy.enabledProtocols = enabledProtocols;
return copy;
}

Expand Down Expand Up @@ -245,6 +255,7 @@ public HttpExporter build() {
isPlainHttp ? null : tlsConfigHelper.getSslContext(),
isPlainHttp ? null : tlsConfigHelper.getTrustManager(),
executorService,
enabledProtocols,
// 4mb to align with spec guidance - even though we don't do anything with the
// response today, we will so better to have future-looking memory profile
4 * 1024L * 1024L));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
@AutoValue
abstract class ImmutableHttpSenderConfig implements HttpSenderConfig {

@Override
@Nullable
public abstract List<String> getEnabledProtocols();

@SuppressWarnings("TooManyParameters")
static HttpSenderConfig create(
URI endpoint,
Expand All @@ -36,6 +40,7 @@ static HttpSenderConfig create(
@Nullable SSLContext sslContext,
@Nullable X509TrustManager trustManager,
@Nullable ExecutorService executorService,
@Nullable List<String> enabledProtocols,
long maxResponseBodySize) {
return new AutoValue_ImmutableHttpSenderConfig(
endpoint,
Expand All @@ -49,6 +54,7 @@ static HttpSenderConfig create(
sslContext,
trustManager,
executorService,
enabledProtocols,
maxResponseBodySize);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import javax.annotation.Nullable;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLParameters;

/**
* {@link HttpSender} which is backed by JDK {@link HttpClient}.
Expand Down Expand Up @@ -118,9 +119,10 @@ public final class JdkHttpSender implements HttpSender {
@Nullable ProxyOptions proxyOptions,
@Nullable SSLContext sslContext,
@Nullable ExecutorService executorService,
@Nullable List<String> enabledProtocols,
long maxResponseBodySize) {
this(
configureClient(sslContext, connectTimeout, proxyOptions),
configureClient(sslContext, connectTimeout, proxyOptions, enabledProtocols),
endpoint,
contentType,
compressor,
Expand All @@ -144,14 +146,20 @@ private static ExecutorService newExecutor() {
private static HttpClient configureClient(
@Nullable SSLContext sslContext,
Duration connectTimeout,
@Nullable ProxyOptions proxyOptions) {
@Nullable ProxyOptions proxyOptions,
@Nullable List<String> enabledProtocols) {
HttpClient.Builder builder = HttpClient.newBuilder().connectTimeout(connectTimeout);
if (sslContext != null) {
builder.sslContext(sslContext);
}
if (proxyOptions != null) {
builder.proxy(proxyOptions.getProxySelector());
}
if (enabledProtocols != null) {
SSLParameters sslParameters = new SSLParameters();
sslParameters.setProtocols(enabledProtocols.toArray(new String[0]));
builder.sslParameters(sslParameters);
}
return builder.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public HttpSender createSender(HttpSenderConfig httpSenderConfig) {
httpSenderConfig.getProxyOptions(),
httpSenderConfig.getSslContext(),
httpSenderConfig.getExecutorService(),
httpSenderConfig.getEnabledProtocols(),
httpSenderConfig.getMaxResponseBodySize());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ void defaultExecutor_isBounded() {
null,
null,
null,
null,
Long.MAX_VALUE);

try {
Expand Down Expand Up @@ -223,6 +224,7 @@ void connectTimeout() {
null,
null,
null,
null,
Long.MAX_VALUE);

assertThat(sender)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ public OkHttpHttpSender(
@Nullable SSLContext sslContext,
@Nullable X509TrustManager trustManager,
@Nullable ExecutorService executorService,
@Nullable List<String> enabledProtocols,
long maxResponseBodySize) {
int callTimeoutMillis = (int) Math.min(timeout.toMillis(), Integer.MAX_VALUE);
int connectTimeoutMillis = (int) Math.min(connectTimeout.toMillis(), Integer.MAX_VALUE);
Expand Down Expand Up @@ -111,17 +112,28 @@ public OkHttpHttpSender(
boolean isPlainHttp = endpoint.getScheme().equals("http");
if (isPlainHttp) {
builder.connectionSpecs(Collections.singletonList(ConnectionSpec.CLEARTEXT));
} else if (sslContext != null) {
X509TrustManager effectiveTrustManager = trustManager;

if (effectiveTrustManager == null) {
try {
effectiveTrustManager = TlsUtil.defaultTrustManager();
} catch (SSLException e) {
throw new IllegalStateException("Unable to initialize default trust manager", e);
} else {
if (enabledProtocols != null) {
ConnectionSpec spec =
new ConnectionSpec.Builder(ConnectionSpec.COMPATIBLE_TLS)
.tlsVersions(enabledProtocols.toArray(new String[0]))
.build();

builder.connectionSpecs(Collections.singletonList(spec));
}

if (sslContext != null) {
X509TrustManager effectiveTrustManager = trustManager;

if (effectiveTrustManager == null) {
try {
effectiveTrustManager = TlsUtil.defaultTrustManager();
} catch (SSLException e) {
throw new IllegalStateException("Unable to initialize default trust manager", e);
}
}
builder.sslSocketFactory(sslContext.getSocketFactory(), effectiveTrustManager);
}
builder.sslSocketFactory(sslContext.getSocketFactory(), effectiveTrustManager);
}

this.client = builder.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public HttpSender createSender(HttpSenderConfig httpSenderConfig) {
httpSenderConfig.getSslContext(),
httpSenderConfig.getTrustManager(),
httpSenderConfig.getExecutorService(),
httpSenderConfig.getEnabledProtocols(),
httpSenderConfig.getMaxResponseBodySize());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ void send_rejectedExecution_callsOnError() {
null,
null,
executor,
null,
Long.MAX_VALUE);

AtomicReference<HttpResponse> responseRef = new AtomicReference<>();
Expand Down Expand Up @@ -216,6 +217,7 @@ private static OkHttpHttpSender newSender(
null,
null,
executorService,
null,
Long.MAX_VALUE);
}

Expand Down Expand Up @@ -248,6 +250,7 @@ void constructor_usesDefaultTrustManagerWhenTrustManagerIsNull() throws Exceptio
sslContext,
null,
null,
null,
Long.MAX_VALUE))
.doesNotThrowAnyException();
}
Expand Down Expand Up @@ -276,6 +279,7 @@ void constructor_wrapsDefaultTrustManagerFailure() throws Exception {
sslContext,
null,
null,
null,
Long.MAX_VALUE))
.isInstanceOf(IllegalStateException.class)
.hasMessage("Unable to initialize default trust manager")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ OkHttpHttpSender createSender(String endpoint) {
null,
null,
null,
null,
Long.MAX_VALUE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ public interface HttpSenderConfig {
@Nullable
ExecutorService getExecutorService();

@Nullable
default List<String> getEnabledProtocols() {
return null;
}

/**
* The maximum number of bytes to read from a response body. Defaults to 4 MiB.
*
Expand Down
Loading