|
30 | 30 | import com.linecorp.armeria.testing.junit5.server.SelfSignedCertificateExtension; |
31 | 31 | import com.linecorp.armeria.testing.junit5.server.ServerExtension; |
32 | 32 | import io.github.netmikey.logunit.api.LogCapturer; |
| 33 | +import io.netty.handler.ssl.ClientAuth; |
33 | 34 | import io.opentelemetry.common.ComponentLoader; |
34 | 35 | import io.opentelemetry.exporter.internal.FailedExportException; |
35 | 36 | import io.opentelemetry.exporter.internal.TlsUtil; |
@@ -159,6 +160,41 @@ protected void configure(ServerBuilder sb) { |
159 | 160 | } |
160 | 161 | }; |
161 | 162 |
|
| 163 | + // Separate server that requires client authentication. |
| 164 | + // Used to verify client mTLS works even when no custom trust |
| 165 | + // certificates are configured. |
| 166 | + @RegisterExtension |
| 167 | + @Order(4) |
| 168 | + static final ServerExtension mtlsServer = new ServerExtension() { |
| 169 | + @Override |
| 170 | + protected void configure(ServerBuilder sb) { |
| 171 | + sb.service( |
| 172 | + "/v1/traces", |
| 173 | + new CollectorService<>( |
| 174 | + ExportTraceServiceRequest::parseFrom, |
| 175 | + ExportTraceServiceRequest::getResourceSpansList)); |
| 176 | + sb.service( |
| 177 | + "/v1/metrics", |
| 178 | + new CollectorService<>( |
| 179 | + ExportMetricsServiceRequest::parseFrom, |
| 180 | + ExportMetricsServiceRequest::getResourceMetricsList)); |
| 181 | + sb.service( |
| 182 | + "/v1/logs", |
| 183 | + new CollectorService<>( |
| 184 | + ExportLogsServiceRequest::parseFrom, |
| 185 | + ExportLogsServiceRequest::getResourceLogsList)); |
| 186 | + |
| 187 | + sb.http(0); |
| 188 | + sb.https(0); |
| 189 | + sb.tls(TlsKeyPair.of(certificate.privateKey(), certificate.certificate())); |
| 190 | + sb.tlsCustomizer( |
| 191 | + ssl -> { |
| 192 | + ssl.trustManager(clientCertificate.certificate()); |
| 193 | + ssl.clientAuth(ClientAuth.REQUIRE); |
| 194 | + }); |
| 195 | + } |
| 196 | + }; |
| 197 | + |
162 | 198 | private static class CollectorService<T> implements HttpService { |
163 | 199 | private final ThrowingExtractor<byte[], T, InvalidProtocolBufferException> parse; |
164 | 200 | private final Function<T, List<? extends Object>> getResourceTelemetry; |
@@ -461,6 +497,24 @@ void clientTls(byte[] privateKey) throws Exception { |
461 | 497 | } |
462 | 498 | } |
463 | 499 |
|
| 500 | + @ParameterizedTest |
| 501 | + @ArgumentsSource(ClientPrivateKeyProvider.class) |
| 502 | + void clientTlsWithoutTrustedCertificates(byte[] privateKey) throws Exception { |
| 503 | + try (TelemetryExporter<T> exporter = |
| 504 | + exporterBuilder() |
| 505 | + .setEndpoint(mtlsServer.httpsUri() + path) |
| 506 | + // Intentionally DO NOT configure trusted certificates. |
| 507 | + .setClientTls( |
| 508 | + privateKey, |
| 509 | + Files.readAllBytes(clientCertificate.certificateFile().toPath())) |
| 510 | + .build()) { |
| 511 | + |
| 512 | + CompletableResultCode result = |
| 513 | + exporter.export(Collections.singletonList(generateFakeTelemetry())); |
| 514 | + |
| 515 | + assertThat(result.join(10, TimeUnit.SECONDS).isSuccess()).isTrue(); |
| 516 | + } |
| 517 | + } |
464 | 518 | private static class ClientPrivateKeyProvider implements ArgumentsProvider { |
465 | 519 | @Override |
466 | 520 | @SuppressWarnings("PrimitiveArrayPassedToVarargsMethod") |
|
0 commit comments