Add TlsConfigHelper for additional TLS configurability (#5246)
* add TlsConfigHelper for additional TLS configurability and wire up internal builders. * add javadoc and spotless * add keys for "validity" testing. * fix tests * fix tests * address code review comments * fix typo * allow keymanager to be nullable. * fix test * so....much...null......away * backfill tests * checkstyle * test coverage * address code review comments
This commit is contained in:
parent
e871805ee2
commit
895075f9e5
|
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.exporter.internal;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import java.util.logging.Logger;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.X509KeyManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
/**
|
||||
* Utility class to help with management of TLS related components. This class is ultimately
|
||||
* responsible for enabling TLS via callbacks passed to the configure[...]() methods. This class is
|
||||
* only intended for internal OpenTelemetry exporter usage and should not be used by end-users.
|
||||
*
|
||||
* <p>This class is internal and is hence not for public use. Its APIs are unstable and can change
|
||||
* at any time.
|
||||
*/
|
||||
public class TlsConfigHelper {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(TlsConfigHelper.class.getName());
|
||||
|
||||
private final TlsUtility tlsUtil;
|
||||
|
||||
@Nullable private X509KeyManager keyManager;
|
||||
@Nullable private X509TrustManager trustManager;
|
||||
@Nullable private SSLSocketFactory sslSocketFactory;
|
||||
|
||||
public TlsConfigHelper() {
|
||||
this(new TlsUtility() {});
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
TlsConfigHelper(TlsUtility tlsUtil) {
|
||||
this.tlsUtil = tlsUtil;
|
||||
}
|
||||
|
||||
/** Sets the X509TrustManager. */
|
||||
public TlsConfigHelper setTrustManager(X509TrustManager trustManager) {
|
||||
this.trustManager = trustManager;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new X509TrustManager from the given cert content.
|
||||
*
|
||||
* @param trustedCertsPem Certificate in PEM format.
|
||||
* @return this
|
||||
*/
|
||||
public TlsConfigHelper createTrustManager(byte[] trustedCertsPem) {
|
||||
try {
|
||||
this.trustManager = tlsUtil.trustManager(trustedCertsPem);
|
||||
} catch (SSLException e) {
|
||||
throw new IllegalStateException(
|
||||
"Error creating X509TrustManager with provided certs. Are they valid X.509 in PEM format?",
|
||||
e);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new X509KeyManager from the given private key and certificate, both in PEM format.
|
||||
*
|
||||
* @param privateKeyPem Private key content in PEM format.
|
||||
* @param certificatePem Certificate content in PEM format.
|
||||
* @return this
|
||||
*/
|
||||
public TlsConfigHelper createKeyManager(byte[] privateKeyPem, byte[] certificatePem) {
|
||||
try {
|
||||
if (keyManager != null) {
|
||||
logger.warning(
|
||||
"Previous X509 Key manager is being replaced. This is probably an error and should only be set once.");
|
||||
}
|
||||
keyManager = tlsUtil.keyManager(privateKeyPem, certificatePem);
|
||||
return this;
|
||||
} catch (SSLException e) {
|
||||
throw new IllegalStateException(
|
||||
"Error creating X509KeyManager with provided certs. Are they valid X.509 in PEM format?",
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns the X509KeyManager.
|
||||
*
|
||||
* @return this
|
||||
*/
|
||||
public TlsConfigHelper setKeyManager(X509KeyManager keyManager) {
|
||||
if (this.keyManager != null) {
|
||||
logger.warning(
|
||||
"Previous X509 Key manager is being replaced. This is probably an error and should only be set once.");
|
||||
}
|
||||
this.keyManager = keyManager;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the SSLSocketFactory, which is passed into the callback within
|
||||
* configureWithSocketFactory().
|
||||
*/
|
||||
public TlsConfigHelper setSslSocketFactory(SSLSocketFactory sslSocketFactory) {
|
||||
this.sslSocketFactory = sslSocketFactory;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Functional wrapper type used in configure methods. Exists primarily to declare checked
|
||||
* SSLException.
|
||||
*/
|
||||
public interface SslSocketFactoryConfigurer {
|
||||
void configure(SSLSocketFactory sslSocketFactory, X509TrustManager trustManager)
|
||||
throws SSLException;
|
||||
}
|
||||
|
||||
/**
|
||||
* Functional wrapper type used in configure methods. Exists primarily to declare checked
|
||||
* SSLException.
|
||||
*/
|
||||
public interface KeyManagerConfigurer {
|
||||
void configure(X509TrustManager trustManager, @Nullable X509KeyManager keyManager)
|
||||
throws SSLException;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures TLS by invoking the given callback with the X509TrustManager and X509KeyManager. If
|
||||
* the trust manager or key manager have not yet been configured, this method does nothing.
|
||||
*/
|
||||
public void configureWithKeyManager(KeyManagerConfigurer configurer) {
|
||||
if (trustManager == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
configurer.configure(trustManager, keyManager);
|
||||
} catch (SSLException e) {
|
||||
wrapException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures TLS by invoking the provided consumer with a new SSLSocketFactory and the
|
||||
* preconfigured X509TrustManager. If the trust manager has not been configured, this method does
|
||||
* nothing.
|
||||
*/
|
||||
public void configureWithSocketFactory(SslSocketFactoryConfigurer configurer) {
|
||||
if (trustManager == null) {
|
||||
warnIfOtherComponentsConfigured();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
SSLSocketFactory sslSocketFactory = this.sslSocketFactory;
|
||||
if (sslSocketFactory == null) {
|
||||
sslSocketFactory = tlsUtil.sslSocketFactory(keyManager, trustManager);
|
||||
}
|
||||
configurer.configure(sslSocketFactory, trustManager);
|
||||
} catch (SSLException e) {
|
||||
wrapException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void wrapException(SSLException e) {
|
||||
throw new IllegalStateException(
|
||||
"Could not configure TLS connection, are certs in valid X.509 in PEM format?", e);
|
||||
}
|
||||
|
||||
private void warnIfOtherComponentsConfigured() {
|
||||
if (sslSocketFactory != null) {
|
||||
logger.warning("sslSocketFactory has been configured without an X509TrustManager.");
|
||||
return;
|
||||
}
|
||||
if (keyManager != null) {
|
||||
logger.warning("An X509KeyManager has been configured without an X509TrustManager.");
|
||||
}
|
||||
}
|
||||
|
||||
// Exists for testing
|
||||
interface TlsUtility {
|
||||
default SSLSocketFactory sslSocketFactory(
|
||||
@Nullable X509KeyManager keyManager, X509TrustManager trustManager) throws SSLException {
|
||||
return TlsUtil.sslSocketFactory(keyManager, trustManager);
|
||||
}
|
||||
|
||||
default X509TrustManager trustManager(byte[] trustedCertificatesPem) throws SSLException {
|
||||
return TlsUtil.trustManager(trustedCertificatesPem);
|
||||
}
|
||||
|
||||
default X509KeyManager keyManager(byte[] privateKeyPem, byte[] certificatePem)
|
||||
throws SSLException {
|
||||
return TlsUtil.keyManager(privateKeyPem, certificatePem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -89,7 +89,7 @@ public final class TlsUtil {
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates {@link KeyManager} initiaded by keystore containing single private key with matching
|
||||
* Creates {@link KeyManager} initiated by keystore containing single private key with matching
|
||||
* certificate chain.
|
||||
*/
|
||||
public static X509KeyManager keyManager(byte[] privateKeyPem, byte[] certificatePem)
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import io.grpc.stub.MetadataUtils;
|
|||
import io.opentelemetry.api.GlobalOpenTelemetry;
|
||||
import io.opentelemetry.api.metrics.MeterProvider;
|
||||
import io.opentelemetry.exporter.internal.ExporterBuilderUtil;
|
||||
import io.opentelemetry.exporter.internal.TlsUtil;
|
||||
import io.opentelemetry.exporter.internal.TlsConfigHelper;
|
||||
import io.opentelemetry.exporter.internal.marshal.Marshaler;
|
||||
import io.opentelemetry.exporter.internal.okhttp.OkHttpUtil;
|
||||
import io.opentelemetry.exporter.internal.retry.RetryInterceptor;
|
||||
|
|
@ -29,9 +29,6 @@ import java.util.concurrent.TimeUnit;
|
|||
import java.util.function.BiFunction;
|
||||
import java.util.function.Supplier;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.X509KeyManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import okhttp3.Headers;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Protocol;
|
||||
|
|
@ -55,9 +52,7 @@ public class GrpcExporterBuilder<T extends Marshaler> {
|
|||
private URI endpoint;
|
||||
private boolean compressionEnabled = false;
|
||||
private final Map<String, String> headers = new HashMap<>();
|
||||
@Nullable private byte[] trustedCertificatesPem;
|
||||
@Nullable private byte[] privateKeyPem;
|
||||
@Nullable private byte[] certificatePem;
|
||||
private final TlsConfigHelper tlsConfigHelper = new TlsConfigHelper();
|
||||
@Nullable private RetryPolicy retryPolicy;
|
||||
private Supplier<MeterProvider> meterProviderSupplier = GlobalOpenTelemetry::getMeterProvider;
|
||||
|
||||
|
|
@ -103,14 +98,13 @@ public class GrpcExporterBuilder<T extends Marshaler> {
|
|||
return this;
|
||||
}
|
||||
|
||||
public GrpcExporterBuilder<T> setTrustedCertificates(byte[] trustedCertificatesPem) {
|
||||
this.trustedCertificatesPem = trustedCertificatesPem;
|
||||
public GrpcExporterBuilder<T> configureTrustManager(byte[] trustedCertificatesPem) {
|
||||
tlsConfigHelper.createTrustManager(trustedCertificatesPem);
|
||||
return this;
|
||||
}
|
||||
|
||||
public GrpcExporterBuilder<T> setClientTls(byte[] privateKeyPem, byte[] certificatePem) {
|
||||
this.privateKeyPem = privateKeyPem;
|
||||
this.certificatePem = certificatePem;
|
||||
public GrpcExporterBuilder<T> configureKeyManager(byte[] privateKeyPem, byte[] certificatePem) {
|
||||
tlsConfigHelper.createKeyManager(privateKeyPem, certificatePem);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -139,20 +133,7 @@ public class GrpcExporterBuilder<T extends Marshaler> {
|
|||
|
||||
clientBuilder.callTimeout(Duration.ofNanos(timeoutNanos));
|
||||
|
||||
if (trustedCertificatesPem != null) {
|
||||
try {
|
||||
X509TrustManager trustManager = TlsUtil.trustManager(trustedCertificatesPem);
|
||||
X509KeyManager keyManager = null;
|
||||
if (privateKeyPem != null && certificatePem != null) {
|
||||
keyManager = TlsUtil.keyManager(privateKeyPem, certificatePem);
|
||||
}
|
||||
clientBuilder.sslSocketFactory(
|
||||
TlsUtil.sslSocketFactory(keyManager, trustManager), trustManager);
|
||||
} catch (SSLException e) {
|
||||
throw new IllegalStateException(
|
||||
"Could not set trusted certificates, are they valid X.509 in PEM format?", e);
|
||||
}
|
||||
}
|
||||
tlsConfigHelper.configureWithSocketFactory(clientBuilder::sslSocketFactory);
|
||||
|
||||
String endpoint = this.endpoint.resolve(grpcEndpointPath).toString();
|
||||
if (endpoint.startsWith("http://")) {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import io.grpc.ManagedChannel;
|
|||
import io.grpc.ManagedChannelBuilder;
|
||||
import io.grpc.netty.GrpcSslContexts;
|
||||
import io.grpc.netty.NettyChannelBuilder;
|
||||
import io.netty.handler.ssl.SslContext;
|
||||
import io.opentelemetry.exporter.internal.TlsUtil;
|
||||
import io.opentelemetry.exporter.internal.retry.RetryPolicy;
|
||||
import io.opentelemetry.exporter.internal.retry.RetryUtil;
|
||||
|
|
@ -46,47 +47,45 @@ public final class ManagedChannelUtil {
|
|||
*/
|
||||
public static void setClientKeysAndTrustedCertificatesPem(
|
||||
ManagedChannelBuilder<?> managedChannelBuilder,
|
||||
@Nullable byte[] privateKeyPem,
|
||||
@Nullable byte[] certificatePem,
|
||||
byte[] trustedCertificatesPem)
|
||||
X509TrustManager tmf,
|
||||
@Nullable X509KeyManager kmf)
|
||||
throws SSLException {
|
||||
requireNonNull(managedChannelBuilder, "managedChannelBuilder");
|
||||
requireNonNull(trustedCertificatesPem, "trustedCertificatesPem");
|
||||
|
||||
X509TrustManager tmf = TlsUtil.trustManager(trustedCertificatesPem);
|
||||
X509KeyManager kmf = null;
|
||||
if (privateKeyPem != null && certificatePem != null) {
|
||||
kmf = TlsUtil.keyManager(privateKeyPem, certificatePem);
|
||||
}
|
||||
requireNonNull(tmf, "X509TrustManager");
|
||||
|
||||
// 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;
|
||||
nettyBuilder.sslContext(
|
||||
GrpcSslContexts.forClient().keyManager(kmf).trustManager(tmf).build());
|
||||
} 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;
|
||||
nettyBuilder.sslContext(
|
||||
io.grpc.netty.shaded.io.grpc.netty.GrpcSslContexts.forClient()
|
||||
.trustManager(tmf)
|
||||
.keyManager(kmf)
|
||||
.build());
|
||||
} else if (managedChannelBuilder
|
||||
.getClass()
|
||||
.getName()
|
||||
.equals("io.grpc.okhttp.OkHttpChannelBuilder")) {
|
||||
io.grpc.okhttp.OkHttpChannelBuilder okHttpBuilder =
|
||||
(io.grpc.okhttp.OkHttpChannelBuilder) managedChannelBuilder;
|
||||
okHttpBuilder.sslSocketFactory(TlsUtil.sslSocketFactory(kmf, tmf));
|
||||
} else {
|
||||
throw new SSLException(
|
||||
"TLS certificate configuration not supported for unrecognized ManagedChannelBuilder "
|
||||
+ managedChannelBuilder.getClass().getName());
|
||||
String channelBuilderClassName = managedChannelBuilder.getClass().getName();
|
||||
switch (channelBuilderClassName) {
|
||||
case "io.grpc.netty.NettyChannelBuilder":
|
||||
{
|
||||
NettyChannelBuilder nettyBuilder = (NettyChannelBuilder) managedChannelBuilder;
|
||||
SslContext sslContext =
|
||||
GrpcSslContexts.forClient().keyManager(kmf).trustManager(tmf).build();
|
||||
nettyBuilder.sslContext(sslContext);
|
||||
break;
|
||||
}
|
||||
case "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;
|
||||
io.grpc.netty.shaded.io.netty.handler.ssl.SslContext sslContext =
|
||||
io.grpc.netty.shaded.io.grpc.netty.GrpcSslContexts.forClient()
|
||||
.trustManager(tmf)
|
||||
.keyManager(kmf)
|
||||
.build();
|
||||
nettyBuilder.sslContext(sslContext);
|
||||
break;
|
||||
}
|
||||
case "io.grpc.okhttp.OkHttpChannelBuilder":
|
||||
io.grpc.okhttp.OkHttpChannelBuilder okHttpBuilder =
|
||||
(io.grpc.okhttp.OkHttpChannelBuilder) managedChannelBuilder;
|
||||
okHttpBuilder.sslSocketFactory(TlsUtil.sslSocketFactory(kmf, tmf));
|
||||
break;
|
||||
default:
|
||||
throw new SSLException(
|
||||
"TLS certificate configuration not supported for unrecognized ManagedChannelBuilder "
|
||||
+ channelBuilderClassName);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ package io.opentelemetry.exporter.internal.okhttp;
|
|||
import io.opentelemetry.api.GlobalOpenTelemetry;
|
||||
import io.opentelemetry.api.metrics.MeterProvider;
|
||||
import io.opentelemetry.exporter.internal.ExporterBuilderUtil;
|
||||
import io.opentelemetry.exporter.internal.TlsUtil;
|
||||
import io.opentelemetry.exporter.internal.TlsConfigHelper;
|
||||
import io.opentelemetry.exporter.internal.auth.Authenticator;
|
||||
import io.opentelemetry.exporter.internal.marshal.Marshaler;
|
||||
import io.opentelemetry.exporter.internal.retry.RetryInterceptor;
|
||||
|
|
@ -18,7 +18,7 @@ import java.time.Duration;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Supplier;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.X509KeyManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import okhttp3.Headers;
|
||||
|
|
@ -44,9 +44,8 @@ public final class OkHttpExporterBuilder<T extends Marshaler> {
|
|||
private boolean compressionEnabled = false;
|
||||
private boolean exportAsJson = false;
|
||||
@Nullable private Headers.Builder headersBuilder;
|
||||
@Nullable private byte[] trustedCertificatesPem;
|
||||
@Nullable private byte[] privateKeyPem;
|
||||
@Nullable private byte[] certificatePem;
|
||||
|
||||
private final TlsConfigHelper tlsConfigHelper = new TlsConfigHelper();
|
||||
@Nullable private RetryPolicy retryPolicy;
|
||||
private Supplier<MeterProvider> meterProviderSupplier = GlobalOpenTelemetry::getMeterProvider;
|
||||
@Nullable private Authenticator authenticator;
|
||||
|
|
@ -91,14 +90,28 @@ public final class OkHttpExporterBuilder<T extends Marshaler> {
|
|||
return this;
|
||||
}
|
||||
|
||||
public OkHttpExporterBuilder<T> setTrustedCertificates(byte[] trustedCertificatesPem) {
|
||||
this.trustedCertificatesPem = trustedCertificatesPem;
|
||||
public OkHttpExporterBuilder<T> configureTrustManager(byte[] trustedCertificatesPem) {
|
||||
tlsConfigHelper.createTrustManager(trustedCertificatesPem);
|
||||
return this;
|
||||
}
|
||||
|
||||
public OkHttpExporterBuilder<T> setClientTls(byte[] privateKeyPem, byte[] certificatePem) {
|
||||
this.privateKeyPem = privateKeyPem;
|
||||
this.certificatePem = certificatePem;
|
||||
public OkHttpExporterBuilder<T> setTrustManager(X509TrustManager trustManager) {
|
||||
tlsConfigHelper.setTrustManager(trustManager);
|
||||
return this;
|
||||
}
|
||||
|
||||
public OkHttpExporterBuilder<T> configureKeyManager(byte[] privateKeyPem, byte[] certificatePem) {
|
||||
tlsConfigHelper.createKeyManager(privateKeyPem, certificatePem);
|
||||
return this;
|
||||
}
|
||||
|
||||
public OkHttpExporterBuilder<T> setKeyManager(X509KeyManager keyManager) {
|
||||
tlsConfigHelper.setKeyManager(keyManager);
|
||||
return this;
|
||||
}
|
||||
|
||||
public OkHttpExporterBuilder<T> setSslSocketFactory(SSLSocketFactory sslSocketFactory) {
|
||||
tlsConfigHelper.setSslSocketFactory(sslSocketFactory);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -123,21 +136,7 @@ public final class OkHttpExporterBuilder<T extends Marshaler> {
|
|||
.dispatcher(OkHttpUtil.newDispatcher())
|
||||
.callTimeout(Duration.ofNanos(timeoutNanos));
|
||||
|
||||
if (trustedCertificatesPem != null) {
|
||||
try {
|
||||
X509TrustManager trustManager = TlsUtil.trustManager(trustedCertificatesPem);
|
||||
X509KeyManager keyManager = null;
|
||||
if (privateKeyPem != null && certificatePem != null) {
|
||||
keyManager = TlsUtil.keyManager(privateKeyPem, certificatePem);
|
||||
}
|
||||
clientBuilder.sslSocketFactory(
|
||||
TlsUtil.sslSocketFactory(keyManager, trustManager), trustManager);
|
||||
} catch (SSLException e) {
|
||||
throw new IllegalStateException(
|
||||
"Could not set trusted certificate for OTLP HTTP connection, are they valid X.509 in PEM format?",
|
||||
e);
|
||||
}
|
||||
}
|
||||
tlsConfigHelper.configureWithSocketFactory(clientBuilder::sslSocketFactory);
|
||||
|
||||
Headers headers = headersBuilder == null ? null : headersBuilder.build();
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* Copyright The OpenTelemetry Authors
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package io.opentelemetry.exporter.internal;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.linecorp.armeria.testing.junit5.server.SelfSignedCertificateExtension;
|
||||
import io.github.netmikey.logunit.api.LogCapturer;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.X509KeyManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class TlsConfigHelperTest {
|
||||
@RegisterExtension
|
||||
static final SelfSignedCertificateExtension serverTls = new SelfSignedCertificateExtension();
|
||||
|
||||
@RegisterExtension
|
||||
LogCapturer logs = LogCapturer.create().captureForLogger(TlsConfigHelper.class.getName());
|
||||
|
||||
@Mock TlsConfigHelper.TlsUtility tlsUtil;
|
||||
|
||||
@Test
|
||||
void createTrustManager_exceptionMapped() throws Exception {
|
||||
when(tlsUtil.trustManager(any())).thenThrow(new SSLException("boom"));
|
||||
TlsConfigHelper helper = new TlsConfigHelper(tlsUtil);
|
||||
assertThrows(
|
||||
IllegalStateException.class,
|
||||
() -> {
|
||||
helper.createTrustManager(serverTls.certificate().getEncoded());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void createKeymanager_exceptionMapped() throws Exception {
|
||||
when(tlsUtil.keyManager(any(), any())).thenThrow(new SSLException("boom"));
|
||||
TlsConfigHelper helper = new TlsConfigHelper(tlsUtil);
|
||||
assertThrows(
|
||||
IllegalStateException.class,
|
||||
() -> {
|
||||
helper.createKeyManager(
|
||||
serverTls.privateKey().getEncoded(), serverTls.certificate().getEncoded());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void socketFactory_happyPathWithBytes() throws Exception {
|
||||
|
||||
byte[] cert = serverTls.certificate().getEncoded();
|
||||
byte[] key = serverTls.privateKey().getEncoded();
|
||||
AtomicReference<X509TrustManager> seenTrustManager = new AtomicReference<>();
|
||||
AtomicReference<SSLSocketFactory> seenSocketFactory = new AtomicReference<>();
|
||||
|
||||
X509TrustManager trustManager = mock(X509TrustManager.class);
|
||||
X509KeyManager keyManager = mock(X509KeyManager.class);
|
||||
SSLSocketFactory sslSocketFactory = mock(SSLSocketFactory.class);
|
||||
|
||||
when(tlsUtil.trustManager(cert)).thenReturn(trustManager);
|
||||
when(tlsUtil.keyManager(key, cert)).thenReturn(keyManager);
|
||||
when(tlsUtil.sslSocketFactory(keyManager, trustManager)).thenReturn(sslSocketFactory);
|
||||
|
||||
TlsConfigHelper helper = new TlsConfigHelper(tlsUtil);
|
||||
|
||||
helper.createKeyManager(key, cert);
|
||||
helper.createTrustManager(cert);
|
||||
helper.configureWithSocketFactory(
|
||||
(sf, tm) -> {
|
||||
seenTrustManager.set(tm);
|
||||
seenSocketFactory.set(sf);
|
||||
});
|
||||
assertSame(trustManager, seenTrustManager.get());
|
||||
assertSame(sslSocketFactory, seenSocketFactory.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void socketFactory_noTrustManager() {
|
||||
TlsConfigHelper helper = new TlsConfigHelper(tlsUtil);
|
||||
helper.configureWithSocketFactory(
|
||||
(sf, tm) -> {
|
||||
fail("Should not have called due to missing trust manager");
|
||||
});
|
||||
verifyNoInteractions(tlsUtil);
|
||||
}
|
||||
|
||||
@Test
|
||||
void socketFactoryCallbackExceptionHandled() {
|
||||
X509TrustManager trustManager = mock(X509TrustManager.class);
|
||||
|
||||
TlsConfigHelper helper = new TlsConfigHelper(tlsUtil);
|
||||
|
||||
helper.setTrustManager(trustManager);
|
||||
assertThrows(
|
||||
IllegalStateException.class,
|
||||
() -> {
|
||||
helper.configureWithSocketFactory(
|
||||
(sf, tm) -> {
|
||||
throw new SSLException("bad times");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void configureWithKeyManagerHappyPath() {
|
||||
AtomicReference<X509TrustManager> seenTrustManager = new AtomicReference<>();
|
||||
AtomicReference<X509KeyManager> seenKeyManager = new AtomicReference<>();
|
||||
|
||||
X509TrustManager trustManager = mock(X509TrustManager.class);
|
||||
X509KeyManager keyManager = mock(X509KeyManager.class);
|
||||
|
||||
TlsConfigHelper helper = new TlsConfigHelper(tlsUtil);
|
||||
|
||||
helper.setTrustManager(trustManager);
|
||||
helper.setKeyManager(keyManager);
|
||||
helper.configureWithKeyManager(
|
||||
(tm, km) -> {
|
||||
seenTrustManager.set(tm);
|
||||
seenKeyManager.set(km);
|
||||
});
|
||||
assertThat(seenTrustManager.get()).isSameAs(trustManager);
|
||||
assertThat(seenKeyManager.get()).isSameAs(keyManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
void configureWithKeyManagerExceptionHandled() {
|
||||
X509TrustManager trustManager = mock(X509TrustManager.class);
|
||||
X509KeyManager keyManager = mock(X509KeyManager.class);
|
||||
|
||||
TlsConfigHelper helper = new TlsConfigHelper(tlsUtil);
|
||||
|
||||
helper.setTrustManager(trustManager);
|
||||
helper.setKeyManager(keyManager);
|
||||
assertThrows(
|
||||
IllegalStateException.class,
|
||||
() ->
|
||||
helper.configureWithKeyManager(
|
||||
(trustManager1, keyManager1) -> {
|
||||
throw new SSLException("ouchey");
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void configureWithKeyManagerNoTrustManager() {
|
||||
TlsConfigHelper helper = new TlsConfigHelper(tlsUtil);
|
||||
helper.configureWithKeyManager(
|
||||
(tm, km) -> {
|
||||
fail();
|
||||
});
|
||||
verifyNoInteractions(tlsUtil);
|
||||
}
|
||||
|
||||
@Test
|
||||
void setKeyManagerReplacesAndWarns() {
|
||||
X509KeyManager keyManager1 = mock(X509KeyManager.class);
|
||||
X509KeyManager keyManager2 = mock(X509KeyManager.class);
|
||||
|
||||
TlsConfigHelper helper = new TlsConfigHelper(tlsUtil);
|
||||
|
||||
helper.setTrustManager(mock(X509TrustManager.class));
|
||||
helper.setKeyManager(keyManager1);
|
||||
helper.setKeyManager(keyManager2);
|
||||
|
||||
helper.configureWithKeyManager((tm, km) -> assertSame(km, keyManager2));
|
||||
logs.assertContains("Previous X509 Key manager is being replaced");
|
||||
}
|
||||
|
||||
@Test
|
||||
void createKeyManagerReplacesAndWarns() throws Exception {
|
||||
X509KeyManager keyManager1 = mock(X509KeyManager.class);
|
||||
X509KeyManager keyManager2 = mock(X509KeyManager.class);
|
||||
|
||||
byte[] cert = serverTls.certificate().getEncoded();
|
||||
byte[] key = serverTls.privateKey().getEncoded();
|
||||
|
||||
when(tlsUtil.keyManager(key, cert)).thenReturn(keyManager2);
|
||||
TlsConfigHelper helper = new TlsConfigHelper(tlsUtil);
|
||||
|
||||
helper.setTrustManager(mock(X509TrustManager.class));
|
||||
helper.setKeyManager(keyManager1);
|
||||
helper.createKeyManager(key, cert);
|
||||
|
||||
helper.configureWithKeyManager((tm, km) -> assertSame(km, keyManager2));
|
||||
logs.assertContains("Previous X509 Key manager is being replaced");
|
||||
}
|
||||
}
|
||||
|
|
@ -109,13 +109,13 @@ public final class JaegerGrpcSpanExporterBuilder {
|
|||
* use the system default trusted certificates.
|
||||
*/
|
||||
public JaegerGrpcSpanExporterBuilder setTrustedCertificates(byte[] trustedCertificatesPem) {
|
||||
delegate.setTrustedCertificates(trustedCertificatesPem);
|
||||
delegate.configureTrustManager(trustedCertificatesPem);
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Sets the client key and chain to use for verifying servers when mTLS is enabled. */
|
||||
public JaegerGrpcSpanExporterBuilder setClientTls(byte[] privateKeyPem, byte[] certificatePem) {
|
||||
delegate.setClientTls(privateKeyPem, certificatePem);
|
||||
delegate.configureKeyManager(privateKeyPem, certificatePem);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import com.google.protobuf.InvalidProtocolBufferException;
|
|||
import com.linecorp.armeria.server.ServerBuilder;
|
||||
import com.linecorp.armeria.server.ServiceRequestContext;
|
||||
import com.linecorp.armeria.server.grpc.protocol.AbstractUnaryGrpcService;
|
||||
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.api.common.AttributeKey;
|
||||
|
|
@ -39,7 +40,6 @@ import io.opentelemetry.sdk.trace.data.StatusData;
|
|||
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
|
@ -88,6 +88,12 @@ class JaegerGrpcSpanExporterTest {
|
|||
@RegisterExtension
|
||||
LogCapturer logs = LogCapturer.create().captureForType(OkHttpGrpcExporter.class);
|
||||
|
||||
@RegisterExtension
|
||||
static final SelfSignedCertificateExtension serverTls = new SelfSignedCertificateExtension();
|
||||
|
||||
@RegisterExtension
|
||||
static final SelfSignedCertificateExtension clientTls = new SelfSignedCertificateExtension();
|
||||
|
||||
private static JaegerGrpcSpanExporter exporter;
|
||||
|
||||
@BeforeAll
|
||||
|
|
@ -285,22 +291,21 @@ class JaegerGrpcSpanExporterTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void validTrustedConfig() {
|
||||
void validTrustedConfig() throws Exception {
|
||||
assertThatCode(
|
||||
() ->
|
||||
JaegerGrpcSpanExporter.builder()
|
||||
.setTrustedCertificates("foobar".getBytes(StandardCharsets.UTF_8)))
|
||||
.setTrustedCertificates(serverTls.certificate().getEncoded()))
|
||||
.doesNotThrowAnyException();
|
||||
}
|
||||
|
||||
@Test
|
||||
void validClientKeyConfig() {
|
||||
void validClientKeyConfig() throws Exception {
|
||||
assertThatCode(
|
||||
() ->
|
||||
JaegerGrpcSpanExporter.builder()
|
||||
.setClientTls(
|
||||
"foobar".getBytes(StandardCharsets.UTF_8),
|
||||
"foobar".getBytes(StandardCharsets.UTF_8)))
|
||||
clientTls.privateKey().getEncoded(), serverTls.certificate().getEncoded()))
|
||||
.doesNotThrowAnyException();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ public final class OtlpHttpMetricExporterBuilder {
|
|||
* use the system default trusted certificates.
|
||||
*/
|
||||
public OtlpHttpMetricExporterBuilder setTrustedCertificates(byte[] trustedCertificatesPem) {
|
||||
delegate.setTrustedCertificates(trustedCertificatesPem);
|
||||
delegate.configureTrustManager(trustedCertificatesPem);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -108,7 +108,7 @@ public final class OtlpHttpMetricExporterBuilder {
|
|||
* The key must be PKCS8, and both must be in PEM format.
|
||||
*/
|
||||
public OtlpHttpMetricExporterBuilder setClientTls(byte[] privateKeyPem, byte[] certificatePem) {
|
||||
delegate.setClientTls(privateKeyPem, certificatePem);
|
||||
delegate.configureKeyManager(privateKeyPem, certificatePem);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ public final class OtlpHttpSpanExporterBuilder {
|
|||
* use the system default trusted certificates.
|
||||
*/
|
||||
public OtlpHttpSpanExporterBuilder setTrustedCertificates(byte[] trustedCertificatesPem) {
|
||||
delegate.setTrustedCertificates(trustedCertificatesPem);
|
||||
delegate.configureTrustManager(trustedCertificatesPem);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -96,7 +96,7 @@ public final class OtlpHttpSpanExporterBuilder {
|
|||
* The key must be PKCS8, and both must be in PEM format.
|
||||
*/
|
||||
public OtlpHttpSpanExporterBuilder setClientTls(byte[] privateKeyPem, byte[] certificatePem) {
|
||||
delegate.setClientTls(privateKeyPem, certificatePem);
|
||||
delegate.configureKeyManager(privateKeyPem, certificatePem);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ public final class OtlpGrpcMetricExporterBuilder {
|
|||
* use the system default trusted certificates.
|
||||
*/
|
||||
public OtlpGrpcMetricExporterBuilder setTrustedCertificates(byte[] trustedCertificatesPem) {
|
||||
delegate.setTrustedCertificates(trustedCertificatesPem);
|
||||
delegate.configureTrustManager(trustedCertificatesPem);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -140,7 +140,7 @@ public final class OtlpGrpcMetricExporterBuilder {
|
|||
* The key must be PKCS8, and both must be in PEM format.
|
||||
*/
|
||||
public OtlpGrpcMetricExporterBuilder setClientTls(byte[] privateKeyPem, byte[] certificatePem) {
|
||||
delegate.setClientTls(privateKeyPem, certificatePem);
|
||||
delegate.configureKeyManager(privateKeyPem, certificatePem);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ public final class OtlpGrpcSpanExporterBuilder {
|
|||
* use the system default trusted certificates.
|
||||
*/
|
||||
public OtlpGrpcSpanExporterBuilder setTrustedCertificates(byte[] trustedCertificatesPem) {
|
||||
delegate.setTrustedCertificates(trustedCertificatesPem);
|
||||
delegate.configureTrustManager(trustedCertificatesPem);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -124,7 +124,7 @@ public final class OtlpGrpcSpanExporterBuilder {
|
|||
* The key must be PKCS8, and both must be in PEM format.
|
||||
*/
|
||||
public OtlpGrpcSpanExporterBuilder setClientTls(byte[] privateKeyPem, byte[] certificatePem) {
|
||||
delegate.setClientTls(privateKeyPem, certificatePem);
|
||||
delegate.configureKeyManager(privateKeyPem, certificatePem);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ public final class OtlpHttpLogRecordExporterBuilder {
|
|||
* use the system default trusted certificates.
|
||||
*/
|
||||
public OtlpHttpLogRecordExporterBuilder setTrustedCertificates(byte[] trustedCertificatesPem) {
|
||||
delegate.setTrustedCertificates(trustedCertificatesPem);
|
||||
delegate.configureTrustManager(trustedCertificatesPem);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -93,7 +93,7 @@ public final class OtlpHttpLogRecordExporterBuilder {
|
|||
*/
|
||||
public OtlpHttpLogRecordExporterBuilder setClientTls(
|
||||
byte[] privateKeyPem, byte[] certificatePem) {
|
||||
delegate.setClientTls(privateKeyPem, certificatePem);
|
||||
delegate.configureKeyManager(privateKeyPem, certificatePem);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ public final class OtlpGrpcLogRecordExporterBuilder {
|
|||
* use the system default trusted certificates.
|
||||
*/
|
||||
public OtlpGrpcLogRecordExporterBuilder setTrustedCertificates(byte[] trustedCertificatesPem) {
|
||||
delegate.setTrustedCertificates(trustedCertificatesPem);
|
||||
delegate.configureTrustManager(trustedCertificatesPem);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -125,7 +125,7 @@ public final class OtlpGrpcLogRecordExporterBuilder {
|
|||
*/
|
||||
public OtlpGrpcLogRecordExporterBuilder setClientTls(
|
||||
byte[] privateKeyPem, byte[] certificatePem) {
|
||||
delegate.setClientTls(privateKeyPem, certificatePem);
|
||||
delegate.configureKeyManager(privateKeyPem, certificatePem);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -304,8 +304,10 @@ public abstract class AbstractGrpcTelemetryExporterTest<T, U extends Message> {
|
|||
void tls() throws Exception {
|
||||
TelemetryExporter<T> exporter =
|
||||
exporterBuilder()
|
||||
.setEndpoint(server.httpsUri().toString())
|
||||
.setTrustedCertificates(Files.readAllBytes(certificate.certificateFile().toPath()))
|
||||
.setClientTls(
|
||||
certificate.privateKey().getEncoded(), certificate.certificate().getEncoded())
|
||||
.setEndpoint(server.httpsUri().toString())
|
||||
.build();
|
||||
try {
|
||||
CompletableResultCode result =
|
||||
|
|
@ -337,10 +339,9 @@ public abstract class AbstractGrpcTelemetryExporterTest<T, U extends Message> {
|
|||
() ->
|
||||
exporterBuilder()
|
||||
.setEndpoint(server.httpsUri().toString())
|
||||
.setTrustedCertificates("foobar".getBytes(StandardCharsets.UTF_8))
|
||||
.build())
|
||||
.setTrustedCertificates("foobar".getBytes(StandardCharsets.UTF_8)))
|
||||
.isInstanceOf(IllegalStateException.class)
|
||||
.hasMessageContaining("Could not set trusted certificates");
|
||||
.hasMessageContaining("Error creating X509TrustManager with provided certs.");
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
|
|
@ -652,8 +653,7 @@ public abstract class AbstractGrpcTelemetryExporterTest<T, U extends Message> {
|
|||
.doesNotThrowAnyException();
|
||||
|
||||
assertThatCode(
|
||||
() ->
|
||||
exporterBuilder().setTrustedCertificates("foobar".getBytes(StandardCharsets.UTF_8)))
|
||||
() -> exporterBuilder().setTrustedCertificates(certificate.certificate().getEncoded()))
|
||||
.doesNotThrowAnyException();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -368,10 +368,9 @@ public abstract class AbstractHttpTelemetryExporterTest<T, U extends Message> {
|
|||
() ->
|
||||
exporterBuilder()
|
||||
.setEndpoint(server.httpsUri() + path)
|
||||
.setTrustedCertificates("foobar".getBytes(StandardCharsets.UTF_8))
|
||||
.build())
|
||||
.setTrustedCertificates("foobar".getBytes(StandardCharsets.UTF_8)))
|
||||
.isInstanceOf(IllegalStateException.class)
|
||||
.hasMessageContaining("Could not set trusted certificate");
|
||||
.hasMessageContaining("Error creating X509TrustManager with provided certs");
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
|
|
@ -555,8 +554,7 @@ public abstract class AbstractHttpTelemetryExporterTest<T, U extends Message> {
|
|||
.doesNotThrowAnyException();
|
||||
|
||||
assertThatCode(
|
||||
() ->
|
||||
exporterBuilder().setTrustedCertificates("foobar".getBytes(StandardCharsets.UTF_8)))
|
||||
() -> exporterBuilder().setTrustedCertificates(certificate.certificate().getEncoded()))
|
||||
.doesNotThrowAnyException();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import static java.util.Objects.requireNonNull;
|
|||
|
||||
import io.grpc.ManagedChannel;
|
||||
import io.grpc.ManagedChannelBuilder;
|
||||
import io.opentelemetry.exporter.internal.TlsConfigHelper;
|
||||
import io.opentelemetry.exporter.internal.grpc.ManagedChannelUtil;
|
||||
import io.opentelemetry.exporter.internal.otlp.OtlpUserAgent;
|
||||
import io.opentelemetry.exporter.internal.retry.RetryPolicy;
|
||||
|
|
@ -18,7 +19,6 @@ import java.time.Duration;
|
|||
import java.util.Collection;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.net.ssl.SSLException;
|
||||
|
||||
/**
|
||||
* Wraps a {@link TelemetryExporterBuilder}, delegating methods to upstream gRPC's {@link
|
||||
|
|
@ -40,9 +40,7 @@ public final class ManagedChannelTelemetryExporterBuilder<T>
|
|||
|
||||
@Nullable private ManagedChannelBuilder<?> channelBuilder;
|
||||
|
||||
@Nullable private byte[] privateKeyPem;
|
||||
@Nullable private byte[] certificatePem;
|
||||
@Nullable private byte[] trustedCertificatesPem;
|
||||
private final TlsConfigHelper tlsConfigHelper = new TlsConfigHelper();
|
||||
|
||||
@Override
|
||||
public TelemetryExporterBuilder<T> setEndpoint(String endpoint) {
|
||||
|
|
@ -89,14 +87,13 @@ public final class ManagedChannelTelemetryExporterBuilder<T>
|
|||
|
||||
@Override
|
||||
public TelemetryExporterBuilder<T> setTrustedCertificates(byte[] certificates) {
|
||||
this.trustedCertificatesPem = certificates;
|
||||
tlsConfigHelper.createTrustManager(certificates);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TelemetryExporterBuilder<T> setClientTls(byte[] privateKeyPem, byte[] certificatePem) {
|
||||
this.privateKeyPem = privateKeyPem;
|
||||
this.certificatePem = certificatePem;
|
||||
tlsConfigHelper.createKeyManager(privateKeyPem, certificatePem);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -126,15 +123,13 @@ public final class ManagedChannelTelemetryExporterBuilder<T>
|
|||
@Override
|
||||
public TelemetryExporter<T> build() {
|
||||
requireNonNull(channelBuilder, "channel");
|
||||
if (trustedCertificatesPem != null) {
|
||||
try {
|
||||
ManagedChannelUtil.setClientKeysAndTrustedCertificatesPem(
|
||||
channelBuilder, privateKeyPem, certificatePem, trustedCertificatesPem);
|
||||
} catch (SSLException e) {
|
||||
throw new IllegalStateException(
|
||||
"Could not set trusted certificates, are they valid X.509 in PEM format?", e);
|
||||
}
|
||||
}
|
||||
|
||||
tlsConfigHelper.configureWithKeyManager(
|
||||
(tm, km) -> {
|
||||
requireNonNull(channelBuilder, "channel");
|
||||
ManagedChannelUtil.setClientKeysAndTrustedCertificatesPem(channelBuilder, tm, km);
|
||||
});
|
||||
|
||||
ManagedChannel channel = channelBuilder.build();
|
||||
delegate.setChannel(channel);
|
||||
TelemetryExporter<T> delegateExporter = delegate.build();
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import io.grpc.ManagedChannelBuilder;
|
|||
import io.grpc.Metadata;
|
||||
import io.grpc.stub.MetadataUtils;
|
||||
import io.opentelemetry.exporter.internal.ExporterBuilderUtil;
|
||||
import io.opentelemetry.exporter.internal.TlsConfigHelper;
|
||||
import io.opentelemetry.exporter.internal.grpc.ManagedChannelUtil;
|
||||
import io.opentelemetry.exporter.internal.grpc.MarshalerServiceStub;
|
||||
import io.opentelemetry.exporter.internal.marshal.Marshaler;
|
||||
|
|
@ -25,7 +26,6 @@ import java.time.Duration;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Function;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.net.ssl.SSLException;
|
||||
|
||||
final class DefaultGrpcServiceBuilder<ReqT extends Marshaler, ResT extends UnMarshaler>
|
||||
implements GrpcServiceBuilder<ReqT, ResT> {
|
||||
|
|
@ -39,10 +39,8 @@ final class DefaultGrpcServiceBuilder<ReqT extends Marshaler, ResT extends UnMar
|
|||
private URI endpoint;
|
||||
private boolean compressionEnabled = false;
|
||||
@Nullable private Metadata metadata;
|
||||
@Nullable private byte[] trustedCertificatesPem;
|
||||
@Nullable private byte[] privateKeyPem;
|
||||
@Nullable private byte[] certificatePem;
|
||||
@Nullable private RetryPolicy retryPolicy;
|
||||
private final TlsConfigHelper tlsConfigHelper = new TlsConfigHelper();
|
||||
|
||||
// Visible for testing
|
||||
DefaultGrpcServiceBuilder(
|
||||
|
|
@ -101,14 +99,13 @@ final class DefaultGrpcServiceBuilder<ReqT extends Marshaler, ResT extends UnMar
|
|||
public DefaultGrpcServiceBuilder<ReqT, ResT> setTrustedCertificates(
|
||||
byte[] trustedCertificatesPem) {
|
||||
requireNonNull(trustedCertificatesPem, "trustedCertificatesPem");
|
||||
this.trustedCertificatesPem = trustedCertificatesPem;
|
||||
tlsConfigHelper.createTrustManager(trustedCertificatesPem);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GrpcServiceBuilder<ReqT, ResT> setClientTls(byte[] privateKeyPem, byte[] certificatePem) {
|
||||
this.privateKeyPem = privateKeyPem;
|
||||
this.certificatePem = certificatePem;
|
||||
tlsConfigHelper.createKeyManager(privateKeyPem, certificatePem);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -147,17 +144,10 @@ final class DefaultGrpcServiceBuilder<ReqT extends Marshaler, ResT extends UnMar
|
|||
managedChannelBuilder.intercept(MetadataUtils.newAttachHeadersInterceptor(metadata));
|
||||
}
|
||||
|
||||
if (trustedCertificatesPem != null) {
|
||||
try {
|
||||
ManagedChannelUtil.setClientKeysAndTrustedCertificatesPem(
|
||||
managedChannelBuilder, privateKeyPem, certificatePem, trustedCertificatesPem);
|
||||
} catch (SSLException e) {
|
||||
throw new IllegalStateException(
|
||||
"Could not set trusted certificates for gRPC TLS connection, are they valid "
|
||||
+ "X.509 in PEM format?",
|
||||
e);
|
||||
}
|
||||
}
|
||||
tlsConfigHelper.configureWithKeyManager(
|
||||
(tm, km) ->
|
||||
ManagedChannelUtil.setClientKeysAndTrustedCertificatesPem(
|
||||
managedChannelBuilder, tm, km));
|
||||
|
||||
if (retryPolicy != null) {
|
||||
managedChannelBuilder.defaultServiceConfig(toServiceConfig(grpcServiceName, retryPolicy));
|
||||
|
|
|
|||
|
|
@ -8,15 +8,19 @@ package io.opentelemetry.sdk.extension.trace.jaeger.sampler;
|
|||
import static org.assertj.core.api.Assertions.assertThatCode;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
import com.linecorp.armeria.testing.junit5.server.SelfSignedCertificateExtension;
|
||||
import io.opentelemetry.exporter.internal.retry.RetryPolicy;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
class DefaultGrpcServiceBuilderTest {
|
||||
|
||||
@RegisterExtension
|
||||
static final SelfSignedCertificateExtension serverTls = new SelfSignedCertificateExtension();
|
||||
|
||||
private static DefaultGrpcServiceBuilder<
|
||||
SamplingStrategyParametersMarshaler, SamplingStrategyResponseUnMarshaler>
|
||||
exporterBuilder() {
|
||||
|
|
@ -52,8 +56,7 @@ class DefaultGrpcServiceBuilderTest {
|
|||
.doesNotThrowAnyException();
|
||||
|
||||
assertThatCode(
|
||||
() ->
|
||||
exporterBuilder().setTrustedCertificates("foobar".getBytes(StandardCharsets.UTF_8)))
|
||||
() -> exporterBuilder().setTrustedCertificates(serverTls.certificate().getEncoded()))
|
||||
.doesNotThrowAnyException();
|
||||
|
||||
assertThatCode(() -> exporterBuilder().addRetryPolicy(RetryPolicy.getDefault()))
|
||||
|
|
|
|||
Loading…
Reference in New Issue