diff --git a/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/exporter/otlp/OtlpExporterProcessor.java b/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/exporter/otlp/OtlpExporterProcessor.java index b73a77d3ac387..4365478d1183c 100644 --- a/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/exporter/otlp/OtlpExporterProcessor.java +++ b/extensions/opentelemetry/deployment/src/main/java/io/quarkus/opentelemetry/deployment/exporter/otlp/OtlpExporterProcessor.java @@ -24,6 +24,7 @@ import io.quarkus.opentelemetry.runtime.config.runtime.exporter.OtlpExporterRuntimeConfig; import io.quarkus.opentelemetry.runtime.exporter.otlp.LateBoundBatchSpanProcessor; import io.quarkus.opentelemetry.runtime.exporter.otlp.OTelExporterRecorder; +import io.quarkus.tls.TlsConfigurationRegistry; import io.quarkus.tls.TlsRegistryBuildItem; import io.quarkus.vertx.core.deployment.CoreVertxBuildItem; @@ -64,6 +65,7 @@ void createBatchSpanProcessor(OTelExporterRecorder recorder, .unremovable() .addInjectionPoint(ParameterizedType.create(DotName.createSimple(Instance.class), new Type[] { ClassType.create(DotName.createSimple(SpanExporter.class.getName())) }, null)) + .addInjectionPoint(ClassType.create(DotName.createSimple(TlsConfigurationRegistry.class))) .createWith(recorder.batchSpanProcessorForOtlp(otelRuntimeConfig, exporterRuntimeConfig, vertxBuildItem.getVertx())) .done()); diff --git a/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/config/runtime/exporter/OtlpExporterTracesConfig.java b/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/config/runtime/exporter/OtlpExporterTracesConfig.java index 91a84e735ab07..e815230ac4fd2 100644 --- a/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/config/runtime/exporter/OtlpExporterTracesConfig.java +++ b/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/config/runtime/exporter/OtlpExporterTracesConfig.java @@ -74,6 +74,15 @@ public interface OtlpExporterTracesConfig { @WithName("trust-cert") TrustCert trustCert(); + /** + * The name of the TLS configuration to use. + *

+ * If not set and the default TLS configuration is configured ({@code quarkus.tls.*}) then that will be used. + * If a name is configured, it uses the configuration from {@code quarkus.tls..*} + * If a name is configured, but no TLS configuration is found with that name then an error will be thrown. + */ + Optional tlsConfigurationName(); + /** * Set proxy options */ diff --git a/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/exporter/otlp/OTelExporterRecorder.java b/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/exporter/otlp/OTelExporterRecorder.java index 36f56a76cd4d9..4ba8a52a6e6b9 100644 --- a/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/exporter/otlp/OTelExporterRecorder.java +++ b/extensions/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/exporter/otlp/OTelExporterRecorder.java @@ -24,7 +24,6 @@ import io.opentelemetry.sdk.trace.export.BatchSpanProcessor; import io.opentelemetry.sdk.trace.export.BatchSpanProcessorBuilder; import io.opentelemetry.sdk.trace.export.SpanExporter; -import io.quarkus.arc.Arc; import io.quarkus.arc.SyntheticCreationalContext; import io.quarkus.opentelemetry.runtime.config.runtime.OTelRuntimeConfig; import io.quarkus.opentelemetry.runtime.config.runtime.exporter.CompressionType; @@ -35,7 +34,6 @@ import io.quarkus.tls.TlsConfigurationRegistry; import io.vertx.core.Vertx; import io.vertx.core.http.HttpClientOptions; -import io.vertx.core.net.KeyCertOptions; import io.vertx.core.net.PemKeyCertOptions; import io.vertx.core.net.PemTrustOptions; import io.vertx.core.net.ProxyOptions; @@ -63,7 +61,10 @@ public LateBoundBatchSpanProcessor apply( } try { - var spanExporter = createSpanExporter(exporterRuntimeConfig, vertx.get(), baseUri); + TlsConfigurationRegistry tlsConfigurationRegistry = context + .getInjectedReference(TlsConfigurationRegistry.class); + var spanExporter = createSpanExporter(exporterRuntimeConfig, vertx.get(), baseUri, + tlsConfigurationRegistry); BatchSpanProcessorBuilder processorBuilder = BatchSpanProcessor.builder(spanExporter); @@ -80,7 +81,9 @@ public LateBoundBatchSpanProcessor apply( } private SpanExporter createSpanExporter(OtlpExporterRuntimeConfig exporterRuntimeConfig, - Vertx vertx, final URI baseUri) { + Vertx vertx, + URI baseUri, + TlsConfigurationRegistry tlsConfigurationRegistry) { OtlpExporterTracesConfig tracesConfig = exporterRuntimeConfig.traces(); if (tracesConfig.protocol().isEmpty()) { throw new IllegalStateException("No OTLP protocol specified. " + @@ -89,9 +92,9 @@ private SpanExporter createSpanExporter(OtlpExporterRuntimeConfig exporterRuntim String protocol = tracesConfig.protocol().get(); if (GRPC.equals(protocol)) { - return createOtlpGrpcSpanExporter(exporterRuntimeConfig, vertx, baseUri); + return createOtlpGrpcSpanExporter(exporterRuntimeConfig, vertx, baseUri, tlsConfigurationRegistry); } else if (HTTP_PROTOBUF.equals(protocol)) { - return createHttpSpanExporter(exporterRuntimeConfig, vertx, baseUri, protocol); + return createHttpSpanExporter(exporterRuntimeConfig, vertx, baseUri, protocol, tlsConfigurationRegistry); } throw new IllegalArgumentException(String.format("Unsupported OTLP protocol %s specified. " + @@ -99,7 +102,8 @@ private SpanExporter createSpanExporter(OtlpExporterRuntimeConfig exporterRuntim } private SpanExporter createOtlpGrpcSpanExporter(OtlpExporterRuntimeConfig exporterRuntimeConfig, - Vertx vertx, final URI baseUri) { + Vertx vertx, final URI baseUri, + TlsConfigurationRegistry tlsConfigurationRegistry) { OtlpExporterTracesConfig tracesConfig = exporterRuntimeConfig.traces(); @@ -111,13 +115,14 @@ private SpanExporter createOtlpGrpcSpanExporter(OtlpExporterRuntimeConfig export determineCompression(tracesConfig), tracesConfig.timeout(), populateTracingExportHttpHeaders(tracesConfig), - new HttpClientOptionsConsumer(tracesConfig, baseUri), + new HttpClientOptionsConsumer(tracesConfig, baseUri, tlsConfigurationRegistry), vertx); } private SpanExporter createHttpSpanExporter(OtlpExporterRuntimeConfig exporterRuntimeConfig, Vertx vertx, - URI baseUri, String protocol) { + URI baseUri, String protocol, + TlsConfigurationRegistry tlsConfigurationRegistry) { OtlpExporterTracesConfig tracesConfig = exporterRuntimeConfig.traces(); @@ -132,7 +137,7 @@ private SpanExporter createHttpSpanExporter(OtlpExporterRuntimeConfig exporterRu tracesConfig.timeout(), populateTracingExportHttpHeaders(tracesConfig), exportAsJson ? "application/json" : "application/x-protobuf", - new HttpClientOptionsConsumer(tracesConfig, baseUri), + new HttpClientOptionsConsumer(tracesConfig, baseUri, tlsConfigurationRegistry), vertx), MeterProvider::noop, exportAsJson)); @@ -193,10 +198,15 @@ private static boolean excludeDefaultEndpoint(String endpoint) { static class HttpClientOptionsConsumer implements Consumer { private final OtlpExporterTracesConfig tracesConfig; private final URI baseUri; + private final Optional maybeTlsConfiguration; + private final TlsConfigurationRegistry tlsConfigurationRegistry; - public HttpClientOptionsConsumer(OtlpExporterTracesConfig tracesConfig, URI baseUri) { + public HttpClientOptionsConsumer(OtlpExporterTracesConfig tracesConfig, URI baseUri, + TlsConfigurationRegistry tlsConfigurationRegistry) { this.tracesConfig = tracesConfig; this.baseUri = baseUri; + this.maybeTlsConfiguration = TlsConfiguration.from(tlsConfigurationRegistry, tracesConfig.tlsConfigurationName()); + this.tlsConfigurationRegistry = tlsConfigurationRegistry; } @Override @@ -208,24 +218,22 @@ public void accept(HttpClientOptions options) { } private void configureTLS(HttpClientOptions options) { - // TODO: this can reuse existing stuff when https://github.com/quarkusio/quarkus/pull/33228 is in - options.setKeyCertOptions(toPemKeyCertOptions()); - options.setPemTrustOptions(toPemTrustOptions()); + configureKeyCertOptions(options); + configureTrustOptions(options); if (OTelExporterUtil.isHttps(baseUri)) { options.setSsl(true); options.setUseAlpn(true); } - boolean globalTrustAll = false; - if (Arc.container() != null) { - TlsConfigurationRegistry registry = Arc.container().select(TlsConfigurationRegistry.class).orNull(); - if (registry != null) { - globalTrustAll = registry.getDefault().map(TlsConfiguration::isTrustAll).orElse(false); - } - } - - if (globalTrustAll) { + boolean trustAll = maybeTlsConfiguration.map(TlsConfiguration::isTrustAll).orElseGet( + new Supplier<>() { + @Override + public Boolean get() { + return tlsConfigurationRegistry.getDefault().map(TlsConfiguration::isTrustAll).orElse(false); + } + }); + if (trustAll) { options.setTrustAll(true); options.setVerifyHost(false); } @@ -279,10 +287,15 @@ private void configureProxyOptionsFromJDKSysProps(HttpClientOptions options) { } } - private KeyCertOptions toPemKeyCertOptions() { + private void configureKeyCertOptions(HttpClientOptions options) { + if (maybeTlsConfiguration.isPresent()) { + options.setKeyCertOptions(maybeTlsConfiguration.get().getKeyStoreOptions()); + return; + } + OtlpExporterTracesConfig.KeyCert keyCert = tracesConfig.keyCert(); if (keyCert.certs().isEmpty() && keyCert.keys().isEmpty()) { - return null; + return; } PemKeyCertOptions pemKeyCertOptions = new PemKeyCertOptions(); @@ -296,10 +309,15 @@ private KeyCertOptions toPemKeyCertOptions() { pemKeyCertOptions.addKeyPath(cert); } } - return pemKeyCertOptions; + options.setKeyCertOptions(pemKeyCertOptions); } - private PemTrustOptions toPemTrustOptions() { + private void configureTrustOptions(HttpClientOptions options) { + if (maybeTlsConfiguration.isPresent()) { + options.setTrustOptions(maybeTlsConfiguration.get().getTrustStoreOptions()); + return; + } + OtlpExporterTracesConfig.TrustCert trustCert = tracesConfig.trustCert(); if (trustCert.certs().isPresent()) { List certs = trustCert.certs().get(); @@ -308,10 +326,9 @@ private PemTrustOptions toPemTrustOptions() { for (String cert : trustCert.certs().get()) { pemTrustOptions.addCertPath(cert); } - return pemTrustOptions; + options.setPemTrustOptions(pemTrustOptions); } } - return null; } } } diff --git a/extensions/opentelemetry/runtime/src/test/java/io/quarkus/opentelemetry/runtime/exporter/otlp/HttpClientOptionsConsumerTest.java b/extensions/opentelemetry/runtime/src/test/java/io/quarkus/opentelemetry/runtime/exporter/otlp/HttpClientOptionsConsumerTest.java index be2057f2e97e4..16b7a6c815499 100644 --- a/extensions/opentelemetry/runtime/src/test/java/io/quarkus/opentelemetry/runtime/exporter/otlp/HttpClientOptionsConsumerTest.java +++ b/extensions/opentelemetry/runtime/src/test/java/io/quarkus/opentelemetry/runtime/exporter/otlp/HttpClientOptionsConsumerTest.java @@ -15,6 +15,8 @@ import io.quarkus.opentelemetry.runtime.config.runtime.exporter.CompressionType; import io.quarkus.opentelemetry.runtime.config.runtime.exporter.OtlpExporterTracesConfig; +import io.quarkus.tls.TlsConfiguration; +import io.quarkus.tls.TlsConfigurationRegistry; import io.vertx.core.http.HttpClientOptions; class HttpClientOptionsConsumerTest { @@ -23,7 +25,8 @@ class HttpClientOptionsConsumerTest { void testNoProxy() { OTelExporterRecorder.HttpClientOptionsConsumer consumer = new OTelExporterRecorder.HttpClientOptionsConsumer( createExporterConfig(false), - URI.create("http://localhost:4317")); + URI.create("http://localhost:4317"), + new NoopTlsConfigurationRegistry()); HttpClientOptions httpClientOptions = new HttpClientOptions(); consumer.accept(httpClientOptions); @@ -34,7 +37,8 @@ void testNoProxy() { void testWithProxy() { OTelExporterRecorder.HttpClientOptionsConsumer consumer = new OTelExporterRecorder.HttpClientOptionsConsumer( createExporterConfig(true), - URI.create("http://localhost:4317")); + URI.create("http://localhost:4317"), + new NoopTlsConfigurationRegistry()); HttpClientOptions httpClientOptions = new HttpClientOptions(); consumer.accept(httpClientOptions); @@ -102,6 +106,11 @@ public Optional> certs() { }; } + @Override + public Optional tlsConfigurationName() { + return Optional.empty(); + } + @Override public ProxyConfig proxyOptions() { return new ProxyConfig() { @@ -133,4 +142,21 @@ public Optional host() { } }; } + + private static class NoopTlsConfigurationRegistry implements TlsConfigurationRegistry { + @Override + public Optional get(String name) { + return Optional.empty(); + } + + @Override + public Optional getDefault() { + return Optional.empty(); + } + + @Override + public void register(String name, TlsConfiguration configuration) { + + } + } } diff --git a/extensions/opentelemetry/runtime/src/test/java/io/quarkus/opentelemetry/runtime/exporter/otlp/OtlpExporterProviderTest.java b/extensions/opentelemetry/runtime/src/test/java/io/quarkus/opentelemetry/runtime/exporter/otlp/OtlpExporterProviderTest.java index f666ca71b1911..b3391b3aa932e 100644 --- a/extensions/opentelemetry/runtime/src/test/java/io/quarkus/opentelemetry/runtime/exporter/otlp/OtlpExporterProviderTest.java +++ b/extensions/opentelemetry/runtime/src/test/java/io/quarkus/opentelemetry/runtime/exporter/otlp/OtlpExporterProviderTest.java @@ -136,6 +136,11 @@ public Optional> certs() { }; } + @Override + public Optional tlsConfigurationName() { + return Optional.empty(); + } + @Override public ProxyConfig proxyOptions() { return new ProxyConfig() { diff --git a/extensions/tls-registry/runtime/src/main/java/io/quarkus/tls/TlsConfiguration.java b/extensions/tls-registry/runtime/src/main/java/io/quarkus/tls/TlsConfiguration.java index 1492f172adac4..2046ec9d8caad 100644 --- a/extensions/tls-registry/runtime/src/main/java/io/quarkus/tls/TlsConfiguration.java +++ b/extensions/tls-registry/runtime/src/main/java/io/quarkus/tls/TlsConfiguration.java @@ -23,7 +23,7 @@ static Optional from(TlsConfigurationRegistry registry, Option } return maybeConfiguration; } - return registry.getDefault(); + return Optional.empty(); } /** diff --git a/integration-tests/opentelemetry-vertx-exporter/src/test/java/io/quarkus/it/opentelemetry/vertx/exporter/OtelCollectorLifecycleManager.java b/integration-tests/opentelemetry-vertx-exporter/src/test/java/io/quarkus/it/opentelemetry/vertx/exporter/OtelCollectorLifecycleManager.java index 51b2900a7a428..1c2df7c6a0df1 100644 --- a/integration-tests/opentelemetry-vertx-exporter/src/test/java/io/quarkus/it/opentelemetry/vertx/exporter/OtelCollectorLifecycleManager.java +++ b/integration-tests/opentelemetry-vertx-exporter/src/test/java/io/quarkus/it/opentelemetry/vertx/exporter/OtelCollectorLifecycleManager.java @@ -50,6 +50,7 @@ public class OtelCollectorLifecycleManager implements QuarkusTestResourceLifecyc private boolean enableTLS = false; private boolean preventTrustCert = false; private boolean enableCompression = false; + private String tlsRegistryName = null; private Vertx vertx; private HttpServer server; @@ -77,6 +78,10 @@ public void init(Map initArgs) { if (initArgs.containsKey("protocol")) { protocol = initArgs.get("protocol"); } + + if (initArgs.containsKey("tlsRegistryName")) { + tlsRegistryName = initArgs.get("tlsRegistryName"); + } } @Override @@ -130,11 +135,21 @@ public Map start() { if (enableTLS) { result.put("quarkus.otel.exporter.otlp.traces.endpoint", "https://" + collector.getHost() + ":" + collector.getMappedPort(secureEndpointPort)); - if (!preventTrustCert) { - result.put("quarkus.otel.exporter.otlp.traces.trust-cert.certs", serverTls.certificatePath()); + if (tlsRegistryName != null) { + result.put("quarkus.otel.exporter.otlp.traces.tls-configuration-name", tlsRegistryName); + if (!preventTrustCert) { + result.put(String.format("quarkus.tls.%s.trust-store.pem.certs", tlsRegistryName), + serverTls.certificatePath()); + } + result.put(String.format("quarkus.tls.%s.key-store.pem.0.cert", tlsRegistryName), clientTlS.certificatePath()); + result.put(String.format("quarkus.tls.%s.key-store.pem.0.key", tlsRegistryName), clientTlS.privateKeyPath()); + } else { + if (!preventTrustCert) { + result.put("quarkus.otel.exporter.otlp.traces.trust-cert.certs", serverTls.certificatePath()); + } + result.put("quarkus.otel.exporter.otlp.traces.key-cert.certs", clientTlS.certificatePath()); + result.put("quarkus.otel.exporter.otlp.traces.key-cert.keys", clientTlS.privateKeyPath()); } - result.put("quarkus.otel.exporter.otlp.traces.key-cert.certs", clientTlS.certificatePath()); - result.put("quarkus.otel.exporter.otlp.traces.key-cert.keys", clientTlS.privateKeyPath()); } else { result.put("quarkus.otel.exporter.otlp.traces.endpoint", "http://" + collector.getHost() + ":" + collector.getMappedPort(inSecureEndpointPort)); diff --git a/integration-tests/opentelemetry-vertx-exporter/src/test/java/io/quarkus/it/opentelemetry/vertx/exporter/http/HttpWithTLSWithCompressionUsingRegistryTest.java b/integration-tests/opentelemetry-vertx-exporter/src/test/java/io/quarkus/it/opentelemetry/vertx/exporter/http/HttpWithTLSWithCompressionUsingRegistryTest.java new file mode 100644 index 0000000000000..e00d9ca008237 --- /dev/null +++ b/integration-tests/opentelemetry-vertx-exporter/src/test/java/io/quarkus/it/opentelemetry/vertx/exporter/http/HttpWithTLSWithCompressionUsingRegistryTest.java @@ -0,0 +1,18 @@ +package io.quarkus.it.opentelemetry.vertx.exporter.http; + +import io.quarkus.it.opentelemetry.vertx.exporter.AbstractExporterTest; +import io.quarkus.it.opentelemetry.vertx.exporter.OtelCollectorLifecycleManager; +import io.quarkus.test.common.QuarkusTestResource; +import io.quarkus.test.common.ResourceArg; +import io.quarkus.test.junit.QuarkusTest; + +@QuarkusTest +@QuarkusTestResource(value = OtelCollectorLifecycleManager.class, initArgs = { + @ResourceArg(name = "enableTLS", value = "true"), + @ResourceArg(name = "enableCompression", value = "true"), + @ResourceArg(name = "protocol", value = "http/protobuf"), + @ResourceArg(name = "tlsRegistryName", value = "otel") +}, restrictToAnnotatedClass = true) +public class HttpWithTLSWithCompressionUsingRegistryTest extends AbstractExporterTest { + +}